From 8e4d7928a7b3dfdbf127cf0645082f0181b99f28 Mon Sep 17 00:00:00 2001 From: robbertuittenbroek Date: Mon, 3 Feb 2025 12:47:10 +0100 Subject: [PATCH] Make editable fields easier to edit and group provenance as one block. --- amt/api/deps.py | 3 +- amt/api/editable.py | 41 +++++++++++----- amt/api/routes/algorithm.py | 2 + amt/locale/base.pot | 8 ++-- amt/locale/en_US/LC_MESSAGES/messages.mo | Bin 989 -> 989 bytes amt/locale/en_US/LC_MESSAGES/messages.po | 8 ++-- amt/locale/nl_NL/LC_MESSAGES/messages.mo | Bin 14069 -> 14066 bytes amt/locale/nl_NL/LC_MESSAGES/messages.po | 10 ++-- amt/site/static/scss/layout.scss | 10 +++- amt/site/static/ts/amt.ts | 12 +++++ amt/site/templates/macros/cards.html.j2 | 27 ++++++----- amt/site/templates/macros/editable.html.j2 | 53 +++++++++++---------- 12 files changed, 107 insertions(+), 67 deletions(-) diff --git a/amt/api/deps.py b/amt/api/deps.py index 879029c9..733cabf8 100644 --- a/amt/api/deps.py +++ b/amt/api/deps.py @@ -12,7 +12,7 @@ from starlette.background import BackgroundTask from starlette.templating import _TemplateResponse # pyright: ignore [reportPrivateUsage] -from amt.api.editable import is_editable_resource +from amt.api.editable import is_editable_resource, is_parent_editable from amt.api.editable_util import replace_digits_in_brackets, resolve_resource_list_path from amt.api.http_browser_caching import url_for_cache from amt.api.localizable import LocalizableEnum @@ -168,6 +168,7 @@ def hasattr_jinja(obj: object, attributes: str) -> bool: templates.env.globals.update(permission=permission) # pyright: ignore [reportUnknownMemberType] templates.env.globals.update(hasattr=hasattr_jinja) # pyright: ignore [reportUnknownMemberType] templates.env.globals.update(is_path_with_list=is_path_with_list) # pyright: ignore [reportUnknownMemberType] +templates.env.globals.update(is_parent_editable=is_parent_editable) # pyright: ignore [reportUnknownMemberType] templates.env.globals.update(resolve_resource_list_path=resolve_resource_list_path) # pyright: ignore [reportUnknownMemberType] templates.env.tests["permission"] = permission # pyright: ignore [reportUnknownMemberType] templates.env.add_extension("jinja2_base64_filters.Base64Filters") # pyright: ignore [reportUnknownMemberType] diff --git a/amt/api/editable.py b/amt/api/editable.py index c73c1da6..af08af2c 100644 --- a/amt/api/editable.py +++ b/amt/api/editable.py @@ -42,11 +42,6 @@ class Editables: validator=EditableValidatorMinMaxLength(min_length=3, max_length=100), ) - ALGORITHM_EDITABLE_AUTHOR = Editable( - full_resource_path="algorithm/{algorithm_id}/system_card/provenance/author", - implementation_type=WebFormFieldImplementationType.TEXT, - ) - ALGORITHM_EDITABLE_SYSTEMCARD_OWNERS = Editable( full_resource_path="algorithm/{algorithm_id}/system_card/owners[*]", implementation_type=WebFormFieldImplementationType.PARENT, @@ -145,14 +140,23 @@ class Editables: ) ALGORITHM_EDITABLE_LIFECYCLE.add_bidirectional_couple(ALGORITHM_EDITABLE_SYSTEMCARD_STATUS) - ALGORITHM_EDITABLE_PROVENANCE_GIT_COMMIT_HASH = Editable( - full_resource_path="algorithm/{algorithm_id}/system_card/provenance/git_commit_hash", - implementation_type=WebFormFieldImplementationType.TEXT, - ) - - ALGORITHM_EDITABLE_PROVENANCE_URI = Editable( - full_resource_path="algorithm/{algorithm_id}/system_card/provenance/uri", - implementation_type=WebFormFieldImplementationType.TEXT, + ALGORITHM_EDITABLE_PROVENANCE = Editable( + full_resource_path="algorithm/{algorithm_id}/system_card/provenance", + implementation_type=WebFormFieldImplementationType.PARENT, + children=[ + Editable( + full_resource_path="algorithm/{algorithm_id}/system_card/provenance/author", + implementation_type=WebFormFieldImplementationType.TEXT, + ), + Editable( + full_resource_path="algorithm/{algorithm_id}/system_card/provenance/git_commit_hash", + implementation_type=WebFormFieldImplementationType.TEXT, + ), + Editable( + full_resource_path="algorithm/{algorithm_id}/system_card/provenance/uri", + implementation_type=WebFormFieldImplementationType.TEXT, + ), + ], ) ALGORITHM_EDITABLE_VERSION = Editable( @@ -546,3 +550,14 @@ def set_path(obj: dict[str, Any] | object, path: str, value: typing.Any) -> None def is_editable_resource(full_resource_path: str, editables: dict[str, ResolvedEditable]) -> bool: return editables.get(replace_digits_in_brackets(full_resource_path), None) is not None + + +def is_parent_editable(editables: dict[str, ResolvedEditable], full_resource_path: str) -> bool: + full_resource_path = replace_digits_in_brackets(full_resource_path) + editable = editables.get(full_resource_path) + if editable is None: + print(full_resource_path + " : " + "false, no match") + return False + result = editable.implementation_type == WebFormFieldImplementationType.PARENT + print(full_resource_path + " : " + str(result)) + return result diff --git a/amt/api/routes/algorithm.py b/amt/api/routes/algorithm.py index d92756b8..e4109f26 100644 --- a/amt/api/routes/algorithm.py +++ b/amt/api/routes/algorithm.py @@ -429,6 +429,7 @@ async def get_algorithm_cancel( "resource_object": editable.resource_object, "full_resource_path": full_resource_path, "editable_object": editable, + "editables": get_resolved_editables(context_variables={"algorithm_id": algorithm_id}), } return templates.TemplateResponse(request, "parts/view_cell.html.j2", context) @@ -479,6 +480,7 @@ async def get_algorithm_update( "resource_object": editable.resource_object, "full_resource_path": full_resource_path, "editable_object": editable, + "editables": get_resolved_editables(context_variables={"algorithm_id": algorithm_id}), } return templates.TemplateResponse(request, "parts/view_cell.html.j2", context) diff --git a/amt/locale/base.pot b/amt/locale/base.pot index 724da9f8..794a8b4b 100644 --- a/amt/locale/base.pot +++ b/amt/locale/base.pot @@ -414,8 +414,8 @@ msgid "measure executed" msgstr "" #: amt/site/templates/algorithms/details_compliance.html.j2:69 -#: amt/site/templates/macros/editable.html.j2:67 -#: amt/site/templates/macros/editable.html.j2:72 +#: amt/site/templates/macros/editable.html.j2:68 +#: amt/site/templates/macros/editable.html.j2:73 #: amt/site/templates/macros/tasks.html.j2:82 msgid "Edit" msgstr "" @@ -464,12 +464,12 @@ msgid "Read more on the algoritmekader" msgstr "" #: amt/site/templates/algorithms/details_measure_modal.html.j2:64 -#: amt/site/templates/macros/editable.html.j2:174 +#: amt/site/templates/macros/editable.html.j2:175 msgid "Save" msgstr "" #: amt/site/templates/algorithms/details_measure_modal.html.j2:68 -#: amt/site/templates/macros/editable.html.j2:179 +#: amt/site/templates/macros/editable.html.j2:180 #: amt/site/templates/organizations/parts/add_members_modal.html.j2:26 msgid "Cancel" msgstr "" diff --git a/amt/locale/en_US/LC_MESSAGES/messages.mo b/amt/locale/en_US/LC_MESSAGES/messages.mo index 738f59d744c7bbb468cf5ea758aea138d08b66f8..64aa8f8eb9b65f382e892da9a4a8788ae831eb8e 100644 GIT binary patch delta 32 ocmcc1ewTg28Af3v10z#i10!7nV+BJaD-%;~1H;Yt8UHZ?0HFH`g#Z8m 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 071e3fd6..68e1199e 100644 --- a/amt/locale/en_US/LC_MESSAGES/messages.po +++ b/amt/locale/en_US/LC_MESSAGES/messages.po @@ -415,8 +415,8 @@ msgid "measure executed" msgstr "" #: amt/site/templates/algorithms/details_compliance.html.j2:69 -#: amt/site/templates/macros/editable.html.j2:67 -#: amt/site/templates/macros/editable.html.j2:72 +#: amt/site/templates/macros/editable.html.j2:68 +#: amt/site/templates/macros/editable.html.j2:73 #: amt/site/templates/macros/tasks.html.j2:82 msgid "Edit" msgstr "" @@ -465,12 +465,12 @@ msgid "Read more on the algoritmekader" msgstr "" #: amt/site/templates/algorithms/details_measure_modal.html.j2:64 -#: amt/site/templates/macros/editable.html.j2:174 +#: amt/site/templates/macros/editable.html.j2:175 msgid "Save" msgstr "" #: amt/site/templates/algorithms/details_measure_modal.html.j2:68 -#: amt/site/templates/macros/editable.html.j2:179 +#: amt/site/templates/macros/editable.html.j2:180 #: amt/site/templates/organizations/parts/add_members_modal.html.j2:26 msgid "Cancel" msgstr "" diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.mo b/amt/locale/nl_NL/LC_MESSAGES/messages.mo index 3ebf3e4040f8e06e0461d76831c6b70048ca84b5..45e3fdb590911a0fe38233ad46a029f8b52ece09 100644 GIT binary patch delta 1267 zcmXZbSx8h-9LMp$<&rw%lG@Ow*K)~Rni;p0dMSiNXjP&i3XQ>DTwcNmV(OtlihPhD z35J9s16wETp+G3g7D!Nnqz8Ryd+?>Ak__tmb1n??Ip^GS|L1@H=iHxN-@ESRrbIH# zY@oy}6{DDrBe)75y5nzL-(d>lv$zhwpo58}W(8P`x!8nW3}Gf7$3#4d4xYvijFwtt zY2k!TW;qO`V>TAJ2GB!)Cn~|cn1Ufxq8)e;yHWFAAhB&4SKuO6V`7=vO5BRc*n&!Q ze_6yViAE;_jo5{%$OtNtN2p4?!Wx`&`+1wq>gZRX7Cz?odr|RjqAGA3mFQzk!wDoO zn?hA&F+xLutlVq^)T081a6NY7Mm&c_c*`Asi`vOND$oy9!V9SP(<S?4iupO0QGb-~|REauJf%{Mk^`p-868bQT3OI%;@e^E*lXxDdQFkR&89(Aa zRQwBAWt{&IjVuOUq7s>L`=8LE{|i0nW43lsgi5pui?IQf&{0$(J*dlg0u}EvYW^_l z{ZV&(3^Q5Zp3?C0U<#G_9O{yNMD2JUbveJG7E0O@AJ4-x^w(e>Ud1N7?>_&HyXpVM zHf-_7k7OA6*$96@*0&iN+My>9-@$6ULB9YM_&Mg|2h@)L;2m^=@yj%cd+0Bq=I`Rl zXX6pnd%dWm96)XCI_juKF_KARoQ5vRBQD^xX2geI*2Okvf zh*f*Mxj8|9u(r}4tn^nqfnZ}zZMi=XJK$_f&S>okcZU1Ir^4M%dwX~6T1i{hfBQy~ AJOBUy delta 1254 zcmXZbT}YEr9LMpKn$vX7rI{?PP0gvjn7Ra47ZDUiu`X(Q(+H(S&CHrXVHfivqKi?~ zZh|Zr7(qsg3&JiEf}-pN8Yn^1gK;~VC-}L=Q+>+{Ljntz2|4oXsIpc zG{#)5H6|aESb)P=hL5cNx0dhGM*l2U;8%2`&1=j$tiw{=gLVv|1G_N?FQ6L-unUu3 z6I+@%r_PuXI*L#QRayG5ka#z$z=LSR5US8HcHkM*xR*$7GmUw;h%IQVH)bVn!(0rY z3JuoBj9E@2LWdtuV-XIc3VDp$iPz}EIV&!2Fs7Bb5jF8KEAB((yNB9=QBPz5ib-nVbeJa?gX!h`wP zfGW^u8S~R9pkoKB!u_bqJ5XB`MkVe?O%z9+=`~!9NmRmd)D}-*Hm30sPNVKhXjA5h z`%(F?;AX@557H>6;}xoq87uybZsOlqh%QEJ1zuF4O}HMnqYCOm6%s{V#`CCrH&Ek; zQ16de{p09he)Eimod;8>%I8p*>=SCm^Qg=D12s`zW2V0x2Z$?i72d{O_|SU(2Lr_a zFo=OInIjoOerA}zX683DG_*oTQ)UGfc!#(OmG}j&#gC{J|HTJb-JH2hX*@u@fEvG# zEAPZk)O&rXqr8q<*j?07jbO|{<0%bYk~Hd4eL!vDEb5H2xcY7ALM1qaS$G(0@QBra z5tT2F+POj8i%BfOZx~<3j$o0-wVI}-&+8_ifCh}Aj^H_Jf=OJ1Z%}9X1rrmVt%)(u q&QwdGy)<#$U6yKhx8*w9!_m%DXV3NaMvsP1o``gZQ@3h^#s2}MkCGw) diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.po b/amt/locale/nl_NL/LC_MESSAGES/messages.po index 19094a46..0a2fc46b 100644 --- a/amt/locale/nl_NL/LC_MESSAGES/messages.po +++ b/amt/locale/nl_NL/LC_MESSAGES/messages.po @@ -434,8 +434,8 @@ msgid "measure executed" msgstr "maatregelen uitgevoerd" #: amt/site/templates/algorithms/details_compliance.html.j2:69 -#: amt/site/templates/macros/editable.html.j2:67 -#: amt/site/templates/macros/editable.html.j2:72 +#: amt/site/templates/macros/editable.html.j2:68 +#: amt/site/templates/macros/editable.html.j2:73 #: amt/site/templates/macros/tasks.html.j2:82 msgid "Edit" msgstr "Bewerk" @@ -484,12 +484,12 @@ msgid "Read more on the algoritmekader" msgstr "Lees meer op het algoritmekader" #: amt/site/templates/algorithms/details_measure_modal.html.j2:64 -#: amt/site/templates/macros/editable.html.j2:174 +#: amt/site/templates/macros/editable.html.j2:175 msgid "Save" msgstr "Opslaan" #: amt/site/templates/algorithms/details_measure_modal.html.j2:68 -#: amt/site/templates/macros/editable.html.j2:179 +#: amt/site/templates/macros/editable.html.j2:180 #: amt/site/templates/organizations/parts/add_members_modal.html.j2:26 msgid "Cancel" msgstr "Annuleren" @@ -912,5 +912,5 @@ msgstr "Resultaten voor" #: amt/site/templates/parts/tasks_search.html.j2:50 msgid "Assignee" -msgstr "Verantwoordelijke" +msgstr "Toegewezen aan" diff --git a/amt/site/static/scss/layout.scss b/amt/site/static/scss/layout.scss index 99fced4f..042b1556 100644 --- a/amt/site/static/scss/layout.scss +++ b/amt/site/static/scss/layout.scss @@ -64,7 +64,7 @@ main { background-color: var(--rvo-color-lichtblauw-150); border-radius: 10px; height: calc(100% - 30px); /* todo (robbert): this is a display hack */ - padding: 0.01px; /* this is an avoid margin collapse hack */ + padding-top: 5px; } .progress-card-container { @@ -492,4 +492,12 @@ main { } } +.amt-editable-block:not(:has(form)) { + &:hover { + background-color: var(--rvo-color-grijs-100); + box-shadow: 0 0 5px 5px var(--rvo-color-grijs-100); + cursor: pointer; + } +} + /* stylelint-enable */ diff --git a/amt/site/static/ts/amt.ts b/amt/site/static/ts/amt.ts index 44a7bfde..d23129d1 100644 --- a/amt/site/static/ts/amt.ts +++ b/amt/site/static/ts/amt.ts @@ -53,6 +53,18 @@ function initPage() { "

