From 7721361433f0eb6e81951bd4ffecd49629c84065 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 8 Sep 2026 11:20:23 +0200 Subject: [PATCH 1/9] [NAE-2472] Menu Item improvements - fix cyclic path detection - remove URI destination fields from menu item creation form --- .../engine/menu/utils/MenuItemUtils.java | 5 +- .../engine-processes/menu/menu_item.xml | 43 -------------- .../engine/menu/MenuItemUtilsTest.java | 56 +++++++++++++++++++ 3 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 src/test/java/com/netgrif/application/engine/menu/MenuItemUtilsTest.java diff --git a/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java b/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java index b7b3107a8b..a899f69815 100644 --- a/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java +++ b/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java @@ -92,7 +92,10 @@ public static String findTaskIdInCase(Case useCase, String transId) { * */ public static boolean isCyclicNodePath(Case folderItem, String destUri) { String oldNodePath = (String) folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH); - return oldNodePath != null && destUri.contains(oldNodePath); + if (oldNodePath == null || destUri == null) { + return false; + } + return destUri.contains(oldNodePath + "/") || destUri.endsWith(oldNodePath); } /** diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 01b2dc56b0..f01ccc8a69 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -873,49 +873,6 @@ - - move_dest_uri - - editable - required - - - 0 - 1 - 1 - 2 - - outline - - - - move_dest_uri_new_node - - editable - - - 2 - 1 - 1 - 1 - - outline - - - - move_add_node - - editable - - - 3 - 1 - 1 - 1 - - outline - - configuration_templates diff --git a/src/test/java/com/netgrif/application/engine/menu/MenuItemUtilsTest.java b/src/test/java/com/netgrif/application/engine/menu/MenuItemUtilsTest.java new file mode 100644 index 0000000000..8f6cbd3899 --- /dev/null +++ b/src/test/java/com/netgrif/application/engine/menu/MenuItemUtilsTest.java @@ -0,0 +1,56 @@ +package com.netgrif.application.engine.menu; + +import com.netgrif.application.engine.menu.domain.MenuItemConstants; +import com.netgrif.application.engine.menu.utils.MenuItemUtils; +import com.netgrif.application.engine.workflow.domain.Case; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@SpringBootTest +@ActiveProfiles({"test"}) +@ExtendWith(SpringExtension.class) +public class MenuItemUtilsTest { + + @Test + public void testIsCyclicNodePath_withCyclicPath_returnsTrue() { + Case folderItem = mock(Case.class); + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn("/node1/node2"); + boolean result = MenuItemUtils.isCyclicNodePath(folderItem, "/node1/node2/node3"); + assertTrue(result); + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn("/node1/node2"); + result = MenuItemUtils.isCyclicNodePath(folderItem, "/node4/node1/node2/node3"); + assertTrue(result); + } + + @Test + public void testIsCyclicNodePath_withNonCyclicPath_returnsFalse() { + Case folderItem = mock(Case.class); + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn("/node1/node2"); + boolean result = MenuItemUtils.isCyclicNodePath(folderItem, "/node3/node4"); + assertFalse(result); + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn("/node1/node2"); + result = MenuItemUtils.isCyclicNodePath(folderItem, null); + assertFalse(result); + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn("/node1/node2"); + result = MenuItemUtils.isCyclicNodePath(folderItem, "/node1/node2_2/node3"); + assertFalse(result); + + + when(folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)).thenReturn(null); + result = MenuItemUtils.isCyclicNodePath(folderItem, "/node1/node2"); + assertFalse(result); + } + +} From bbe2a8f61aa253b4d37265193f9698ad26a5ed28 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 8 Sep 2026 11:43:44 +0200 Subject: [PATCH 2/9] [NAE-2472] Menu Item improvements - add ordering to configuration templates - make configuration template data field autocomplete --- .../menu/service/MenuItemTemplateHolder.java | 28 +++++++++++-------- .../engine-processes/menu/menu_item.xml | 3 ++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java index c3573264c2..8037e245da 100644 --- a/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java +++ b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java @@ -5,6 +5,7 @@ import com.netgrif.application.engine.menu.utils.MenuItemUtils; import com.netgrif.application.engine.petrinet.domain.I18nString; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -26,16 +27,19 @@ public class MenuItemTemplateHolder { * The key is the template identifier (String), and the value is the Template instance. *

*/ - private final static Map templates = Map.of( - TabbedCaseViewTemplate.IDENTIFIER, new TabbedCaseViewTemplate(), - TabbedTaskViewTemplate.IDENTIFIER, new TabbedTaskViewTemplate(), - SimpleCaseViewTemplate.IDENTIFIER, new SimpleCaseViewTemplate(), - SimpleTaskViewTemplate.IDENTIFIER, new SimpleTaskViewTemplate(), - SingleTaskViewTemplate.IDENTIFIER, new SingleTaskViewTemplate(), - TabbedTicketViewTemplate.IDENTIFIER, new TabbedTicketViewTemplate(), - CustomViewTemplate.IDENTIFIER, new CustomViewTemplate(), - FolderTemplate.IDENTIFIER, new FolderTemplate() - ); + private final static Map templates; + + static { + templates = new LinkedHashMap<>(); + templates.put(FolderTemplate.IDENTIFIER, new FolderTemplate()); + templates.put(TabbedCaseViewTemplate.IDENTIFIER, new TabbedCaseViewTemplate()); + templates.put(TabbedTaskViewTemplate.IDENTIFIER, new TabbedTaskViewTemplate()); + templates.put(SimpleCaseViewTemplate.IDENTIFIER, new SimpleCaseViewTemplate()); + templates.put(SimpleTaskViewTemplate.IDENTIFIER, new SimpleTaskViewTemplate()); + templates.put(SingleTaskViewTemplate.IDENTIFIER, new SingleTaskViewTemplate()); + templates.put(TabbedTicketViewTemplate.IDENTIFIER, new TabbedTicketViewTemplate()); + templates.put(CustomViewTemplate.IDENTIFIER, new CustomViewTemplate()); + } /** @@ -116,7 +120,9 @@ public static Map transformToOptions() { return templates.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, - entry -> entry.getValue().getName() + entry -> entry.getValue().getName(), + (a, b) -> a, + LinkedHashMap::new )); } } diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index f01ccc8a69..93bf8a640e 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -665,6 +665,9 @@ com.netgrif.application.engine.menu.service.MenuItemTemplateHolder.transformToOptions() + + autocomplete + From 1057128399dff2b4f0904123cc98736ebdddd5e8 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 8 Sep 2026 12:53:15 +0200 Subject: [PATCH 3/9] [NAE-2472] Menu Item improvements - update behavior logic and texts in menu item processes --- .../menu/case_view_configuration.xml | 49 +++++++++++++++---- .../engine-processes/menu/menu_item.xml | 28 +++++------ .../menu/task_view_configuration.xml | 1 - 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml b/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml index 77bf89b0f7..b56e6604b1 100644 --- a/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml +++ b/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml @@ -534,7 +534,7 @@ case_show_more_menu editable - +
1 0 @@ -562,7 +562,7 @@ case_empty_content_text editable - + 0 1 @@ -576,7 +576,7 @@ case_empty_content_icon editable - + 1 1 @@ -590,7 +590,7 @@ case_empty_content_icon_preview visible - + 2 1 @@ -604,7 +604,7 @@ case_all_allowed_nets editable - + 0 2 @@ -613,11 +613,25 @@ outline + + 0 + + + trans: t.this, + case_all_allowed_nets: f.case_all_allowed_nets, + case_allowed_nets: f.case_allowed_nets, + case_inherit_allowed_nets: f.case_inherit_allowed_nets; + + make [case_allowed_nets, case_inherit_allowed_nets], hidden on trans when { case_all_allowed_nets.value } + make [case_allowed_nets, case_inherit_allowed_nets], editable on trans when { !case_all_allowed_nets.value } + + +
case_allowed_nets - editable + hidden 1 @@ -631,8 +645,8 @@ case_inherit_allowed_nets - editable - + hidden + 2 2 @@ -828,6 +842,24 @@ outline + + 0 + + + trans: t.this, + show_create_case_button: f.show_create_case_button, + require_title_in_creation: f.require_title_in_creation, + create_case_button_title: f.create_case_button_title, + create_case_button_icon: f.create_case_button_icon, + create_case_button_icon_preview: f.create_case_button_icon_preview, + banned_nets_in_creation: f.banned_nets_in_creation; + + make [require_title_in_creation, create_case_button_title, create_case_button_icon, create_case_button_icon_preview, banned_nets_in_creation], hidden on trans when { !show_create_case_button.value } + make [require_title_in_creation, create_case_button_title, create_case_button_icon, banned_nets_in_creation], editable on trans when { show_create_case_button.value } + make create_case_button_icon_preview, visible on trans when { show_create_case_button.value } + + + require_title_in_creation @@ -1063,7 +1095,6 @@ case_headers_sort_mode_active editable - required 0 diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 93bf8a640e..6426ae1b4f 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -299,7 +299,7 @@ menu_icon Menu icon identifier - Material icon identifier. List of icons with identifiers is available online. + Material icon identifier icon: f.this, iconPreview: f.menu_icon_preview; @@ -326,7 +326,6 @@ menu_name_as_visible Name of the item - Will be shown in the menu autocomplete @@ -334,7 +333,6 @@ menu_name Name of the item - Will be shown in the menu menu_name_as_visible: f.menu_name_as_visible, name: f.menu_name; @@ -502,7 +500,7 @@ tab_icon Tab icon identifier - Material icon identifier. List of icons with identifiers is available online. + Material icon identifier icon: f.this, iconPreview: f.tab_icon_preview; @@ -674,7 +672,7 @@ Náhľad ikony Identifikátor ikony - Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. + Identifikátor Material ikony. Pridaj k povoleným roliam Odstráň z povolených rolí Pridaj k zakázaným roliam @@ -687,9 +685,8 @@ Identifikátor duplikovanej položky Musí byť jedinečný Názov položky - Bude zobrazený v menu Identifikátor ikony v karte - Identifikátor Material ikony. Zoznam ikon s identifikátormi je dostupný online. + Identifikátor Material ikony. Náhľad ikony v karte Zobraziť ikonu v karte? Názov položky @@ -722,14 +719,14 @@ Zoradiť pod-položky Vytvoriť menu položku Konfiguračná šablóna - Rola - Zobrazenie + Povolenia + Zobrazenie v karte Menu položka Ikonevorschau Ikone ID - Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. + Material Ikone ID Zu zulässigen Rollen hinzufügen Aus zulässigen Rollen entfernen Zu verbotenen Rollen hinzufügen @@ -737,7 +734,7 @@ Ihre Prozesse Wählen Sie einen Prozess mit Rollen aus, die Sie zu Listen mit zulässigen oder verbotenen Rollen hinzufügen möchten. Verfügbare Rollen - Material Ikone ID. Liste den Ikonen mit IDs ist online verfügbar. + Material Ikone ID Beispiel: "demo-tabbed-views" Rollen Zulässige Rollen @@ -750,7 +747,6 @@ Identifikator der kopierten Ansicht Muss einzigartig sein Titel des Eintrages - Wird im Menü angezeigt Ikonen Identifikator der Registerkarte Vorschau der Registerkarte Ikone Zeige die Registerkarte Ikone an? @@ -777,8 +773,8 @@ Untereintrage sortieren Erstellen Konfigurationsvorlage - Rolle - Ansicht + Berechtigungen + Ansicht der Registerkarte Menüeintrag @@ -1455,7 +1451,7 @@ role_settings 400 48 - + person auto @@ -1626,7 +1622,7 @@ view_settings 528 48 - + image auto diff --git a/src/main/resources/petriNets/engine-processes/menu/task_view_configuration.xml b/src/main/resources/petriNets/engine-processes/menu/task_view_configuration.xml index 0b1ea4c7be..37b6906162 100644 --- a/src/main/resources/petriNets/engine-processes/menu/task_view_configuration.xml +++ b/src/main/resources/petriNets/engine-processes/menu/task_view_configuration.xml @@ -706,7 +706,6 @@ task_headers_sort_mode_active editable - required 0 From e3bb987e32a26d10d6d829609f45d81a859260cf Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 8 Sep 2026 19:31:04 +0200 Subject: [PATCH 4/9] [NAE-2472] Menu Item improvements - add info text for item ordering --- .../engine-processes/menu/menu_item.xml | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 6426ae1b4f..6113b07d91 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -256,6 +256,20 @@ childItemForms </data> + <data type="i18n"> + <id>empty_child_items_info</id> + <title/> + <init dynamic="true"> + new com.netgrif.application.engine.petrinet.domain.I18nString("This menu item has no child items to order.", + [sk: "Táto menu položka neobsahuje žiadnu položku na zoradenie", de: "Zu diesem Menüpunkt gibt es keine Untergerichte."]) + </init> + <component> + <name>text</name> + <property key="plainText">true</property> + <property key="fontSize">20</property> + <property key="boldText">true</property> + </component> + </data> <data type="boolean" immediate="true"> <id>is_folder</id> <title/> @@ -1299,30 +1313,53 @@ </roleRef> <dataGroup> <id>children_order_0</id> - <cols>4</cols> + <cols>3</cols> <layout>grid</layout> + <dataRef> + <id>empty_child_items_info</id> + <logic> + <behavior>hidden</behavior> + </logic> + <layout> + <x>1</x> + <y>0</y> + <rows>1</rows> + <cols>1</cols> + <template>material</template> + <appearance>outline</appearance> + </layout> + </dataRef> <dataRef> <id>childItemForms</id> <logic> <behavior>editable</behavior> - <action trigger="get"> - forms: f.childItemForms, - ids: f.childItemIds; - - def orderedTaskIds = ids.value?.collect { id -> workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } - change forms value { orderedTaskIds } - </action> </logic> <layout> <x>0</x> - <y>0</y> + <y>1</y> <rows>1</rows> - <cols>4</cols> + <cols>3</cols> <template>material</template> <appearance>outline</appearance> </layout> </dataRef> </dataGroup> + <event type="assign"> + <id>assign</id> + <actions phase="pre"> + <action> + trans: t.this, + empty_child_items_info: f.empty_child_items_info, + forms: f.childItemForms, + ids: f.childItemIds; + + def orderedTaskIds = ids.value?.collect { id -> workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } + make empty_child_items_info, visible on trans when { orderedTaskIds.isEmpty() } + make empty_child_items_info, hidden on trans when { !orderedTaskIds.isEmpty() } + change forms value { orderedTaskIds } + </action> + </actions> + </event> </transition> <transition> <id>row_for_ordering</id> From 0df35df4e198853c40afacd54c9057e2d111c49f Mon Sep 17 00:00:00 2001 From: chvostek <chvostek@netgrif.com> Date: Tue, 8 Sep 2026 19:43:16 +0200 Subject: [PATCH 5/9] [NAE-2472] Menu Item improvements - improve form of duplicate menu item --- .../engine-processes/menu/menu_item.xml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 6113b07d91..a51906fa9c 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -1264,6 +1264,28 @@ <template>material</template> <appearance>outline</appearance> </layout> + <event type="set"> + <id>0</id> + <actions phase="post"> + <action> + duplicate_view_identifier: f.duplicate_view_identifier, + duplicate_new_title: f.duplicate_new_title; + + if (duplicate_view_identifier.value != null && !duplicate_view_identifier.value.isEmpty() + || duplicate_new_title.value == null) { + return + } + + String defaultName = duplicate_new_title.value.defaultValue + if (defaultName == null || defaultName.isEmpty()) { + defaultName = menu_name.value.translations?.values()?.find() + } + + String identifier = com.netgrif.application.engine.menu.utils.MenuItemUtils.sanitize(defaultName) + change duplicate_view_identifier value { identifier } + </action> + </actions> + </event> </dataRef> <dataRef> <id>duplicate_view_identifier</id> @@ -1279,6 +1301,27 @@ <template>material</template> <appearance>outline</appearance> </layout> + <event type="set"> + <id>0</id> + <actions phase="post"> + <action> + duplicate_view_identifier: f.duplicate_view_identifier; + + if (menuItemService.existsMenuItem(duplicate_view_identifier.value)) { + change duplicate_view_identifier validations { validation('''regex $.^''', + new com.netgrif.application.engine.petrinet.domain.I18nString("Such menu item already exists", + [sk: "Taká položka menu už existuje", de: "Ein solcher Menüeintrag existiert bereits"])) + } + } else { + change duplicate_view_identifier validations { null } + String sanitizedIdentifier = com.netgrif.application.engine.menu.utils.MenuItemUtils.sanitize(duplicate_view_identifier.value) + if (duplicate_view_identifier.value != sanitizedIdentifier) { + change duplicate_view_identifier value { sanitizedIdentifier } + } + } + </action> + </actions> + </event> </dataRef> </dataGroup> <event type="finish"> @@ -1289,6 +1332,7 @@ title: f.duplicate_new_title; duplicateMenuItem(useCase, title.value, identifier.value) + Frontend.reloadMenu() </action> </actions> <title name="duplicate_item_finish">Duplicate From 3ff4ad0a156b3373ed69803b1eebbc0bf5afa90c Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 8 Sep 2026 19:47:05 +0200 Subject: [PATCH 6/9] [NAE-2472] Menu Item improvements - add icon configuration when creating item --- .../engine-processes/menu/menu_item.xml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index a51906fa9c..431fb43446 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -901,6 +901,34 @@ outline + + menu_icon + + editable + + + 0 + 3 + 1 + 2 + + outline + + + + menu_icon_preview + + visible + + + 2 + 3 + 1 + 2 + + standard + + assign From a20a434da361e0a3f05a8771f33633344d5e23d7 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 9 Sep 2026 10:21:36 +0200 Subject: [PATCH 7/9] [NAE-2472] Menu Item improvements - add authority configuration to menu item --- .../engine/menu/domain/MenuItemBody.java | 6 +-- .../engine/menu/domain/MenuItemConstants.java | 1 + .../engine-processes/menu/menu_item.xml | 54 +++++++++++++++---- .../engine/menu/MenuItemServiceTest.java | 1 + 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java index ea8ef6dd76..3d42b8da67 100644 --- a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java +++ b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java @@ -10,9 +10,7 @@ import lombok.Data; import lombok.NoArgsConstructor; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Class, that holds configurable attributes of menu item. @@ -26,6 +24,7 @@ public class MenuItemBody { private String menuIcon = "filter_none"; private I18nString menuName; + private List allowedAuthorities = List.of("ROLE_USER"); private Map allowedRoles = new HashMap<>(); private Map bannedRoles = new HashMap<>(); private boolean useCustomView = false; @@ -198,6 +197,7 @@ public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCas outcome.putDataSetEntry(MenuItemConstants.FIELD_CUSTOM_VIEW_SELECTOR, FieldType.TEXT, this.customViewSelector); outcome.putDataSetEntry(MenuItemConstants.FIELD_IS_AUTO_SELECT, FieldType.BOOLEAN, this.isAutoSelect); + outcome.putDataSetEntry(MenuItemConstants.FIELD_ALLOWED_AUTHORITIES, FieldType.MULTICHOICE_MAP, this.allowedAuthorities); outcome.putDataSetEntryOptions(MenuItemConstants.FIELD_ALLOWED_ROLES, FieldType.MULTICHOICE_MAP, this.allowedRoles); outcome.putDataSetEntryOptions(MenuItemConstants.FIELD_BANNED_ROLES, FieldType.MULTICHOICE_MAP, this.bannedRoles); outcome.putDataSetEntry(MenuItemConstants.FIELD_CONFIGURATION_TEMPLATES, FieldType.ENUMERATION_MAP, this.configurationTemplateIdentifier); diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java index c4ab1f141c..895f7fc55c 100644 --- a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java +++ b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java @@ -9,6 +9,7 @@ public class MenuItemConstants { public static final String FIELD_IS_FOLDER = "is_folder"; public static final String FIELD_IDENTIFIER = "menu_item_identifier"; public static final String FIELD_APPEND_MENU_ITEM = "append_menu_item_stringId"; + public static final String FIELD_ALLOWED_AUTHORITIES = "allowed_authorities"; public static final String FIELD_ALLOWED_ROLES = "allowed_roles"; public static final String FIELD_BANNED_ROLES = "banned_roles"; public static final String FIELD_MENU_NAME = "menu_name"; diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 431fb43446..5d46b61d60 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -469,6 +469,17 @@ [:] + + allowed_authorities + Allowed authorities + todo 2472 + + + + + + user + use_custom_view Use custom view? @@ -736,6 +747,11 @@ Povolenia Zobrazenie v karte Menu položka + todo 2472 + todo 2472 + todo 2472 + todo 2472 + todo 2472 Ikonevorschau @@ -790,6 +806,11 @@ Berechtigungen Ansicht der Registerkarte Menüeintrag + todo 2472 + todo 2472 + todo 2472 + todo 2472 + todo 2472 @@ -1580,13 +1601,28 @@ 3 grid - processes_available + allowed_authorities editable 0 0 + 1 + 3 + 0 + + outline + + + + processes_available + + editable + + + 0 + 1 2 1 0 @@ -1601,7 +1637,7 @@ 1 - 0 + 1 2 1 0 @@ -1616,7 +1652,7 @@ 2 - 0 + 1 1 1 0 @@ -1630,7 +1666,7 @@ 2 - 1 + 2 1 1 0 @@ -1644,7 +1680,7 @@ 0 - 2 + 3 1 3 0 @@ -1658,7 +1694,7 @@ 0 - 3 + 4 1 2 0 @@ -1673,7 +1709,7 @@ 2 - 3 + 4 1 1 0 @@ -1687,7 +1723,7 @@ 0 - 4 + 5 1 2 0 @@ -1702,7 +1738,7 @@ 2 - 4 + 5 1 1 0 diff --git a/src/test/java/com/netgrif/application/engine/menu/MenuItemServiceTest.java b/src/test/java/com/netgrif/application/engine/menu/MenuItemServiceTest.java index 1f18dc3f42..d7ba08735d 100644 --- a/src/test/java/com/netgrif/application/engine/menu/MenuItemServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/menu/MenuItemServiceTest.java @@ -135,6 +135,7 @@ private void createByTemplateAndAssert(MenuItemBody menuItemBody) throws Transit assertEquals(menuItemBody.isUseTabbedView(), menuItemCase.getFieldValue(MenuItemConstants.FIELD_USE_TABBED_VIEW)); assertEquals(menuItemBody.isUseCustomView(), menuItemCase.getFieldValue(MenuItemConstants.FIELD_USE_CUSTOM_VIEW)); assertEquals(menuItemBody.getConfigurationTemplateIdentifier(), menuItemCase.getFieldValue(MenuItemConstants.FIELD_CONFIGURATION_TEMPLATES)); + assertEquals(List.of("ROLE_USER"), menuItemCase.getFieldValue(MenuItemConstants.FIELD_ALLOWED_AUTHORITIES)); assertEquals((menuItemBody.getUri() + uriService.getUriSeparator() + menuItemBody.getIdentifier()).replaceAll("//", uriService.getUriSeparator()), menuItemCase.getFieldValue(MenuItemConstants.FIELD_NODE_PATH)); From cf551d963d4eda9b843d154d70049b9abf3fc680 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 9 Sep 2026 10:25:40 +0200 Subject: [PATCH 8/9] [NAE-2472] Menu Item improvements - add translations --- .../engine-processes/menu/menu_item.xml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 5d46b61d60..5a9a15a616 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -472,7 +472,6 @@ allowed_authorities Allowed authorities - todo 2472 @@ -747,11 +746,10 @@ Povolenia Zobrazenie v karte Menu položka - todo 2472 - todo 2472 - todo 2472 - todo 2472 - todo 2472 + Povolené autority + Používateľ + Admin + Anonymný používateľ Ikonevorschau @@ -806,11 +804,10 @@ Berechtigungen Ansicht der Registerkarte Menüeintrag - todo 2472 - todo 2472 - todo 2472 - todo 2472 - todo 2472 + Zulässige Behörden + Benutzer + Admin + Anonymer Nutzer From 56a8bd15b96aab21d19260b440de0cf5ca780fe9 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 9 Sep 2026 11:39:56 +0200 Subject: [PATCH 9/9] [NAE-2472] Menu Item improvements - resolve PR comments --- .../menu/case_view_configuration.xml | 64 +++++++++---------- .../engine-processes/menu/menu_item.xml | 6 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml b/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml index b56e6604b1..2329ace50e 100644 --- a/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml +++ b/src/main/resources/petriNets/engine-processes/menu/case_view_configuration.xml @@ -155,6 +155,24 @@ show_create_case_button Show create case button? true + + 0 + + + trans: t.create_case_btn_settings, + show_create_case_button: f.show_create_case_button, + require_title_in_creation: f.require_title_in_creation, + create_case_button_title: f.create_case_button_title, + create_case_button_icon: f.create_case_button_icon, + create_case_button_icon_preview: f.create_case_button_icon_preview, + banned_nets_in_creation: f.banned_nets_in_creation; + + make [require_title_in_creation, create_case_button_title, create_case_button_icon, create_case_button_icon_preview, banned_nets_in_creation], hidden on trans when { !show_create_case_button.value } + make [require_title_in_creation, create_case_button_title, create_case_button_icon, banned_nets_in_creation], editable on trans when { show_create_case_button.value } + make create_case_button_icon_preview, visible on trans when { show_create_case_button.value } + + + require_title_in_creation @@ -351,6 +369,20 @@ case_all_allowed_nets All allowed nets? true + + 0 + + + trans: t.settings, + case_all_allowed_nets: f.case_all_allowed_nets, + case_allowed_nets: f.case_allowed_nets, + case_inherit_allowed_nets: f.case_inherit_allowed_nets; + + make [case_allowed_nets, case_inherit_allowed_nets], hidden on trans when { case_all_allowed_nets.value } + make [case_allowed_nets, case_inherit_allowed_nets], editable on trans when { !case_all_allowed_nets.value } + + + case_inherit_allowed_nets @@ -613,20 +645,6 @@ outline - - 0 - - - trans: t.this, - case_all_allowed_nets: f.case_all_allowed_nets, - case_allowed_nets: f.case_allowed_nets, - case_inherit_allowed_nets: f.case_inherit_allowed_nets; - - make [case_allowed_nets, case_inherit_allowed_nets], hidden on trans when { case_all_allowed_nets.value } - make [case_allowed_nets, case_inherit_allowed_nets], editable on trans when { !case_all_allowed_nets.value } - - - case_allowed_nets @@ -842,24 +860,6 @@ outline - - 0 - - - trans: t.this, - show_create_case_button: f.show_create_case_button, - require_title_in_creation: f.require_title_in_creation, - create_case_button_title: f.create_case_button_title, - create_case_button_icon: f.create_case_button_icon, - create_case_button_icon_preview: f.create_case_button_icon_preview, - banned_nets_in_creation: f.banned_nets_in_creation; - - make [require_title_in_creation, create_case_button_title, create_case_button_icon, create_case_button_icon_preview, banned_nets_in_creation], hidden on trans when { !show_create_case_button.value } - make [require_title_in_creation, create_case_button_title, create_case_button_icon, banned_nets_in_creation], editable on trans when { show_create_case_button.value } - make create_case_button_icon_preview, visible on trans when { show_create_case_button.value } - - - require_title_in_creation diff --git a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml index 5a9a15a616..3102eb6243 100644 --- a/src/main/resources/petriNets/engine-processes/menu/menu_item.xml +++ b/src/main/resources/petriNets/engine-processes/menu/menu_item.xml @@ -477,7 +477,7 @@ - user + ROLE_USER use_custom_view @@ -1324,7 +1324,7 @@ String defaultName = duplicate_new_title.value.defaultValue if (defaultName == null || defaultName.isEmpty()) { - defaultName = menu_name.value.translations?.values()?.find() + defaultName = duplicate_new_title.value.translations?.values()?.find() } String identifier = com.netgrif.application.engine.menu.utils.MenuItemUtils.sanitize(defaultName) @@ -1443,7 +1443,7 @@ forms: f.childItemForms, ids: f.childItemIds; - def orderedTaskIds = ids.value?.collect { id -> workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } + def orderedTaskIds = ids.value?.collect { id -> workflowService.findOne(id).tasks.find { it.transition == "row_for_ordering" }.task } ?: [] make empty_child_items_info, visible on trans when { orderedTaskIds.isEmpty() } make empty_child_items_info, hidden on trans when { !orderedTaskIds.isEmpty() } change forms value { orderedTaskIds }