Skip to content

Commit

Permalink
Adds projects filter (#264)
Browse files Browse the repository at this point in the history
  • Loading branch information
uittenbroekrobbert authored Oct 16, 2024
2 parents 9df2c7e + beaba71 commit d3ec543
Show file tree
Hide file tree
Showing 21 changed files with 568 additions and 169 deletions.
11 changes: 2 additions & 9 deletions amt/api/ai_act_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from fastapi import Request

from amt.api.publication_category import PublicationCategories
from amt.core.internationalization import get_current_translation


Expand Down Expand Up @@ -72,15 +73,7 @@ def get_ai_act_profile_selector(request: Request) -> AiActProfileSelector:
"AI-model voor algemene doeleinden",
)
role_options = ("aanbieder", "gebruiksverantwoordelijke")
publication_category_options = (
"impactvol algoritme",
"niet-impactvol algoritme",
"hoog-risico AI",
"geen hoog-risico AI",
"verboden AI",
"uitzondering van toepassing",
"niet van toepassing",
)
publication_category_options = (*(p.value for p in PublicationCategories), "niet van toepassing")
systemic_risk_options = ("systeemrisico", "geen systeemrisico", "niet van toepassing")
transparency_obligations_options = (
"transparantieverplichtingen",
Expand Down
47 changes: 47 additions & 0 deletions amt/api/publication_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import logging
from enum import Enum

from fastapi import Request

from amt.core.internationalization import get_current_translation
from amt.schema.publication_category import PublicationCategory

logger = logging.getLogger(__name__)


class PublicationCategories(Enum):
IMPACTVOL_ALGORITME = "impactvol algoritme"
NIET_IMPACTVOL_ALGORITME = "niet-impactvol algoritme"
HOOG_RISICO_AI = "hoog-risico AI"
GEEN_HOOG_RISICO_AI = "geen hoog-risico AI"
VERBODEN_AI = "verboden AI"
UITZONDERING_VAN_TOEPASSING = "uitzondering van toepassing"


def get_publication_category(key: PublicationCategories | None, request: Request) -> PublicationCategory | None:
"""
Given the key and translation, returns the translated text.
:param key: the key
:param request: request to get the current language
:return: a Publication Category model with the correct translation
"""

if key is None:
return None

translations = get_current_translation(request)
_ = translations.gettext
# translations are determined at runtime, which is why we use the dictionary below
keys = {
PublicationCategories.IMPACTVOL_ALGORITME: _("Impactful algorithm"),
PublicationCategories.NIET_IMPACTVOL_ALGORITME: _("Non-impactful algorithm"),
PublicationCategories.HOOG_RISICO_AI: _("High-risk AI"),
PublicationCategories.GEEN_HOOG_RISICO_AI: _("No high-risk AI"),
PublicationCategories.VERBODEN_AI: _("Forbidden AI"),
PublicationCategories.UITZONDERING_VAN_TOEPASSING: _("Exception of application"),
}
return PublicationCategory(id=key.name, name=keys[key])


def get_publication_categories(request: Request) -> list[PublicationCategory | None]:
return [get_publication_category(p, request) for p in PublicationCategories]
58 changes: 50 additions & 8 deletions amt/api/routes/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

from amt.api.ai_act_profile import get_ai_act_profile_selector
from amt.api.deps import templates
from amt.api.lifecycles import get_lifecycles
from amt.api.lifecycles import Lifecycles, get_lifecycle, get_lifecycles
from amt.api.navigation import Navigation, resolve_base_navigation_items, resolve_navigation_items
from amt.api.publication_category import PublicationCategories, get_publication_categories, get_publication_category
from amt.schema.localized_value_item import LocalizedValueItem
from amt.schema.project import ProjectNew
from amt.services.instruments import InstrumentsService
from amt.services.projects import ProjectsService
Expand All @@ -16,6 +18,24 @@
logger = logging.getLogger(__name__)


def get_localized_value(key: str, value: str, request: Request) -> LocalizedValueItem:
match key:
case "lifecycle":
lifecycle = get_lifecycle(Lifecycles[value], request)
if lifecycle:
return LocalizedValueItem(value=value, display_value=lifecycle.name)
else:
return LocalizedValueItem(value=value, display_value="Unknown")
case "publication-category":
publication_category = get_publication_category(PublicationCategories[value], request)
if publication_category:
return LocalizedValueItem(value=value, display_value=publication_category.name)
else:
return LocalizedValueItem(value=value, display_value="Unknown")
case _:
return LocalizedValueItem(value=value, display_value="Unknown filter option")


@router.get("/")
async def get_root(
request: Request,
Expand All @@ -24,7 +44,25 @@ async def get_root(
limit: int = Query(100, ge=1),
search: str = Query(""),
) -> HTMLResponse:
projects = projects_service.paginate(skip=skip, limit=limit, search=search)
active_filters = {
k.removeprefix("active-filter-"): v
for k, v in request.query_params.items()
if k.startswith("active-filter") and v != ""
}
add_filters = {
k.removeprefix("add-filter-"): v
for k, v in request.query_params.items()
if k.startswith("add-filter") and v != ""
}
drop_filters = [v for k, v in request.query_params.items() if k.startswith("drop-filter") and v != ""]
filters = {k: v for k, v in (active_filters | add_filters).items() if k not in drop_filters}
localized_filters = {k: get_localized_value(k, v, request) for k, v in filters.items()}

projects = projects_service.paginate(skip=skip, limit=limit, search=search, filters=filters)
# todo: the lifecycle has to be 'localized', maybe for display 'Project' should become a different object
for project in projects:
project.lifecycle = get_lifecycle(project.lifecycle, request) # pyright: ignore [reportAttributeAccessIssue]

next = skip + limit

sub_menu_items = resolve_navigation_items([Navigation.PROJECTS_OVERVIEW], request) # pyright: ignore [reportUnusedVariable] # noqa
Expand All @@ -36,15 +74,19 @@ async def get_root(
"projects": projects,
"next": next,
"limit": limit,
"start": skip,
"search": search,
"lifecycles": get_lifecycles(request),
"publication_categories": get_publication_categories(request),
"filters": localized_filters,
}

if request.state.htmx:
return templates.TemplateResponse(
request, "projects/_list.html.j2", {"projects": projects, "next": next, "search": search, "limit": limit}
)

return templates.TemplateResponse(request, "projects/index.html.j2", context)
if request.state.htmx and drop_filters:
return templates.TemplateResponse(request, "parts/project_search.html.j2", context)
elif request.state.htmx:
return templates.TemplateResponse(request, "parts/filter_list.html.j2", context)
else:
return templates.TemplateResponse(request, "projects/index.html.j2", context)


@router.get("/new")
Expand Down
102 changes: 81 additions & 21 deletions amt/locale/base.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-10-16 09:55+0200\n"
"POT-Creation-Date: 2024-10-16 10:41+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -17,27 +17,27 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.16.0\n"

#: amt/api/ai_act_profile.py:23
#: amt/api/ai_act_profile.py:24
msgid "Type"
msgstr ""

#: amt/api/ai_act_profile.py:25
#: amt/api/ai_act_profile.py:26
msgid "Is the application open source?"
msgstr ""

#: amt/api/ai_act_profile.py:27
#: amt/api/ai_act_profile.py:28
msgid "Publication Category"
msgstr ""

#: amt/api/ai_act_profile.py:29
#: amt/api/ai_act_profile.py:30
msgid "Is there a systemic risk?"
msgstr ""

#: amt/api/ai_act_profile.py:31
#: amt/api/ai_act_profile.py:32
msgid "Is there a transparency obligation?"
msgstr ""

#: amt/api/ai_act_profile.py:33
#: amt/api/ai_act_profile.py:34
msgid "Role"
msgstr ""

Expand Down Expand Up @@ -82,7 +82,7 @@ msgstr ""
msgid "Home"
msgstr ""

#: amt/api/navigation.py:46 amt/site/templates/projects/index.html.j2:7
#: amt/api/navigation.py:46 amt/site/templates/parts/project_search.html.j2:9
msgid "Projects"
msgstr ""

Expand Down Expand Up @@ -138,6 +138,30 @@ msgstr ""
msgid "Instruments"
msgstr ""

#: amt/api/publication_category.py:36
msgid "Impactful algorithm"
msgstr ""

#: amt/api/publication_category.py:37
msgid "Non-impactful algorithm"
msgstr ""

#: amt/api/publication_category.py:38
msgid "High-risk AI"
msgstr ""

#: amt/api/publication_category.py:39
msgid "No high-risk AI"
msgstr ""

#: amt/api/publication_category.py:40
msgid "Forbidden AI"
msgstr ""

#: amt/api/publication_category.py:41
msgid "Exception of application"
msgstr ""

#: amt/core/exceptions.py:20
msgid ""
"An error occurred while configuring the options for '{field}'. Please "
Expand Down Expand Up @@ -239,7 +263,7 @@ msgstr ""
msgid "An error occurred. Please try again later"
msgstr ""

#: amt/site/templates/layouts/base.html.j2:11
#: amt/site/templates/layouts/base.html.j2:1
msgid "Algorithmic Management Toolkit (AMT)"
msgstr ""

Expand Down Expand Up @@ -270,6 +294,7 @@ msgstr ""
#: amt/site/templates/pages/assessment_card.html.j2:7
#: amt/site/templates/pages/model_card.html.j2:6
#: amt/site/templates/pages/system_card.html.j2:4
#: amt/site/templates/parts/filter_list.html.j2:66
#: amt/site/templates/projects/details_info.html.j2:32
msgid "Last updated"
msgstr ""
Expand Down Expand Up @@ -312,6 +337,37 @@ msgstr ""
msgid "Algorithm Management Toolkit"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:16
msgid " ago"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:25
msgid "result"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:26
msgid "results"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:28
msgid "for"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:58
msgid ""
"No projects match your selected filters. Try adjusting your filters or "
"clearing them to see more projects."
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:64
#: amt/site/templates/projects/new.html.j2:23
msgid "Project name"
msgstr ""

#: amt/site/templates/parts/filter_list.html.j2:65
msgid "Phase"
msgstr ""

#: amt/site/templates/parts/footer.html.j2:10
msgid "About us"
msgstr ""
Expand All @@ -338,6 +394,22 @@ msgstr ""
msgid "Everyone is welcome to make comments and suggestions."
msgstr ""

#: amt/site/templates/parts/project_search.html.j2:14
msgid "New project"
msgstr ""

#: amt/site/templates/parts/project_search.html.j2:29
msgid "Find project..."
msgstr ""

#: amt/site/templates/parts/project_search.html.j2:48
msgid "Select lifecycle"
msgstr ""

#: amt/site/templates/parts/project_search.html.j2:59
msgid "Select publication category"
msgstr ""

#: amt/site/templates/projects/details_base.html.j2:24
msgid "Does the algorithm meet the requirements?"
msgstr ""
Expand Down Expand Up @@ -490,22 +562,10 @@ msgstr ""
msgid "Edit measure"
msgstr ""

#: amt/site/templates/projects/index.html.j2:12
msgid "New project"
msgstr ""

#: amt/site/templates/projects/index.html.j2:28
msgid "Find project..."
msgstr ""

#: amt/site/templates/projects/new.html.j2:7
msgid "Create a new project"
msgstr ""

#: amt/site/templates/projects/new.html.j2:23
msgid "Project name"
msgstr ""

#: amt/site/templates/projects/new.html.j2:26
msgid "Your project name here"
msgstr ""
Expand Down
Binary file modified amt/locale/en_US/LC_MESSAGES/messages.mo
Binary file not shown.
Loading

0 comments on commit d3ec543

Please sign in to comment.