Skip to content

Commit 3175aa8

Browse files
committed
added tags to ui
1 parent 80d200a commit 3175aa8

File tree

6 files changed

+95
-17
lines changed

6 files changed

+95
-17
lines changed

events/api.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
create_repeat_event,
88
delete_event,
99
edit_event,
10+
get_all_tags,
1011
get_datetime_from_string,
1112
get_event_by_id,
1213
get_event_by_slug,
1314
get_events_by_time,
15+
get_tags_by_string,
1416
get_timedelta_from_string,
1517
)
1618
from schema import Event, Tag, Week
@@ -573,13 +575,16 @@ def delete_event_api(event_id: int) -> tuple[Response, int]:
573575
return jsonify({"message": "Event deleted successfully"}), 200
574576

575577

576-
# TODO: might want to refactor getting tags to utils
577-
578-
579578
@events_api_bp.route("/tags", methods=["GET"])
580579
def get_tags() -> tuple[Response, int]:
581580
"""Get all tags
582581
---
582+
parameters:
583+
- name: query
584+
in: query
585+
type: string
586+
required: false
587+
description: A query string to filter tags by name.
583588
security: []
584589
responses:
585590
200:
@@ -591,7 +596,10 @@ def get_tags() -> tuple[Response, int]:
591596
404:
592597
description: No tags found.
593598
"""
594-
tags = Tag.query.order_by(Tag.name).all()
599+
query_string = request.args.get("query", "")
600+
tags = (
601+
get_tags_by_string(query_string, limit=-1) if query_string else get_all_tags()
602+
)
595603
if not tags:
596604
return jsonify({"error": "No tags found"}), 404
597605
return jsonify([tag.to_dict() for tag in tags]), 200

events/ui.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from config import colours, icons
66
from events.utils import (
77
create_event,
8+
get_all_tags,
89
get_datetime_from_string,
910
get_event_by_slug,
1011
get_timedelta_from_string,
@@ -19,6 +20,8 @@
1920
def create(error: str | None = None) -> str | Response: # noqa: PLR0911
2021
"""Create a new event."""
2122

23+
tags = [tag.name for tag in get_all_tags()]
24+
2225
# if getting, return the ui for creating an event
2326
if request.method == "GET":
2427
return render_template(
@@ -29,6 +32,7 @@ def create(error: str | None = None) -> str | Response: # noqa: PLR0911
2932
event=None,
3033
icons=icons,
3134
colours=colours,
35+
tags=tags,
3236
)
3337

3438
# if posting, create the event
@@ -74,11 +78,8 @@ def create(error: str | None = None) -> str | Response: # noqa: PLR0911
7478
return redirect(url_for("events_ui.create"))
7579

7680
# parse tags
77-
tags = (
78-
[tag.strip() for tag in request.form["tags"].split(",")]
79-
if request.form["tags"]
80-
else []
81-
)
81+
tags = request.form.getlist("tags[]")
82+
tags = [tag.strip().lower() for tag in tags if tag.strip()] if tags else []
8283

8384
# attempt to create the event
8485
event = create_event(

events/utils.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ def create_event( # noqa: PLR0913
9292
db.session.rollback()
9393
return "Unable to find or create a week for the event date"
9494

95+
# add the event to db to allow tags
96+
db.session.add(event)
97+
9598
# attach tags to the event
9699
# check all tags exist, create if not
97100
for tag in tags:
@@ -101,8 +104,6 @@ def create_event( # noqa: PLR0913
101104
db.session.add(tag_obj)
102105
event.tags.append(tag_obj)
103106

104-
# add the event to the session and commit
105-
db.session.add(event)
106107
db.session.commit()
107108

108109
return event
@@ -402,3 +403,16 @@ def get_name_from_hex(hex_colour: str) -> str | None:
402403
if hex_code.lower() == hex_colour.lower():
403404
return name
404405
return None
406+
407+
408+
def get_all_tags() -> list[Tag]:
409+
"""Get all tags from the database"""
410+
return Tag.query.order_by(Tag.name).all()
411+
412+
413+
def get_tags_by_string(search: str, limit: int = 10) -> list[Tag]:
414+
"""get tags by a string query"""
415+
search = search.lower()
416+
query = Tag.query.filter(Tag.name.ilike(f"%{search}%")).order_by(Tag.name) # type: ignore
417+
418+
return query.limit(limit).all() if limit != -1 else query.all()

static/js/tags.min.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

static/sass/custom/_tags.scss

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// All from https://github.com/lekoala/bootstrap5-tags/blob/master/_tags.scss
2+
3+
// Add pseudo focus support
4+
.form-control-focus {
5+
color: var(--bs-body-color, $input-focus-color);
6+
background-color: var(--bs-form-control-bg, var(--bs-body-bg, $input-focus-bg));
7+
border-color: $input-focus-border-color;
8+
outline: 0;
9+
10+
@if $enable-shadows {
11+
@include box-shadow($input-box-shadow, $input-focus-box-shadow);
12+
}
13+
14+
@else {
15+
// Avoid using mixin so we can pass custom focus shadow properly
16+
box-shadow: $input-focus-box-shadow;
17+
}
18+
}
19+
20+
@each $state, $data in $form-validation-states {
21+
.was-validated :#{$state}+.form-control-focus {
22+
border-color: map-get($data, "color");
23+
box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba(map-get($data, "color"), $input-btn-focus-color-opacity);
24+
}
25+
}
26+
27+
// Add pseudo placeholder support
28+
.form-floating .form-control.form-placeholder-shown:not(.form-control-focus)~label {
29+
opacity: unset;
30+
transform: unset;
31+
}
32+
33+
// Add pseudo disabled support
34+
.form-control-disabled {
35+
background-color: var(--bs-form-control-disabled-bg, var(--bs-secondary-bg, $input-disabled-bg));
36+
opacity: 1;
37+
}
38+
39+
// mark support
40+
.tags-menu mark {
41+
text-decoration: underline;
42+
background: none;
43+
color: currentColor;
44+
padding: 0;
45+
}

templates/events/form.html

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
{% block header %}
66
<script src="{{ url_for('static', filename='js/event-management.js') }}"></script>
7+
<script type="module">
8+
import Tags from "{{ url_for('static', filename='js/tags.min.js') }}";
9+
Tags.init();
10+
</script>
711
{% endblock %}
812

913
{% block content %}
@@ -177,15 +181,15 @@ <h1>Create Event</h1>
177181
</div>
178182

179183
<!-- tags -->
180-
<!-- badge and created tags? -->
184+
<!-- tags from https://github.com/lekoala/bootstrap5-tags -->
181185
<div class="form-floating col-md-8 offset-md-2">
182-
<input type="text" name="tags" id="tags" class="form-control no-validate" placeholder="tag1,tag2,tag3">
183-
<label for="tags">Tags</label>
184-
<datalist id="tags-list">
186+
<select class="form-select" id="tags" name="tags[]" multiple data-allow-new="true" data-allow-clear="true" data-separator=" |,| ">
187+
<option value="" disabled selected>Select tags</option>
185188
{% for tag in tags %}
186-
<option value="{{ tag }}">
189+
<option value="{{ tag }}">{{ tag }}</option>
187190
{% endfor %}
188-
</datalist>
191+
</select>
192+
<label for="tags">Tags</label>
189193
</div>
190194

191195
<!-- submit -->

0 commit comments

Comments
 (0)