diff --git a/server/app.py b/server/app.py index a2d8f1b..7b275b2 100644 --- a/server/app.py +++ b/server/app.py @@ -284,6 +284,13 @@ def _template_are_multiple_considered(elem_ids: Iterable[int]) -> Mapping[int, b return are_multiple_considered(elem_ids) +@flask_app.template_filter() +def filter_preference_tags(tags: Iterable[Tag]) -> Iterable[Tag]: + for t in tags: + if t.use_for_preferences: + yield t + + #### # Routes #### @@ -838,14 +845,28 @@ def show_stats_queries() -> ResponseReturnValue: @flask_app.route("/tag") -def show_tag() -> ResponseReturnValue: - tag_list: List[Tag] = Tag.select() +def show_root_tags() -> ResponseReturnValue: + tag_list: List[Tag] = orm.select( + t for t in Tag if len(t.super_tag_list) <= 0 + ).order_by(Tag.title, Tag.id) return render_template( - "tag_list.htm", + "tag/list.htm", tag_list=tag_list, ) +@flask_app.route("/tag/") +def show_tag_element(tag_id: int) -> ResponseReturnValue: + tag: Optional[Tag] = Tag.get(id=tag_id) + if tag is None: + return make_response(f"Not found", 404) + return render_template( + "tag/element.htm", + tag=tag, + tag_media_list=tag.media_list.order_by(MediaElement.sort_key), + ) + + @flask_app.route("/debug/test") def test() -> ResponseReturnValue: first: MediaElement = MediaElement.select().first() @@ -1301,3 +1322,42 @@ def api_media_set_dependent() -> ResponseReturnValue: def api_tag_delete_temporary() -> ResponseReturnValue: Tag.scrub_temporary_tags() return redirect_back_or_okay() + + +@flask_app.route("/api/tag/", methods=["GET", "POST"]) +def api_tag(tag_id: int) -> ResponseReturnValue: + tag: Tag = Tag.get(id=tag_id) + if tag is None: + return { + "status": False, + "error": f"Object not found", + }, 404 + if request.method == "GET": + return { + "status": True, + "data": { + "id": tag.id, + "title": tag.title, + "notes": tag.notes, + "use_for_preferences": tag.use_for_preferences, + "super_tags": [t.id for t in tag.super_tag_list], + "sub_tags": [t.id for t in tag.sub_tag_list], + }, + }, 200 + elif request.method == "POST": + data = request.form.to_dict() + if "redirect" in data: + del data["redirect"] + KEY_CONVETER: Mapping[str, Callable[[str], Any]] = { + "title": str, + "notes": str, + "use_for_preferences": environ_bool, + } + for key in data: + if key not in KEY_CONVETER: + return { + "status": False, + "error": f"Cannot set key {key!r} on Tag", + }, 400 + tag.set(**{key: KEY_CONVETER[key](val) for key, val in data.items()}) + return redirect_back_or_okay() diff --git a/server/entertainment_decider/models/entities.py b/server/entertainment_decider/models/entities.py index d4e40b5..16ca143 100644 --- a/server/entertainment_decider/models/entities.py +++ b/server/entertainment_decider/models/entities.py @@ -200,6 +200,10 @@ class Tag(db.Entity, Tagable, TagProto["Tag"]): def orm_super_tags(self) -> Query[Tag]: return self.super_tag_list if self.use_for_preferences else [] + @property + def info_link(self) -> str: + return f"/tag/{self.id}" + class TagKey(db.Entity): num_id: int = orm.PrimaryKey(int, auto=True) diff --git a/server/templates/collection_element.htm b/server/templates/collection_element.htm index 3710e71..8397ff5 100644 --- a/server/templates/collection_element.htm +++ b/server/templates/collection_element.htm @@ -66,7 +66,7 @@ {% endif %} {% if collection.all_tags %}
  • - Tags: {{ collection.all_tags | map(attribute="title") | sort | join(" | ") }} + Tags: {{ macros.tag_list(collection.all_tags | filter_preference_tags) }}
  • {% endif %} {% if collection.watch_in_order %} diff --git a/server/templates/collection_list.htm b/server/templates/collection_list.htm index ff8327f..fac6928 100644 --- a/server/templates/collection_list.htm +++ b/server/templates/collection_list.htm @@ -42,7 +42,7 @@ {{ collection.title }} - {{ collection.assigned_tags | map(attribute="title") | sort | join(" | ") }} + {{ macros.tag_list(collection.assigned_tags) }} {% endfor %} diff --git a/server/templates/macros.htm b/server/templates/macros.htm index 0447598..1d1c020 100644 --- a/server/templates/macros.htm +++ b/server/templates/macros.htm @@ -657,3 +657,47 @@ {% endfor %} {%- endmacro %} + +{% macro tag_list(tags) -%} + {%- for t in tags | sort(attribute="title") -%} + {%- if loop.index > 1 -%} + {{ " | " }} + {%- endif -%} + {{ t.title }} + {%- endfor -%} +{%- endmacro %} + +{% macro tag_table(tag_list) %} + + + + + + + + {% for tag in tag_list %} + {{ tag_table_entry(tag) }} + {% endfor %} +
    IdTitleUse for Pref.Notes
    +{%- endmacro %} + +{% macro tag_table_entry(tag) %} + {%- set api_uri = "/api/tag/" + tag.id|string -%} + {%- set fragment = "tag_" + tag.id|string -%} + + + {{- tag.id -}} + + + + {{- tag.title -}} + + + + {{ post_form(api_uri, "use_for_preferences", tag.use_for_preferences | tenary("false", "true"), tag.use_for_preferences | tenary("Yes", "no"), fragment) }} + + + {{- tag.notes or "" -}} + + +{%- endmacro %} diff --git a/server/templates/media_element.htm b/server/templates/media_element.htm index f6b96fb..8a4e68d 100644 --- a/server/templates/media_element.htm +++ b/server/templates/media_element.htm @@ -57,7 +57,7 @@ {% endif %} {% if element.all_tags %}
  • - Tags: {{ element.all_tags | map(attribute="title") | join(" | ") }} + Tags: {{ macros.tag_list(element.all_tags | filter_preference_tags) }}
  • {% endif %} diff --git a/server/templates/tag/element.htm b/server/templates/tag/element.htm new file mode 100644 index 0000000..2905fe9 --- /dev/null +++ b/server/templates/tag/element.htm @@ -0,0 +1,57 @@ +{% import "macros.htm" as macros %} + + + {% set title = tag.title %} + + + {{ title }} - Tag + {{ macros.shared_style() }} + + + {{ macros.body_header() }} +

    {{ title }}

    +

    Notes

    +
    {{ tag.notes or "" }}
    +

    Properties

    + + {% if tag.super_tag_list | length > 0 %} +

    Super Tags

    + {{ macros.tag_table(tag.super_tag_list | sort(attribute="title")) }} + {% endif %} + {% if tag.sub_tag_list | length > 0 %} +

    Sub Tags

    + {{ macros.tag_table(tag.sub_tag_list | sort(attribute="title")) }} + {% endif %} + {% if tag.collection_list | length > 0 %} +

    Collections

    + + {% endif %} + {% if tag.media_list | length > 0 %} +

    Elements

    + {{ macros.media_thumbnail_list( + elements=tag_media_list, + check_considered=True, + link_collection=True, + ) }} + {% endif %} + + + diff --git a/server/templates/tag/list.htm b/server/templates/tag/list.htm new file mode 100644 index 0000000..5259366 --- /dev/null +++ b/server/templates/tag/list.htm @@ -0,0 +1,15 @@ +{% import "macros.htm" as macros %} + + + {% set title = tag_list | length | string + " Tags listed" %} + + + {{ title }} + {{ macros.shared_style() }} + + + {{ macros.body_header() }} +

    {{ title }}

    + {{ macros.tag_table(tag_list) }} + + diff --git a/server/templates/tag_list.htm b/server/templates/tag_list.htm deleted file mode 100644 index eca2b92..0000000 --- a/server/templates/tag_list.htm +++ /dev/null @@ -1,55 +0,0 @@ -{% import "macros.htm" as macros %} - - - {% set title = tag_list | length | string + " Tags known" %} - - - {{ title }} - {{ macros.shared_style() }} - - - {{ macros.body_header() }} -

    {{ title }}

    - - - - - - - - - - {% macro format_tag(tag) %} - {{ tag.id }} - {% endmacro %} - {% macro format_tag_list(tag_list) %} - {% for tag in tag_list|sort(attribute="id") %} - {{ format_tag(tag) }} - {{ " | " if not loop.last }} - {% endfor %} - {% endmacro %} - {% for tag in tag_list %} - - - - - - - - - {% endfor %} -
    IdTitleUse for Pref.Super TagsSub TagsNotes
    - {{ tag.id }} - - {{ tag.title }} - - {{ tag.use_for_preferences | tenary("Yes", "no") }} - - {{ format_tag_list(tag.super_tag_list) }} - - {{ format_tag_list(tag.sub_tag_list) }} - - {{ tag.notes or "" }} -
    - -