diff --git a/amt/api/ai_act_profile.py b/amt/api/ai_act_profile.py index d29785907..967b4ed3c 100644 --- a/amt/api/ai_act_profile.py +++ b/amt/api/ai_act_profile.py @@ -4,6 +4,7 @@ from fastapi import Request +from amt.api.publication_category import PublicationCategories from amt.core.internationalization import get_current_translation @@ -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", diff --git a/amt/api/navigation.py b/amt/api/navigation.py index b3089e6ae..a50d3b486 100644 --- a/amt/api/navigation.py +++ b/amt/api/navigation.py @@ -98,6 +98,9 @@ class Navigation: PROJECT_DETAILS = BaseNavigationItem( display_text=DisplayText.DETAILS, url="/project/{project_id}/details/system_card" ) + PROJECT_MODEL = BaseNavigationItem( + display_text=DisplayText.MODEL, url="/project/{project_id}/details/model/inference" + ) PROJECT_NEW = BaseNavigationItem(display_text=DisplayText.NEW, url="/projects/new") PROJECT_SYSTEM_INFO = BaseNavigationItem(display_text=DisplayText.INFO, url="/project/{project_id}/details") PROJECT_SYSTEM_ALGORITHM_DETAILS = BaseNavigationItem( diff --git a/amt/api/publication_category.py b/amt/api/publication_category.py new file mode 100644 index 000000000..3096687ee --- /dev/null +++ b/amt/api/publication_category.py @@ -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] diff --git a/amt/api/routes/project.py b/amt/api/routes/project.py index 824615c6d..652035451 100644 --- a/amt/api/routes/project.py +++ b/amt/api/routes/project.py @@ -5,6 +5,7 @@ from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse +from pydantic import BaseModel, Field from amt.api.deps import templates from amt.api.lifecycles import get_lifecycle @@ -18,8 +19,11 @@ from amt.core.exceptions import AMTNotFound, AMTRepositoryError from amt.enums.status import Status from amt.models import Project +from amt.schema.measure import ExtendedMeasureTask, MeasureTask +from amt.schema.requirement import RequirementTask from amt.schema.system_card import SystemCard from amt.schema.task import MovedTask +from amt.services import task_registry from amt.services.instruments_and_requirements_state import InstrumentStateService, RequirementsStateService from amt.services.projects import ProjectsService from amt.services.storage import StorageFactory @@ -77,6 +81,7 @@ def get_project_details_tabs(request: Request) -> list[NavigationItem]: [ Navigation.PROJECT_SYSTEM_INFO, Navigation.PROJECT_SYSTEM_ALGORITHM_DETAILS, + Navigation.PROJECT_MODEL, Navigation.PROJECT_REQUIREMENTS, Navigation.PROJECT_DATA_CARD, Navigation.PROJECT_TASKS, @@ -242,6 +247,42 @@ async def get_system_card( return templates.TemplateResponse(request, "pages/system_card.html.j2", context) +@router.get("/{project_id}/details/model/inference") +async def get_project_inference( + request: Request, project_id: int, projects_service: Annotated[ProjectsService, Depends(ProjectsService)] +) -> HTMLResponse: + project = get_project_or_error(project_id, projects_service, request) + + breadcrumbs = resolve_base_navigation_items( + [ + Navigation.PROJECTS_ROOT, + BaseNavigationItem(custom_display_text=project.name, url="/project/{project_id}/details/model/inference"), + Navigation.PROJECT_MODEL, + ], + request, + ) + + system_card_data = get_system_card_data() + instrument_state = get_instrument_state() + requirements_state = get_requirements_state(project.system_card) + + tab_items = get_project_details_tabs(request) + + context = { + "lifecycle": get_lifecycle(project.lifecycle, request), + "last_edited": project.last_edited, + "system_card": system_card_data, + "instrument_state": instrument_state, + "requirements_state": requirements_state, + "project": project, + "project_id": project.id, + "breadcrumbs": breadcrumbs, + "tab_items": tab_items, + } + + return templates.TemplateResponse(request, "projects/details_inference.html.j2", context) + + # !!! # Implementation of this endpoint is for now independent of the project ID, meaning # that the same system card is rendered for all project ID's. This is due to the fact @@ -274,8 +315,27 @@ async def get_system_card_requirements( system_card = project.system_card requirements = fetch_requirements([requirement.urn for requirement in system_card.requirements]) - # Get measures that correspond to the requirements. - requirements_and_measures = [(requirement, fetch_measures(requirement.links)) for requirement in requirements] + # Get measures that correspond to the requirements and merge them with the measuretasks + requirements_and_measures = [] + for requirement in requirements: + completed_measures_count = 0 + linked_measures = fetch_measures(requirement.links) + extended_linked_measures: list[ExtendedMeasureTask] = [] + for measure in linked_measures: + measure_task = find_measure_task(system_card, measure.urn) + if measure_task: + ext_measure_task = ExtendedMeasureTask( + name=measure.name, + description=measure.description, + urn=measure.urn, + state=measure_task.state, + value=measure_task.value, + version=measure_task.version, + ) + if ext_measure_task.state == "done": + completed_measures_count += 1 + extended_linked_measures.append(ext_measure_task) + requirements_and_measures.append((requirement, completed_measures_count, extended_linked_measures)) # pyright: ignore [reportUnknownMemberType] context = { "instrument_state": instrument_state, @@ -290,6 +350,100 @@ async def get_system_card_requirements( return templates.TemplateResponse(request, "projects/details_requirements.html.j2", context) +def find_measure_task(system_card: SystemCard, urn: str) -> MeasureTask | None: + for measure in system_card.measures: + if measure.urn == urn: + return measure + return None + + +def find_requirement_task(system_card: SystemCard, requirement_urn: str) -> RequirementTask | None: + for requirement in system_card.requirements: + if requirement.urn == requirement_urn: + return requirement + return None + + +def find_requirement_tasks_by_measure_urn(system_card: SystemCard, measure_urn: str) -> list[RequirementTask]: + requirement_mapper: dict[str, RequirementTask] = {} + for requirement_task in system_card.requirements: + requirement_mapper[requirement_task.urn] = requirement_task + + requirement_tasks: list[RequirementTask] = [] + measure = fetch_measures([measure_urn]) + for requirement_urn in measure[0].links: + # TODO: This is because measure are linked to too many requirement not applicable in our use case + if len(fetch_requirements([requirement_urn])) > 0: + requirement_tasks.append(requirement_mapper[requirement_urn]) + + return requirement_tasks + + +@router.get("/{project_id}/measure/{measure_urn}") +async def get_measure( + request: Request, + project_id: int, + measure_urn: str, + projects_service: Annotated[ProjectsService, Depends(ProjectsService)], +) -> HTMLResponse: + project = get_project_or_error(project_id, projects_service, request) + measure = task_registry.fetch_measures([measure_urn]) + measure_task = find_measure_task(project.system_card, measure_urn) + + context = { + "measure": measure[0], + "measure_state": measure_task.state, # pyright: ignore [reportOptionalMemberAccess] + "measure_value": measure_task.value, # pyright: ignore [reportOptionalMemberAccess] + "project_id": project_id, + } + + return templates.TemplateResponse(request, "projects/details_measure_modal.html.j2", context) + + +class MeasureUpdate(BaseModel): + measure_state: str = Field(default=None) + measure_value: str = Field(default=None) + + +@router.post("/{project_id}/measure/{measure_urn}") +async def update_measure_value( + request: Request, + project_id: int, + measure_urn: str, + measure_update: MeasureUpdate, + projects_service: Annotated[ProjectsService, Depends(ProjectsService)], +) -> HTMLResponse: + project = get_project_or_error(project_id, projects_service, request) + + measure_task = find_measure_task(project.system_card, measure_urn) + measure_task.state = measure_update.measure_state # pyright: ignore [reportOptionalMemberAccess] + measure_task.value = measure_update.measure_value # pyright: ignore [reportOptionalMemberAccess] + + # update for the linked requirements the state based on all it's measures + requirement_tasks = find_requirement_tasks_by_measure_urn(project.system_card, measure_urn) + requirement_urns = [requirement_task.urn for requirement_task in requirement_tasks] + requirements = fetch_requirements(requirement_urns) + + for requirement in requirements: + count_completed = 0 + for link_measure_urn in requirement.links: + link_measure_task = find_measure_task(project.system_card, link_measure_urn) + if link_measure_task: # noqa: SIM102 + if link_measure_task.state == "done": + count_completed += 1 + requirement_task = find_requirement_task(project.system_card, requirement.urn) + if count_completed == len(requirement.links): + requirement_task.state = "done" # pyright: ignore [reportOptionalMemberAccess] + elif count_completed == 0 and len(requirement.links) > 0: + requirement_task.state = "to do" # pyright: ignore [reportOptionalMemberAccess] + else: + requirement_task.state = "in progress" # pyright: ignore [reportOptionalMemberAccess] + + projects_service.update(project) + # TODO: FIX THIS!! The page now reloads at the top, which is annoying + return templates.Redirect(request, f"/project/{project_id}/details/system_card/requirements") + + # !!! # Implementation of this endpoint is for now independent of the project ID, meaning # that the same system card is rendered for all project ID's. This is due to the fact diff --git a/amt/api/routes/projects.py b/amt/api/routes/projects.py index 411591b72..1fa7376bc 100644 --- a/amt/api/routes/projects.py +++ b/amt/api/routes/projects.py @@ -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 @@ -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, @@ -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 @@ -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") diff --git a/amt/locale/base.pot b/amt/locale/base.pot index a7e53ed3c..d9a4ae046 100644 --- a/amt/locale/base.pot +++ b/amt/locale/base.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-14 12:11+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 \n" "Language-Team: LANGUAGE \n" @@ -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 "" @@ -66,6 +66,7 @@ msgid "Verification and Validation" msgstr "" #: amt/api/lifecycles.py:45 +#: amt/site/templates/projects/details_measure_modal.html.j2:66 msgid "Implementation" msgstr "" @@ -81,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 "" @@ -137,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 " @@ -205,12 +230,16 @@ msgstr "" msgid "Email" msgstr "" -#: amt/site/templates/auth/profile.html.j2:40 +#: amt/site/templates/auth/profile.html.j2:49 #: amt/site/templates/parts/header.html.j2:92 #: amt/site/templates/parts/header.html.j2:151 msgid "Language" msgstr "" +#: amt/site/templates/auth/profile.html.j2:54 +msgid "Select language" +msgstr "" + #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:5 msgid "Not logged in" msgstr "" @@ -220,7 +249,7 @@ msgid "Please login to view this page" msgstr "" #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:11 -#: amt/site/templates/pages/landingpage.html.j2:16 +#: amt/site/templates/pages/landingpage.html.j2:17 #: amt/site/templates/parts/header.html.j2:103 #: amt/site/templates/parts/header.html.j2:161 msgid "Login" @@ -234,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 "" @@ -251,10 +280,10 @@ msgid "Reviewing" msgstr "" #: amt/site/templates/macros/tasks.html.j2:32 -#: amt/site/templates/projects/details_base.html.j2:22 -#: amt/site/templates/projects/details_base.html.j2:43 -#: amt/site/templates/projects/details_base.html.j2:69 -#: amt/site/templates/projects/details_base.html.j2:91 +#: amt/site/templates/projects/details_base.html.j2:27 +#: amt/site/templates/projects/details_base.html.j2:52 +#: amt/site/templates/projects/details_base.html.j2:78 +#: amt/site/templates/projects/details_base.html.j2:100 msgid "Done" msgstr "" @@ -265,7 +294,8 @@ 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/projects/details_info.html.j2:35 +#: amt/site/templates/parts/filter_list.html.j2:66 +#: amt/site/templates/projects/details_info.html.j2:32 msgid "Last updated" msgstr "" @@ -307,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 "" @@ -333,73 +394,176 @@ msgstr "" msgid "Everyone is welcome to make comments and suggestions." msgstr "" -#: amt/site/templates/projects/details_base.html.j2:3 -#: amt/site/templates/projects/details_data.html.j2:3 -#: amt/site/templates/projects/details_info.html.j2:3 -#: amt/site/templates/projects/details_instruments.html.j2:3 -#: amt/site/templates/projects/details_requirements.html.j2:3 -msgid "AMT Placeholder information page" +#: 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/projects/details_base.html.j2:20 +#: 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 "" -#: amt/site/templates/projects/details_base.html.j2:41 -#: amt/site/templates/projects/details_base.html.j2:89 +#: amt/site/templates/projects/details_base.html.j2:48 +#: amt/site/templates/projects/details_base.html.j2:98 msgid "To do" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:55 +#: amt/site/templates/projects/details_base.html.j2:50 +msgid "In progress" +msgstr "" + +#: amt/site/templates/projects/details_base.html.j2:64 msgid "Go to all requirements" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:66 +#: amt/site/templates/projects/details_base.html.j2:75 msgid "Which instruments are executed?" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:103 +#: amt/site/templates/projects/details_base.html.j2:112 msgid "Go to all instruments" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:10 +#: amt/site/templates/projects/details_data.html.j2:3 +#: amt/site/templates/projects/details_instruments.html.j2:3 +msgid "To be implemented" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:7 +msgid "Floor area (m²):" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:16 +msgid "Plot size (m²):" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:25 +msgid "Building year:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:34 +msgid "Object type:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:43 +msgid "Number of annexes:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:52 +msgid "Neighborhood code:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:61 +msgid "Quality rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:73 +msgid "Maintenance rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:85 +msgid "Amenities rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:97 +msgid "Location rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:113 +msgid "Estimate WOZ Value" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:117 +msgid "Estimated WOZ Value" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:119 +msgid "Undefined" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:175 +msgid "Failed to estimate WOZ value: " +msgstr "" + +#: amt/site/templates/projects/details_info.html.j2:7 +#: amt/site/templates/projects/details_measure_modal.html.j2:19 msgid "Description" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:14 +#: amt/site/templates/projects/details_info.html.j2:11 msgid "Repository" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:20 +#: amt/site/templates/projects/details_info.html.j2:17 msgid "Project code" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:24 +#: amt/site/templates/projects/details_info.html.j2:21 msgid "Lifecyle" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:39 +#: amt/site/templates/projects/details_info.html.j2:36 msgid "Labels" msgstr "" -#: amt/site/templates/projects/details_requirements.html.j2:22 -msgid "measures executed" +#: amt/site/templates/projects/details_measure_modal.html.j2:28 +msgid "Read more on the algoritmekader" msgstr "" -#: amt/site/templates/projects/index.html.j2:12 -msgid "New project" +#: amt/site/templates/projects/details_measure_modal.html.j2:37 +msgid "Status" msgstr "" -#: amt/site/templates/projects/index.html.j2:28 -msgid "Find project..." +#: amt/site/templates/projects/details_measure_modal.html.j2:44 +#: amt/site/templates/projects/details_measure_modal.html.j2:46 +msgid "to do" msgstr "" -#: amt/site/templates/projects/new.html.j2:7 -msgid "Create a new project" +#: amt/site/templates/projects/details_measure_modal.html.j2:49 +#: amt/site/templates/projects/details_measure_modal.html.j2:51 +msgid "in progress" msgstr "" -#: amt/site/templates/projects/new.html.j2:23 -msgid "Project name" +#: amt/site/templates/projects/details_measure_modal.html.j2:54 +#: amt/site/templates/projects/details_measure_modal.html.j2:56 +msgid "done" +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:69 +msgid "" +"Describe how the measure has been implemented, including challenges and " +"solutions." +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:80 +msgid "Save" +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:84 +msgid "Cancel" +msgstr "" + +#: amt/site/templates/projects/details_requirements.html.j2:25 +msgid "measures executed" +msgstr "" + +#: amt/site/templates/projects/details_requirements.html.j2:54 +msgid "Edit measure" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:7 +msgid "Create a new project" msgstr "" #: amt/site/templates/projects/new.html.j2:26 @@ -461,7 +625,7 @@ msgstr "" msgid "Create Project" msgstr "" -#: amt/site/templates/projects/new.html.j2:191 +#: amt/site/templates/projects/new.html.j2:193 msgid "Copy results and close" msgstr "" diff --git a/amt/locale/en_US/LC_MESSAGES/messages.mo b/amt/locale/en_US/LC_MESSAGES/messages.mo index 0e5d05bbf..3ad814664 100644 Binary files a/amt/locale/en_US/LC_MESSAGES/messages.mo and b/amt/locale/en_US/LC_MESSAGES/messages.mo differ diff --git a/amt/locale/en_US/LC_MESSAGES/messages.po b/amt/locale/en_US/LC_MESSAGES/messages.po index 28eeecf33..10c038873 100644 --- a/amt/locale/en_US/LC_MESSAGES/messages.po +++ b/amt/locale/en_US/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-14 12:11+0200\n" +"POT-Creation-Date: 2024-10-16 10:41+0200\n" "PO-Revision-Date: 2024-07-25 21:01+0200\n" "Last-Translator: FULL NAME \n" "Language: en_US\n" @@ -18,27 +18,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 "" @@ -67,6 +67,7 @@ msgid "Verification and Validation" msgstr "" #: amt/api/lifecycles.py:45 +#: amt/site/templates/projects/details_measure_modal.html.j2:66 msgid "Implementation" msgstr "" @@ -82,7 +83,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 "" @@ -138,6 +139,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 " @@ -206,12 +231,16 @@ msgstr "" msgid "Email" msgstr "" -#: amt/site/templates/auth/profile.html.j2:40 +#: amt/site/templates/auth/profile.html.j2:49 #: amt/site/templates/parts/header.html.j2:92 #: amt/site/templates/parts/header.html.j2:151 msgid "Language" msgstr "" +#: amt/site/templates/auth/profile.html.j2:54 +msgid "Select language" +msgstr "" + #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:5 msgid "Not logged in" msgstr "" @@ -221,7 +250,7 @@ msgid "Please login to view this page" msgstr "" #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:11 -#: amt/site/templates/pages/landingpage.html.j2:16 +#: amt/site/templates/pages/landingpage.html.j2:17 #: amt/site/templates/parts/header.html.j2:103 #: amt/site/templates/parts/header.html.j2:161 msgid "Login" @@ -235,7 +264,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 "" @@ -252,10 +281,10 @@ msgid "Reviewing" msgstr "" #: amt/site/templates/macros/tasks.html.j2:32 -#: amt/site/templates/projects/details_base.html.j2:22 -#: amt/site/templates/projects/details_base.html.j2:43 -#: amt/site/templates/projects/details_base.html.j2:69 -#: amt/site/templates/projects/details_base.html.j2:91 +#: amt/site/templates/projects/details_base.html.j2:27 +#: amt/site/templates/projects/details_base.html.j2:52 +#: amt/site/templates/projects/details_base.html.j2:78 +#: amt/site/templates/projects/details_base.html.j2:100 msgid "Done" msgstr "" @@ -266,7 +295,8 @@ 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/projects/details_info.html.j2:35 +#: amt/site/templates/parts/filter_list.html.j2:66 +#: amt/site/templates/projects/details_info.html.j2:32 msgid "Last updated" msgstr "" @@ -308,6 +338,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 "" @@ -334,73 +395,176 @@ msgstr "" msgid "Everyone is welcome to make comments and suggestions." msgstr "" -#: amt/site/templates/projects/details_base.html.j2:3 -#: amt/site/templates/projects/details_data.html.j2:3 -#: amt/site/templates/projects/details_info.html.j2:3 -#: amt/site/templates/projects/details_instruments.html.j2:3 -#: amt/site/templates/projects/details_requirements.html.j2:3 -msgid "AMT Placeholder information page" +#: 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/projects/details_base.html.j2:20 +#: 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 "" -#: amt/site/templates/projects/details_base.html.j2:41 -#: amt/site/templates/projects/details_base.html.j2:89 +#: amt/site/templates/projects/details_base.html.j2:48 +#: amt/site/templates/projects/details_base.html.j2:98 msgid "To do" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:55 +#: amt/site/templates/projects/details_base.html.j2:50 +msgid "In progress" +msgstr "" + +#: amt/site/templates/projects/details_base.html.j2:64 msgid "Go to all requirements" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:66 +#: amt/site/templates/projects/details_base.html.j2:75 msgid "Which instruments are executed?" msgstr "" -#: amt/site/templates/projects/details_base.html.j2:103 +#: amt/site/templates/projects/details_base.html.j2:112 msgid "Go to all instruments" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:10 +#: amt/site/templates/projects/details_data.html.j2:3 +#: amt/site/templates/projects/details_instruments.html.j2:3 +msgid "To be implemented" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:7 +msgid "Floor area (m²):" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:16 +msgid "Plot size (m²):" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:25 +msgid "Building year:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:34 +msgid "Object type:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:43 +msgid "Number of annexes:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:52 +msgid "Neighborhood code:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:61 +msgid "Quality rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:73 +msgid "Maintenance rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:85 +msgid "Amenities rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:97 +msgid "Location rating:" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:113 +msgid "Estimate WOZ Value" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:117 +msgid "Estimated WOZ Value" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:119 +msgid "Undefined" +msgstr "" + +#: amt/site/templates/projects/details_inference.html.j2:175 +msgid "Failed to estimate WOZ value: " +msgstr "" + +#: amt/site/templates/projects/details_info.html.j2:7 +#: amt/site/templates/projects/details_measure_modal.html.j2:19 msgid "Description" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:14 +#: amt/site/templates/projects/details_info.html.j2:11 msgid "Repository" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:20 +#: amt/site/templates/projects/details_info.html.j2:17 msgid "Project code" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:24 +#: amt/site/templates/projects/details_info.html.j2:21 msgid "Lifecyle" msgstr "" -#: amt/site/templates/projects/details_info.html.j2:39 +#: amt/site/templates/projects/details_info.html.j2:36 msgid "Labels" msgstr "" -#: amt/site/templates/projects/details_requirements.html.j2:22 -msgid "measures executed" +#: amt/site/templates/projects/details_measure_modal.html.j2:28 +msgid "Read more on the algoritmekader" msgstr "" -#: amt/site/templates/projects/index.html.j2:12 -msgid "New project" +#: amt/site/templates/projects/details_measure_modal.html.j2:37 +msgid "Status" msgstr "" -#: amt/site/templates/projects/index.html.j2:28 -msgid "Find project..." +#: amt/site/templates/projects/details_measure_modal.html.j2:44 +#: amt/site/templates/projects/details_measure_modal.html.j2:46 +msgid "to do" msgstr "" -#: amt/site/templates/projects/new.html.j2:7 -msgid "Create a new project" +#: amt/site/templates/projects/details_measure_modal.html.j2:49 +#: amt/site/templates/projects/details_measure_modal.html.j2:51 +msgid "in progress" msgstr "" -#: amt/site/templates/projects/new.html.j2:23 -msgid "Project name" +#: amt/site/templates/projects/details_measure_modal.html.j2:54 +#: amt/site/templates/projects/details_measure_modal.html.j2:56 +msgid "done" +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:69 +msgid "" +"Describe how the measure has been implemented, including challenges and " +"solutions." +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:80 +msgid "Save" +msgstr "" + +#: amt/site/templates/projects/details_measure_modal.html.j2:84 +msgid "Cancel" +msgstr "" + +#: amt/site/templates/projects/details_requirements.html.j2:25 +msgid "measures executed" +msgstr "" + +#: amt/site/templates/projects/details_requirements.html.j2:54 +msgid "Edit measure" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:7 +msgid "Create a new project" msgstr "" #: amt/site/templates/projects/new.html.j2:26 @@ -462,10 +626,7 @@ msgstr "" msgid "Create Project" msgstr "" -#: amt/site/templates/projects/new.html.j2:191 +#: amt/site/templates/projects/new.html.j2:193 msgid "Copy results and close" msgstr "" -#~ msgid "Algortime Management Toolkit" -#~ msgstr "" - diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.mo b/amt/locale/nl_NL/LC_MESSAGES/messages.mo index 0a0aa8373..1d724d877 100644 Binary files a/amt/locale/nl_NL/LC_MESSAGES/messages.mo and b/amt/locale/nl_NL/LC_MESSAGES/messages.mo differ diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.po b/amt/locale/nl_NL/LC_MESSAGES/messages.po index 478965fe7..72a798854 100644 --- a/amt/locale/nl_NL/LC_MESSAGES/messages.po +++ b/amt/locale/nl_NL/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-14 12:11+0200\n" +"POT-Creation-Date: 2024-10-16 10:41+0200\n" "PO-Revision-Date: 2024-07-25 21:01+0200\n" "Last-Translator: FULL NAME \n" "Language: nl_NL\n" @@ -18,27 +18,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 "Type AI toepassing" -#: amt/api/ai_act_profile.py:25 +#: amt/api/ai_act_profile.py:26 msgid "Is the application open source?" msgstr "Is de applicatie open source?" -#: amt/api/ai_act_profile.py:27 +#: amt/api/ai_act_profile.py:28 msgid "Publication Category" msgstr "Publicatiecategorie" -#: amt/api/ai_act_profile.py:29 +#: amt/api/ai_act_profile.py:30 msgid "Is there a systemic risk?" msgstr "Is er sprake van systematisch risico?" -#: amt/api/ai_act_profile.py:31 +#: amt/api/ai_act_profile.py:32 msgid "Is there a transparency obligation?" msgstr "Zijn er transparantieverplichtingen?" -#: amt/api/ai_act_profile.py:33 +#: amt/api/ai_act_profile.py:34 msgid "Role" msgstr "Rol" @@ -67,6 +67,7 @@ msgid "Verification and Validation" msgstr "Verficatie en validatie" #: amt/api/lifecycles.py:45 +#: amt/site/templates/projects/details_measure_modal.html.j2:66 msgid "Implementation" msgstr "Implementeren" @@ -82,7 +83,7 @@ msgstr "Uitfaseren" msgid "Home" msgstr "Start" -#: 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 "Projecten" @@ -138,6 +139,30 @@ msgstr "Model" msgid "Instruments" msgstr "Instrumenten" +#: amt/api/publication_category.py:36 +msgid "Impactful algorithm" +msgstr "Impactvol algoritme" + +#: amt/api/publication_category.py:37 +msgid "Non-impactful algorithm" +msgstr "Niet-impactvol algoritme" + +#: amt/api/publication_category.py:38 +msgid "High-risk AI" +msgstr "Hoog-risico AI" + +#: amt/api/publication_category.py:39 +msgid "No high-risk AI" +msgstr "Geen hoog-risico AI" + +#: amt/api/publication_category.py:40 +msgid "Forbidden AI" +msgstr "Verboden AI" + +#: amt/api/publication_category.py:41 +msgid "Exception of application" +msgstr "Uitzondering van toepassing" + #: amt/core/exceptions.py:20 msgid "" "An error occurred while configuring the options for '{field}'. Please " @@ -214,12 +239,16 @@ msgstr "Naam" msgid "Email" msgstr "Email" -#: amt/site/templates/auth/profile.html.j2:40 +#: amt/site/templates/auth/profile.html.j2:49 #: amt/site/templates/parts/header.html.j2:92 #: amt/site/templates/parts/header.html.j2:151 msgid "Language" msgstr "Taal" +#: amt/site/templates/auth/profile.html.j2:54 +msgid "Select language" +msgstr "Taal" + #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:5 msgid "Not logged in" msgstr "Niet ingelogd" @@ -229,7 +258,7 @@ msgid "Please login to view this page" msgstr "Meld u aan om deze pagina te bekijken" #: amt/site/templates/errors/AMTAuthorizationError_401.html.j2:11 -#: amt/site/templates/pages/landingpage.html.j2:16 +#: amt/site/templates/pages/landingpage.html.j2:17 #: amt/site/templates/parts/header.html.j2:103 #: amt/site/templates/parts/header.html.j2:161 msgid "Login" @@ -243,7 +272,7 @@ msgstr "Er is een fout opgetreden" msgid "An error occurred. Please try again later" msgstr "Er is een fout opgetreden. Probeer het later opnieuw." -#: amt/site/templates/layouts/base.html.j2:11 +#: amt/site/templates/layouts/base.html.j2:1 msgid "Algorithmic Management Toolkit (AMT)" msgstr "Algoritme Management Toolkit (AMT)" @@ -260,10 +289,10 @@ msgid "Reviewing" msgstr "Beoordelen" #: amt/site/templates/macros/tasks.html.j2:32 -#: amt/site/templates/projects/details_base.html.j2:22 -#: amt/site/templates/projects/details_base.html.j2:43 -#: amt/site/templates/projects/details_base.html.j2:69 -#: amt/site/templates/projects/details_base.html.j2:91 +#: amt/site/templates/projects/details_base.html.j2:27 +#: amt/site/templates/projects/details_base.html.j2:52 +#: amt/site/templates/projects/details_base.html.j2:78 +#: amt/site/templates/projects/details_base.html.j2:100 msgid "Done" msgstr "Afgerond" @@ -274,7 +303,8 @@ msgstr "Onbekend" #: 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/projects/details_info.html.j2:35 +#: amt/site/templates/parts/filter_list.html.j2:66 +#: amt/site/templates/projects/details_info.html.j2:32 msgid "Last updated" msgstr "Laatst bijgewerkt" @@ -316,6 +346,39 @@ msgstr "AMT Placeholder informatie pagina's" msgid "Algorithm Management Toolkit" msgstr "Algoritme Management Toolkit" +#: amt/site/templates/parts/filter_list.html.j2:16 +msgid " ago" +msgstr "geleden" + +#: amt/site/templates/parts/filter_list.html.j2:25 +msgid "result" +msgstr "resultaat" + +#: amt/site/templates/parts/filter_list.html.j2:26 +msgid "results" +msgstr "resultaten" + +#: amt/site/templates/parts/filter_list.html.j2:28 +msgid "for" +msgstr "voor" + +#: 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 "" +"Er zijn geen projecten die overeen komen met de geselecteerde filters. " +"Pas de filters aan of verwijder ze om meer projecten te zien." + +#: amt/site/templates/parts/filter_list.html.j2:64 +#: amt/site/templates/projects/new.html.j2:23 +msgid "Project name" +msgstr "Project naam" + +#: amt/site/templates/parts/filter_list.html.j2:65 +msgid "Phase" +msgstr "Fase" + #: amt/site/templates/parts/footer.html.j2:10 msgid "About us" msgstr "Over ons" @@ -342,75 +405,180 @@ msgstr "Deze website is in ontwikkeling. Alle versies ontstaan op een open manie msgid "Everyone is welcome to make comments and suggestions." msgstr "Iedereen mag opmerkingen en suggesties doen." -#: amt/site/templates/projects/details_base.html.j2:3 -#: amt/site/templates/projects/details_data.html.j2:3 -#: amt/site/templates/projects/details_info.html.j2:3 -#: amt/site/templates/projects/details_instruments.html.j2:3 -#: amt/site/templates/projects/details_requirements.html.j2:3 -msgid "AMT Placeholder information page" -msgstr "AMT Placeholder informatie pagina's" +#: amt/site/templates/parts/project_search.html.j2:14 +msgid "New project" +msgstr "Nieuw project" + +#: amt/site/templates/parts/project_search.html.j2:29 +msgid "Find project..." +msgstr "Zoek project..." -#: amt/site/templates/projects/details_base.html.j2:20 +#: amt/site/templates/parts/project_search.html.j2:48 +msgid "Select lifecycle" +msgstr "Levenscyclus" + +#: amt/site/templates/parts/project_search.html.j2:59 +msgid "Select publication category" +msgstr "Publicatiecategorie" + +#: amt/site/templates/projects/details_base.html.j2:24 msgid "Does the algorithm meet the requirements?" -msgstr "Voldoet het algoritme aan alle vereisten?" +msgstr "Voldoet het algoritme aan de vereisten?" -#: amt/site/templates/projects/details_base.html.j2:41 -#: amt/site/templates/projects/details_base.html.j2:89 +#: amt/site/templates/projects/details_base.html.j2:48 +#: amt/site/templates/projects/details_base.html.j2:98 msgid "To do" msgstr "Te doen" -#: amt/site/templates/projects/details_base.html.j2:55 +#: amt/site/templates/projects/details_base.html.j2:50 +msgid "In progress" +msgstr "Onderhanden" + +#: amt/site/templates/projects/details_base.html.j2:64 msgid "Go to all requirements" -msgstr "Ga naar alle vereisten" +msgstr "Ga naar alle Vereisten" -#: amt/site/templates/projects/details_base.html.j2:66 +#: amt/site/templates/projects/details_base.html.j2:75 msgid "Which instruments are executed?" msgstr "Welke instrumenten zijn uitgevoerd?" -#: amt/site/templates/projects/details_base.html.j2:103 +#: amt/site/templates/projects/details_base.html.j2:112 msgid "Go to all instruments" -msgstr "Ga naar alle instrumenten" +msgstr "Ga naar all instrumenten" + +#: amt/site/templates/projects/details_data.html.j2:3 +#: amt/site/templates/projects/details_instruments.html.j2:3 +msgid "To be implemented" +msgstr "Nog te implementeren" -#: amt/site/templates/projects/details_info.html.j2:10 +#: amt/site/templates/projects/details_inference.html.j2:7 +msgid "Floor area (m²):" +msgstr "Vloeroppervlakte (m²):" + +#: amt/site/templates/projects/details_inference.html.j2:16 +msgid "Plot size (m²):" +msgstr "Perceelgrootte (m²):" + +#: amt/site/templates/projects/details_inference.html.j2:25 +msgid "Building year:" +msgstr "Bouwjaar:" + +#: amt/site/templates/projects/details_inference.html.j2:34 +msgid "Object type:" +msgstr "Objecttype:" + +#: amt/site/templates/projects/details_inference.html.j2:43 +msgid "Number of annexes:" +msgstr "Aantal bijgebouwen:" + +#: amt/site/templates/projects/details_inference.html.j2:52 +msgid "Neighborhood code:" +msgstr "Buurtcode:" + +#: amt/site/templates/projects/details_inference.html.j2:61 +msgid "Quality rating:" +msgstr "Kwaliteitsbeoordeling:" + +#: amt/site/templates/projects/details_inference.html.j2:73 +msgid "Maintenance rating:" +msgstr "Onderhoudsbeoordeling:" + +#: amt/site/templates/projects/details_inference.html.j2:85 +msgid "Amenities rating:" +msgstr "Voorzieningenbeoordeling:" + +#: amt/site/templates/projects/details_inference.html.j2:97 +msgid "Location rating:" +msgstr "Locatiebeoordeling:" + +#: amt/site/templates/projects/details_inference.html.j2:113 +msgid "Estimate WOZ Value" +msgstr "WOZ-waarde schatten" + +#: amt/site/templates/projects/details_inference.html.j2:117 +msgid "Estimated WOZ Value" +msgstr "Geschatte WOZ-waarde" + +#: amt/site/templates/projects/details_inference.html.j2:119 +msgid "Undefined" +msgstr "Ongedefinieerd" + +#: amt/site/templates/projects/details_inference.html.j2:175 +msgid "Failed to estimate WOZ value: " +msgstr "Fout bij het schatten van de WOZ-waarde: " + +#: amt/site/templates/projects/details_info.html.j2:7 +#: amt/site/templates/projects/details_measure_modal.html.j2:19 msgid "Description" msgstr "Omschrijving" -#: amt/site/templates/projects/details_info.html.j2:14 +#: amt/site/templates/projects/details_info.html.j2:11 msgid "Repository" msgstr "Repository" -#: amt/site/templates/projects/details_info.html.j2:20 +#: amt/site/templates/projects/details_info.html.j2:17 msgid "Project code" msgstr "Project" -#: amt/site/templates/projects/details_info.html.j2:24 +#: amt/site/templates/projects/details_info.html.j2:21 msgid "Lifecyle" msgstr "Levenscyclus" -#: amt/site/templates/projects/details_info.html.j2:39 +#: amt/site/templates/projects/details_info.html.j2:36 msgid "Labels" msgstr "Labels" -#: amt/site/templates/projects/details_requirements.html.j2:22 +#: amt/site/templates/projects/details_measure_modal.html.j2:28 +msgid "Read more on the algoritmekader" +msgstr "Lees meer op het algoritmekader" + +#: amt/site/templates/projects/details_measure_modal.html.j2:37 +msgid "Status" +msgstr "Status" + +#: amt/site/templates/projects/details_measure_modal.html.j2:44 +#: amt/site/templates/projects/details_measure_modal.html.j2:46 +msgid "to do" +msgstr "Te doen" + +#: amt/site/templates/projects/details_measure_modal.html.j2:49 +#: amt/site/templates/projects/details_measure_modal.html.j2:51 +msgid "in progress" +msgstr "Onderhanden" + +#: amt/site/templates/projects/details_measure_modal.html.j2:54 +#: amt/site/templates/projects/details_measure_modal.html.j2:56 +msgid "done" +msgstr "Afgerond" + +#: amt/site/templates/projects/details_measure_modal.html.j2:69 +msgid "" +"Describe how the measure has been implemented, including challenges and " +"solutions." +msgstr "" +"Beschrijf hoe de maatregel is geimplementeerd, inclusief uitdagingen " +"enoplossingen." + +#: amt/site/templates/projects/details_measure_modal.html.j2:80 +msgid "Save" +msgstr "Opslaan" + +#: amt/site/templates/projects/details_measure_modal.html.j2:84 +msgid "Cancel" +msgstr "Annuleren" + +#: amt/site/templates/projects/details_requirements.html.j2:25 msgid "measures executed" msgstr "maatregelen uitgevoerd" -#: amt/site/templates/projects/index.html.j2:12 -msgid "New project" -msgstr "Nieuw project" - -#: amt/site/templates/projects/index.html.j2:28 -msgid "Find project..." -msgstr "Zoek project..." +#: amt/site/templates/projects/details_requirements.html.j2:54 +msgid "Edit measure" +msgstr "Maatregel aanpassen" #: amt/site/templates/projects/new.html.j2:7 msgid "Create a new project" msgstr "Maak een nieuw project" -#: amt/site/templates/projects/new.html.j2:23 -msgid "Project name" -msgstr "Project naam" - #: amt/site/templates/projects/new.html.j2:26 msgid "Your project name here" msgstr "Jouw projectnaam hier" @@ -475,10 +643,7 @@ msgstr "Kies één of meerdere instrumenten" msgid "Create Project" msgstr "Maak project" -#: amt/site/templates/projects/new.html.j2:191 +#: amt/site/templates/projects/new.html.j2:193 msgid "Copy results and close" msgstr "Resultaten overnemen en sluiten" -#~ msgid "Algortime Management Toolkit" -#~ msgstr "Algoritme Management Toolkit" - diff --git a/amt/repositories/projects.py b/amt/repositories/projects.py index 956327f6c..b485b8a86 100644 --- a/amt/repositories/projects.py +++ b/amt/repositories/projects.py @@ -8,6 +8,7 @@ from sqlalchemy.orm import Session from sqlalchemy_utils import escape_like # pyright: ignore[reportMissingTypeStubs, reportUnknownVariableType] +from amt.api.publication_category import PublicationCategories from amt.core.exceptions import AMTRepositoryError from amt.models import Project from amt.repositories.deps import get_session @@ -56,11 +57,23 @@ def find_by_id(self, project_id: int) -> Project: logger.exception("Project not found") raise AMTRepositoryError from e - def paginate(self, skip: int, limit: int, search: str) -> list[Project]: + def paginate(self, skip: int, limit: int, search: str, filters: dict[str, str]) -> list[Project]: try: statement = select(Project) if search != "": statement = statement.filter(Project.name.ilike(f"%{escape_like(search)}%")) + if filters: + for key, value in filters.items(): + match key: + case "lifecycle": + statement = statement.filter(Project.lifecycle == value) + case "publication-category": + statement = statement.filter( + Project.system_card_json["ai_act_profile"]["publication_category"].as_string() + == PublicationCategories[value].value + ) + case _: + raise TypeError("Unknown filter type") # noqa statement = statement.order_by(func.lower(Project.name)).offset(skip).limit(limit) return list(self.session.execute(statement).scalars()) except Exception as e: diff --git a/amt/schema/localized_value_item.py b/amt/schema/localized_value_item.py new file mode 100644 index 000000000..22be25b9d --- /dev/null +++ b/amt/schema/localized_value_item.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel + + +class LocalizedValueItem(BaseModel): + value: str + display_value: str diff --git a/amt/schema/measure.py b/amt/schema/measure.py index 35a1a6205..f5b0b4452 100644 --- a/amt/schema/measure.py +++ b/amt/schema/measure.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel +from pydantic import BaseModel, Field class MeasureBase(BaseModel): @@ -14,3 +14,9 @@ class MeasureTask(MeasureBase): class Measure(MeasureBase): name: str description: str + links: list[str] = Field(default=[]) + + +class ExtendedMeasureTask(MeasureTask): + name: str + description: str diff --git a/amt/schema/publication_category.py b/amt/schema/publication_category.py new file mode 100644 index 000000000..3ce7c08e9 --- /dev/null +++ b/amt/schema/publication_category.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel + + +class PublicationCategory(BaseModel): + id: str + name: str diff --git a/amt/services/projects.py b/amt/services/projects.py index d7941c973..d9c7bb79d 100644 --- a/amt/services/projects.py +++ b/amt/services/projects.py @@ -62,8 +62,10 @@ def create(self, project_new: ProjectNew) -> Project: return project - def paginate(self, skip: int, limit: int, search: str) -> list[Project]: - return self.repository.paginate(skip=skip, limit=limit, search=search) + def paginate(self, skip: int, limit: int, search: str, filters: dict[str, str]) -> list[Project]: + return self.repository.paginate(skip=skip, limit=limit, search=search, filters=filters) def update(self, project: Project) -> Project: + # TODO: Is this the right place to sync system cards: system_card and system_card_json? + project.sync_system_card() return self.repository.save(project) diff --git a/amt/services/task_registry.py b/amt/services/task_registry.py index fa5b27cda..adb5dce25 100644 --- a/amt/services/task_registry.py +++ b/amt/services/task_registry.py @@ -1,5 +1,6 @@ import logging from collections.abc import Sequence +from functools import lru_cache from pathlib import Path from typing import Any @@ -36,38 +37,51 @@ def get_requirements_and_measures( return requirements_card, measure_card -def fetch_requirements(urns: Sequence[str]) -> list[Requirement]: +@lru_cache +def fetch_all_requirements() -> dict[str, Requirement]: """ Fetch requirements with URN in urns. """ - # TODO: make this cacheable (not use a sequence/list as input argument) mock_registry_path = Path("example_registry/requirements") - requirements: list[Requirement] = [] + requirements: dict[str, Requirement] = {} - required_urns: set[str] = set(urns) for requirement_path in mock_registry_path.glob("*.yaml"): requirement: Any = StorageFactory.init( storage_type="file", location=requirement_path.parent, filename=requirement_path.name ).read() - if requirement["urn"] in required_urns: - requirements.append(Requirement(**requirement)) + requirements[requirement["urn"]] = Requirement(**requirement) return requirements -def fetch_measures(urns: Sequence[str]) -> list[Measure]: +def fetch_requirements(urns: Sequence[str]) -> list[Requirement]: + """ + Fetch requirements with URN in urns. + """ + all_requirements = fetch_all_requirements() + return [all_requirements[urn] for urn in urns if urn in all_requirements] + + +@lru_cache +def fetch_all_measures() -> dict[str, Measure]: """ Fetch measures with URN in urns. """ mock_registry_path = Path("example_registry/measures") - measures: list[Measure] = [] + measures: dict[str, Measure] = {} - required_urns: set[str] = set(urns) for measure_path in mock_registry_path.glob("*.yaml"): measure: Any = StorageFactory.init( storage_type="file", location=measure_path.parent, filename=measure_path.name ).read() - if measure["urn"] in required_urns: - measures.append(Measure(**measure)) + measures[measure["urn"]] = Measure(**measure) return measures + + +def fetch_measures(urns: Sequence[str]) -> list[Measure]: + """ + Fetch measures with URN in urns. + """ + all_measures = fetch_all_measures() + return [all_measures[urn] for urn in urns if urn in all_measures] diff --git a/amt/site/static/scss/layout.scss b/amt/site/static/scss/layout.scss index e54db8d23..85bc99335 100644 --- a/amt/site/static/scss/layout.scss +++ b/amt/site/static/scss/layout.scss @@ -47,6 +47,10 @@ main { margin-top: 1em; } +.margin-top-middle { + margin-top: 0.5em; +} + .margin-bottom-small { margin-bottom: 0.5em; } diff --git a/amt/site/static/ts/amt.ts b/amt/site/static/ts/amt.ts index ae3754aa5..21af22d9b 100644 --- a/amt/site/static/ts/amt.ts +++ b/amt/site/static/ts/amt.ts @@ -100,8 +100,8 @@ export function hideMobileMenu() { window.setCookie = setCookie; window.htmx = htmx; -export function openModal() { - const el: Element | null = document.getElementById("decision-tree-modal"); +export function openModal(id: string) { + const el: Element | null = document.getElementById(id); if (el != null) { el.classList.remove("display-none"); } @@ -118,16 +118,16 @@ class AiActProfile { ) {} } -export function closeModal() { +export function closeModal(id: string) { // Do not show modal. - const el: Element | null = document.getElementById("decision-tree-modal"); + const el: Element | null = document.getElementById(id); if (el != null) { el.classList.add("display-none"); } } -export function closeModalSave() { - closeModal(); +export function closeModalSave(id: string) { + closeModal(id); // Get decision tree state from local store. const decision_tree_state = localStorage?.getItem("labelsbycategory"); @@ -153,3 +153,28 @@ export function closeModalSave() { }); } } + +export function updateSearchCounter() { + let count = 0; + if (document.getElementById("search-results-table")) { + // @ts-expect-error No error expected + // prettier-ignore + count = document.getElementById("search-results-table").getElementsByTagName("tr").length - 1; + } + if (document.getElementById("search-results-counter")) { + // @ts-expect-error No error expected + document.getElementById("search-results-counter").innerText = String(count); + } + if (count == 1) { + // @ts-expect-error No error expected + document.getElementById("search-results-single").className = ""; + // @ts-expect-error No error expected + document.getElementById("search-results-multiple").className = + "display-none"; + } else { + // @ts-expect-error No error expected + document.getElementById("search-results-single").className = "display-none"; + // @ts-expect-error No error expected + document.getElementById("search-results-multiple").className = ""; + } +} diff --git a/amt/site/templates/parts/filter_list.html.j2 b/amt/site/templates/parts/filter_list.html.j2 new file mode 100644 index 000000000..538fdbf64 --- /dev/null +++ b/amt/site/templates/parts/filter_list.html.j2 @@ -0,0 +1,73 @@ +{% macro item(loop, project, search, filters) -%} + + + {{ project.name }} + + + {{ project.lifecycle.name }} + + + {{ project.last_edited | time_ago(language) }} {% trans %} ago{% endtrans %} + + +{% endmacro %} +{% if start > 0 %} + {% for project in projects %}{{ item(loop, project, search, filters) }}{% endfor %} +{% else %} +
+ 0 + + {% trans %}results{% endtrans %} + {% if search or filters %} + {% trans %}for{% endtrans %} + {% if search %}'{{ search }}'{% endif %} + {% endif %} +
+ + {% for key, localized_value in filters.items() %} + + + {{ localized_value.display_value }} + + + {% endfor %} +
+
+ {% if projects|length ==0 %} +
+ {% trans %}No projects match your selected filters. Try adjusting your filters or clearing them to see more projects.{% endtrans %} +
+ {% else %} + + + + + + + + + {% for project in projects %}{{ item(loop, project, search, filters) }}{% endfor %} +
{% trans %}Project name{% endtrans %}{% trans %}Phase{% endtrans %}{% trans %}Last updated{% endtrans %}
+ {% endif %} +{% endif %} + diff --git a/amt/site/templates/parts/project_search.html.j2 b/amt/site/templates/parts/project_search.html.j2 new file mode 100644 index 000000000..47a74c5b7 --- /dev/null +++ b/amt/site/templates/parts/project_search.html.j2 @@ -0,0 +1,75 @@ +
+
+
+

{% trans %}Projects{% endtrans %}

+
+ +
+
+
+
+
+
+
+ + +
+
+ +
+
+ +
+
+
+
+
+
+
+
{% include 'parts/filter_list.html.j2' %}
+
diff --git a/amt/site/templates/projects/_list.html.j2 b/amt/site/templates/projects/_list.html.j2 deleted file mode 100644 index a1e0d0015..000000000 --- a/amt/site/templates/projects/_list.html.j2 +++ /dev/null @@ -1,17 +0,0 @@ -{% for project in projects %} - {% if loop.last and projects|length == limit %} -
  • - {{ project.name }} -
  • - {% else %} -
  • - {{ project.name }} -
  • - {% endif %} -{% endfor %} diff --git a/amt/site/templates/projects/details_base.html.j2 b/amt/site/templates/projects/details_base.html.j2 index eec4d3a7c..2a4aad872 100644 --- a/amt/site/templates/projects/details_base.html.j2 +++ b/amt/site/templates/projects/details_base.html.j2 @@ -1,8 +1,12 @@ {% extends 'layouts/base.html.j2' %} -{% block title %} - {% trans %}AMT Placeholder information page{% endtrans %} -{% endblock %} +{% block title %}{{ project.name }} | AMT{% endblock %} {% block content %} +

    {{ project.name }}

    @@ -19,7 +23,8 @@ role="img" aria-label="">{% trans %}Does the algorithm meet the requirements?{% endtrans %} - {{ requirements_state.count_0 }}/{{ requirements_state.count_1 }} {% trans %}Done{% endtrans %} + {{ requirements_state.count_0 }}/{{ requirements_state.count_1 }} + {% trans %}Done{% endtrans %}
      {% for requirement in requirements_state.states %} @@ -29,8 +34,10 @@
      -
      +
      {% if requirement.state == "to do" %} +
      + {% elif requirement.state == "in progress" %}
      {% else %}
      @@ -39,6 +46,8 @@
      {% if requirement.state == "to do" %} {% trans %}To do{% endtrans %} + {% elif requirement.state == "in progress" %} + {% trans %}In progress{% endtrans %} {% else %} {% trans %}Done{% endtrans %} {% endif %} @@ -77,7 +86,7 @@
      -
      +
      {% if instrument.in_progress == 1 %}
      {% else %} diff --git a/amt/site/templates/projects/details_data.html.j2 b/amt/site/templates/projects/details_data.html.j2 index b505f2f2a..22c9ad136 100644 --- a/amt/site/templates/projects/details_data.html.j2 +++ b/amt/site/templates/projects/details_data.html.j2 @@ -1,5 +1,4 @@ {% extends 'projects/details_base.html.j2' %} -{% block title %} - {% trans %}AMT Placeholder information page{% endtrans %} +{% block detail_content %} +
      {% trans %}To be implemented{% endtrans %}
      {% endblock %} -{% block detail_content %}
      To be implemented
      {% endblock %} diff --git a/amt/site/templates/projects/details_inference.html.j2 b/amt/site/templates/projects/details_inference.html.j2 new file mode 100644 index 000000000..5339af992 --- /dev/null +++ b/amt/site/templates/projects/details_inference.html.j2 @@ -0,0 +1,183 @@ +{% extends 'projects/details_base.html.j2' %} +{% block detail_content %} +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      {% trans %}Floor area (m²):{% endtrans %} + +
      {% trans %}Plot size (m²):{% endtrans %} + +
      {% trans %}Building year:{% endtrans %} + +
      {% trans %}Object type:{% endtrans %} + +
      {% trans %}Number of annexes:{% endtrans %} + +
      {% trans %}Neighborhood code:{% endtrans %} + +
      {% trans %}Quality rating:{% endtrans %} + +
      {% trans %}Maintenance rating:{% endtrans %} + +
      {% trans %}Amenities rating:{% endtrans %} + +
      {% trans %}Location rating:{% endtrans %} + +
      + +
      {% trans %}Estimated WOZ Value{% endtrans %} + {% trans %}Undefined{% endtrans %} +
      +
      + + +{% endblock %} diff --git a/amt/site/templates/projects/details_info.html.j2 b/amt/site/templates/projects/details_info.html.j2 index 52eb926d0..d74057bff 100644 --- a/amt/site/templates/projects/details_info.html.j2 +++ b/amt/site/templates/projects/details_info.html.j2 @@ -1,7 +1,4 @@ {% extends 'projects/details_base.html.j2' %} -{% block title %} - {% trans %}AMT Placeholder information page{% endtrans %} -{% endblock %} {% block detail_content %}
      diff --git a/amt/site/templates/projects/details_instruments.html.j2 b/amt/site/templates/projects/details_instruments.html.j2 index b505f2f2a..22c9ad136 100644 --- a/amt/site/templates/projects/details_instruments.html.j2 +++ b/amt/site/templates/projects/details_instruments.html.j2 @@ -1,5 +1,4 @@ {% extends 'projects/details_base.html.j2' %} -{% block title %} - {% trans %}AMT Placeholder information page{% endtrans %} +{% block detail_content %} +
      {% trans %}To be implemented{% endtrans %}
      {% endblock %} -{% block detail_content %}
      To be implemented
      {% endblock %} diff --git a/amt/site/templates/projects/details_measure_modal.html.j2 b/amt/site/templates/projects/details_measure_modal.html.j2 new file mode 100644 index 000000000..3075fe8fc --- /dev/null +++ b/amt/site/templates/projects/details_measure_modal.html.j2 @@ -0,0 +1,89 @@ +
      +

      {{ measure.name }}

      +
      +
      +
      +
      +
      + {# Description #} +
      +
      + +
      {{ measure.description }}
      +
      + +
      + {# Status#} +
      +
      + +
      +
      + +
      +
      + {# Implementation#} +
      +
      + +
      + +
      +
      +
      +

      + + +

      + +
      +
      +
      diff --git a/amt/site/templates/projects/details_requirements.html.j2 b/amt/site/templates/projects/details_requirements.html.j2 index 1d77c09e1..0ee802013 100644 --- a/amt/site/templates/projects/details_requirements.html.j2 +++ b/amt/site/templates/projects/details_requirements.html.j2 @@ -1,12 +1,9 @@ {% extends 'projects/details_base.html.j2' %} -{% block title %} - {% trans %}AMT Placeholder information page{% endtrans %} -{% endblock %} {% block detail_content %}
      - {% for (requirement, measures) in requirements_and_measures %} + {% for (requirement, completed_measures_count, measures) in requirements_and_measures %}
      - +

      -
      - 0 / {{ measures | length }} {% trans %}measures executed{% endtrans %} + {% if completed_measures_count == 0 %} +
      + {% elif completed_measures_count < measures | length %} +
      + {% else %} +
      + {% endif %} + {{ completed_measures_count }} / {{ measures | length }} {% trans %}measures executed{% endtrans %}

      {% for measure in measures %}
      -
      -
      -

      {{ measure.name }}

      +
      + {% if measure.state == "to do" %} +
      + {% elif measure.state == "in progress" %} +
      + {% elif measure.state == "done" %} +
      + {% else %} + {# This should not happen, red could be for overdue.#} +
      + {% endif %} +
      +

      {{ loop.index }}. {{ measure.name }}

      +

      {{ measure.value }}

      + + + {% trans %}Edit measure{% endtrans %} + +
      -

      {{ measure.description }}

      {% endfor %}
      diff --git a/amt/site/templates/projects/index.html.j2 b/amt/site/templates/projects/index.html.j2 index 7821509b5..8043b7478 100644 --- a/amt/site/templates/projects/index.html.j2 +++ b/amt/site/templates/projects/index.html.j2 @@ -1,57 +1,6 @@ {% extends 'layouts/base.html.j2' %} {% block content %}
      -
      -
      -
      -

      {% trans %}Projects{% endtrans %}

      -
      - -
      -
      -
      -
      -
      -
      - - -
      - -
      -
      -
      -
        - {% include 'projects/_list.html.j2' %} -
      -
      +
      {% include 'parts/project_search.html.j2' %}
      -
      {% endblock %} diff --git a/amt/site/templates/projects/new.html.j2 b/amt/site/templates/projects/new.html.j2 index 15ef13784..124acf25f 100644 --- a/amt/site/templates/projects/new.html.j2 +++ b/amt/site/templates/projects/new.html.j2 @@ -65,7 +65,7 @@
      @@ -182,13 +182,16 @@
      ' not in response.content def test_get_new_projects(client: TestClient, init_instruments: Generator[None, None, None]) -> None: diff --git a/tests/e2e/test_scroll_project.py b/tests/e2e/test_scroll_project.py index 0055c2cf2..304b6b84f 100644 --- a/tests/e2e/test_scroll_project.py +++ b/tests/e2e/test_scroll_project.py @@ -6,7 +6,7 @@ def test_e2e_scroll_projects(page: Page) -> None: page.goto("/projects/") - project_links = page.locator("#project-search-results > li").count() + project_links = page.locator("#search-results-table tr").count() - 1 assert project_links == 100 @@ -18,5 +18,5 @@ def test_e2e_scroll_projects(page: Page) -> None: response = response_info.value assert response.status == 200 - project_links = page.locator("#project-search-results > li").count() + project_links = page.locator("#search-results-table tr").count() assert project_links > 100 diff --git a/tests/e2e/test_search_project.py b/tests/e2e/test_search_project.py index 1b2dec430..ec8a5cf0e 100644 --- a/tests/e2e/test_search_project.py +++ b/tests/e2e/test_search_project.py @@ -6,13 +6,15 @@ def test_e2e_search_projects(page: Page) -> None: page.goto("/projects/") - project_links = page.locator("#project-search-results > li").count() + project_links = page.locator("#search-results-table tr").count() - 1 assert 90 <= project_links <= 101 page.locator("#project-search-input").fill("10") - with page.expect_response("/projects/?skip=0&search=10", timeout=3000) as response_info: + with page.expect_response( + "/projects/?skip=0&search=10&add-filter-lifecycle=&add-filter-publication-category=", timeout=3000 + ) as response_info: expect(page.get_by_text("Project 10", exact=True)).to_be_visible() expect(page.get_by_text("Project 100", exact=True)).to_be_visible() @@ -24,13 +26,15 @@ def test_e2e_search_projects(page: Page) -> None: def test_e2e_search_scroll_projects(page: Page) -> None: page.goto("/projects/") - project_links = page.locator("#project-search-results > li").count() + project_links = page.locator("#search-results-table tr").count() - 1 assert 90 <= project_links <= 101 page.locator("#project-search-input").fill("Project") - with page.expect_request("/projects/?skip=0&search=Project", timeout=3000) as _: - project_links = page.locator("#project-search-results > li").count() + with page.expect_request( + "/projects/?skip=0&search=Project&add-filter-lifecycle=&add-filter-publication-category=", timeout=3000 + ) as _: + project_links = page.locator("#search-results-table tr").count() - 1 expect(page.get_by_text("Project 100", exact=True)).to_be_visible() assert 90 <= project_links <= 101 diff --git a/tests/repositories/test_projects.py b/tests/repositories/test_projects.py index e820eb33d..83c79640f 100644 --- a/tests/repositories/test_projects.py +++ b/tests/repositories/test_projects.py @@ -1,5 +1,6 @@ import pytest from amt.core.exceptions import AMTRepositoryError +from amt.models import Project from amt.repositories.projects import ProjectsRepository from tests.constants import default_project from tests.database_test_utils import DatabaseTestUtils @@ -85,7 +86,7 @@ def test_paginate(db: DatabaseTestUtils): db.given([default_project()]) project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=3, search="") + result: list[Project] = project_repository.paginate(skip=0, limit=3, search="", filters={}) assert len(result) == 1 @@ -94,7 +95,7 @@ def test_paginate_more(db: DatabaseTestUtils): db.given([default_project(), default_project(), default_project(), default_project()]) project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=3, search="") + result: list[Project] = project_repository.paginate(skip=0, limit=3, search="", filters={}) assert len(result) == 3 @@ -110,7 +111,7 @@ def test_paginate_capitalize(db: DatabaseTestUtils): ) project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=4, search="") + result: list[Project] = project_repository.paginate(skip=0, limit=4, search="", filters={}) assert len(result) == 4 assert result[0].name == "Aaa" @@ -130,7 +131,7 @@ def test_search(db: DatabaseTestUtils): ) project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=4, search="bbb") + result: list[Project] = project_repository.paginate(skip=0, limit=4, search="bbb", filters={}) assert len(result) == 1 assert result[0].name == "bbb" @@ -147,7 +148,7 @@ def test_search_multiple(db: DatabaseTestUtils): ) project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=4, search="A") + result: list[Project] = project_repository.paginate(skip=0, limit=4, search="A", filters={}) assert len(result) == 2 assert result[0].name == "Aaa" @@ -156,7 +157,7 @@ def test_search_multiple(db: DatabaseTestUtils): def test_search_no_results(db: DatabaseTestUtils): project_repository = ProjectsRepository(db.get_session()) - result = project_repository.paginate(skip=0, limit=4, search="A") + result: list[Project] = project_repository.paginate(skip=0, limit=4, search="A", filters={}) assert len(result) == 0 @@ -165,4 +166,4 @@ def test_raises_exception(db: DatabaseTestUtils): project_repository = ProjectsRepository(db.get_session()) with pytest.raises(AMTRepositoryError): - project_repository.paginate(skip="a", limit=3, search="") # type: ignore + project_repository.paginate(skip="a", limit=3, search="", filters={}) # type: ignore