Placeholder: Error while connecting to server { + if ((e.target as HTMLElement).classList.contains("amt-editable-block")) { + const linkEl = (e.target as HTMLElement)!.querySelectorAll( + ".amt-edit-link", + )[0]; + if (linkEl) { + (linkEl as HTMLElement).click(); + } + } + }); + const columns = document.getElementsByClassName( "progress-cards-container", ) as HTMLCollectionOf; diff --git a/amt/site/templates/macros/cards.html.j2 b/amt/site/templates/macros/cards.html.j2 index 7cd0ce0c..e9f150d2 100644 --- a/amt/site/templates/macros/cards.html.j2 +++ b/amt/site/templates/macros/cards.html.j2 @@ -16,19 +16,20 @@
{% if is_editable_resource(full_resource_path, editables) %} {{ editable(algorithm, relative_resource_path, full_resource_path) }} - {% endif %} - {% if value.__class__.__name__ == 'dict' %} - {% set value = value.items() %} - {% endif %} - {% for subkey, subvalue in value %} - {{ render_attribute(subkey) }}: - {% if is_editable_resource(full_resource_path + "/" + subkey, editables) %} - {{ editable(algorithm, relative_resource_path + "/" + subkey, full_resource_path + "/" + subkey) }} - {% else %} - {{ render_value(subkey, subvalue, depth+1, base_resource_path, path) }} + {% else %} + {% if value.__class__.__name__ == 'dict' %} + {% set value = value.items() %} {% endif %} - {% if not loop.last %}
{% endif %} - {% endfor %} + {% for subkey, subvalue in value %} + {{ render_attribute(subkey) }}: + {% if is_editable_resource(full_resource_path + "/" + subkey, editables) %} + {{ editable(algorithm, relative_resource_path + "/" + subkey, full_resource_path + "/" + subkey) }} + {% else %} + {{ render_value(subkey, subvalue, depth+1, base_resource_path, path) }} + {% endif %} + {% if not loop.last %}
{% endif %} + {% endfor %} + {% endif %}
{% elif isinstance(value, 'list') %} {% if key == "assessments" %} @@ -61,7 +62,7 @@ {% endif %} {% else %} {% if is_editable_resource(full_resource_path, editables) %} - {{ editable(algorithm, relative_resource_path, full_resource_path) }} +
{{ editable(algorithm, relative_resource_path, full_resource_path) }}
{% else %} {{ value }} {% endif %} diff --git a/amt/site/templates/macros/editable.html.j2 b/amt/site/templates/macros/editable.html.j2 index b1d5c376..c825346a 100644 --- a/amt/site/templates/macros/editable.html.j2 +++ b/amt/site/templates/macros/editable.html.j2 @@ -2,17 +2,15 @@ {{ attribute.capitalize().replace("_", " ") }} {%- endmacro %} {% macro editable(obj, relative_resource_path, full_resource_path, editable_object = None) %} - {# TODO: maybe editable self should contain the type of container?#} - {% if is_path_with_list(full_resource_path) %} - {# we know it is a list, but not what is in the list.. this now only works for editables with children #} + {% if is_parent_editable(editables, full_resource_path) %} {% if editable_object is none %} {% set editable_object = editables[replace_digits_in_brackets(full_resource_path)] %} {% endif %} -
+
{% if editable_object.children is not none and editable_object.children | length > 0 %} {% for child_editable in editable_object.children %} {{ render_attribute(child_editable.last_path_item() ) }}: - {{ nested_value(obj, resolve_resource_list_path(full_resource_path, child_editable.relative_resource_path) ) }} + {{ display_value(child_editable.last_path_item() , nested_value(obj, resolve_resource_list_path(full_resource_path, child_editable.relative_resource_path))) }} {% if not loop.last %}
{% endif %} {% endfor %} {% else %} @@ -21,7 +19,7 @@ {{ edit_link(base_href, full_resource_path) }}
{% else %} - +
{% if editable_object is not none %} {% set value = editable_object.value %} {% else %} @@ -36,30 +34,33 @@ {{ edit_link(base_href, full_resource_path) }} {% else %} - {% if key == "uri" or key == "link" or key == "upl" %} - {{ value }} - {% elif key == "oin" %} - {{ value }} - {% elif key == "email" %} - {{ value }} - {% elif key == "urn" %} - {{ value }} - {% elif value is string and value.startswith('http') %} - {{ value }} - {% else %} - {{ value }} - {% endif %} + {{ display_value(key, value) }} {{ edit_link(base_href, full_resource_path) }} {% endif %} - +
+ {% endif %} +{% endmacro %} +{% macro display_value(key, value) %} + {% if key == "uri" or key == "link" or key == "upl" %} + {{ value }} + {% elif key == "oin" %} + {{ value }} + {% elif key == "email" %} + {{ value }} + {% elif key == "urn" %} + {{ value }} + {% elif value is string and value.startswith('http') %} + {{ value }} + {% else %} + {{ value }} {% endif %} {% endmacro %} {% macro edit_link(base_href, full_resource_path) %} -
- {{ render_attribute(child_editable.last_path_item() ) }}: + {{ render_attribute(child_editable.last_path_item() ) }}:
{{ inline_editor_form_field(child_editable) }}