From 6adba221e41eead634ebc6a1106955aa6e15b6d1 Mon Sep 17 00:00:00 2001 From: Laurens Weijs Date: Wed, 4 Dec 2024 15:48:37 +0100 Subject: [PATCH] Add download route & clickable icon --- .gitignore | 3 + amt/api/routes/algorithm.py | 18 +++++- amt/locale/base.pot | 32 +++++----- amt/locale/en_US/LC_MESSAGES/messages.mo | Bin 989 -> 989 bytes amt/locale/en_US/LC_MESSAGES/messages.po | 30 +++++----- amt/locale/nl_NL/LC_MESSAGES/messages.mo | Bin 14052 -> 14051 bytes amt/locale/nl_NL/LC_MESSAGES/messages.po | 32 +++++----- amt/site/static/scss/layout.scss | 35 +++++++++++ amt/site/static/ts/amt.ts | 55 ++++++++++++++++++ .../templates/algorithms/details_base.html.j2 | 27 ++++++--- 10 files changed, 177 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index d6e6b144..b2407927 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,6 @@ amt/site/static/js/* # ignore webpack build files amt/site/templates/layouts/base.html.j2 + +# downloaded system_cards +*00:00.yaml diff --git a/amt/api/routes/algorithm.py b/amt/api/routes/algorithm.py index 42e6c7b8..126f1d3e 100644 --- a/amt/api/routes/algorithm.py +++ b/amt/api/routes/algorithm.py @@ -1,10 +1,12 @@ import asyncio +import datetime import logging from collections.abc import Sequence from typing import Annotated, Any, cast +import yaml from fastapi import APIRouter, Depends, Request -from fastapi.responses import HTMLResponse +from fastapi.responses import FileResponse, HTMLResponse from pydantic import BaseModel, Field from amt.api.deps import templates @@ -736,3 +738,17 @@ async def get_model_card( } return templates.TemplateResponse(request, "pages/model_card.html.j2", context) + + +@router.get("/{algorithm_id}/details/system_card/download") +async def download_algorithm_system_card_as_yaml( + algorithm_id: int, algorithms_service: Annotated[AlgorithmsService, Depends(AlgorithmsService)], request: Request +) -> FileResponse: + algorithm = await get_algorithm_or_error(algorithm_id, algorithms_service, request) + filename = algorithm.name + "_" + datetime.datetime.now(datetime.UTC).isoformat() + ".yaml" + with open(filename, "w") as outfile: + yaml.dump(algorithm.system_card.model_dump(), outfile) + try: + return FileResponse(filename, filename=filename) + except AMTRepositoryError as e: + raise AMTNotFound from e diff --git a/amt/locale/base.pot b/amt/locale/base.pot index 63ed74ae..0e8a820e 100644 --- a/amt/locale/base.pot +++ b/amt/locale/base.pot @@ -8,14 +8,14 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 0001-01-01 00:00+0000\n" -"PO-Revision-Date: 0001-01-01 00:00+0000\n" +"POT-Creation-Date: 2024-12-09 10:35+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.15.0\n" +"Generated-By: Babel 2.16.0\n" #: amt/api/ai_act_profile.py:24 msgid "Type" @@ -323,40 +323,40 @@ msgstr "" msgid "No" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:57 -msgid "Delete algorithm" +#: amt/site/templates/algorithms/details_base.html.j2:63 +msgid "Download as YAML" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:74 +#: amt/site/templates/algorithms/details_base.html.j2:87 msgid "Does the algorithm meet the requirements?" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:77 -#: amt/site/templates/algorithms/details_base.html.j2:103 -#: amt/site/templates/algorithms/details_base.html.j2:134 -#: amt/site/templates/algorithms/details_base.html.j2:157 +#: amt/site/templates/algorithms/details_base.html.j2:90 +#: amt/site/templates/algorithms/details_base.html.j2:116 +#: amt/site/templates/algorithms/details_base.html.j2:147 +#: amt/site/templates/algorithms/details_base.html.j2:170 #: amt/site/templates/macros/tasks.html.j2:32 msgid "Done" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:99 -#: amt/site/templates/algorithms/details_base.html.j2:155 +#: amt/site/templates/algorithms/details_base.html.j2:112 +#: amt/site/templates/algorithms/details_base.html.j2:168 msgid "To do" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:101 +#: amt/site/templates/algorithms/details_base.html.j2:114 msgid "In progress" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:117 +#: amt/site/templates/algorithms/details_base.html.j2:130 msgid "Go to all requirements" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:131 +#: amt/site/templates/algorithms/details_base.html.j2:144 msgid "Which instruments are executed?" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:171 +#: amt/site/templates/algorithms/details_base.html.j2:184 msgid "Go to all instruments" msgstr "" diff --git a/amt/locale/en_US/LC_MESSAGES/messages.mo b/amt/locale/en_US/LC_MESSAGES/messages.mo index 738f59d744c7bbb468cf5ea758aea138d08b66f8..f14e1c9e07a2aa3a7aa859df2abafb4a06398473 100644 GIT binary patch delta 32 ocmcc1ewTg28Af3v10xe%LnB=SO9ev%D`Qh_1H;Yt8UHZ?0HHAnhyVZp delta 16 Ycmcc1ewTg28OF(97{xX}V*Jer074%Jb^rhX diff --git a/amt/locale/en_US/LC_MESSAGES/messages.po b/amt/locale/en_US/LC_MESSAGES/messages.po index 288912d0..92bbab77 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: 0001-01-01 00:00+0000\n" +"POT-Creation-Date: 2024-12-09 10:35+0100\n" "PO-Revision-Date: 0001-01-01 00:00+0000\n" "Last-Translator: FULL NAME \n" "Language: en_US\n" @@ -16,7 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.15.0\n" +"Generated-By: Babel 2.16.0\n" #: amt/api/ai_act_profile.py:24 msgid "Type" @@ -324,40 +324,40 @@ msgstr "" msgid "No" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:57 -msgid "Delete algorithm" +#: amt/site/templates/algorithms/details_base.html.j2:63 +msgid "Download as YAML" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:74 +#: amt/site/templates/algorithms/details_base.html.j2:87 msgid "Does the algorithm meet the requirements?" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:77 -#: amt/site/templates/algorithms/details_base.html.j2:103 -#: amt/site/templates/algorithms/details_base.html.j2:134 -#: amt/site/templates/algorithms/details_base.html.j2:157 +#: amt/site/templates/algorithms/details_base.html.j2:90 +#: amt/site/templates/algorithms/details_base.html.j2:116 +#: amt/site/templates/algorithms/details_base.html.j2:147 +#: amt/site/templates/algorithms/details_base.html.j2:170 #: amt/site/templates/macros/tasks.html.j2:32 msgid "Done" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:99 -#: amt/site/templates/algorithms/details_base.html.j2:155 +#: amt/site/templates/algorithms/details_base.html.j2:112 +#: amt/site/templates/algorithms/details_base.html.j2:168 msgid "To do" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:101 +#: amt/site/templates/algorithms/details_base.html.j2:114 msgid "In progress" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:117 +#: amt/site/templates/algorithms/details_base.html.j2:130 msgid "Go to all requirements" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:131 +#: amt/site/templates/algorithms/details_base.html.j2:144 msgid "Which instruments are executed?" msgstr "" -#: amt/site/templates/algorithms/details_base.html.j2:171 +#: amt/site/templates/algorithms/details_base.html.j2:184 msgid "Go to all instruments" msgstr "" diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.mo b/amt/locale/nl_NL/LC_MESSAGES/messages.mo index b82af76b8d758a86dd865b03d5088e4b75bf12d1..a84759a86053d444e9617a99170983f29c50fb8d 100644 GIT binary patch delta 1325 zcmX}rTS!zv9LModvt8G=t@-1O`%6sRR5P%x z#Ll$|*U;}nB{uB%5cB9yVJ^-&{UxlR?kQAIC~;MK6w^5*S0(avam~d1;*B zG-eo3aaK?Zf1?+pWyWm4Jy?XNu@HNl@ln)Cr%~%?P>Ii?)_+8ucp3Gbd%ImJAF9In zaT>~aGb+O>$6crl_n`;tFasMT8+C$S)FZu)s>C3wRKJY{+HxmV@jn3j>Y(d@K1d_CwLjKHW{^^bj%k9L&c$fZ8RNw?Q<5$!hYv83G z!7HfwS4`}8uVu-W$x{`(B9e+I}?a?22R!J#+yyuTkV*&j)sFX5DH2Z`Ky@HBoQExmPwUou_*E2v&>%t%V+fhuVaD$oT~;2T(sw@{UOfLiw)weO5S{|d|KFW@RneW%e+<0mRW z-xe?9E2sqSB2zYsdXDe>@g=|i3nPpNwt6RSK%J}w2XGH6k!e%~U*j5F!D8ZD$u_S7 z5mcrvSdFcy1QMtXPNO#N_4|FO6I@0;&a0?O+(ec9HY(6VRK;HS^Yf^RXa3J~|I7Xl zf-$rGOhix{oy2zRLEYUmBx##MKK6|--Er-9FYy@Or@s>wID_5z1NFudywpS3kD8yu zQsUbZjVknyw;CWQ#E}`B)8f$P8vvC1csYTTK zFW9XOe$&v2b9nk~7{CyAq5_^mUBx*p$BU@>A=DL&p#qGf0!&~9PNLSm#lhoFlY7{S kG00ssI2 diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.po b/amt/locale/nl_NL/LC_MESSAGES/messages.po index e1c86fab..8a18c99c 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: 0001-01-01 00:00+0000\n" +"POT-Creation-Date: 2024-12-09 10:35+0100\n" "PO-Revision-Date: 0001-01-01 00:00+0000\n" "Last-Translator: FULL NAME \n" "Language: nl_NL\n" @@ -16,7 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.15.0\n" +"Generated-By: Babel 2.16.0\n" #: amt/api/ai_act_profile.py:24 msgid "Type" @@ -338,40 +338,40 @@ msgstr "Ja" msgid "No" msgstr "Nee" -#: amt/site/templates/algorithms/details_base.html.j2:57 -msgid "Delete algorithm" -msgstr "Verwijder algoritme" +#: amt/site/templates/algorithms/details_base.html.j2:63 +msgid "Download as YAML" +msgstr "Download naar YAML" -#: amt/site/templates/algorithms/details_base.html.j2:74 +#: amt/site/templates/algorithms/details_base.html.j2:87 msgid "Does the algorithm meet the requirements?" msgstr "Voldoet het algoritme aan de vereisten?" -#: amt/site/templates/algorithms/details_base.html.j2:77 -#: amt/site/templates/algorithms/details_base.html.j2:103 -#: amt/site/templates/algorithms/details_base.html.j2:134 -#: amt/site/templates/algorithms/details_base.html.j2:157 +#: amt/site/templates/algorithms/details_base.html.j2:90 +#: amt/site/templates/algorithms/details_base.html.j2:116 +#: amt/site/templates/algorithms/details_base.html.j2:147 +#: amt/site/templates/algorithms/details_base.html.j2:170 #: amt/site/templates/macros/tasks.html.j2:32 msgid "Done" msgstr "Afgerond" -#: amt/site/templates/algorithms/details_base.html.j2:99 -#: amt/site/templates/algorithms/details_base.html.j2:155 +#: amt/site/templates/algorithms/details_base.html.j2:112 +#: amt/site/templates/algorithms/details_base.html.j2:168 msgid "To do" msgstr "Te doen" -#: amt/site/templates/algorithms/details_base.html.j2:101 +#: amt/site/templates/algorithms/details_base.html.j2:114 msgid "In progress" msgstr "Onderhanden" -#: amt/site/templates/algorithms/details_base.html.j2:117 +#: amt/site/templates/algorithms/details_base.html.j2:130 msgid "Go to all requirements" msgstr "Ga naar alle Vereisten" -#: amt/site/templates/algorithms/details_base.html.j2:131 +#: amt/site/templates/algorithms/details_base.html.j2:144 msgid "Which instruments are executed?" msgstr "Welke instrumenten zijn uitgevoerd?" -#: amt/site/templates/algorithms/details_base.html.j2:171 +#: amt/site/templates/algorithms/details_base.html.j2:184 msgid "Go to all instruments" msgstr "Ga naar all instrumenten" diff --git a/amt/site/static/scss/layout.scss b/amt/site/static/scss/layout.scss index 66003a24..e6dcff3a 100644 --- a/amt/site/static/scss/layout.scss +++ b/amt/site/static/scss/layout.scss @@ -162,6 +162,7 @@ main { &.amt-layout-grid-columns--two { grid-template-columns: repeat(2, 1fr); } + /* stylelint-enable */ } @@ -389,6 +390,40 @@ main { visibility: visible; } +.dropdown-content { + display: none; + position: absolute; + background-color: #f9f9f9; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + z-index: 1; +} + +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.dropdown-content a:hover { + background-color: #f1f1f1; +} + +.dropdown:hover .dropdown-content { + display: block; +} + +.dropdown-underlay { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; +} + /* stylelint-enable */ .amt-cursor-pointer { diff --git a/amt/site/static/ts/amt.ts b/amt/site/static/ts/amt.ts index 47d93a26..88d03875 100644 --- a/amt/site/static/ts/amt.ts +++ b/amt/site/static/ts/amt.ts @@ -308,6 +308,61 @@ export function hide_form_search_options(id: string) { }, 250); } +export function hide_download_dropdown() { + const dropdownContent = document.querySelector( + ".dropdown-content", + ) as HTMLElement; + const dropdownUnderlay = document.querySelector( + ".dropdown-underlay", + ) as HTMLElement; + + if (dropdownContent && dropdownUnderlay) { + dropdownContent.style.display = "none"; + dropdownUnderlay.style.display = "none"; + } else { + console.error("Could not find dropdown elements."); + } +} + +export function show_download_dropdown() { + const dropdownContent = document.querySelector( + ".dropdown-content", + ) as HTMLElement; + const dropdownUnderlay = document.querySelector( + ".dropdown-underlay", + ) as HTMLElement; + + if (dropdownContent && dropdownUnderlay) { + dropdownContent.style.display = "block"; + dropdownUnderlay.style.display = "block"; + } else { + console.error("Could not find dropdown elements."); + } +} + +export async function download_as_yaml( + algorithm_id: string, + algorithm_name: string, +): Promise { + try { + const response = await fetch( + `/algorithm/${algorithm_id}/details/system_card/download`, + ); + const blob = await response.blob(); // Get the response as a Blob + + const url = window.URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + const filename = algorithm_name + "_" + new Date().toISOString() + ".yaml"; + link.setAttribute("download", filename); + document.body.appendChild(link); + link.click(); + } catch (error) { + console.error("Error downloading system card:", error); + } + hide_download_dropdown(); +} + export function add_field_on_enter(id: string) { if (!event) { return; diff --git a/amt/site/templates/algorithms/details_base.html.j2 b/amt/site/templates/algorithms/details_base.html.j2 index c561ac0f..34029a32 100644 --- a/amt/site/templates/algorithms/details_base.html.j2 +++ b/amt/site/templates/algorithms/details_base.html.j2 @@ -49,13 +49,26 @@