diff --git a/app.py b/app.py index 377133e..47b7699 100644 --- a/app.py +++ b/app.py @@ -10,7 +10,7 @@ from werkzeug.exceptions import HTTPException from website.content import get_projects, get_tools, sanitize_input_tags, load_content_items, get_content, \ get_applets, get_projects_languages, get_projects_by_languages, get_sorted_tools_by_tags, \ - get_sorted_projects_by_tags + get_sorted_projects_by_tags, get_tools_linked_tags, get_tools_unlinked_tags from website.contributors import reload_contributors_data from website.domains import ALLOWED_DOMAINS from website.l10n.utils import get_user_lang, localize, reload_strings, l10n_url_abs, l10n_url_switch, DEFAULT_LANG @@ -125,6 +125,8 @@ def inject_processors(): get_tools=get_tools, get_sorted_projects_by_tags=get_sorted_projects_by_tags, get_sorted_tools_by_tags=get_sorted_tools_by_tags, + get_tools_unlinked_tags=get_tools_unlinked_tags, + get_tools_linked_tags=get_tools_linked_tags, # Renderers render_button=render_button, diff --git a/data/strings/en/content.json b/data/strings/en/content.json index d1ccf49..aa3a86e 100644 --- a/data/strings/en/content.json +++ b/data/strings/en/content.json @@ -83,5 +83,7 @@ "content.commons.lang.luxembourgish": "Luxembourgish", "content.commons.lang.english.639-3": "English (eng)", "content.commons.lang.french.639-3": "French (fra)", - "content.commons.lang.luxembourgish.639-3": "Luxembourgish (ltz)" + "content.commons.lang.luxembourgish.639-3": "Luxembourgish (ltz)", + + "filters.summary": "Click to show/hide tag filters" } \ No newline at end of file diff --git a/data/strings/fr/content.json b/data/strings/fr/content.json index 8c2d9b5..b4bd510 100644 --- a/data/strings/fr/content.json +++ b/data/strings/fr/content.json @@ -76,5 +76,7 @@ "content.commons.lang.luxembourgish": "Luxembourgeois", "content.commons.lang.english.639-3": "Anglais (eng)", "content.commons.lang.french.639-3": "Français (fra)", - "content.commons.lang.luxembourgish.639-3": "Luxembourgeois (ltz)" + "content.commons.lang.luxembourgish.639-3": "Luxembourgeois (ltz)", + + "filters.summary": "Cliquez pour afficher/cacher les filtres" } \ No newline at end of file diff --git a/data/tools/.png-optimizer.yml b/data/tools/.png-optimizer.yml index 112a589..bc36220 100644 --- a/data/tools/.png-optimizer.yml +++ b/data/tools/.png-optimizer.yml @@ -28,4 +28,4 @@ tools: title_key: "meta.title" subtitle_key: "article.subtitle" tags: - - "undefined" + - "graphics" diff --git a/data/tools/.svg-to-png.yml b/data/tools/.svg-to-png.yml index 653ad52..4047877 100644 --- a/data/tools/.svg-to-png.yml +++ b/data/tools/.svg-to-png.yml @@ -24,7 +24,7 @@ metadata: title_key: "meta.title" subtitle_key: "article.subtitle" tags: - - "undefined" + - "graphics" resources: scripts: - "svg-to-png.mjs" diff --git a/data/tools/png-analyser.yml b/data/tools/png-analyser.yml index e5e0e8f..859c10b 100644 --- a/data/tools/png-analyser.yml +++ b/data/tools/png-analyser.yml @@ -27,4 +27,5 @@ tools: title_key: "meta.title" subtitle_key: "article.subtitle" tags: - - "undefined" + - "graphics" + - "analyser" diff --git a/static/resources/NibblePoker/css/extra.css b/static/resources/NibblePoker/css/extra.css index 2008f31..03668e9 100644 --- a/static/resources/NibblePoker/css/extra.css +++ b/static/resources/NibblePoker/css/extra.css @@ -29,3 +29,11 @@ input[type=file].np-file-input-drop { margin-top: calc(1rem* 0.5); margin-bottom: calc(1rem* 0.5); } + +.hide-if-last:last-child { + display: none; +} + +.hide-if-first:first-child { + display: none; +} diff --git a/templates/pages/_content_index.jinja b/templates/pages/_content_index.jinja index 32e6ace..18ea607 100644 --- a/templates/pages/_content_index.jinja +++ b/templates/pages/_content_index.jinja @@ -1,7 +1,6 @@ {% extends "base_www.jinja" %} {% block main_content %} - {% block content_filters %}{% endblock %} - + {% block content_listing %}{% endblock %} {% endblock %} diff --git a/templates/pages/project_index.jinja b/templates/pages/project_index.jinja index 5fe8bab..6c64d3c 100644 --- a/templates/pages/project_index.jinja +++ b/templates/pages/project_index.jinja @@ -16,7 +16,7 @@ {% for project_data in get_sorted_projects_by_tags(requested_tags) %} -
+
diff --git a/templates/pages/tools_index.jinja b/templates/pages/tools_index.jinja index 7817897..ad4439c 100644 --- a/templates/pages/tools_index.jinja +++ b/templates/pages/tools_index.jinja @@ -9,13 +9,34 @@ {% endblock %} {% block content_filters %} -[Tools filters here !] +
+ {{ l10n("filters.summary", "content", user_lang) }} +
+ + {% for linked_tag in get_tools_linked_tags(requested_tags) %} + + #{{ linked_tag }} + (+) + + {% endfor %} + +
+ + {% for unlinked_tag in get_tools_unlinked_tags(requested_tags) %} + + #{{ unlinked_tag }} + (+) + + {% endfor %} + +
+
{% endblock %} {% block content_listing %} {% for tool_data in get_sorted_tools_by_tags(requested_tags) %} -
+
diff --git a/website/content/__init__.py b/website/content/__init__.py index ec64cd3..7fa39df 100644 --- a/website/content/__init__.py +++ b/website/content/__init__.py @@ -54,6 +54,22 @@ def get_tools() -> LockedDict[str, ContentTool]: return __CONTENT.tools +def get_tools_tags() -> list[str]: + tool: ContentTool + + return sorted( + set( + [tag for tool in __CONTENT.tools.values() for tag in tool.metadata.general.tags] + ) + ) + + #returned_list: list[str] = list() + #for tool in __CONTENT.tools.values(): + # tool: ContentTool + # returned_list = returned_list + tool.metadata.general.tags + #return list(set(returned_list)) + + def get_sorted_tools_by_tags(tags: Optional[list[str]]) -> list[ContentProject]: if tags is None: return sorted(__CONTENT.tools.values(), key=lambda x: x.metadata.index.priority, reverse=True) @@ -67,6 +83,37 @@ def get_sorted_tools_by_tags(tags: Optional[list[str]]) -> list[ContentProject]: return sorted(returned_list, key=lambda x: x.metadata.index.priority, reverse=True) +def get_tools_unlinked_tags(tags: Optional[list[str]]) -> list[str]: + """Returns a list of tags which are not used with any tools that has one or more of the given tags.""" + # TODO: cache the result !!! + + all_tags = get_tools_tags() + linked_tags = get_tools_linked_tags(tags) + + if tags is None: + return [tag for tag in all_tags if tag not in linked_tags] + else: + return [tag for tag in all_tags if (tag not in linked_tags and tag not in tags)] + + +def get_tools_linked_tags(tags: Optional[list[str]]) -> list[str]: + """Returns a list of tags which are used in any tools that has one or more of the given tags.""" + # TODO: cache the result !!! + + returned_list = list() + + if tags is not None: + relevant_tools = get_sorted_tools_by_tags(tags) + + for relevant_tool in relevant_tools: + returned_list = returned_list + relevant_tool.metadata.general.tags + + returned_list = set(returned_list) + returned_list = [tag for tag in returned_list if tag not in tags] + + return returned_list + + def sanitize_input_tags(input_tags: str) -> list[str]: tags: list[str] = input_tags.split(";") for tag in tags: