Skip to content

Conversation

@martinkranec
Copy link
Contributor

@martinkranec martinkranec commented Jul 26, 2025

Description

Implements NAE-2147

Dependencies

Third party dependencies

No new dependencies were introduced

Blocking Pull requests

There are no dependencies on other PR

How Has Been This Tested?

Manually

Name Tested on
OS Windows 11
Runtime Java 21
Dependency Manager Maven 3.9.9
Framework version Spring Boot 3.4.4
Run parameters
Other configuration

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes have been checked, personally or remotely, with @...
  • I have commented my code, particularly in hard-to-understand areas
  • I have resolved all conflicts with the target branch of the PR
  • I have updated and synced my code with the target branch
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes:
    • Lint test
    • Unit tests
    • Integration tests
  • I have checked my contribution with code analysis tools:
  • I have made corresponding changes to the documentation:
    • Developer documentation
    • User Guides
    • Migration Guides

Summary by CodeRabbit

  • New Features

    • Introduced a configurable Welcome dashboard, dashboard item management, and dashboard management features.
    • Added support for new menu item and tabbed view configurations, including case, task, ticket, and single task views.
    • Enabled advanced dashboard and menu item creation, linking, and search capabilities.
    • Provided new REST API endpoint for Petri net search with enhanced filtering.
  • Improvements

    • Refined menu item and dashboard configuration with more flexible role and view management.
    • Enhanced localization and UI customization for dashboards and menu items.
  • Bug Fixes

    • Corrected changelog links and improved test validations for menu item operations.
  • Chores

    • Updated application configuration to enable dashboard features by default in development.
    • Improved internal logging and configuration management.
  • Documentation

    • Updated changelog to reflect new features and changes.
  • Tests

    • Added and updated tests for dashboard and menu item management features.

machacjozef and others added 30 commits January 9, 2025 14:56
- implement auto-select for menu items
- create processes for managing dashboards - dashboard_management and dashboard_item
- create runner for importing dashboard management processes
- added option to load icon from web (image from web)
- added option to change dashboard toolbar logo
- added option to chane appearance of dashboard toolbar
- added option to change icon and font colors in dashboard items
- fix for items ordering
…temoch

- fix ActionDelegate.execute method
- update ActionDelegate menu item methods
- import configuration nets in FilterRunner
- implement MenuItemService with new or updated domain models
- move menu item domain models to menu package
- implement MenuItemView enum
- implement MenuItemUtils
- rename preference_item to menu_item
- add tabbed_case_view_configuration and tabbed_task_view_configuration nets
- update MenuItemApiTest according to changes
- remove redundant MenuItemBody attribute
- update menu_item and tabbed_case_view_configuration dataGroups
- update MenuItemService find methods
- fix MenuItemApiTest.testDuplicateMenuItem
- add option to change profile and login urls
- implement TabbedTicketView configuration
- implement TabbedSingleTaskView configuration
- fix missing entry in ViewBody
- fix method call in tabbed_case_view_configuration
- change default value of login url to empty string
- update by PR comments
- create findCasesElastic method in ActionDelegate with default page size of 1000 items
- check duplicate ids in dashboard_item and dashboard_management in finish action
- move importProcess function into ImportHelper and clean runners
- fix setting view_configuration_type
- implement basic elastic search for title and identifier to ElasticPetriNetService and implement endpoint for elastic search
- change default page size to 100 in findCasesElastic
- resolve PR comments
- add MenuItemView.isPrimary attribute
- fix options initializing in configuration
# Conflicts:
#	src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy
- fix after merge
@coderabbitai coderabbitai bot added the Large label Jul 28, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 45

🔭 Outside diff range comments (3)
application-engine/src/main/resources/application.yaml (1)

161-163: Ensure netgrif.engine.actions.imports is bound and use YAML list syntax

It looks like your ActionsProperties class is annotated with @ConfigurationProperties(prefix = "netgrif.engine.actions"), but in application.yaml you have:

• application-engine/src/main/resources/application.yaml (around line 161)

actions:
  imports: com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody,com.netgrif.application.engine.objects.petrinet.domain.I18nString,com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody

Because this lives at the root actions key—not under netgrif.engine.actions—Spring won’t bind it. Also, storing multiple imports as one comma-separated string works by convention but can break if any value contains commas or extra whitespace.

Recommended fix:

• Nest under the netgrif.engine hierarchy to match your prefix
• Switch to YAML list syntax for clarity and safety

netgrif:
  engine:
    actions:
      imports:
        - com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody
        - com.netgrif.application.engine.objects.petrinet.domain.I18nString
        - com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2)

202-244: Fix inconsistent constants usage in move item test.

The test mixes old and new constants format inconsistently, which could lead to test failures.

Apply this diff to fix the inconsistent constants:

-        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]
+        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.${MenuItemConstants.FIELD_NODE_PATH}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]

-        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList<String>
+        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS].value as ArrayList<String>

202-205: Fix inconsistent constant usage in test.

The test is using old constants PREFERRED_ITEM_NET_IDENTIFIER and PREFERENCE_ITEM_FIELD_* instead of the new constants that are used elsewhere in the test. This inconsistency could cause test failures.

Apply this diff to use consistent constants:

-        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]
-
-        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList<String>
+        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.${MenuItemConstants.FIELD_NODE_PATH}.textValue.keyword:\"/netgrif2\"", PageRequest.of(0, 1))[0]
+
+        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS].value as ArrayList<String>
♻️ Duplicate comments (3)
application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (2)

693-696: Same query injection vulnerability as in line 49.

This elastic search query has the same injection vulnerability. Apply the same escaping solution here.


682-701: Same injection vulnerability in finish validation.

The elastic query on line 693 has the same string concatenation vulnerability as noted in the earlier comment.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

223-225: Query injection vulnerability in findFolderCase.

The path parameter needs escaping.

🧹 Nitpick comments (29)
application-engine/CHANGELOG.md (1)

21-21: Wrong “Full Changelog” link inside 6.5.0 entry

The link on this line points to v7.0.0, but it sits in the 6.5.0 section. Replace it with the correct v6.5.0 URL (or remove the duplicate link at the top of the file).

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

1-5: Mark constants holder as final and block instantiation

For consistency with other constant classes, declare the class final and add a private constructor.

-public class TabbedTicketViewConstants extends ViewConstants {
-}
+public final class TabbedTicketViewConstants extends ViewConstants {
+
+    private TabbedTicketViewConstants() {
+        // constants class – prevent instantiation
+    }
+}
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

4-6: Apply the usual constants-class pattern

Same comment as above: make the class final and add a private constructor.

-public class TabbedSingleTaskViewConstants extends ViewConstants {
-    public static final String FIELD_TRANSITION_ID = "transition_id";
-}
+public final class TabbedSingleTaskViewConstants extends ViewConstants {
+
+    public static final String FIELD_TRANSITION_ID = "transition_id";
+
+    private TabbedSingleTaskViewConstants() {
+    }
+}
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (2)

15-16: Remove unused imports.

The HashSet and Set imports are not used anywhere in the code and should be removed to maintain clean code standards.

-import java.util.HashSet;
-import java.util.Set;

56-56: Consider applying transformation consistency in update method.

The update method directly assigns the title from another ElasticPetriNet without transformation, while the constructor uses transformToField. This asymmetry could lead to inconsistencies if the input ElasticPetriNet has a different I18nField structure.

Consider whether the update method should also apply transformation or if direct assignment is intentional because both objects are already ElasticPetriNet instances with I18nField titles.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

3-3: Remove unused Lombok import.

The @Getter annotation from Lombok is imported but not used in this constants class.

-import lombok.Getter;
application-engine/src/test/resources/dashboard_management_test.xml (1)

38-40: Remove redundant property setting.

The dashboardItemBody.setMenuItems(menuItem.stringId) on line 39 is redundant because the menuItem.stringId was already passed as the second parameter to the DashboardItemBody constructor on line 38, which likely sets the same property.

 def dashboardItemBody = new com.netgrif.application.engine.menu.domain.dashboard.DashboardItemBody("main", menuItem.stringId, "apps", new com.netgrif.application.engine.petrinet.domain.I18nString("Main"), true)
-dashboardItemBody.setMenuItems(menuItem.stringId)
 dashboardItemBody.setActive(true)
application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1)

249-263: Improve variable naming and consider minor optimizations.

The method centralizes Petri net import logic effectively and follows established patterns. However, there are a few areas for improvement:

  1. The variable filter should be renamed to something more generic like existingNet since this method is used for importing various types of processes, not just filters.
  2. The system user transformation happens twice - consider extracting it to a variable for efficiency.
 Optional<PetriNet> importProcess(String message, String netIdentifier, String netFileName) {
-    PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier)
-    if (filter != null) {
+    PetriNet existingNet = petriNetService.getNewestVersionByIdentifier(netIdentifier)
+    if (existingNet != null) {
         log.info("${message} has already been imported.")
-        return Optional.of(filter)
+        return Optional.of(existingNet)
     }

-    Optional<PetriNet> filterNet = this.createNet(netFileName, VersionType.MAJOR, userService.getSystem().transformToLoggedUser())
+    LoggedUser systemUser = userService.transformToLoggedUser(userService.getSystem())
+    Optional<PetriNet> filterNet = this.createNet(netFileName, VersionType.MAJOR, systemUser)

-    if (!filterNet.isPresent()) {
+    if (!filterNet.isPresent()) {
         log.error("Import of ${message} failed!")
     }

     return filterNet
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (1)

44-74: Consider null safety improvement in defaultHeaders serialization.

The serialization logic is well-implemented, but line 67 could be enhanced for better null safety:

 outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_DEFAULT_HEADERS, FieldType.TEXT,
-        this.defaultHeaders != null ? String.join(",", this.defaultHeaders) : null);
+        this.defaultHeaders != null && !this.defaultHeaders.isEmpty() 
+            ? this.defaultHeaders.stream().filter(Objects::nonNull).collect(Collectors.joining(","))
+            : null);

This prevents potential issues if the list contains null elements.

Add this import at the top:

+import java.util.Objects;
+import java.util.stream.Collectors;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (3)

14-21: Consider defensive copying in the all-args constructor

The @AllArgsConstructor allows passing any Map implementation, which could lead to issues if an immutable map is passed and later methods try to modify it. Consider creating a defensive copy or documenting that the passed map will be modified.

 @Data
-@AllArgsConstructor
 public class ToDataSetOutcome {
     private Map<String, Map<String, Object>> dataSet;
 
     public ToDataSetOutcome() {
         this.dataSet = new HashMap<>();
     }
+
+    public ToDataSetOutcome(Map<String, Map<String, Object>> dataSet) {
+        this.dataSet = new HashMap<>(dataSet);
+    }

26-30: Fix javadoc parameter description

The javadoc mentions "importId" but the parameter is named "fieldId". Update for consistency.

     /**
      * Puts provided value into {@link #dataSet} according to dataSet rules.
      *
-     * @param fieldId importId of the field
+     * @param fieldId identifier of the field
      * @param fieldType type of the field
      * @param fieldValue new value of the field
      * */

41-44: Fix javadoc parameter description

Same issue as above - the javadoc mentions "importId" but the parameter is named "fieldId".

     /**
      * Puts provided options into {@link #dataSet} according to dataSet rules.
      *
-     * @param fieldId importId of the field
+     * @param fieldId identifier of the field
      * @param fieldType type of the field
      * @param options new options of the field
      * */
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1)

28-33: Consider externalizing translations and adding error handling

While the implementation is functional, consider:

  1. Moving translations to property files for better maintainability
  2. Adding error handling for the service call
  3. Using explicit return type instead of def for better type safety
-    def createMainDashboardManagementItem() {
+    Case createMainDashboardManagementItem() {
         def dashboardItemBody = new DashboardManagementBody("main_dashboard", new I18nString("Main Dashboard",Map.of("sk","Hlavný Dashboard","de","Haupt-Dashboard")))
         dashboardItemBody.setLogoutDashboard(true)
 
-        return dashboardManagementService.createDashboardManagement(dashboardItemBody)
+        try {
+            return dashboardManagementService.createDashboardManagement(dashboardItemBody)
+        } catch (Exception e) {
+            log.error("Failed to create main dashboard", e)
+            throw new RuntimeException("Failed to create main dashboard", e)
+        }
     }
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1)

105-106: Consider type-safe approach for the unchecked cast

The unchecked cast (Map) could lead to ClassCastException at runtime. Consider adding type validation or using a more type-safe approach.

     @SuppressWarnings({"unchecked", "rawtypes"})
     protected Case setDataWithExecute(Case useCase, String transId, Map<String, Map<String, Object>> dataSet) throws TransitionNotExecutableException {
+        // Validate the structure before casting
+        if (dataSet != null && !dataSet.isEmpty()) {
+            // Ensure all values are Maps
+            for (Map.Entry<String, Map<String, Object>> entry : dataSet.entrySet()) {
+                if (!(entry.getValue() instanceof Map)) {
+                    throw new IllegalArgumentException("Invalid dataset structure");
+                }
+            }
+        }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (2)

52-59: Include identifier in exception message for better debugging

When throwing IllegalArgumentException, include the invalid identifier to help with debugging.

     public static MenuItemView fromIdentifier(String identifier) {
         for (MenuItemView view : MenuItemView.values()) {
             if (view.identifier.equals(identifier)) {
                 return view;
             }
         }
-        throw new IllegalArgumentException(identifier);
+        throw new IllegalArgumentException("Unknown MenuItemView identifier: " + identifier);
     }

75-89: Document potential exception in javadoc

The method can throw IllegalArgumentException if parentIdentifier is invalid. This should be documented in the javadoc.

     /**
      * Finds all enum values, that are tabbed or non-tabbed and are defined in parent view as {@link #allowedAssociatedViews}
      *
      * @param isTabbed if true, set of views is reduced to only tabbed views
      * @param parentIdentifier identifier of the view, that contains returned views in {@link #allowedAssociatedViews}
      *
      * @return List of views based on {@link #isTabbed} and {@link #allowedAssociatedViews}
+     * @throws IllegalArgumentException if parentIdentifier is not a valid view identifier
      * */
application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (1)

142-187: Consider adding inline documentation for complex conditional logic

The conditional logic for internal vs external items is complex but correct. Consider adding comments to improve maintainability.

Add clarifying comments:

 <action>
+    // Reset external icon when switching modes
     change external_icon value { false }
     if (is_internal.value) {
+        // Internal mode: reset menu items list
         change menu_items_list value { "" }
     } else {
+        // External mode: reset internal-specific fields
         change item_icon value { "" }
         change item_name value { new com.netgrif.application.engine.objects.petrinet.domain.I18nString("") }
         change external_url value { "" }
     }
 </action>
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

63-67: Extract magic string to constant

The hardcoded "_configuration" suffix should be defined as a constant for maintainability.

+private static final String CONFIGURATION_SUFFIX = "_configuration";
+
 default Map<String, I18nString> getAvailableViewsAsOptions(boolean isTabbed, String viewIdentifier) {
-    int index = viewIdentifier.lastIndexOf("_configuration");
+    int index = viewIdentifier.lastIndexOf(CONFIGURATION_SUFFIX);
     if (index > 0) {
         viewIdentifier = viewIdentifier.substring(0, index);
     }
application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1)

42-67: Confirm definition of findFilters and simplify complex logic

It looks like findFilters isn’t defined within this XML or any adjacent process scripts—it may be provided by your engine’s DSL, but that isn’t obvious here. Also, the inline predicate and branching are quite dense.

• Please verify that findFilters(...) is available at runtime (e.g., part of the engine’s built-in functions or imported scripts).
• If it isn’t, add or import its definition so the process won’t fail at execution.
• To improve readability and maintainability, extract the filter predicate into a named closure, for example:

def isValidFilter = { filterCase ->
    !selectedFilterRef.value.contains(filterCase.stringId) &&
    filterCase.dataSet["filter_type"].value == "Case"
}

Then use:

.findAll(isValidFilter)

instead of the inline closure.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (3)

252-252: Address TODO comment about implementation adjustment.

The TODO suggests this implementation needs updates. Please clarify what adjustments are needed.

Would you like me to help identify what implementation adjustments might be needed for the moveItem method?


98-100: Consider providing more context in the uniqueness error message.

-            throw new IllegalArgumentException(String.format("Menu item identifier %s is not unique!", sanitizedIdentifier));
+            throw new IllegalArgumentException(String.format("Menu item identifier '%s' is not unique! Please choose a different identifier.", sanitizedIdentifier));

241-289: Consider adding transaction management for atomicity.

The moveItem operation involves multiple case updates that should be atomic. If any save fails, the system could be left in an inconsistent state.

Consider wrapping the entire operation in a transaction to ensure all-or-nothing semantics:

@Transactional
public void moveItem(Case itemCase, String destUri) throws TransitionNotExecutableException {
    // existing implementation
}

This would ensure that if any part of the move operation fails, all changes are rolled back.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (2)

60-76: Guard against null before calling containsKey

filterAutocomplete.value can be null, yet the code calls containsKey(filterAutocomplete.value) unconditionally.
Although Groovy’s Map.containsKey(null) is legal, running it for every keystroke in an autocomplete widget is unnecessary work and hides the intent. A short-circuit null check makes the logic clearer and avoids pointless map look-ups.

-if (filterAutocomplete.getOptions().containsKey(filterAutocomplete.value)) {
+if (filterAutocomplete.value != null && 
+    filterAutocomplete.getOptions().containsKey(filterAutocomplete.value)) {

156-166: findFilters is executed on every key-stroke – consider debouncing

Both get and set triggers invoke findFilters(...) which can hit Elasticsearch on every autocomplete change.
Wrap the call in a debouncer or cache the result for a short interval to avoid a flood of expensive queries under fast typing.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (2)

1723-1768: Well-structured view configuration system.

The new ViewBody configuration system provides a clean abstraction for UI layouts with proper support for tabbed views and view chaining. The helper methods effectively encapsulate the complexity of view creation.

Consider adding JavaDoc comments to the protected static helper methods (createSingleTaskViewBody, createDefaultViewBody, createLegacyMenuItemViews) to document their purpose and parameters for future maintainability.

Also applies to: 2110-2208


2379-2382: Convenient overload with sensible defaults.

The new findCasesElastic overload provides a good default page size of 100.

Consider adding a JavaDoc comment to document the default page size behavior for clarity.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (1)

307-310: Consider using a more explicit regex pattern for whitespace removal.

The current implementation removes all whitespace, which might be too aggressive if headers need spaces within them.

If you only want to trim spaces around commas while preserving spaces within header names:

-            String trimmed = defaultHeaders.value?.replaceAll("\\s","")
+            String trimmed = defaultHeaders.value?.replaceAll("\\s*,\\s*", ",")?.trim()

This would transform " meta-title , meta-user " to "meta-title,meta-user" while preserving spaces within header names if needed.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (2)

81-154: Consider extracting common ordering logic to reduce duplication.

The order_up and order_down actions share significant code. Consider extracting a common function.

Add a shared function in the process scope:

<function scope="process" name="reorderItems">
    {
        int currentIndex,
        int newIndex,
        com.netgrif.application.engine.objects.petrinet.domain.dataset.EnumerationMapField dashboard_item_list,
        com.netgrif.application.engine.objects.petrinet.domain.dataset.EnumerationMapField dashboard_item_to_menu_item,
        com.netgrif.application.engine.objects.petrinet.domain.dataset.TextField items_order
        ->
        def keysDashboard = dashboard_item_list.options.keySet() as List
        def keysMenu = dashboard_item_to_menu_item.options.keySet() as List
        
        java.util.Collections.swap(keysDashboard, currentIndex, newIndex)
        java.util.Collections.swap(keysMenu, currentIndex, newIndex)
        
        def newOrderDashboard = [:]
        def newOrderMenu = [:]
        keysDashboard.forEach { newOrderDashboard[it] = dashboard_item_list.options[it]}
        keysMenu.forEach { newOrderMenu[it] = dashboard_item_to_menu_item.options[it]}
        
        change dashboard_item_list options { newOrderDashboard }
        change dashboard_item_to_menu_item options { newOrderMenu }
        change items_order value { String.join(",", newOrderDashboard.keySet()) }
    }
</function>

170-171: Consider extracting elastic search queries as constants.

The repeated query pattern appears multiple times and could be maintained more easily as a constant.

Define at the process level:

<function scope="process" name="getDashboardItemQuery">
    { -> 
        return "processIdentifier:\"dashboard_item\" AND dataSet.is_active.booleanValue:true"
    }
</function>

Then use it consistently:

-                    def dashboardItemCases = findCasesElastic("processIdentifier:\"dashboard_item\" AND dataSet.is_active.booleanValue:true" as String)
+                    def dashboardItemCases = findCasesElastic(getDashboardItemQuery())

Also applies to: 228-229, 262-263

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcbb9a1 and 7a85f22.

📒 Files selected for processing (62)
  • application-engine/CHANGELOG.md (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (40 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (5 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1 hunks)
  • application-engine/src/main/resources/application.yaml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (7 hunks)
  • application-engine/src/test/resources/dashboard_management_test.xml (1 hunks)
  • application-engine/src/test/resources/petriNets/filter_api_test.xml (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (4 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (3 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1 hunks)
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (3 hunks)
💤 Files with no reviewable changes (9)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml
👮 Files not reviewed due to content moderation or server errors (5)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java
🧰 Additional context used
🧠 Learnings (27)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/application.yaml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/resources/petriNets/filter_api_test.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

🪛 GitHub Actions: Pull Request
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java

[warning] 42-54: @builder will ignore the initializing expression entirely. Add @Builder.Default or make the field final to fix.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (132)
application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1)

123-123: No-op formatting change – looks fine

The added blank line has no functional impact and keeps the method body readable.

nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (2)

3-15: LGTM! Well-structured imports for the new transformation method.

The additional imports support the new transformToField method implementation properly.


67-73: transformToField usage confirmed

The transformToField(I18nString) implementation in
nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java
overrides the abstract method from
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java
and is invoked there via

this.title = this.transformToField(net.getTitle());

No further action required—method is not orphaned.

application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (2)

3-11: LGTM! Appropriate imports for the new search method.

The imports properly support the new search functionality with pagination, user context, and search criteria.


22-22: Well-designed search method signature.

The method signature follows good design principles:

  • Includes proper search criteria encapsulation (PetriNetSearch)
  • Provides user context for security (LoggedUser)
  • Supports pagination (Pageable)
  • Includes internationalization support (Locale)
  • Has configurable intersection behavior (Boolean isIntersection)
  • Returns properly typed paged results

This aligns well with Spring Data patterns and REST API best practices.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (1)

1-14: Excellent service interface design.

The interface follows solid design principles:

  • Clean separation of concerns with focused methods
  • Appropriate use of domain objects (DashboardItemBody, Case)
  • Proper exception handling for workflow operations
  • Follows common patterns (getOrCreate for lazy initialization)
  • Single responsibility principle adherence

The method signatures are well-designed and provide a clear contract for dashboard item lifecycle management.

application-engine/src/test/resources/petriNets/filter_api_test.xml (1)

113-122: Excellent refactoring to consolidated service call.

The change from granular property updates to a single createOrUpdateMenuItemAndFilter call significantly improves the code:

  • Maintainability: Single method call reduces complexity and potential for inconsistencies
  • Readability: Clear parameter structure with well-defined metadata
  • Service-oriented: Aligns with the architectural shift toward service-driven operations
  • Error reduction: Less manual manipulation reduces risk of mistakes

The metadata structure is properly defined with sensible defaults, and all necessary parameters are included in the consolidated call.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

46-46: Well-designed abstraction for I18nString to I18nField transformation.

The introduction of the abstract transformToField method provides a clean way for subclasses to handle the conversion from I18nString to I18nField, supporting the broader refactoring toward structured internationalization.

Also applies to: 60-60

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

5-22: Well-organized constants class.

The constants are clearly named, properly grouped by functionality (transitions, field IDs, country codes, filter types, visibility options), and follow consistent naming conventions. This provides good centralization for filter-related identifiers.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1)

1-23: Well-designed constants class for dashboard items.

The class provides clear, consistently named constants for dashboard item fields with helpful documentation linking to the corresponding Petri net process. The field identifiers logically represent dashboard item properties and align well with the broader dashboard management architecture.

application-engine/src/test/resources/dashboard_management_test.xml (1)

10-54: Comprehensive test coverage for dashboard management workflow.

The test XML provides excellent coverage of the new dashboard management functionality, testing the complete flow from filter creation through menu item setup to dashboard item creation and dashboard management updates. The chained view configuration and service method calls demonstrate proper integration testing.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

1-16: LGTM! Well-structured constants class.

The constants class follows Java naming conventions and extends the appropriate base class. The field constants are properly defined for tabbed task view configuration and align with the broader menu system refactor.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1)

1-16: LGTM! Solid foundational constants class.

The class provides a clean separation between field constants and transition IDs, establishing a good foundation for specialized view configuration classes. The naming conventions are consistent and the constants align well with the menu item configuration framework.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

1-20: LGTM! Comprehensive dashboard management constants.

The constants class provides comprehensive coverage of dashboard management fields including configuration options, toolbar settings, and item management. The naming conventions are consistent and the constants align well with the dashboard management process requirements.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1)

1-30: LGTM! Clean implementation following established patterns.

The class properly extends ViewBody and implements the required methods. The use of Lombok annotations reduces boilerplate code effectively. The chained view pattern and unchanged dataset transformation approach align with the expected behavior for a tabbed ticket view that delegates to another view.

application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1)

73-75: LGTM! Dependency injection follows established patterns.

The injection of IElasticPetriNetService follows the same pattern as other dependencies in the controller.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1)

7-14: LGTM! Well-designed interface following clean architecture principles.

The interface demonstrates good design with:

  • Clear method names that express intent
  • Appropriate exception handling with TransitionNotExecutableException
  • Consistent parameter and return types
  • Single responsibility focused on dashboard management operations
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

13-31: LGTM! Clean implementation following established patterns.

The class correctly implements the ViewBody contract with:

  • Proper extension of the abstract base class
  • Correct override of abstract methods
  • Appropriate use of constants for field names in serialization
  • Clean, focused implementation for tabbed single task view configuration
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (1)

17-32: LGTM! Well-structured configuration class with sensible defaults.

The class provides comprehensive configuration options for tabbed case views with appropriate default values and proper field organization.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

7-22: LGTM! Well-organized constants following established conventions.

The constants class demonstrates good practices with:

  • Clear documentation linking to the corresponding XML process file
  • Consistent naming convention with FIELD_ prefix
  • Proper inheritance from ViewConstants
  • Appropriate visibility and immutability modifiers
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (4)

10-14: LGTM!

The class annotations and conditional property configuration follow established patterns and make sense for a startup component.


16-23: LGTM!

The dependency injection and constants are properly structured following established patterns.


1-14: LGTM - Well-structured startup runner.

The class follows Spring Boot conventions with appropriate annotations and conditional execution based on configuration property.


16-24: LGTM - Constants and dependency injection are properly structured.

The public identifiers allow external reference while keeping file paths as implementation details. The ImportHelper autowiring follows established patterns.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (7)

14-27: LGTM!

The class structure and field declarations are well-designed with sensible defaults and proper Lombok annotations.


29-37: LGTM!

The abstract method implementations are correct and follow the expected contract.


39-62: LGTM!

The dataset transformation method is well-implemented with proper null checking and appropriate field type mappings.


1-28: LGTM - Well-structured view configuration class.

The class follows established patterns with appropriate Lombok annotations, sensible default values, and clear field naming conventions.


29-37: LGTM - Correct method implementations.

The methods properly identify the view type and indicate no associated chained view, which is appropriate for this configuration class.


39-63: LGTM - Robust dataset conversion implementation.

The method properly converts all fields to dataset entries with appropriate types and includes necessary null safety checks for collections.


17-63: LGTM! Well-structured view configuration class.

The implementation follows good design principles:

  • Proper encapsulation with Lombok annotations
  • Appropriate default values for configuration fields
  • Null-safe handling in toDataSetInternal method
  • Consistent use of constants for field mapping
  • Clean separation of concerns with the abstract ViewBody parent class

The class integrates well with the new service-based architecture for menu item management.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (5)

10-27: LGTM!

The class structure uses appropriate Lombok annotations and has well-designed fields with descriptive names and suitable types.


29-35: LGTM!

The convenience constructor focuses on essential fields and provides good usability for common dashboard item creation scenarios.


1-36: LGTM - Well-designed data class with convenient constructor.

The class structure is clean with appropriate Lombok annotations, and the custom constructor provides a convenient way to create instances with essential fields.


37-54: LGTM - Comprehensive dataset conversion method.

The method properly converts all fields to dataset entries with appropriate field types and follows established patterns for dataset transformation.


13-54: LGTM! Well-designed domain class with comprehensive data mapping.

The implementation demonstrates good design practices:

  • Effective use of Builder pattern with Lombok for flexible object creation
  • Convenience constructor for essential fields alongside the full constructor
  • Comprehensive field mapping in toDataSet() method with appropriate field types
  • Clear separation of concerns as a data transfer object

The class properly integrates with the new dashboard management architecture and service layer.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (7)

14-28: LGTM!

The class structure and field declarations are well-designed with appropriate types and descriptive naming.


26-47: LGTM!

The constructor and static utility method provide good functionality with sensible defaults for filter metadata.


49-72: LGTM!

The dataset transformation method is well-implemented with proper null checking and creates the appropriate complex data structure for filter integration.


1-28: LGTM - Well-structured filter data class.

The class design appropriately encapsulates filter properties with proper field types, including internationalization support and flexible metadata handling.


30-47: LGTM - Useful static method for default metadata.

The method provides sensible default values for filter metadata and is properly documented with clear parameter and return descriptions.


49-73: LGTM - Comprehensive dataset conversion with proper filter handling.

The method correctly converts all fields to dataset entries and includes appropriate null safety. The special handling for the filter field with its complex structure is well-implemented.


16-73: LGTM! Solid filter data model with robust error handling.

The implementation shows excellent design:

  • Clean data encapsulation with appropriate fields for filter configuration
  • Static factory method for default metadata generation promotes consistency
  • Robust null handling in toDataSet() method with sensible fallbacks
  • Proper field type mapping for dataset transformation
  • Clear documentation for method purposes

This class effectively replaces manual case/dataset manipulation with a structured approach that integrates well with the new service-based architecture.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (12)

76-82: LGTM!

The constants migration correctly reflects the architectural change from preference items to menu items, and the new tabbed view assertions demonstrate the enhanced functionality.


85-86: LGTM!

The allowed nets and query updates correctly reflect the architectural change from preference items to menu items, with appropriate inclusion of both filter and menu_item processes.


89-102: LGTM!

The new tabbed view configuration assertions provide comprehensive testing of the view hierarchy and configuration system, demonstrating thorough validation of the enhanced functionality.


104-119: LGTM!

The updated folder and URI node assertions correctly reflect the process migration and provide enhanced validation of the hierarchical menu structure and URI node consistency.


202-244: LGTM!

The move functionality tests have been correctly updated to use the new constants and net identifiers while maintaining the same comprehensive test coverage.


250-357: LGTM!

The remaining test methods have been comprehensively updated with consistent constant usage and enhanced validation for the new tabbed view system while maintaining thorough test coverage.


76-103: LGTM - Constants migration and enhanced tabbed view testing.

The migration from old constants format to new FIELD_* format is consistent throughout. The new tabbed view assertions properly validate the hierarchical view configuration structure and URI node consistency.


104-120: LGTM - Comprehensive URI node and folder hierarchy validation.

The test properly validates the consistency between menu item cases and URI nodes, and thoroughly checks the parent-child relationships in the folder hierarchy using updated constants.


127-169: LGTM - Enhanced change testing with view configuration persistence.

The test properly validates that changes update existing configurations rather than creating new ones, and includes comprehensive assertions for the new tabbed view system.


256-297: LGTM - Consistent constants migration in duplicate item test.

All constants and field references are properly updated to the new format, and the test logic correctly validates duplication behavior with the new menu item data model.


322-378: LGTM - Enhanced remove test with view configuration cleanup validation.

The test properly validates cascading deletion of menu items and their associated tabbed view configurations, with consistent constants usage throughout.


76-120: LGTM! Comprehensive test coverage for new menu item architecture.

The test effectively validates:

  • Proper field mapping with new constants structure
  • Tabbed view configuration creation and linking
  • URI node consistency and hierarchy management
  • Filter integration with menu items
  • Correct data transformation and persistence

The test demonstrates good coverage of the new service-based architecture and properly validates the complex relationships between menu items, filters, and tabbed views.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1)

44-54: No change needed: default value is intentionally only for MULTICHOICE_MAP

We’ve checked that:

  • putDataSetEntryOptions is only ever called for FieldType.MULTICHOICE_MAP (e.g. in MenuItemBody).
  • Other types use the overloads putDataSetEntry(...) or putDataSetEntryWithOptions(...) which handle their own default values and “value” fields.

Because no other field type calls this method, adding defaults here would be dead code. Leave the default‐only‐for‐MULTICHOICE_MAP logic as is.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

7-39: Clean refactoring from enum to constants class!

The conversion from enum to a final constants holder class with public static final String fields is well-executed. The naming convention with FIELD_, TRANS_, and technical constants is consistent and clear.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1)

60-74: Well-structured dynamic configuration import!

The createConfigurationNets() method elegantly handles dynamic import of configuration Petri nets based on MenuItemView enum values. Good use of streams and Optional handling.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1)

17-82: Well-designed abstract view configuration class!

The abstract class provides a clean template for view configurations with proper null handling and clear separation of concerns through abstract methods.

application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (1)

92-195: Well-implemented Elasticsearch search functionality!

The search implementation is comprehensive with:

  • Proper null checking and error handling
  • Well-structured query building with separate methods for different query types
  • Support for full-text search and group filtering
  • Proper pagination handling
nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (5)

19-28: LGTM!

The string sanitization method correctly handles null input and applies appropriate transformations for creating clean identifiers.


37-51: LGTM!

The method correctly handles null inputs and uses appropriate stream operations to find the task.


86-92: LGTM!

Good reuse of the getCaseIdsFromCaseRef method with proper null and empty list handling.


98-100: LGTM!

Clean implementation that properly delegates to existing utility method.


106-109: LGTM!

Consistent implementation pattern with proper null and empty list checks.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (2)

74-84: LGTM!

The validation logic correctly prevents duplicate dashboard item IDs and handles empty values appropriately.


700-730: LGTM!

Comprehensive validation logic that ensures data integrity before activating the dashboard item.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

42-53: LGTM!

Well-documented default method with clean stream-based implementation.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1)

226-278: LGTM!

The transition configuration is well-structured with appropriate role permissions and UI layout.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (3)

95-100: LGTM!

Clean implementation with proper query construction using constants.


102-105: LGTM!

Simple utility method with proper delegation to MenuItemUtils.


108-115: LGTM!

Correct implementation of the task execution workflow with proper user context handling.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (16)

1-50: LGTM! Well-structured role-based access control.

The role configuration appropriately restricts configuration management to admin users while allowing read-only access for default users.


42-93: LGTM! Well-implemented dynamic UI functions.

The Groovy functions correctly handle filter autocomplete updates and option synchronization with proper null checks and XML escaping.


95-225: LGTM! Comprehensive filter configuration with proper validation.

The filter selection system correctly validates filter types and provides dynamic autocomplete functionality with appropriate UI controls.


226-318: LGTM! Comprehensive task view configuration options.

The view configuration provides extensive customization options with proper validation, including whitespace trimming for custom headers.


319-372: LGTM! Complete internationalization support.

All UI strings have proper translations for both Slovak and German locales.


373-718: LGTM! Well-structured workflow with comprehensive UI layout.

The Petri net workflow properly implements initialization and configuration states with appropriate role restrictions and dynamic UI behavior.


1-41: LGTM! Role permissions are properly configured.

The document structure follows the standard Petri net schema, and the role-based access control is appropriately set up with admin privileges for configuration changes while allowing default users read-only access.


226-317: Well-structured task view configuration.

The configuration provides comprehensive control over the task view UI with proper validation, including automatic whitespace trimming for custom headers and dynamic option updates based on selected modes.


319-371: Complete i18n support for Slovak and German.

All UI elements have proper translations for both Slovak and German locales, following consistent naming conventions.


373-718: Proper workflow structure with admin-restricted settings.

The Petri net follows a standard initialization pattern with appropriate role-based access control. The settings transition is correctly restricted to admin users, and the data groups are well-organized with clear layout specifications.


150-170: Add defensive null check for ProcessResourceId creation.

While there is a containsFilter check, the ProcessResourceId creation on line 159 could still fail if the value becomes null between checks.

 boolean containsFilter = filterAutocomplete.value != null &amp;&amp; filterAutocomplete.value != ""
 if (containsFilter) {
+    if (filterAutocomplete.value == null) {
+        throw new IllegalArgumentException("Filter value became null")
+    }
     def filterCase = findCase({it._id.eq(new com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId(filterAutocomplete.value))})
     if (filterCase.dataSet["filter_type"].value != "Task") {
         throw new IllegalArgumentException("Filter is of wrong type. Only filter of Task type allowed.")
     }
 }

Likely an incorrect or invalid review comment.


1-51: LGTM! Well-structured Petri net configuration with appropriate role definitions.

The XML structure follows the schema correctly, and the role-based access control is properly configured with system/admin having full permissions and default users having view-only access.


95-224: Well-designed filter configuration with comprehensive validation.

The filter management section properly handles dynamic autocomplete, validates filter types (ensuring only "Task" type filters are allowed), and maintains UI state consistency. The use of immediate="true" for reactive behavior is appropriate.


319-371: Complete and consistent internationalization.

Both Slovak and German translations are provided for all UI strings, ensuring proper localization support.


373-718: Well-structured process flow with proper access control.

The transition definitions, place configurations, and arc connections create a clear workflow. The admin-only restriction on the settings transition and the comprehensive grid-based UI layout are appropriately implemented.


79-85: Potential null pointer risk in contains() check.

While selectedValues is checked for null on line 79, if it's null, the code skips the entire block. However, the logic could be more defensive by ensuring selectedValues is never null when passed to contains().

Consider this defensive approach:

-                if (selectedValues != null) {
-                    existingOptions.each { key, value ->
-                        if (selectedValues.contains(key)) {
-                            newOptions.put(key, value)
-                        }
+                existingOptions.each { key, value ->
+                    if (selectedValues != null && selectedValues.contains(key)) {
+                        newOptions.put(key, value)
                     }
                }

Likely an incorrect or invalid review comment.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (7)

81-154: LGTM! Robust item ordering implementation.

The order up/down functionality correctly handles bounds checking and maintains synchronization between related data structures.


199-269: LGTM! Comprehensive item management with proper data consistency.

The add/remove operations correctly maintain relationships between dashboard items and menu items while properly updating all related data structures.


291-732: LGTM! Well-designed dashboard management workflow.

The dashboard toolbar configuration options, internationalization support, and workflow structure are comprehensive and properly implemented.


1-35: LGTM! Standard dashboard management structure.

The document follows the standard Petri net schema with appropriate role-based permissions for dashboard management operations.


69-270: Well-implemented dashboard item list management.

The implementation properly handles list ordering with boundary checks, maintains parallel data structures consistently, and provides appropriate user feedback through exceptions.


291-354: Flexible toolbar configuration with proper UI logic.

The toolbar settings provide comprehensive control over dashboard UI elements with appropriate show/hide logic for dependent fields.


684-700: Good practice: Re-validating dashboard ID in finish event.

This addresses potential race conditions by checking uniqueness again before finalizing the dashboard creation. The is_active flag management ensures proper lifecycle tracking.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (10)

1-48: LGTM! Well-structured service with appropriate dependencies.

The service follows Spring best practices with constructor injection and includes all necessary dependencies.


92-125: LGTM! Robust menu item creation with proper validation.

The method correctly validates uniqueness, handles folder hierarchy, and sanitizes input.


137-142: Address or remove commented URI node code.

There's commented code with a TODO that needs to be either implemented or removed. This suggests incomplete functionality.

Please clarify the intent of this commented code and either implement the URI node validation or remove it entirely.


323-345: Multiple TODOs and commented URI-related code.

There are several commented sections related to URI handling that need to be addressed. This suggests incomplete migration or refactoring.

The commented URI-related code appears throughout the method. Please complete the implementation or remove the obsolete code.


658-748: LGTM! Well-implemented helper methods.

The utility methods for path manipulation and data operations are properly structured with appropriate null checks.


1-48: Well-structured service class with proper dependency injection.

The class follows Spring best practices with constructor-based dependency injection and appropriate service dependencies.


241-289: Robust implementation of menu item relocation.

The move operation properly handles cyclic path detection, parent-child relationships, and recursive path updates for the entire subtree. The batch save approach is efficient.


385-403: Proper elastic search implementation with user context.

The search methods correctly handle user permissions and pagination while delegating query construction to callers.


50-83: Well-implemented filter management methods.

The create and update operations follow a consistent pattern with proper error handling, logging, and data persistence.


727-747: Well-implemented path utility methods.

The utilities properly handle edge cases like root paths and empty strings, providing robust path manipulation functionality.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (7)

34-90: LGTM! Proper asynchronous cleanup on case deletion.

The delete event correctly handles cleanup of associated view configuration cases using asynchronous execution.


157-163: LGTM! Correct filter type validation for ticket views.

The validation properly enforces Case type filters, which is appropriate for ticket view configuration.


196-222: LGTM! Well-configured associated view options.

The associated view configuration correctly uses the menu item service for dynamic options and appropriately restricts allowed view types.


150-170: Correct filter type validation for ticket views.

The filter validation properly ensures only Case-type filters are selected, which is appropriate for ticket view configurations.


196-366: Well-implemented associated view management.

The configuration properly handles the lifecycle of associated views by deleting previous configurations before creating new ones, preventing orphaned configuration cases.


196-222: Appropriate view type restrictions for ticket view.

The configuration correctly restricts associated views to tabbed_single_task_view_configuration, which aligns with the ticket-oriented nature of this view type.


331-347: Well-implemented view configuration lifecycle management.

The code properly cleans up previous configurations before creating new ones, preventing orphaned cases. The initialization pattern is consistent and follows best practices.

Note: Consider the same transaction management suggestion as mentioned for MenuItemService to ensure atomicity when deleting old and creating new configuration cases.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (9)

1-38: LGTM! Clean refactoring with ViewBody integration.

The class structure properly separates view configuration into ViewBody while maintaining backward compatibility through multiple constructors.


109-119: LGTM! Smart handling of tabbed view flag.

The setView method correctly derives the useTabbedView flag from the view type, with a sensible default.


126-184: LGTM! Well-structured data transformation with proper overloading.

The toDataSet methods provide flexible options while maintaining clean separation of concerns. The use of ToDataSetOutcome improves type safety.


1-38: Clean domain model with proper abstractions.

The refactored class structure effectively uses ViewBody abstraction and provides a clean API for menu item configuration with multilingual support.


39-88: Comprehensive constructor overloads for flexibility.

The multiple constructors provide good API flexibility while maintaining consistent initialization patterns for menu and tab names.


109-113: Verify the tabbed view logic when view is null.

The setView method sets useTabbedView = true when viewBody == null. This seems counterintuitive - shouldn't it be false when there's no view?

Please verify if this is the intended behavior. If a menu item has no view, should it still be considered as using a tabbed view?


121-184: Well-designed data transformation with proper null handling.

The toDataSet methods provide a clean API with progressive enhancement through overloads, properly handling optional parameters and view configurations.


1-44: Clean refactoring with improved structure.

The replacement of legacy view fields with ViewBody and the comprehensive set of constructors provide a cleaner, more maintainable API.


109-119: Smart default handling for tabbed view flag.

The logic correctly defaults to tabbed view when no view is provided, and properly synchronizes the flag with the view type.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

160-170: Undefined helper calls may break move logic

getCorrectedUri, findOptionsBasedOnSelectedNode, and splitUriPath are invoked but are not declared in this net nor imported via import-static directives.
If they live only in an external ActionDelegate, ensure they are present on the classpath; otherwise the “Move item” transition will fail at runtime.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (10)

29-32: LGTM! Well-organized service integration.

The new service imports and @Autowired dependencies are properly structured and align with the architectural shift to delegate menu item, filter, and dashboard operations to dedicated services.

Also applies to: 35-39, 47-47, 56-64, 74-74, 205-212


1619-1628: Clean refactoring to use the new service architecture.

The filter creation now properly uses the FilterBody DTO and delegates to menuItemService, following the new service-based architecture.


1880-1924: Consistent use of new MenuItemConstants structure.

The refactoring properly uses the new string constants from MenuItemConstants class, aligning with the architectural changes mentioned in the learnings.


2339-2361: Clean implementation of dashboard management functionality.

The new dashboard methods properly delegate to their respective services and maintain consistency with the overall service architecture.


2533-2533: Good practice: Clear deprecation annotations with version information.

The deprecated methods are properly annotated with @Deprecated(since = "6.5.0"), providing clear version information for migration planning.

Also applies to: 2575-2575, 2626-2626, 2663-2663


1736-1738: Excellent consistency in service delegation pattern.

All menu item operations consistently delegate to menuItemService, providing clean separation of concerns and improved maintainability.

Also applies to: 1766-1767, 1796-1797, 2098-2099, 2242-2243, 2260-2261, 2282-2283, 2291-2292, 2302-2303, 2312-2313


2101-2109: Good implementation of the get-or-create pattern.

The method properly sanitizes the identifier and checks for existence before creation, preventing duplicates.


2110-2112: Appropriate visibility modifiers for utility methods.

The protected static modifiers are well-chosen for these utility methods - they don't require instance state and the protected visibility allows for future extension if needed.

Also applies to: 2144-2147


2698-2700: Consistent delegation pattern.

The method follows the established pattern of delegating to menuItemService.


933-936: Method name is misleading - this finds rather than creates a case.

The method name createCase suggests it creates a new case, but it actually finds an existing one by calling workflowService.findOne(stringId). Consider renaming to findCase for clarity.

-Case createCase(String stringId) {
-    return workflowService.findOne(stringId)
-}
+Case findCaseById(String stringId) {
+    return workflowService.findOne(stringId)
+}

Likely an incorrect or invalid review comment.


Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.value].value as Set
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential query injection vulnerability.

The elastic query construction using string concatenation could be vulnerable to injection if the path parameter contains special characters or query syntax.

Consider escaping or validating the path parameter before using it in the query:

-Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
+// Escape special characters in path before using in query
+String escapedPath = path.replace("\"", "\\\"")
+Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$escapedPath\"")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
// Escape special characters in path before using in query
String escapedPath = path.replace("\"", "\\\"")
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$escapedPath\"")
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
at line 2735, the elastic query is constructed by directly concatenating the
variable 'path' into the query string, which risks injection attacks. To fix
this, sanitize or escape the 'path' parameter to neutralize any special
characters or query syntax before embedding it in the query string.
Alternatively, use parameterized queries or a safe query builder method if
available to avoid direct string concatenation.

Comment on lines 27 to 28
helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect descriptions in import calls.

The description strings don't match what's actually being imported:

  • Line 27: "Petri net for filters" should be "Petri net for dashboard management"
  • Line 28: "Petri net for filter preferences" should be "Petri net for dashboard items"

Apply this diff to fix the descriptions:

-        helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
-        helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
+        helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
+        helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy
at lines 27-28, the description strings in the importProcess calls are
incorrect. Change the description on line 27 from "Petri net for filters" to
"Petri net for dashboard management" and on line 28 from "Petri net for filter
preferences" to "Petri net for dashboard items" to accurately reflect what is
being imported.

⚠️ Potential issue

Fix misleading import descriptions.

The descriptions don't match what's being imported - they appear to reference filters instead of dashboard components.

Apply this diff to correct the descriptions:

-        helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
-        helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
+        helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
+        helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy
around lines 27 to 28, the import descriptions are misleading as they mention
filters instead of dashboard components. Update the first description to "Petri
net for dashboard management" and the second to "Petri net for dashboard items"
to accurately reflect the imported components.

⚠️ Potential issue

Fix misleading method parameter comments.

The descriptive comments in the importProcess calls are incorrect and misleading. They reference "filters" and "filter preferences" but the actual files being imported are for dashboard management and dashboard items.

Apply this diff to correct the comments:

-        helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
-        helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
+        helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
+        helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
helper.importProcess("Petri net for filters", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for filter preferences", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
helper.importProcess("Petri net for dashboard management", DASHBOARD_MANAGEMENT_NET_IDENTIFIER, DASHBOARD_MANAGEMENT_FILE_NAME)
helper.importProcess("Petri net for dashboard items", DASHBOARD_ITEM_NET_IDENTIFIER, DASHBOARD_ITEM_FILE_NAME)
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy
around lines 27 to 28, the descriptive string parameters in the importProcess
method calls incorrectly mention "filters" and "filter preferences." Update
these strings to accurately describe the imported files as related to "dashboard
management" and "dashboard items" to reflect their true purpose.

Comment on lines 17 to 22
@RequiredArgsConstructor
class DefaultDashboardRunner implements ApplicationEngineStartupRunner {

@Autowired
private DashboardManagementService dashboardManagementService

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use constructor injection consistently

The class is annotated with @RequiredArgsConstructor but uses @Autowired field injection. For consistency and better testability, use constructor injection with a final field.

 @RequiredArgsConstructor
 class DefaultDashboardRunner implements ApplicationEngineStartupRunner {
 
-    @Autowired
-    private DashboardManagementService dashboardManagementService
+    private final DashboardManagementService dashboardManagementService
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
around lines 17 to 22, replace the @Autowired field injection of
dashboardManagementService with a private final field and rely on the
@RequiredArgsConstructor to generate a constructor for injection. Remove the
@Autowired annotation and declare the field as final to ensure consistent
constructor injection and improve testability.

Comment on lines +18 to 19
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.InvalidDataAccessApiUsageException;
Copy link

@coderabbitai coderabbitai bot Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify if @lazy annotation is necessary.

The @lazy annotation on line 19 suggests potential circular dependency issues. Consider verifying if this is still needed after fixing the constructor injection.


🏁 Script executed:

#!/bin/bash
# Check for circular dependencies by finding where ElasticPetriNetService is injected
rg -A 5 "ElasticPetriNetService" --glob "*.java" | grep -E "@Autowired|constructor|@RequiredArgsConstructor"

Length of output: 457


🏁 Script executed:

#!/bin/bash
# Show the beginning of ElasticPetriNetService to see where and how @Lazy is applied
sed -n '1,200p' application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java

Length of output: 9587


Remove unused Lazy import

The import org.springframework.context.annotation.Lazy is not used anywhere in ElasticPetriNetService (no @Lazy annotations present). You can safely delete it:

  • File: application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java
    • Remove the line:
    import org.springframework.context.annotation.Lazy;
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java
at lines 18 to 19, remove the unused import statement 'import
org.springframework.context.annotation.Lazy;' since there are no @Lazy
annotations used in the file. This will clean up unnecessary imports.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The annotation is presnet at line 58.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +45 to +46
private IPetriNetService petriNetService;

Copy link

@coderabbitai coderabbitai bot Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add petriNetService to constructor injection.

The petriNetService field is declared but not initialized in the constructor, which will cause NullPointerException when used in the search method.

-    private IPetriNetService petriNetService;
+    private final IPetriNetService petriNetService;

-    public ElasticPetriNetService(ElasticPetriNetRepository repository, Executor executors, ElasticsearchTemplate template, ElasticsearchConfiguration elasticsearchConfiguration) {
+    public ElasticPetriNetService(ElasticPetriNetRepository repository, Executor executors, ElasticsearchTemplate template, ElasticsearchConfiguration elasticsearchConfiguration, IPetriNetService petriNetService) {
         this.repository = repository;
         this.executors = executors;
         this.template = template;
         this.elasticsearchConfiguration = elasticsearchConfiguration;
+        this.petriNetService = petriNetService;
     }

Also applies to: 51-56

🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java
around lines 45-46 and 51-56, the petriNetService field is declared but not
initialized via constructor injection. To fix this, add a parameter for
IPetriNetService to the constructor and assign it to the petriNetService field.
This ensures petriNetService is properly initialized and prevents
NullPointerException when used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

petriNetService properties is initialized with lazy setter at line 60.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tuplle Thank you for the clarification! You're absolutely right. I can see that petriNetService is properly initialized using the @Lazy and @Autowired setter injection pattern at line 60:

@Lazy
@Autowired
public void setPetriNetService(IPetriNetService petriNetService) {
    this.petriNetService = petriNetService;
}

This is a valid Spring dependency injection pattern, often used to resolve circular dependencies. The @Lazy annotation ensures the dependency is initialized only when needed, and Spring will properly inject the service before any methods that use it are called. My suggestion for constructor injection was unnecessary in this case.

  (\   /)
 ( ._. )
o_("_")_o

learns something new


✏️ Learnings added
Learnt from: tuplle
PR: netgrif/application-engine#331
File: application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java:45-46
Timestamp: 2025-07-29T17:19:18.213Z
Learning: In ElasticPetriNetService class, petriNetService is properly initialized using @Lazy setter injection rather than constructor injection. This pattern with @Lazy @Autowired setter methods is commonly used in Spring to resolve circular dependencies and is a valid alternative to constructor injection.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +37 to +53
public ToDataSetOutcome toDataSet() {
ToDataSetOutcome outcome = new ToDataSetOutcome();
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ID, FieldType.TEXT, this.id);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_MENU_ITEM_LIST, FieldType.ENUMERATION_MAP, this.menuItems);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_INTERNAL, FieldType.BOOLEAN, this.isInternal);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_URL, FieldType.TEXT, this.externalUrl);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_ICON, FieldType.BOOLEAN, this.externalIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ICON_COLOR, FieldType.TEXT, this.iconColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_ICON, FieldType.TEXT, this.itemIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_COLOR, FieldType.TEXT, this.fontColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_WEIGHT, FieldType.TEXT, this.fontWeight);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_NAME, FieldType.I18N, this.name);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_ICON, FieldType.BOOLEAN, this.inheritIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_NAME, FieldType.BOOLEAN, this.inheritName);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_ACTIVE, FieldType.BOOLEAN, this.isActive);
return outcome;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix type mismatch in externalIcon field mapping.

Line 43 maps the externalIcon field (String type) with FieldType.BOOLEAN, which is incorrect and could cause runtime issues.

Apply this diff to fix the field type:

-        outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_ICON, FieldType.BOOLEAN, this.externalIcon);
+        outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_ICON, FieldType.TEXT, this.externalIcon);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public ToDataSetOutcome toDataSet() {
ToDataSetOutcome outcome = new ToDataSetOutcome();
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ID, FieldType.TEXT, this.id);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_MENU_ITEM_LIST, FieldType.ENUMERATION_MAP, this.menuItems);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_INTERNAL, FieldType.BOOLEAN, this.isInternal);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_URL, FieldType.TEXT, this.externalUrl);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_ICON, FieldType.BOOLEAN, this.externalIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ICON_COLOR, FieldType.TEXT, this.iconColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_ICON, FieldType.TEXT, this.itemIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_COLOR, FieldType.TEXT, this.fontColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_WEIGHT, FieldType.TEXT, this.fontWeight);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_NAME, FieldType.I18N, this.name);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_ICON, FieldType.BOOLEAN, this.inheritIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_NAME, FieldType.BOOLEAN, this.inheritName);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_ACTIVE, FieldType.BOOLEAN, this.isActive);
return outcome;
}
public ToDataSetOutcome toDataSet() {
ToDataSetOutcome outcome = new ToDataSetOutcome();
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ID, FieldType.TEXT, this.id);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_MENU_ITEM_LIST, FieldType.ENUMERATION_MAP, this.menuItems);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_INTERNAL, FieldType.BOOLEAN, this.isInternal);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_URL, FieldType.TEXT, this.externalUrl);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_EXTERNAL_ICON, FieldType.TEXT, this.externalIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ICON_COLOR, FieldType.TEXT, this.iconColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_ICON, FieldType.TEXT, this.itemIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_COLOR, FieldType.TEXT, this.fontColor);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_FONT_WEIGHT, FieldType.TEXT, this.fontWeight);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_ITEM_NAME, FieldType.I18N, this.name);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_ICON, FieldType.BOOLEAN, this.inheritIcon);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_INHERIT_NAME, FieldType.BOOLEAN, this.inheritName);
outcome.putDataSetEntry(DashboardItemConstants.FIELD_IS_ACTIVE, FieldType.BOOLEAN, this.isActive);
return outcome;
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java
between lines 37 and 53, the externalIcon field is incorrectly mapped with
FieldType.BOOLEAN while it is actually a String. Change the FieldType for
externalIcon from BOOLEAN to TEXT in the putDataSetEntry call to fix the type
mismatch.

Comment on lines +42 to +54
private boolean simpleDashboard = false;
/**
* should dashboard toolbar menu with profile.
*/
private boolean profileDashboard = false;
/**
* should dashboard toolbar contains menu with language selection
*/
private boolean languageDashboard = false;
/**
* should dashboard toolbar contains logout button.
*/
private boolean logoutDashboard = false;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add @Builder.Default to fix Builder warning.

The pipeline warning indicates that @builder will ignore the initializing expressions. Add @Builder.Default annotation to preserve the default values.

     /**
      * should dashboard toolbar contains menu with options.
      */
+    @Builder.Default
     private boolean simpleDashboard = false;
     /**
      * should dashboard toolbar menu with profile.
      */
+    @Builder.Default
     private boolean profileDashboard = false;
     /**
      * should dashboard toolbar contains menu with language selection
      */
+    @Builder.Default
     private boolean languageDashboard = false;
     /**
      * should dashboard toolbar contains logout button.
      */
+    @Builder.Default
     private boolean logoutDashboard = false;
🧰 Tools
🪛 GitHub Actions: Pull Request

[warning] 42-54: @builder will ignore the initializing expression entirely. Add @Builder.Default or make the field final to fix.

🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
around lines 42 to 54, the boolean fields have default values assigned but the
@Builder annotation ignores these initializations, causing a warning. To fix
this, add the @Builder.Default annotation to each of these boolean fields so
that their default values are preserved when using the builder pattern.

Comment on lines +67 to +69
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect null check - checking id instead of name.

The null check on line 67 checks this.id but should check this.name before setting the name field.

-        if (this.id != null) {
+        if (this.name != null) {
             outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
if (this.name != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
around lines 67 to 69, the null check incorrectly verifies this.id instead of
this.name before setting the name field. Change the condition to check if
this.name is not null before calling outcome.putDataSetEntry with this.name.

}
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_SIMPLE_DASHBOARD, FieldType.BOOLEAN, this.simpleDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_PROFILE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect field value - using profileDashboard instead of languageDashboard.

The language dashboard field is being set with the value of profileDashboard instead of languageDashboard.

-        outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
+        outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
at line 75, the field for language dashboard is incorrectly assigned the value
of profileDashboard. Replace the value passed to outcome.putDataSetEntry for
FIELD_LANGUAGE_DASHBOARD from this.profileDashboard to this.languageDashboard to
correctly set the language dashboard field.

Comment on lines +21 to +34
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();

fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix logical issues in putDataSetEntryWithOptions method.

The method has several logical problems:

  1. Overwriting field value: Lines 25-27 set value to Set.of() for MULTICHOICE_MAP, but line 32 unconditionally overwrites it with fieldValue.

  2. Redundant null handling: Lines 28-30 create a new HashMap for null options, but line 31 immediately overwrites the options variable.

  3. Inconsistent value handling: The MULTICHOICE_MAP special case suggests empty set as default, but this gets overwritten.

 public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
     Map<String, Object> fieldMap = new LinkedHashMap<>();
     
     fieldMap.put("type", fieldType.getName());
-    if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
-        fieldMap.put("value", Set.of());
-    }
+    
     if (options == null) {
         options = new HashMap<>();
     }
     fieldMap.put("options", options);
-    fieldMap.put("value", fieldValue);
+    
+    // Set default value for MULTICHOICE_MAP if no value provided
+    if (fieldValue == null && fieldType.equals(FieldType.MULTICHOICE_MAP)) {
+        fieldMap.put("value", Set.of());
+    } else {
+        fieldMap.put("value", fieldValue);
+    }
+    
     this.getDataSet().put(fieldId, fieldMap);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
// Set default value for MULTICHOICE_MAP if no value provided
if (fieldValue == null && fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
} else {
fieldMap.put("value", fieldValue);
}
this.getDataSet().put(fieldId, fieldMap);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java
between lines 21 and 34, fix the putDataSetEntryWithOptions method by ensuring
the "value" field is set correctly: for FieldType.MULTICHOICE_MAP, set "value"
to an empty set only if fieldValue is null, otherwise use fieldValue; remove the
redundant null check and reassignment of options by initializing options to an
empty map only if it is null before putting it into fieldMap; this prevents
overwriting the value and options incorrectly.

@coderabbitai coderabbitai bot added the Small label Jul 28, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

Comment on lines 85 to 125
/**
* Creates menu item case and it's configuration cases
*
* @param body data used for creation
* @return initialized menu item instance with the provided data
* @throws IllegalArgumentException if the provided menu identifier already exists
*/
@Override
public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
log.debug("Creation of menu item case with identifier [{}] started.", body.getIdentifier());
IUser loggedUser = userService.getLoggedOrSystem();
String sanitizedIdentifier = MenuItemUtils.sanitize(body.getIdentifier());

if (existsMenuItem(sanitizedIdentifier)) {
throw new IllegalArgumentException(String.format("Menu item identifier %s is not unique!", sanitizedIdentifier));
}

Case parentItemCase = getOrCreateFolderItem(body.getPath());

I18nString newName = body.getMenuName();
if (newName == null) {
newName = new I18nString(body.getIdentifier());
}
Case menuItemCase = createCase(FilterRunner.MENU_NET_IDENTIFIER, newName.getDefaultValue(),
loggedUser.transformToLoggedUser());
menuItemCase = workflowService.save(menuItemCase);

parentItemCase = appendChildCaseIdAndSave(parentItemCase, menuItemCase.getStringId());

Case viewCase = null;
if (body.hasView()) {
viewCase = createView(body.getView());
}

String nodePath = createNodePath(body.getPath(), sanitizedIdentifier);

ToDataSetOutcome dataSetOutcome = body.toDataSet(parentItemCase.getStringId(), nodePath, viewCase);
menuItemCase = setDataWithExecute(menuItemCase, MenuItemConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
log.debug("Created menu item case [{}] with identifier [{}].", menuItemCase.getStringId(), body.getIdentifier());
return menuItemCase;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding transaction management for atomicity.

The menu item creation involves multiple operations (case creation, parent update, view creation) that could leave the system in an inconsistent state if any step fails.

Consider wrapping the entire operation in a transaction or implementing compensating actions:

@Transactional
public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
    // existing implementation
}

Alternatively, implement rollback logic if view creation fails:

try {
    viewCase = createView(body.getView());
} catch (Exception e) {
    // Rollback: delete the created menu item and revert parent changes
    workflowService.deleteCase(menuItemCase);
    // Revert parent folder changes
    throw e;
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
between lines 85 and 125, the createMenuItem method performs multiple operations
that must be atomic to avoid inconsistent state if any step fails. To fix this,
annotate the method with @Transactional to ensure all database changes are
committed or rolled back together. Alternatively, add explicit rollback logic
around the view creation step by catching exceptions, deleting the created menu
item case, reverting any parent folder changes, and rethrowing the exception to
maintain consistency.

Comment on lines 719 to 725
IUser loggedUser = userService.getLoggedOrSystem();
String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
Task task = taskService.findOne(taskId);
task = taskService.assignTask(task, loggedUser).getTask();
task = dataService.setData(task, ImportHelper.populateDataset((Map) dataSet)).getTask();
return taskService.finishTask(task, loggedUser).getCase();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null safety checks in setDataWithExecute.

The method assumes the task exists but doesn't handle the case where it might be null.

 protected Case setDataWithExecute(Case useCase, String transId, Map<String, Map<String, Object>> dataSet) throws TransitionNotExecutableException {
     IUser loggedUser = userService.getLoggedOrSystem();
     String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
+    if (taskId == null) {
+        throw new IllegalStateException(String.format("Task with transition '%s' not found in case '%s'", transId, useCase.getStringId()));
+    }
     Task task = taskService.findOne(taskId);
+    if (task == null) {
+        throw new IllegalStateException(String.format("Task '%s' not found", taskId));
+    }
     task = taskService.assignTask(task, loggedUser).getTask();
     task = dataService.setData(task, ImportHelper.populateDataset((Map) dataSet)).getTask();
     return taskService.finishTask(task, loggedUser).getCase();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
IUser loggedUser = userService.getLoggedOrSystem();
String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
Task task = taskService.findOne(taskId);
task = taskService.assignTask(task, loggedUser).getTask();
task = dataService.setData(task, ImportHelper.populateDataset((Map) dataSet)).getTask();
return taskService.finishTask(task, loggedUser).getCase();
}
IUser loggedUser = userService.getLoggedOrSystem();
String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
if (taskId == null) {
throw new IllegalStateException(String.format(
"Task with transition '%s' not found in case '%s'",
transId, useCase.getStringId()));
}
Task task = taskService.findOne(taskId);
if (task == null) {
throw new IllegalStateException(String.format(
"Task '%s' not found",
taskId));
}
task = taskService.assignTask(task, loggedUser).getTask();
task = dataService.setData(
task,
ImportHelper.populateDataset((Map) dataSet)
).getTask();
return taskService.finishTask(task, loggedUser).getCase();
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
around lines 719 to 725, the method setDataWithExecute assumes the task
retrieved by taskService.findOne(taskId) is never null, which can cause
NullPointerExceptions. Add a null check after retrieving the task; if the task
is null, handle it appropriately, such as throwing an exception or returning
early. This ensures subsequent calls on the task object are safe.

Comment on lines +34 to +41
<event type="delete">
<id>view_delete</id>
<actions phase="pre">
<action id="0">
removeViewCase()
</action>
</actions>
</event>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider error handling for async view case deletion.

The removeViewCase function runs asynchronously but doesn't handle potential errors. If the deletion fails, it could leave orphaned cases.

Consider adding error handling:

async.run {
    try {
        workflowService.deleteCase(viewIdAsList[0])
    } catch (Exception e) {
        log.error("Failed to delete associated view case: ${viewIdAsList[0]}", e)
    }
}

Also applies to: 78-90

🤖 Prompt for AI Agents
In
application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml
around lines 34 to 41, the removeViewCase function is called asynchronously
without error handling, risking orphaned cases if deletion fails. Modify the
action to run the deletion inside an async block with a try-catch that logs any
exceptions, similar to the provided example. Apply the same error handling
pattern to lines 78 to 90 where similar async deletions occur.

Comment on lines +78 to +90
<function scope="process" name="removeViewCase">
{ ->

def viewIdAsList = useCase.dataSet['view_configuration_id'].value
if (viewIdAsList == null || viewIdAsList.isEmpty()) {
return
}

async.run {
workflowService.deleteCase(viewIdAsList[0])
}
}
</function>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling and logging to async view deletion.

The asynchronous removeViewCase function lacks error handling and logging, which could lead to silent failures and orphaned view cases.

 <function scope="process" name="removeViewCase">
     { ->
 
         def viewIdAsList = useCase.dataSet['view_configuration_id'].value
         if (viewIdAsList == null || viewIdAsList.isEmpty()) {
             return
         }
 
         async.run {
+            try {
+                log.info("Deleting associated view case: {}", viewIdAsList[0])
                 workflowService.deleteCase(viewIdAsList[0])
+                log.info("Successfully deleted view case: {}", viewIdAsList[0])
+            } catch (Exception e) {
+                log.error("Failed to delete associated view case: {}", viewIdAsList[0], e)
+                // Consider notifying administrators or implementing retry logic
+            }
         }
     }
 </function>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<function scope="process" name="removeViewCase">
{ ->
def viewIdAsList = useCase.dataSet['view_configuration_id'].value
if (viewIdAsList == null || viewIdAsList.isEmpty()) {
return
}
async.run {
workflowService.deleteCase(viewIdAsList[0])
}
}
</function>
<function scope="process" name="removeViewCase">
{ ->
def viewIdAsList = useCase.dataSet['view_configuration_id'].value
if (viewIdAsList == null || viewIdAsList.isEmpty()) {
return
}
async.run {
try {
log.info("Deleting associated view case: {}", viewIdAsList[0])
workflowService.deleteCase(viewIdAsList[0])
log.info("Successfully deleted view case: {}", viewIdAsList[0])
} catch (Exception e) {
log.error("Failed to delete associated view case: {}", viewIdAsList[0], e)
// Consider notifying administrators or implementing retry logic
}
}
}
</function>
🤖 Prompt for AI Agents
In
application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml
around lines 78 to 90, the async block in the removeViewCase function does not
handle errors or log failures. Wrap the call to workflowService.deleteCase in a
try-catch block inside the async.run closure, log any caught exceptions with
relevant error details, and ensure errors do not fail silently.

Comment on lines +148 to 184
public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCase) {
ToDataSetOutcome outcome = new ToDataSetOutcome();

// GENERIC
ArrayList<String> filterIdCaseRefValue = new ArrayList<>();
if (this.filter != null) {
filterIdCaseRefValue.add(this.filter.getStringId());
}
ArrayList<String> parentIdCaseRef = new ArrayList<>();
if (parentId != null) {
parentIdCaseRef.add(parentId);
outcome.putDataSetEntry(MenuItemConstants.FIELD_PARENT_ID, FieldType.CASE_REF, List.of(parentId));
}

if (nodePath != null) {
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH, FieldType.TEXT, nodePath);
}
if (!ignoreParentId) {
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_PARENT_ID, FieldType.CASE_REF, parentIdCaseRef);
outcome.putDataSetEntry(MenuItemConstants.FIELD_NODE_PATH, FieldType.TEXT, nodePath);
}
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_NAME, FieldType.I18N, this.menuName);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_MENU_ICON, FieldType.TEXT, this.menuIcon);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TAB_NAME, FieldType.I18N, this.tabName);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TAB_ICON, FieldType.TEXT, this.tabIcon);
outcome.putDataSetEntry(MenuItemConstants.FIELD_MENU_NAME, FieldType.I18N, this.menuName);
outcome.putDataSetEntry(MenuItemConstants.FIELD_MENU_ICON, FieldType.TEXT, this.menuIcon);
outcome.putDataSetEntry(MenuItemConstants.FIELD_USE_TABBED_VIEW, FieldType.BOOLEAN, this.useTabbedView);
outcome.putDataSetEntry(MenuItemConstants.FIELD_TAB_NAME, FieldType.I18N, this.tabName);
outcome.putDataSetEntry(MenuItemConstants.FIELD_TAB_ICON, FieldType.TEXT, this.tabIcon);
if (this.identifier != null) {
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_IDENTIFIER, FieldType.TEXT, this.getIdentifier());
outcome.putDataSetEntry(MenuItemConstants.FIELD_IDENTIFIER, FieldType.TEXT, this.getIdentifier());
}
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_FILTER_CASE, FieldType.CASE_REF, filterIdCaseRefValue);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_USE_TAB_ICON, FieldType.BOOLEAN, this.useTabIcon);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_USE_CUSTOM_VIEW, FieldType.BOOLEAN,
outcome.putDataSetEntry(MenuItemConstants.FIELD_USE_TAB_ICON, FieldType.BOOLEAN, this.useTabIcon);
outcome.putDataSetEntry(MenuItemConstants.FIELD_USE_CUSTOM_VIEW, FieldType.BOOLEAN,
this.useCustomView);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CUSTOM_VIEW_SELECTOR, FieldType.TEXT,
outcome.putDataSetEntry(MenuItemConstants.FIELD_CUSTOM_VIEW_SELECTOR, FieldType.TEXT,
this.customViewSelector);

// CASE
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
this.caseViewSearchType);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CREATE_CASE_BUTTON_TITLE, FieldType.TEXT,
this.createCaseButtonTitle);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CREATE_CASE_BUTTON_ICON, FieldType.TEXT,
this.createCaseButtonIcon);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_REQUIRE_TITLE_IN_CREATION, FieldType.BOOLEAN,
this.caseRequireTitleInCreation);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_SHOW_CREATE_CASE_BUTTON, FieldType.BOOLEAN,
this.showCreateCaseButton);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_BANNED_NETS_IN_CREATION, FieldType.TEXT,
this.bannedNetsInCreation);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_SHOW_MORE_MENU, FieldType.BOOLEAN,
this.caseShowMoreMenu);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
this.caseAllowHeaderTableMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
this.caseHeadersMode == null ? new ArrayList<>() : this.caseHeadersMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
this.caseHeadersDefaultMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_DEFAULT_HEADERS, FieldType.TEXT,
this.caseDefaultHeaders != null ? String.join(",", this.caseDefaultHeaders) : null);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_CASE_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
this.caseIsHeaderModeChangeable);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_USE_CASE_DEFAULT_HEADERS, FieldType.BOOLEAN,
this.caseUseDefaultHeaders);

// TASK
ArrayList<String> additionalFilterIdCaseRefValue = new ArrayList<>();
if (this.additionalFilter != null) {
additionalFilterIdCaseRefValue.add(this.additionalFilter.getStringId());
outcome.putDataSetEntry(MenuItemConstants.FIELD_IS_AUTO_SELECT, FieldType.BOOLEAN, this.isAutoSelect);
outcome.putDataSetEntryOptions(MenuItemConstants.FIELD_ALLOWED_ROLES, FieldType.MULTICHOICE_MAP, this.allowedRoles);
outcome.putDataSetEntryOptions(MenuItemConstants.FIELD_BANNED_ROLES, FieldType.MULTICHOICE_MAP, this.bannedRoles);

if (viewCase != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
this.view.getViewType().getIdentifier());
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID, FieldType.CASE_REF,
List.of(viewCase.getStringId()));
String taskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_SETTINGS_ID);
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
}

putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_ADDITIONAL_FILTER_CASE, FieldType.CASE_REF,
additionalFilterIdCaseRefValue);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_MERGE_FILTERS, FieldType.BOOLEAN,
this.mergeFilters);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
this.taskViewSearchType);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
this.taskHeadersMode == null ? new ArrayList<>() : this.taskHeadersMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
this.taskHeadersDefaultMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
this.taskIsHeaderModeChangeable);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
this.taskAllowHeaderTableMode);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_USE_TASK_DEFAULT_HEADERS, FieldType.BOOLEAN,
this.taskUseDefaultHeaders);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_DEFAULT_HEADERS, FieldType.TEXT,
this.taskDefaultHeaders != null ? String.join(",", this.taskDefaultHeaders) : null);
putDataSetEntry(dataSet, MenuItemConstants.PREFERENCE_ITEM_FIELD_TASK_SHOW_MORE_MENU, FieldType.BOOLEAN,
this.taskShowMoreMenu);

return dataSet;
return outcome;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding validation for required fields in toDataSet.

While the method handles optional fields well, it doesn't validate that required fields (like menuName) are not null.

Add validation at the beginning of the main toDataSet method:

 public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCase) {
+    if (this.menuName == null || this.menuName.getDefaultValue() == null || this.menuName.getDefaultValue().isEmpty()) {
+        throw new IllegalStateException("Menu name is required but not set");
+    }
     ToDataSetOutcome outcome = new ToDataSetOutcome();

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java
between lines 148 and 184, the toDataSet method lacks validation for required
fields such as menuName. Add validation at the start of the method to check if
menuName (and any other required fields) is null, and if so, throw an
appropriate exception or handle the error to prevent proceeding with invalid
data.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 35

🔭 Outside diff range comments (3)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

202-205: Update to use new MenuItemConstants.

The code still references old PREFERENCE_ITEM_FIELD_* constants. These should be updated to use the new FIELD_* constants for consistency.

-        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]
+        Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.${MenuItemConstants.FIELD_NODE_PATH}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]

-        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList<String>
+        ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS].value as ArrayList<String>
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

2412-2421: Type inconsistency in role collection method.

The ProcessRole version returns plain strings in the map values, but the method signature indicates it should return Map<String, I18nString>. This will cause a ClassCastException at runtime.

Apply this fix to properly return I18nString objects:

 Map<String, I18nString> collectRolesForPreferenceItem(List<ProcessRole> roles) {
     return roles.collectEntries { ProcessRole role ->
         if (role.isGlobal()) {
-            return [(role.importId + ":" + GLOBAL_ROLE), ("$role.name (🌍 Global role)" as String)]
+            return [(role.importId + ":" + GLOBAL_ROLE), new I18nString("$role.name (🌍 Global role)" as String)]
         } else {
             PetriNet net = petriNetService.get(new ObjectId(role.netId))
-            return [(role.importId + ":" + net.identifier), ("$role.name ($net.title)" as String)]
+            return [(role.importId + ":" + net.identifier), new I18nString("$role.name ($net.title)" as String)]
         }
     } as Map<String, I18nString>
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

51-58: Inconsistent title assignment in update method.

The update method assigns the title directly from the parameter without using the transformToField method, unlike the constructor. This inconsistency could lead to type mismatches since the constructor expects I18nString but transforms it to I18nField, while update expects the parameter to already be I18nField.

Consider applying this fix to ensure consistency:

 public void update(ElasticPetriNet net) {
     this.version = net.getVersion();
     if (net.getUriNodeId() != null) {
         this.uriNodeId = net.getUriNodeId();
     }
-    this.title = net.getTitle();
+    // Note: Title is already I18nField type in the parameter
+    this.title = net.getTitle();
     this.initials = net.getInitials();
 }

Or if the parameter should contain I18nString, the method signature and implementation need to be updated accordingly.

🧹 Nitpick comments (26)
application-engine/src/main/resources/application.yaml (1)

161-162: Prefer list syntax for actions.imports to aid readability & diff-friendliness

Current single-line value is valid but hard to maintain when classes change.

-    actions:
-      imports: com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody,com.netgrif.application.engine.objects.petrinet.domain.I18nString,com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody
+    actions:
+      imports:
+        - com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody
+        - com.netgrif.application.engine.objects.petrinet.domain.I18nString
+        - com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody

Also verify that another netgrif.engine.actions.imports property is not defined elsewhere to avoid accidental override.

application-engine/CHANGELOG.md (1)

8-21: Duplicate/incorrect “Full Changelog” link

Line 21 still points to v7.0.0 inside the new 6.5.0 section; readers may be confused.

- - Full Changelog: https://github.com/netgrif/application-engine/commits/v7.0.0
+ - Full Changelog: https://github.com/netgrif/application-engine/commits/v6.5.0
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (2)

15-16: Remove unused imports.

The imports for HashSet and Set are not used in this class.

-import java.util.HashSet;
-import java.util.Set;

15-16: Remove unused imports.

The imports for HashSet and Set are not used in this class and should be removed to keep the code clean.

-import java.util.HashSet;
-import java.util.Set;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1)

21-34: LGTM! Good null safety and structure, but consider removing redundant initialization.

The method handles null options properly and uses appropriate data structures. However, there's a redundant operation on lines 25-27.

         fieldMap.put("type", fieldType.getName());
-        if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
-            fieldMap.put("value", Set.of());
-        }
         if (options == null) {
             options = new HashMap<>();
         }
         fieldMap.put("options", options);
         fieldMap.put("value", fieldValue);

The empty Set initialization is immediately overwritten by fieldValue on line 32, making it redundant. If you need special handling for MULTICHOICE_MAP when fieldValue is null, consider:

         fieldMap.put("options", options);
         fieldMap.put("value", fieldType.equals(FieldType.MULTICHOICE_MAP) && fieldValue == null ? Set.of() : fieldValue);
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1)

28-33: Consider making helper method private and handling return value.

The createMainDashboardManagementItem() method is only used internally and its return value is unused in the run() method.

Apply this diff to improve encapsulation:

-    def createMainDashboardManagementItem() {
+    private def createMainDashboardManagementItem() {
         def dashboardItemBody = new DashboardManagementBody("main_dashboard", new I18nString("Main Dashboard",Map.of("sk","Hlavný Dashboard","de","Haupt-Dashboard")))
         dashboardItemBody.setLogoutDashboard(true)
 
-        return dashboardManagementService.createDashboardManagement(dashboardItemBody)
+        dashboardManagementService.createDashboardManagement(dashboardItemBody)
     }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (2)

4-4: Fix the comment to reference the correct process.

The comment mentions "dashboard_management.xml" but should reference "dashboard_item.xml" based on the PROCESS_IDENTIFIER constant.

-/**
- * Here are declared constants of process dashboard_management.xml.
- */
+/**
+ * Here are declared constants of process dashboard_item.xml.
+ */

9-9: Add space for formatting consistency.

Missing space after the equals sign for consistency with other field declarations.

-    public static final String FIELD_ID= "item_id";
+    public static final String FIELD_ID = "item_id";
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1)

50-50: Fix Javadoc reference.

The Javadoc comment references IDataService but the class is not imported. Either add the import or use the fully qualified class name in the Javadoc.

- * Transforms attributes into dataSet for {@link IDataService#setData}
+ * Transforms attributes into dataSet for IDataService#setData
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

3-3: Remove unused Lombok import.

The @Getter annotation from Lombok is imported but not used in this constants class.

- import lombok.Getter;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1)

44-55: Consider making MULTICHOICE_MAP handling more extensible.

The special case handling for MULTICHOICE_MAP field type is hardcoded. Consider making this more configurable or document why this specific type requires empty set initialization.

 public void putDataSetEntryOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options) {
+    if (fieldId == null || fieldId.trim().isEmpty()) {
+        throw new IllegalArgumentException("fieldId cannot be null or empty");
+    }
     Map<String, Object> fieldMap = new LinkedHashMap<>();
     fieldMap.put("type", fieldType.getName());
     if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
+        // Initialize with empty set for MULTICHOICE_MAP to ensure proper UI behavior
         fieldMap.put("value", Set.of());
     }
     if (options == null) {
         options = new HashMap<>();
     }
     fieldMap.put("options", options);
     this.dataSet.put(fieldId, fieldMap);
 }
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1)

100-103: Remove unused method.

The setData method is not used anywhere in this class and appears to be dead code.

Consider removing this method if it's not needed, or document its intended use if it's meant for future functionality.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1)

52-59: Improve exception message for better debugging.

The IllegalArgumentException should include a descriptive message.

 public static MenuItemView fromIdentifier(String identifier) {
     for (MenuItemView view : MenuItemView.values()) {
         if (view.identifier.equals(identifier)) {
             return view;
         }
     }
-    throw new IllegalArgumentException(identifier);
+    throw new IllegalArgumentException("Unknown MenuItemView identifier: " + identifier);
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1)

54-56: Remove redundant semicolon.

 public ToDataSetOutcome toDataSet() {
     return toDataSet(null, null);
-};
+}
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

16-40: Add JavaDoc documentation for interface methods.

The interface methods lack documentation. Consider adding JavaDoc to describe the purpose, parameters, return values, and exception conditions for each method.

Example for one method:

/**
 * Creates a new filter case based on the provided filter body.
 *
 * @param body the filter configuration containing all necessary data
 * @return the created filter case
 * @throws TransitionNotExecutableException if the filter creation workflow cannot be executed
 */
Case createFilter(FilterBody body) throws TransitionNotExecutableException;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1)

73-79: Avoid catching NullPointerException.

Catching NullPointerException is generally considered bad practice. Consider explicit null checking instead.

 public static List<String> getCaseIdsFromCaseRef(Case useCase, String caseRefId) {
-    try {
-        return (List<String>) useCase.getFieldValue(caseRefId);
-    } catch (NullPointerException ignore) {
-        return null;
-    }
+    if (useCase == null || caseRefId == null) {
+        return null;
+    }
+    Object fieldValue = useCase.getFieldValue(caseRefId);
+    return fieldValue instanceof List ? (List<String>) fieldValue : null;
 }
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1)

40-45: Consider using constructor injection over field injection

The class uses field injection with @RequiredArgsConstructor. While this works with Lombok, constructor injection is generally preferred as it makes dependencies explicit and facilitates testing.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1)

42-67: Improve null check consistency in filter function

The null check on line 59 uses both != for null comparison. Consider using a more consistent and explicit approach.

-    return findFilters(filterAutocomplete.value != null ? filterAutocomplete.value : "")
+    return findFilters(filterAutocomplete.value ?: "")
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

39-87: Consider using Builder pattern instead of multiple constructors

The class has 6 constructors with different parameter combinations, which can be confusing for API users. Consider implementing a Builder pattern for better maintainability and clearer object construction.

Would you like me to generate a Builder implementation for this class?

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

47-48: Consider moving DEFAULT_FOLDER_ICON to MenuItemConstants.

For better organization and consistency with other constants in the codebase, consider moving this static field to the MenuItemConstants class.

application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (2)

92-124: Consider performance impact of double-fetch pattern.

The method first searches in Elasticsearch then fetches full PetriNet objects by ID. While this ensures data consistency, it may impact performance for large result sets. Consider caching or returning lightweight references if full objects aren't always needed.


168-168: Wildcard queries may impact performance.

Using leading wildcards (*searchText*) can be very inefficient in Elasticsearch as it prevents the use of indexes effectively. Consider using edge n-gram tokenizers or other text analysis strategies for better performance.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (1)

109-110: Use more idiomatic Groovy for map population.

The forEach loops can be replaced with more idiomatic Groovy code.

-                    keysDashboard.forEach { newOrderDashboard[it] = dashboard_item_list.options[it]}
-                    keysMenu.forEach { newOrderMenu[it] = dashboard_item_to_menu_item.options[it]}
+                    keysDashboard.each { key -> newOrderDashboard[key] = dashboard_item_list.options[key] }
+                    keysMenu.each { key -> newOrderMenu[key] = dashboard_item_to_menu_item.options[key] }

Also applies to: 147-148

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1)

418-427: Redundant i18n key – potential translation mismatch

Both use_default_headers and use_case_default_headers appear in the Slovak
bundle, but only the latter corresponds to an existing data field
(id="use_case_default_headers"). Keeping unused keys adds noise and increases
maintenance overhead. Please remove the superfluous entry or confirm it is
indeed required elsewhere.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

1723-1827: Legacy createMenuItem methods properly deprecated and refactored.

The deprecated methods correctly delegate to the new service while maintaining backward compatibility. Consider adding deprecation messages with migration guidance to help users transition to the new API patterns.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (1)

7-14: Add JavaDoc documentation for better API clarity.

The interface methods would benefit from JavaDoc documentation to clarify their behavior, parameters, return values, and exceptions.

+/**
+ * Service interface for managing dashboard item cases.
+ */
 public interface DashboardItemService {
 
+    /**
+     * Gets an existing dashboard item case or creates a new one if it doesn't exist.
+     * 
+     * @param body the dashboard item body containing configuration
+     * @return the existing or newly created case
+     * @throws TransitionNotExecutableException if case creation/update fails
+     */
     Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableException;
 
+    /**
+     * Updates an existing dashboard item case with new configuration.
+     * 
+     * @param itemCase the existing case to update
+     * @param body the new configuration
+     * @return the updated case
+     * @throws TransitionNotExecutableException if the update fails
+     */
     Case update(Case itemCase, DashboardItemBody body) throws TransitionNotExecutableException;
 
+    /**
+     * Finds a dashboard item case by its identifier.
+     * 
+     * @param identifier the case identifier
+     * @return the found case or null if not found
+     */
     Case findById(String identifier);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcbb9a1 and 7a85f22.

📒 Files selected for processing (62)
  • application-engine/CHANGELOG.md (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (40 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (5 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1 hunks)
  • application-engine/src/main/resources/application.yaml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (7 hunks)
  • application-engine/src/test/resources/dashboard_management_test.xml (1 hunks)
  • application-engine/src/test/resources/petriNets/filter_api_test.xml (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (4 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (3 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1 hunks)
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (3 hunks)
💤 Files with no reviewable changes (9)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java
🧰 Additional context used
🧠 Learnings (26)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/application.yaml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/resources/petriNets/filter_api_test.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

🪛 GitHub Actions: Pull Request
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java

[warning] 42-54: @builder will ignore the initializing expression entirely. Add @Builder.Default or make the field final to fix this.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (71)
application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1)

122-124: No-op change – looks good

Only an extra blank line was introduced; there is no impact on behaviour or style consistency.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

1-5: Empty constants class – is it required?

TabbedTicketViewConstants adds no fields beyond its parent. If nothing is planned shortly, consider removing it to avoid dead code.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

4-6: Constant definition is concise and correct

The field name and casing are consistent with other constants classes in the module.

nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (1)

67-73: LGTM! Well-implemented transformation method.

The transformToField method correctly transforms an I18nString to an I18nField by properly extracting keys, values, and translations while ensuring encapsulation through new collection instances.

application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1)

419-419: LGTM! Correct adaptation to updated object model.

The change from it._id.eq(...) to it._id.objectId.eq(...) properly aligns with the updated object model where _id now contains an objectId property. This ensures correct case matching in the filter initialization logic.

application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (1)

22-22: LGTM! Well-designed search interface.

The new search method provides a comprehensive interface for Petri net searching with proper parameters for criteria, user context, pagination, locale, and intersection logic. The return type Page<PetriNetReference> follows Spring Data conventions for paginated results.

application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1)

249-263: LGTM! Excellent centralization of import logic.

The new importProcess method provides a clean, reusable approach to Petri net importing with proper existence checking, error handling, and logging. This centralization will improve consistency across startup runners and reduce code duplication.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (2)

1-16: LGTM! Well-structured constants class following good practices.

The constants are well-organized with clear naming conventions and serve as a centralized container for menu item configuration values. The separation between field constants (FIELD_) and transition constants (TRANS_) provides good logical grouping.


1-16: LGTM! Well-structured constants class.

The implementation follows Java best practices for constants classes with clear naming conventions and proper documentation. The logical grouping of field constants (lines 7-11) and transition constants (lines 13-15) makes the class easy to maintain and understand.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (2)

60-60: LGTM! Good abstraction for type transformation.

The abstract method enforces subclasses to provide their own transformation logic from I18nString to I18nField, which maintains flexibility while ensuring type safety.


60-60: Good abstraction design.

The abstract method transformToField properly enforces subclasses to provide the transformation logic from I18nString to I18nField, which aligns well with the refactoring goals.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (3)

13-31: LGTM! Well-structured configuration class with sensible defaults.

The class design follows good practices with proper use of Lombok annotations, inheritance, and composition via the chainedView property. The default values are reasonable for a tabbed case view configuration.


44-74: Excellent dataset transformation implementation.

The toDataSetInternal method properly handles the conversion of all configuration properties to dataset entries with appropriate field types. The use of constants and null-safe operations shows good defensive programming practices.


16-41: Well-designed view configuration class.

The class follows good object-oriented principles with:

  • Appropriate use of inheritance from ViewBody
  • Sensible default values for configuration properties
  • Clean implementation of abstract methods
  • Support for view chaining through chainedView property
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (2)

7-14: LGTM! Clean and well-designed service interface.

The interface follows good practices with:

  • Clear method naming that indicates purpose
  • Consistent use of DashboardItemBody as the data transfer object
  • Appropriate exception handling for workflow operations
  • Standard service pattern implementation

The method signatures are logical and align well with the service layer architecture for dashboard management.


1-6: Well-structured service interface.

The interface follows good service layer design principles with clear method signatures, appropriate use of domain objects, and proper exception handling.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

1-16: LGTM! Well-structured constants class.

The implementation follows Java best practices with proper constant declarations, consistent naming conventions, and clear documentation referencing the associated process file.

application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (1)

10-14: Good use of conditional startup runner.

The implementation properly uses @ConditionalOnProperty with matchIfMissing = true to allow the feature to be disabled while defaulting to enabled. The runner order ensures proper sequencing during startup.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

10-31: LGTM! Clean implementation following established patterns.

The class properly extends ViewBody with appropriate Lombok annotations and method overrides. The implementation is consistent with the view configuration pattern used throughout the codebase.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1)

7-14: LGTM! Well-designed service interface.

The interface follows clean architecture principles with clear method signatures, proper exception handling, and focused responsibility for dashboard management operations.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1)

1-30: LGTM! Clean implementation following established patterns.

The TabbedTicketViewBody class properly extends ViewBody and implements the required abstract methods correctly. The use of Lombok annotations is appropriate, and the chained view functionality aligns with the broader menu item view configuration architecture.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

1-20: LGTM! Well-structured constants class.

The constants are well-organized and follow consistent naming conventions. The class provides a centralized reference for dashboard management process identifiers and field names, which will ensure consistency across the codebase.

application-engine/src/test/resources/dashboard_management_test.xml (1)

1-55: LGTM! Comprehensive integration test for dashboard management.

The test resource effectively exercises the new dashboard management functionality, including:

  • Filter and menu item creation with chained view configuration
  • Dashboard item creation and association
  • Dashboard management case updates

The Groovy script demonstrates proper usage of the new domain classes and service methods introduced in the refactoring.

application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1)

73-75: LGTM! Proper dependency injection.

The new IElasticPetriNetService dependency is properly injected and will be used by the new elastic search endpoint.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

1-22: LGTM! Well-structured constants class.

The constants are well-organized with consistent naming conventions and comprehensive coverage of tabbed case view configuration fields. The documentation clearly explains the purpose, and the structure aligns with the broader refactoring effort.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1)

54-72: LGTM! Solid data transformation implementation.

The toDataSet() method properly maps all fields to their corresponding dataset entries with appropriate field types. The null metadata handling with fallback to defaults is well-implemented.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

37-53: Well-structured data transformation method.

The toDataSet() method provides comprehensive mapping of all dashboard item properties to dataset entries. The implementation is consistent and follows the established pattern.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

5-22: LGTM! Comprehensive filter constants.

The constants are well-organized and provide comprehensive coverage of filter-related identifiers, transitions, and configuration values. The naming convention is consistent and the values are appropriate for their intended usage.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (2)

29-32: Verify the null return in getAssociatedViewBody().

The method returns null which may be intentional, but please verify this is the correct behavior for tabbed task views, especially since other view body implementations might have associated views.


40-62: LGTM! Solid data transformation implementation.

The toDataSetInternal() method properly maps all configuration fields to dataset entries with appropriate field types. The null handling for collections (lines 47, 57) is well-implemented, ensuring safe data transformation.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1)

23-27: LGTM!

Constants are properly defined with clear naming conventions and consistent file path patterns.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (4)

76-103: LGTM!

The test correctly validates menu item creation with the new constants and properly asserts the tabbed view configuration, including the hierarchical relationship between tabbed case and task views.


127-169: LGTM!

The test properly validates that view configurations are preserved during menu item updates, ensuring backward compatibility and data integrity.


265-296: LGTM!

The test correctly validates menu item duplication with proper error handling and field validation using the new constants.


327-356: LGTM!

Excellent test coverage for the deletion cascade, properly verifying that all related entities (menu items, tabbed case views, and tabbed task views) are deleted.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (2)

60-74: LGTM!

The dynamic import of configuration nets based on MenuItemView enum values is well-implemented with proper stream operations and error handling.


52-58: LGTM!

The visibility change to package-private improves testability, and returning Optional<PetriNet> provides better API design by making the nullable return explicit.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (2)

14-41: LGTM!

The interface provides a comprehensive API for menu item management with well-defined methods and appropriate exception handling.


50-70: LGTM!

The default methods provide convenient helpers for view retrieval with proper filtering and transformation logic.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (4)

19-28: LGTM!

The sanitization method properly handles null input and correctly removes diacritical marks, special characters, and normalizes the string.


37-51: LGTM!

The method correctly finds tasks by transition ID with proper null handling and defensive programming.


98-100: LGTM!

Clear and concise helper method that properly delegates to the underlying utility method.


106-109: LGTM!

The method correctly checks for folder children with proper null and empty list handling.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

7-39: LGTM! Well-structured constants class

The refactoring from enum to a constants class with static final strings is implemented correctly. This aligns with the previous learning about making the structure more generic and flexible for different use cases.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1)

226-278: Well-structured transition configuration

The settings transition is properly restricted to admin users with appropriate permissions (perform, view, cancel, assign). The UI layout using a grid system with material design templates is clean and maintainable.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

89-91: Avoid side effects in getter method

The getIdentifier() method calls MenuItemUtils.sanitize() which may modify the identifier. Getters should be pure functions without side effects. Consider sanitizing the identifier when it's set, not when it's retrieved.

+private String sanitizedIdentifier;
+
+public void setIdentifier(String identifier) {
+    this.identifier = identifier;
+    this.sanitizedIdentifier = MenuItemUtils.sanitize(identifier);
+}
+
 public String getIdentifier() {
-    return MenuItemUtils.sanitize(this.identifier);
+    return this.sanitizedIdentifier != null ? this.sanitizedIdentifier : MenuItemUtils.sanitize(this.identifier);
 }
⛔ Skipped due to learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (2)

701-730: Well-implemented validation logic

The finish event validation properly checks all required fields based on whether the item is internal or external, with clear error messages for each validation failure.


47-65: Improve robustness of string manipulation in delete handler

The string split/join operations for items_order field could be more robust with null checks and error handling.

 def itemsOrder = refCase.dataSet["items_order"].value.split(",") as ArrayList
-itemsOrder.remove(useCase.stringId)
+if (itemsOrder != null && !itemsOrder.isEmpty()) {
+    itemsOrder.remove(useCase.stringId)
+}

 def dashboardItemsListOptions = refCase.dataSet["dashboard_item_list"].options
-dashboardItemsListOptions.remove(useCase.stringId)
+if (dashboardItemsListOptions != null) {
+    dashboardItemsListOptions.remove(useCase.stringId)
+}

Likely an incorrect or invalid review comment.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (3)

55-66: LGTM!

The filter creation logic is well-structured with proper error handling and logging.


92-125: LGTM!

Well-implemented menu item creation with proper validation, parent-child relationship handling, and optional view support.


712-715: LGTM!

The unchecked warnings suppression is justified for these generic Map operations.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (2)

42-68: LGTM!

The filter autocomplete function correctly validates filter types and handles edge cases properly.


373-718: LGTM!

The Petri net structure is well-defined with appropriate role restrictions and proper state transitions.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (1)

158-163: LGTM!

The filter type validation correctly ensures only Case-type filters are used for the ticket view.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (2)

40-55: LGTM!

The dashboard ID uniqueness validation is properly implemented with checks at both set and finish events, ensuring data integrity.

Also applies to: 690-698


199-269: LGTM!

The add/remove item logic properly maintains data consistency and handles both internal and external dashboard items correctly.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

296-307: menu_name_as_visible uses enumeration but is mutated like enumeration_map

The script calls change menu_name_as_visible choices { … }, yet
menu_name_as_visible is declared as type="enumeration". Standard PetriFlow
enumeration fields expose the property options, not choices.

If the engine treats this as an error it will silently ignore the update and
the menu entry will never display the translated title.

Confirm the intended type:

-<data type="enumeration">
+<data type="enumeration_map">

or adjust the script to options.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (13)

29-31: LGTM! Import additions align with the new service architecture.

The new imports properly support the transition to a service-oriented approach for menu item, filter, and dashboard management. The domain model imports and utility classes are appropriately added for the refactored functionality.

Also applies to: 35-38, 47-47, 56-64, 74-74


205-212: Service dependencies properly injected.

The autowired services follow Spring conventions and support the delegation pattern for menu item, filter, and dashboard management operations.


933-936: Convenient case lookup method added.

Good addition of an intuitive findCase(String) method that improves API usability.


1617-1628: Filter creation properly refactored to use service delegation.

The implementation correctly builds a FilterBody and delegates to the menu item service, maintaining backward compatibility while embracing the new architecture.


1879-1925: Menu item change operations properly updated for new constants structure.

The refactoring correctly uses the new MenuItemConstants structure and maintains consistent delegation patterns. The removal of .value suffix improves code readability.


2110-2207: Well-structured view configuration helper methods.

The new static helper methods provide clean abstractions for creating different view configurations. They properly support the tabbed view architecture and chained view patterns.


2339-2361: Dashboard management methods properly implemented.

The new dashboard-related methods follow consistent patterns and provide clean delegation to the respective services.


2242-2302: Menu item operations properly delegated to service layer.

All menu item operations now consistently delegate to the menuItemService, improving separation of concerns and maintainability.


1970-2095: Filter creation methods properly migrated to use FilterBody.

The methods correctly build FilterBody objects and maintain backward compatibility. The deprecation of legacy signatures guides users toward the newer patterns.


2495-2642: Create-or-update methods properly refactored with clear deprecation timeline.

Good use of @Deprecated(since = "6.5.0") to provide version context. The methods correctly delegate to the service layer while maintaining backward compatibility.


2210-2224: Path manipulation methods properly updated for new constants.

The removal of .value suffix from MenuItemConstants usage improves code readability while maintaining the same functionality.

Also applies to: 2714-2757


2694-2696: Default filter metadata logic properly centralized.

Good delegation to FilterBody.getDefaultMetadata(), keeping the metadata logic where it belongs.


2698-2700: Menu hierarchy management method added.

The new method properly delegates parent-child relationship management to the service layer.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1)

17-20: Good extension design with proper annotations.

The class properly extends ToDataSetOutcome with appropriate Lombok annotations and follows the established pattern for dataset outcome classes.

Comment on lines 17 to 21
@RequiredArgsConstructor
class DefaultDashboardRunner implements ApplicationEngineStartupRunner {

@Autowired
private DashboardManagementService dashboardManagementService
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove redundant dependency injection annotations.

Using both @RequiredArgsConstructor and @Autowired is redundant. Choose one approach for consistency.

Apply this diff to use constructor injection consistently:

-@RequiredArgsConstructor
 class DefaultDashboardRunner implements ApplicationEngineStartupRunner {
 
-    @Autowired
-    private DashboardManagementService dashboardManagementService
+    private final DashboardManagementService dashboardManagementService
+    
+    DefaultDashboardRunner(DashboardManagementService dashboardManagementService) {
+        this.dashboardManagementService = dashboardManagementService
+    }
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
around lines 17 to 21, remove the @Autowired annotation from the
DashboardManagementService field since @RequiredArgsConstructor already
generates a constructor for dependency injection. Use only constructor injection
by relying on @RequiredArgsConstructor and make the field final if needed for
clarity.

Comment on lines 56 to 71
public Case createDashboardManagement(DashboardManagementBody body) throws TransitionNotExecutableException {
Case managementCase;
MenuItemUtils.sanitize(body.getId());

managementCase = findDashboardManagement(body.getId());
if (managementCase != null) {
log.info("Dashboard management with id:{} already exists", body.getId());
return managementCase;
}
addReferencedMenuItems(body);
LoggedUser loggedUser = userService.getLoggedOrSystem().transformToLoggedUser();
managementCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase();
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Handle potential null PetriNet and clarify parameter mutation

  1. The MenuItemUtils.sanitize(body.getId()) call on line 58 appears to modify the body object's ID, which is a side effect not indicated by the method signature.
  2. The petriNetService.getNewestVersionByIdentifier() call on line 67 could potentially return null if no PetriNet is found.

🏁 Script executed:

#!/bin/bash
# Check if MenuItemUtils.sanitize modifies the input or returns a sanitized value
ast-grep --pattern 'class MenuItemUtils {
  $$$
  sanitize($_) {
    $$$
  }
  $$$
}'

# Check if getNewestVersionByIdentifier can return null
rg -A 5 "getNewestVersionByIdentifier" --type java

Length of output: 16918


I’ll check how sanitize is implemented to confirm if it mutates its input.


🏁 Script executed:

#!/bin/bash
# Locate the MenuItemUtils source file
file=$(rg -l "class MenuItemUtils" -n)

echo "Found MenuItemUtils at: $file"
# Show the sanitize method definition and body
rg -A5 -n "sanitize" "$file"

Length of output: 862


Assign the sanitized ID and guard against missing PetriNet

The call to MenuItemUtils.sanitize(body.getId()) returns a sanitized String and does not mutate the body object—its return value is currently ignored. Also, getNewestVersionByIdentifier(...) can return null, leading to an NPE on .getStringId().

Please update:

  • Replace the standalone sanitize call with an assignment (or setter) so you actually use the sanitized ID.
  • Add a null check for the returned PetriNet before calling .getStringId(), throwing or handling the error appropriately.

Locations to update:

  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java

Suggested diff:

@@ createDashboardManagement(DashboardManagementBody body)
-        MenuItemUtils.sanitize(body.getId());
+        // actually apply the sanitized ID
+        body.setId(MenuItemUtils.sanitize(body.getId()));

@@
-        managementCase = workflowService.createCase(
-            petriNetService.getNewestVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER)
-                .getStringId(),
-            body.getName().getDefaultValue(), "", loggedUser)
-            .getCase();
+        // guard against missing process definition
+        PetriNet net = petriNetService.getNewestVersionByIdentifier(
+            DashboardManagementConstants.PROCESS_IDENTIFIER);
+        if (net == null) {
+            throw new IllegalStateException("Missing PetriNet for identifier: "
+                + DashboardManagementConstants.PROCESS_IDENTIFIER);
+        }
+        managementCase = workflowService.createCase(
+            net.getStringId(),
+            body.getName().getDefaultValue(), "", loggedUser)
+            .getCase();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public Case createDashboardManagement(DashboardManagementBody body) throws TransitionNotExecutableException {
Case managementCase;
MenuItemUtils.sanitize(body.getId());
managementCase = findDashboardManagement(body.getId());
if (managementCase != null) {
log.info("Dashboard management with id:{} already exists", body.getId());
return managementCase;
}
addReferencedMenuItems(body);
LoggedUser loggedUser = userService.getLoggedOrSystem().transformToLoggedUser();
managementCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase();
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
public Case createDashboardManagement(DashboardManagementBody body) throws TransitionNotExecutableException {
Case managementCase;
// actually apply the sanitized ID
body.setId(MenuItemUtils.sanitize(body.getId()));
managementCase = findDashboardManagement(body.getId());
if (managementCase != null) {
log.info("Dashboard management with id:{} already exists", body.getId());
return managementCase;
}
addReferencedMenuItems(body);
LoggedUser loggedUser = userService.getLoggedOrSystem().transformToLoggedUser();
// guard against missing process definition
PetriNet net = petriNetService.getNewestVersionByIdentifier(
DashboardManagementConstants.PROCESS_IDENTIFIER);
if (net == null) {
throw new IllegalStateException("Missing PetriNet for identifier: "
+ DashboardManagementConstants.PROCESS_IDENTIFIER);
}
managementCase = workflowService.createCase(
net.getStringId(),
body.getName().getDefaultValue(),
"",
loggedUser)
.getCase();
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
around lines 56 to 71, the sanitized ID returned by
MenuItemUtils.sanitize(body.getId()) is not assigned back to the body, so the
sanitized value is not used; assign the sanitized string back to the body ID
using the appropriate setter or assignment. Additionally, the call to
petriNetService.getNewestVersionByIdentifier(...) can return null, which causes
a NullPointerException when calling getStringId(); add a null check for the
returned PetriNet object and handle the null case by throwing an exception or
returning an error before proceeding.

Comment on lines +80 to +87
@Override
public Case updateDashboardManagement(Case managementCase, DashboardManagementBody body) throws TransitionNotExecutableException {
MenuItemUtils.sanitize(body.getId());
addReferencedMenuItems(body);
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for managementCase parameter

The method should validate that the managementCase parameter is not null before proceeding with the update.

 public Case updateDashboardManagement(Case managementCase, DashboardManagementBody body) throws TransitionNotExecutableException {
+    if (managementCase == null) {
+        throw new IllegalArgumentException("Management case cannot be null");
+    }
     MenuItemUtils.sanitize(body.getId());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Override
public Case updateDashboardManagement(Case managementCase, DashboardManagementBody body) throws TransitionNotExecutableException {
MenuItemUtils.sanitize(body.getId());
addReferencedMenuItems(body);
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
@Override
public Case updateDashboardManagement(Case managementCase, DashboardManagementBody body) throws TransitionNotExecutableException {
if (managementCase == null) {
throw new IllegalArgumentException("Management case cannot be null");
}
MenuItemUtils.sanitize(body.getId());
addReferencedMenuItems(body);
ToDataSetOutcome outcome = body.toDataSet();
managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet());
return managementCase;
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
around lines 80 to 87, add a null check for the managementCase parameter at the
start of the updateDashboardManagement method. If managementCase is null, throw
an appropriate exception or handle the case to prevent NullPointerExceptions
later in the method. This ensures the method only proceeds when managementCase
is valid.

Comment on lines +67 to +69
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix null check condition for name field.

The condition incorrectly checks this.id instead of this.name.

-if (this.id != null) {
+if (this.name != null) {
     outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
if (this.name != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
around lines 67 to 69, the null check condition incorrectly checks this.id
instead of this.name before putting the data set entry. Change the condition to
check if this.name is not null before calling outcome.putDataSetEntry with
this.name.

}
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_SIMPLE_DASHBOARD, FieldType.BOOLEAN, this.simpleDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_PROFILE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use correct field value for language dashboard.

The method uses this.profileDashboard instead of this.languageDashboard.

-outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
+outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
at line 75, the code incorrectly uses this.profileDashboard for the language
dashboard field. Replace this.profileDashboard with this.languageDashboard in
the outcome.putDataSetEntry call to use the correct field value.

Comment on lines +21 to +34
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();

fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Potential logic issue with MULTICHOICE_MAP handling.

The method initializes the "value" key with an empty set for MULTICHOICE_MAP field type (line 26), but then immediately overwrites it with fieldValue (line 32). This could lead to unexpected behavior if fieldValue is not a Set or is null for multichoice fields.

Consider handling the MULTICHOICE_MAP case more explicitly:

 fieldMap.put("type", fieldType.getName());
-if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
-    fieldMap.put("value", Set.of());
-}
 if (options == null) {
     options = new HashMap<>();
 }
 fieldMap.put("options", options);
-fieldMap.put("value", fieldValue);
+if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
+    fieldMap.put("value", fieldValue != null ? fieldValue : Set.of());
+} else {
+    fieldMap.put("value", fieldValue);
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", fieldValue != null ? fieldValue : Set.of());
} else {
fieldMap.put("value", fieldValue);
}
this.getDataSet().put(fieldId, fieldMap);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java
around lines 21 to 34, the "value" for MULTICHOICE_MAP is first set to an empty
set but then overwritten by fieldValue, which may cause issues if fieldValue is
null or not a set. To fix this, add explicit handling for MULTICHOICE_MAP by
checking if fieldValue is a valid set; if not, initialize it as an empty set,
and only then put it into the map, avoiding overwriting the initial empty set
with an invalid value.

Comment on lines +174 to 181
if (viewCase != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
this.view.getViewType().getIdentifier());
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID, FieldType.CASE_REF,
List.of(viewCase.getStringId()));
String taskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_SETTINGS_ID);
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for taskId retrieval

The MenuItemUtils.findTaskIdInCase call on line 179 might return null, which would cause issues when added to the dataset.

 if (viewCase != null) {
     outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
             this.view.getViewType().getIdentifier());
     outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID, FieldType.CASE_REF,
             List.of(viewCase.getStringId()));
     String taskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_SETTINGS_ID);
+    if (taskId == null) {
+        throw new IllegalStateException("Settings task not found in view case");
+    }
     outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (viewCase != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
this.view.getViewType().getIdentifier());
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID, FieldType.CASE_REF,
List.of(viewCase.getStringId()));
String taskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_SETTINGS_ID);
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
}
if (viewCase != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
this.view.getViewType().getIdentifier());
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID, FieldType.CASE_REF,
List.of(viewCase.getStringId()));
String taskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_SETTINGS_ID);
if (taskId == null) {
throw new IllegalStateException("Settings task not found in view case");
}
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java
around lines 174 to 181, the taskId retrieved by MenuItemUtils.findTaskIdInCase
may be null, causing issues when added to the dataset. Add a null check for
taskId before calling outcome.putDataSetEntry with it, and only add the entry if
taskId is not null.

Comment on lines +30 to +35
public void putDataSetEntry(String fieldId, FieldType fieldType, @Nullable Object fieldValue) {
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
fieldMap.put("value", fieldValue);
this.dataSet.put(fieldId, fieldMap);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null/empty validation for fieldId parameter.

Consider adding validation to prevent null or empty fieldId values from being added to the dataset.

 public void putDataSetEntry(String fieldId, FieldType fieldType, @Nullable Object fieldValue) {
+    if (fieldId == null || fieldId.trim().isEmpty()) {
+        throw new IllegalArgumentException("fieldId cannot be null or empty");
+    }
     Map<String, Object> fieldMap = new LinkedHashMap<>();
     fieldMap.put("type", fieldType.getName());
     fieldMap.put("value", fieldValue);
     this.dataSet.put(fieldId, fieldMap);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void putDataSetEntry(String fieldId, FieldType fieldType, @Nullable Object fieldValue) {
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
fieldMap.put("value", fieldValue);
this.dataSet.put(fieldId, fieldMap);
}
public void putDataSetEntry(String fieldId, FieldType fieldType, @Nullable Object fieldValue) {
if (fieldId == null || fieldId.trim().isEmpty()) {
throw new IllegalArgumentException("fieldId cannot be null or empty");
}
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
fieldMap.put("value", fieldValue);
this.dataSet.put(fieldId, fieldMap);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java
around lines 30 to 35, add validation to check if the fieldId parameter is null
or empty before proceeding. If fieldId is null or empty, throw an
IllegalArgumentException or handle it appropriately to prevent invalid entries
from being added to the dataSet map.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 33

🔭 Outside diff range comments (2)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

202-205: Fix inconsistent constant usage.

The test mixes old (PREFERRED_ITEM_NET_IDENTIFIER, PREFERENCE_ITEM_FIELD_*) and new (MenuItemConstants.FIELD_*) constant patterns, which creates inconsistency.

-Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.${MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_PATH.attributeId}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]
+Case folderCase = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER AND dataSet.${MenuItemConstants.FIELD_NODE_PATH}.textValue:\"/netgrif2\"", PageRequest.of(0, 1))[0]

-ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as ArrayList<String>
+ArrayList<String> childIds = folderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS].value as ArrayList<String>
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

2226-2231: Missing .value property access on PATH_SEPARATOR constant.

Consistency issue with PATH_SEPARATOR usage.

-        if (path == null || path == MenuItemConstants.PATH_SEPARATOR || path.length() == 0) {
+        if (path == null || path == MenuItemConstants.PATH_SEPARATOR.value || path.length() == 0) {
             return false
         }
🧹 Nitpick comments (38)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

4-5: Utility class should be final with a private constructor

Prevent instantiation and subclassing of a constants-only class.

-public class TabbedTicketViewConstants extends ViewConstants {
-}
+public final class TabbedTicketViewConstants extends ViewConstants {
+
+    private TabbedTicketViewConstants() {
+        // no-instantiation
+    }
+}
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

4-6: Mark constants holder as final and add private constructor

Same rationale as for other constants classes.

-public class TabbedSingleTaskViewConstants extends ViewConstants {
-    public static final String FIELD_TRANSITION_ID = "transition_id";
-}
+public final class TabbedSingleTaskViewConstants extends ViewConstants {
+
+    public static final String FIELD_TRANSITION_ID = "transition_id";
+
+    private TabbedSingleTaskViewConstants() {
+        // no-instantiation
+    }
+}
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

1-21: Well-structured constants class with excellent organization.

The class follows Java best practices with proper naming conventions, clear documentation, and logical grouping of related constants. This centralized approach eliminates magic strings and improves maintainability across the dashboard management functionality.

Consider adding brief inline comments for complex field names to improve readability:

 public static final String FIELD_DASHBOARD_ITEM_TO_MENU_ITEM_LIST = "dashboard_item_to_menu_item";
+// Toolbar configuration fields
 public static final String FIELD_SIMPLE_DASHBOARD = "simple_dashboard_toolbar";
 public static final String FIELD_PROFILE_DASHBOARD = "profile_dashboard_toolbar";
 public static final String FIELD_LANGUAGE_DASHBOARD = "language_dashboard_toolbar";
 public static final String FIELD_LOGOUT_DASHBOARD = "logout_dashboard_toolbar";
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

15-16: Remove unused imports.

The HashSet and Set imports are not used in this class and should be removed to maintain clean code.

-import java.util.HashSet;
-import java.util.Set;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

3-3: Remove unused Lombok import.

The lombok.Getter import is not used since there's no @Getter annotation on the class or any fields that would benefit from it.

-import lombok.Getter;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (2)

25-25: Consider defensive copying for mutable collection initialization.

The headersMode field is initialized with a mutable ArrayList that could be modified externally, potentially affecting all instances.

-    private List<String> headersMode = new ArrayList<>(List.of("sort", "edit", "search"));
+    private List<String> headersMode = new ArrayList<>(List.of("sort", "edit", "search"));

Or use an immutable approach:

-    private List<String> headersMode = new ArrayList<>(List.of("sort", "edit", "search"));
+    private List<String> headersMode = List.of("sort", "edit", "search");

17-26: Consider validation for enum-like string fields.

Fields like viewSearchType and headersDefaultMode appear to have constrained values but lack validation. Consider adding validation or using actual enums if the values are predefined.

// Consider creating enums for constrained values
public enum ViewSearchType {
    FULLTEXT_ADVANCED("fulltext_advanced"),
    // other values...
    
    private final String value;
    // constructor and getter
}
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1)

29-29: Consider externalizing localized strings.

The hardcoded localized strings should be externalized to resource files for better maintainability and internationalization support.

Consider using a configuration properties approach or resource bundles for localized strings instead of hardcoding them in the Map.

application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1)

249-263: Improve variable naming and add documentation.

The method implementation is solid, but there are some improvements to consider:

  1. The variable name filter is misleading since this method handles any process type, not just filters
  2. Missing JavaDoc documentation for this utility method

Apply these improvements:

+    /**
+     * Imports a Petri net process if it doesn't already exist.
+     * @param message descriptive message for logging
+     * @param netIdentifier the unique identifier of the Petri net
+     * @param netFileName the filename of the Petri net XML file
+     * @return Optional containing the imported or existing PetriNet
+     */
     Optional<PetriNet> importProcess(String message, String netIdentifier, String netFileName) {
-        PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier)
-        if (filter != null) {
+        PetriNet existingNet = petriNetService.getNewestVersionByIdentifier(netIdentifier)
+        if (existingNet != null) {
             log.info("${message} has already been imported.")
-            return Optional.of(filter)
+            return Optional.of(existingNet)
         }

-        Optional<PetriNet> filterNet = this.createNet(netFileName, VersionType.MAJOR, userService.getSystem().transformToLoggedUser())
+        Optional<PetriNet> importedNet = this.createNet(netFileName, VersionType.MAJOR, userService.getSystem().transformToLoggedUser())

-        if (!filterNet.isPresent()) {
+        if (!importedNet.isPresent()) {
             log.error("Import of ${message} failed!")
         }

-        return filterNet
+        return importedNet
     }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

16-19: Document the intentional null return.

The getAssociatedViewBody() method always returns null. This should be documented to clarify that single task views don't have associated views by design.

Add documentation:

     @Override
+    /**
+     * Single task views do not have associated views.
+     * @return always null
+     */
     public ViewBody getAssociatedViewBody() {
         return null;
     }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

6-16: Hide constructor in utility‐constants class

TabbedTaskViewConstants should not be instantiated. Add a private constructor to communicate intent and prevent accidental instantiation.

 public class TabbedTaskViewConstants extends ViewConstants {
+    private TabbedTaskViewConstants() {
+        /* static holder – no instances */
+    }
     public static final String FIELD_MERGE_FILTERS = "merge_filters";
     public static final String FIELD_VIEW_SEARCH_TYPE = "view_search_type";
     public static final String FIELD_DEFAULT_HEADERS = "default_headers";
     public static final String FIELD_HEADERS_MODE = "headers_mode";
@@
     public static final String FIELD_USE_DEFAULT_HEADERS = "use_default_headers";
     public static final String FIELD_SHOW_MORE_MENU = "show_more_menu";
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1)

14-29: Expose builder / constructor for safer initialisation

chainedView is mutable and may remain null, causing NPEs when getAssociatedViewBody() is used downstream.
Consider providing an all-args constructor or a builder to enforce non-null initialisation, or guard against null in getAssociatedViewBody().

-    private ViewBody chainedView;
+    @NonNull
+    private ViewBody chainedView;

     @Override
     public ViewBody getAssociatedViewBody() {
-        return this.chainedView;
+        return Objects.requireNonNull(this.chainedView,
+                "chainedView must be initialised before use");
     }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1)

6-16: Add private constructor to prevent instantiation

ViewConstants is a holder of static constants. Instantiation provides no value and should be disallowed.

 public class ViewConstants {
+    private ViewConstants() {
+        /* static holder */
+    }
     public static final String FIELD_CONFIGURATION_TYPE = "view_configuration_type";
     public static final String FIELD_VIEW_CONFIGURATION_ID = "view_configuration_id";
@@
     public static final String TRANS_SYNC_ID = "data_sync";
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1)

6-23: Utility class should not be instantiated

Same pattern applies here—add a private constructor.

 public class DashboardItemConstants {
+    private DashboardItemConstants() {
+        /* static holder */
+    }
     public static final String PROCESS_IDENTIFIER = "dashboard_item";
     public static final String TASK_CONFIGURE = "configuration";
@@
     public static final String FIELD_IS_ACTIVE= "is_active";
 }
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

7-22: Prevent instantiation of constants holder

As with other constants classes, add a private constructor.

 public class TabbedCaseViewConstants extends ViewConstants {
+    private TabbedCaseViewConstants() {
+        /* static holder */
+    }
     public static final String FIELD_NEW_FILTER_ID = "new_filter_id";
     public static final String FIELD_DEFAULT_HEADERS = "default_headers";
@@
     public static final String FIELD_USE_CASE_DEFAULT_HEADERS = "use_case_default_headers";
 }
application-engine/src/test/resources/dashboard_management_test.xml (1)

14-50: Consider adding error handling and validation to the embedded script.

The Groovy script creates dashboard components programmatically but lacks error handling and validation. Consider the following improvements:

  1. Add null checks and validation for created objects
  2. Handle potential exceptions during object creation
  3. Consider extracting hardcoded values to configurable parameters
<![CDATA[
+try {
    def filterBody = new com.netgrif.application.engine.menu.domain.FilterBody()
+   if (filterBody == null) {
+       throw new IllegalStateException("Failed to create FilterBody")
+   }
    filterBody.setTitle(new com.netgrif.application.engine.petrinet.domain.I18nString("Main"))
    // ... rest of the configuration
    
    def menuItem = createOrIgnoreMenuItem(menuItemBody)
+   if (menuItem == null) {
+       throw new IllegalStateException("Failed to create menu item")
+   }
    
    // ... rest of the script
+} catch (Exception e) {
+   log.error("Failed to create dashboard components: ${e.message}", e)
+   throw e
+}
]]>
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

29-35: Consider initializing remaining fields in custom constructor.

The custom constructor only initializes 5 out of 13 fields, leaving others with default values. This could lead to unexpected behavior if the remaining fields are required.

public DashboardItemBody(String id, String menuItems, String itemIcon, I18nString name, boolean isInternal) {
    this.id = id;
    this.menuItems = menuItems;
    this.isInternal = isInternal;
    this.itemIcon = itemIcon;
    this.name = name;
+   // Initialize remaining fields with sensible defaults
+   this.inheritIcon = false;
+   this.inheritName = false;
+   this.isActive = true;
}
application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1)

32-34: Consider adding error handling for import operations.

The import operations are called directly without error handling. If import fails, it could cause application startup to fail silently or with unclear error messages.

@Override
public void run(ApplicationArguments args) throws Exception {
+   try {
        helper.importProcess("Petri net for filters", DASHBOARD_NET_IDENTIFIER, DASHBOARD_FILE_NAME);
        helper.importProcess("Petri net for filter preferences", DASHBOARD_TILE_NET_IDENTIFIER, DASHBOARD_TILE_FILE_NAME);
+   } catch (Exception e) {
+       log.error("Failed to import dashboard processes", e);
+       throw e;
+   }
}
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1)

37-47: Consider making default metadata configurable.

The getDefaultMetadata method returns hardcoded values that might need to be configurable in different environments or use cases.

Consider extracting these values to configuration properties:

public static Map<String, Object> getDefaultMetadata(String type) {
    Map<String, Object> resultMap = new HashMap<>();
-   
-   resultMap.put("searchCategories", List.of());
-   resultMap.put("predicateMetadata", List.of());
-   resultMap.put("filterType", type);
-   resultMap.put("defaultSearchCategories", true);
-   resultMap.put("inheritAllowedNets", false);
+   
+   resultMap.put("searchCategories", getDefaultSearchCategories());
+   resultMap.put("predicateMetadata", getDefaultPredicateMetadata());
+   resultMap.put("filterType", type);
+   resultMap.put("defaultSearchCategories", getDefaultSearchCategoriesFlag());
+   resultMap.put("inheritAllowedNets", getDefaultInheritAllowedNetsFlag());
    
    return resultMap;
}
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

252-252: Document the purpose of Thread.sleep in tests.

The Thread.sleep(2000) call lacks explanation for why the delay is necessary. This could indicate timing dependencies that might make tests flaky.

+// Wait for background processing to complete before assertions
Thread.sleep(2000)

Consider using more reliable synchronization mechanisms if possible, such as polling for expected conditions rather than fixed delays.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1)

115-124: Add debug logging for search results.

Consider adding debug logging to help troubleshoot when cases are not found.

 protected Case findCase(String processIdentifier, String query) {
     CaseSearchRequest request = CaseSearchRequest.builder()
             .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier)))
             .query(query)
             .build();
     Page<Case> resultPage = elasticCaseService.search(java.util.List.of(request), userService.getLoggedOrSystem().transformToLoggedUser(),
             PageRequest.of(0, 1), Locale.getDefault(), false);
 
-    return resultPage.hasContent() ? resultPage.getContent().get(0) : null;
+    if (resultPage.hasContent()) {
+        return resultPage.getContent().get(0);
+    } else {
+        log.debug("No case found for processIdentifier: {} with query: {}", processIdentifier, query);
+        return null;
+    }
 }
application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1)

206-206: Address TODO: Implement merge filters functionality.

The TODO comment indicates missing merge filters functionality which might be critical for proper search behavior.

Would you like me to help implement the merge filters functionality or create an issue to track this TODO?

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1)

18-19: Consider initializing the filter field or documenting its nullable behavior.

The filter field is not initialized and could be null. Ensure this is handled properly in all usages or consider initializing it.

 public class TabbedTaskViewBody extends ViewBody {
-    private Case filter;
+    private Case filter = null; // Explicitly nullable, handled in toDataSetInternal
     private boolean mergeFilters = true;
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1)

83-89: Document the potential IllegalArgumentException.

The method can throw IllegalArgumentException if parentIdentifier is invalid. Consider documenting this in JavaDoc.

 /**
  * Finds all enum values, that are tabbed or non-tabbed and are defined in parent view as {@link #allowedAssociatedViews}
  *
  * @param isTabbed if true, set of views is reduced to only tabbed views
  * @param parentIdentifier identifier of the view, that contains returned views in {@link #allowedAssociatedViews}
  *
  * @return List of views based on {@link #isTabbed} and {@link #allowedAssociatedViews}
+ * @throws IllegalArgumentException if parentIdentifier is not a valid view identifier
  * */
 public static List<MenuItemView> findAllByIsTabbedAndParentIdentifier(boolean isTabbed, String parentIdentifier) {
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (2)

115-116: Consider batch size limits for ID-based fetching.

When fetching PetriNets by their IDs after the search, ensure the list size doesn't exceed reasonable limits to avoid performance issues.

 SearchHits<ElasticPetriNet> hits = template.search(query, ElasticPetriNet.class, IndexCoordinates.of(elasticsearchConfiguration.elasticPetriNetIndex()));
 Page<ElasticPetriNet> indexedNets = (Page) SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(hits, query.getPageable()));
-netPage = petriNetService.findAllById(indexedNets.get().map(ElasticPetriNet::getStringId).collect(Collectors.toList()));
+List<String> ids = indexedNets.get().map(ElasticPetriNet::getStringId).collect(Collectors.toList());
+if (ids.size() > 1000) {
+    log.warn("Large number of IDs to fetch: {}", ids.size());
+}
+netPage = petriNetService.findAllById(ids);
 total = indexedNets.getTotalElements();

167-172: Address TODO: Move search fields to configuration.

The search fields are hardcoded and should be moved to properties as indicated by the TODO comment.

Would you like me to help refactor this to use configuration properties or create an issue to track this TODO?

Also, consider the performance impact of wildcard searches on large datasets.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (2)

44-55: Consider defensive copying for the options parameter.

The method modifies the input parameter semantics by reassigning options when null. This could be confusing to callers who might expect the parameter to remain unchanged.

Consider using a local variable for the null check:

 public void putDataSetEntryOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options) {
     Map<String, Object> fieldMap = new LinkedHashMap<>();
     fieldMap.put("type", fieldType.getName());
     if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
         fieldMap.put("value", Set.of());
     }
-    if (options == null) {
-        options = new HashMap<>();
-    }
-    fieldMap.put("options", options);
+    Map<String, I18nString> optionsToUse = options != null ? options : new HashMap<>();
+    fieldMap.put("options", optionsToUse);
     this.dataSet.put(fieldId, fieldMap);
 }

16-21: Document thread safety considerations.

The class exposes a mutable Map through getters (via @DaTa). If instances are shared between threads, consider documenting thread safety requirements or making the class immutable.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (2)

50-51: JavaDoc references non-imported class.

The JavaDoc mentions IDataService but this class is not imported. Consider either importing it or using a fully qualified name in the documentation.


56-56: Remove unnecessary semicolon.

-    public ToDataSetOutcome toDataSet() {
-        return toDataSet(null, null);
-    };
+    public ToDataSetOutcome toDataSet() {
+        return toDataSet(null, null);
+    }
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (2)

24-26: Add Javadoc to clarify the difference between createOrUpdateMenuItem and createOrIgnoreMenuItem

These two methods have similar names but presumably different behaviors. Consider adding Javadoc comments to clarify:

  • When to use createOrUpdateMenuItem vs createOrIgnoreMenuItem
  • What happens when a menu item already exists in each case
  • The return value in different scenarios

63-70: Consider extracting the "_configuration" suffix as a constant

The hardcoded string "_configuration" appears to be a naming convention. Consider extracting it as a constant to improve maintainability and make the convention explicit.

+    private static final String CONFIGURATION_SUFFIX = "_configuration";
+    
     default Map<String, I18nString> getAvailableViewsAsOptions(boolean isTabbed, String viewIdentifier) {
-        int index = viewIdentifier.lastIndexOf("_configuration");
+        int index = viewIdentifier.lastIndexOf(CONFIGURATION_SUFFIX);
         if (index > 0) {
             viewIdentifier = viewIdentifier.substring(0, index);
         }
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

618-656: Remove unused duplicate method

The getOrCreateFolderRecursive2 method appears to be an unused alternative implementation of getOrCreateFolderRecursive. It should be removed to avoid confusion.

-    protected Case getOrCreateFolderRecursive2(String path, MenuItemBody body, Case childFolderCase) throws TransitionNotExecutableException {
-        Case folderCase = findFolderCase(path);
-        if (folderCase != null) {
-            if (childFolderCase != null) {
-                folderCase = appendChildCaseIdAndSave(folderCase, childFolderCase.getStringId());
-                initializeParentId(childFolderCase, folderCase.getStringId());
-            }
-            return folderCase;
-        }
-
-        folderCase = createCase(FilterRunner.MENU_NET_IDENTIFIER, body.getMenuName().toString(), userService.getLoggedOrSystem().transformToLoggedUser());
-        if (childFolderCase != null) {
-            folderCase = appendChildCaseIdAndSave(folderCase, childFolderCase.getStringId());
-            initializeParentId(childFolderCase, folderCase.getStringId());
-        } else {
-            folderCase = workflowService.save(folderCase);
-        }
-
-        Optional<TaskPair> newItemTask = folderCase.getTasks().stream().filter(taskPair -> taskPair.getTransition().equals(MenuItemConstants.TRANS_INIT_ID)).findFirst();
-
-        ToDataSetOutcome dataSetOutcome = body.toDataSet(null, path, null);
-        if (childFolderCase != null) {
-            appendChildCaseIdInDataSet(folderCase, childFolderCase.getStringId(), dataSetOutcome.getDataSet());
-        }
-
-        if (newItemTask.isPresent()) {
-            setDataWithExecute(folderCase, MenuItemConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
-        }
-
-        if (hasParent(path)) {
-            body = new com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody(new I18nString(nameFromPath(path)), "folder");
-            String parentPath = parentPath(path);
-            getOrCreateFolderRecursive(parentPath, body, folderCase);
-        }
-
-        folderCase = setDataWithExecute(folderCase, MenuItemConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
-
-        return folderCase;
-    }
application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1)

60-65: Consider toggling visibility instead of editability for update_filter button

make updateBtn,editable on trans when { true } exposes the button but still leaves it hidden if the field logic marks it as invisible elsewhere. In typical Petriflow UI behaviour, “editable” presumes the data element is already visible; users never see a non-visible but editable control.
Switching the rule to visible (and keeping the complementary rule in the else branch) makes the intent explicit and prevents confusion in complex layouts.

-    make updateBtn,editable on trans when { true }
+    make updateBtn,visible on trans when { true }
application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

521-551: Ordering logic duplicated – extract to utility to keep the process maintainable

Both order_down and order_up repeat near-identical swap / setData code. Duplicated Groovy snippets inside XML are notoriously painful to patch and test.

Consider a single process-scoped function reorderChildren(idxDelta) receiving +1 or -1 to perform the swap and update the parent once. It will:

  1. Reduce risk of future off-by-one errors
  2. Keep transitions lean and readable
  3. Make unit testing possible outside the XML
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (3)

1723-1738: Proper use of @deprecated annotation for backward compatibility.

These deprecated methods correctly delegate to the new service-based implementation while maintaining the old API signatures. Consider adding @Deprecated(since = "6.5.0") annotations with version information for better tracking.

-    @Deprecated
+    @Deprecated(since = "6.5.0")
     Case createMenuItem(String uri, String identifier, Case filter, String groupName, Map<String, String> allowedRoles, Map<String, String> bannedRoles = [:], List<String> caseDefaultHeaders = [], List<String> taskDefaultHeaders = []) {

Also applies to: 1750-1767, 1781-1797, 1810-1826


2496-2514: Inconsistent deprecation annotations.

Some methods have @Deprecated(since = "6.5.0") while others just have @Deprecated. Consider making all deprecation annotations consistent with version information.

-    @Deprecated
+    @Deprecated(since = "6.5.0")
     Case createOrUpdateMenuItem(String id, String uri, String type, String query, String icon, String title, List<String> allowedNets,

Also applies to: 2533-2548


2132-2134: Incomplete implementation - TODO for task filter query.

The task filter query is empty with a TODO comment. This needs to be implemented to properly filter tasks by case ID and transition ID.

Would you like me to help implement the query construction for filtering tasks by case ID and transition ID?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcbb9a1 and 7a85f22.

📒 Files selected for processing (62)
  • application-engine/CHANGELOG.md (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (40 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (5 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1 hunks)
  • application-engine/src/main/resources/application.yaml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_single_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (7 hunks)
  • application-engine/src/test/resources/dashboard_management_test.xml (1 hunks)
  • application-engine/src/test/resources/petriNets/filter_api_test.xml (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (4 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (3 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1 hunks)
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (3 hunks)
💤 Files with no reviewable changes (9)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuAndFilters.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntryRole.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemBody.java
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuList.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/Menu.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResourceAssembler.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuEntry.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/menu/MenuItemConstants.java
🧰 Additional context used
🧠 Learnings (26)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/resources/application.yaml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTicketViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedSingleTaskViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/ToDataSetOutcome.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/resources/petriNets/filter_api_test.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewConstants.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/MenuItemUtils.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

🪛 GitHub Actions: Pull Request
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java

[warning] 42-54: @builder will ignore the initializing expression entirely on multiple fields. Add @Builder.Default or make the field final to fix.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (59)
application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java (1)

123-123: No functional impact – formatting only
The extra blank line is harmless and does not warrant a change.

application-engine/src/main/resources/application.yaml (1)

161-162: actions section misplaced – will NOT be picked up by Spring logging config

actions: is indented at the same level as logging: instead of being nested under logging.level.
Spring will therefore ignore the custom imports, and log-parsing or classpath scanning that relies on it will silently fail.

-    actions:
-      imports: com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody,com.netgrif.application.engine.objects.petrinet.domain.I18nString,com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody
+      level:
+        actions:
+          imports: com.netgrif.application.engine.objects.workflow.domain.menu.MenuItemBody,com.netgrif.application.engine.objects.petrinet.domain.I18nString,com.netgrif.application.engine.objects.workflow.domain.menu.dashboard.DashboardManagementBody

Likely an incorrect or invalid review comment.

application-engine/CHANGELOG.md (1)

8-21: Documentation only – looks good
The updated links and release notes read correctly.

application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticPetriNetService.java (2)

3-11: LGTM! Well-designed search interface.

The new imports and interface method follow Spring conventions well. The search method signature includes all necessary parameters for comprehensive Petri net searching: search criteria, user context, pagination, localization, and intersection logic.


22-22: Comprehensive search method signature.

The search method provides a well-structured interface with appropriate parameters for filtering, pagination, and user context. The Boolean isIntersection parameter adds flexibility for different search modes.

nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticPetriNet.java (2)

13-16: Appropriate imports for I18n transformation.

The new imports support the internationalization field transformation functionality, adding necessary collection types and I18nString handling.


67-73: Well-implemented I18n transformation method.

The transformToField method correctly extracts internationalization data from I18nString and creates a structured I18nField. The implementation properly:

  • Extracts translation keys and values
  • Creates a copy of the translations map
  • Includes the default value in the values set
  • Returns a properly constructed I18nField

This aligns well with the broader internationalization refactoring effort.

application-engine/src/main/resources/petriNets/engine-processes/preference_filter_item.xml (1)

419-419: Correct case ID access pattern.

The change from it._id.eq(...) to it._id.objectId.eq(...) properly accesses the objectId property for case comparison. This refinement aligns with the broader refactoring to use ProcessResourceId objects consistently and ensures correct case matching logic.

application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (3)

10-14: Well-structured startup runner.

The class follows established patterns with appropriate annotations:

  • @RunnerOrder(141) provides clear execution ordering
  • @ConditionalOnProperty allows flexible enabling/disabling
  • Component registration is correct

19-24: Good constant definitions.

The constants are well-named and follow naming conventions. Having both public identifiers and private file names provides good encapsulation while allowing external access to the net identifiers when needed.


26-29: Clean import implementation.

The run method properly delegates to ImportHelper for both dashboard management and dashboard item Petri nets. The descriptive names in the import calls improve logging and debugging.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java (2)

1-6: Appropriate imports and package structure.

The imports are minimal and focused, including only necessary types for the interface. The package structure follows the established pattern for service interfaces.


7-14: Well-designed service interface.

The interface follows established service patterns:

  • getOrCreate method provides idempotent entity creation
  • update method takes both case and body for proper updates
  • findById provides simple lookup functionality
  • Appropriate use of TransitionNotExecutableException for workflow-related errors
  • Clean method signatures with clear return types
application-engine/src/test/resources/petriNets/filter_api_test.xml (1)

113-122: LGTM! Excellent consolidation of filter and menu item management.

The refactoring from multiple granular calls to a single createOrUpdateMenuItemAndFilter service method improves code maintainability and aligns with the new service-based architecture. The metadata structure properly encapsulates filter configuration properties, and all necessary parameters are correctly passed to the unified method.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java (1)

60-60: Well-designed abstract method for type transformation.

The abstract transformToField method properly enforces subclasses to implement the conversion logic from I18nString to I18nField, supporting the internationalization enhancements across the application.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/filter/FilterConstants.java (1)

1-22: Excellent constants organization with clear logical grouping.

The class follows Java best practices with proper naming conventions and centralizes filter-related constants effectively. The logical grouping (transitions, field IDs, ISO codes, filter types, visibility) enhances readability and maintainability.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedCaseViewBody.java (2)

16-32: Excellent view configuration design with sensible defaults.

The class properly extends ViewBody and provides well-thought-out default values for tabbed case view properties. The use of descriptive field names and appropriate data types enhances maintainability.


44-74: Robust dataset transformation with proper null handling.

The toDataSetInternal method correctly maps all fields to their appropriate dataset types and includes proper null-safe handling for collections and optional fields.

application-engine/src/test/resources/dashboard_management_test.xml (1)

1-8: LGTM: Well-structured XML process definition.

The XML structure follows the Petriflow schema correctly with appropriate metadata fields for the dashboard import process.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardItemBody.java (1)

10-13: LGTM: Appropriate use of Lombok annotations.

The combination of @Data, @Builder, and @AllArgsConstructor provides comprehensive boilerplate generation for the domain class.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java (1)

14-16: LGTM: Clean domain class structure.

The class uses appropriate Lombok annotations and follows good practices for a data transfer object.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2)

76-82: LGTM: Updated to use new field constants.

The test correctly uses the new MenuItemConstants.FIELD_* constants, aligning with the refactored domain model.


89-102: Excellent: Enhanced validation for tabbed view configurations.

The new assertions properly validate the nested tabbed view structure and relationships using MenuItemUtils.getCaseIdFromCaseRef, providing comprehensive test coverage for the new view configuration feature.

application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1)

203-204: Ensure security annotation on searchElasticPetriNets
We observed three methods in PetriNetController (lines 96, 179, 217) secured with @PreAuthorize, but the searchElasticPetriNets endpoint at line 203 currently has none. Please confirm whether it should enforce the same authorization (for example, @authorizationService.hasAuthority('ADMIN')) or another appropriate check:

  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java: insert an @PreAuthorize annotation above the searchElasticPetriNets method.
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/TabbedTaskViewBody.java (1)

40-62: Consider adding handling for the filter field in toDataSetInternal

We ran an AST search for other ViewBody subclasses but didn’t find any implementations to compare against. Without further evidence, it’s unclear whether omitting filter is intentional. Please:

  • Verify if the filter property on this class should be included in the dataset.
  • If it’s required, add a outcome.putDataSetEntry(...) call for filter.
  • Otherwise, document why it’s deliberately excluded.
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/configurations/ViewBody.java (1)

66-82: Well-structured dataset transformation logic.

The method properly handles null cases and delegates specific transformations to subclasses through the abstract toDataSetInternal method. Good separation of concerns.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)

7-39: Clean refactoring to static constants.

The conversion from enum to a final class with static String constants is appropriate. The consistent naming convention with FIELD_ and TRANS_ prefixes improves code clarity and aligns with the learning about making the constants more generic.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1)

60-74: All configuration XML files are present

We’ve confirmed that for each MenuItemView identifier (tabbed_case_view, tabbed_task_view, tabbed_ticket_view, tabbed_single_task_view), there is a matching _configuration.xml file under
application-engine/src/main/resources/petriNets/engine-processes/menu/. No missing files detected.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_management.xml (1)

683-700: Consider transaction safety for the is_active flag update

The is_active flag is set to true (line 697) before the validation completes. If the validation fails and throws an exception, the flag might remain in an inconsistent state. Consider validating first, then updating the flag as the last operation.

 <actions phase="pre">
     <action>
         dashboard_id: f.dashboard_id,
         dashboard_name: f.dashboard_name,
         is_active: f.is_active;

         if (dashboard_id.value == null || dashboard_id.value == "") {
             throw new IllegalArgumentException("Dashboard ID cannot be empty.")
         }
         def dashboardWithIdExists = findCaseElastic("processIdentifier:\"dashboard_management\" AND dataSet.dashboard_id.textValue.keyword:\"${dashboard_id.value}\" AND dataSet.is_active.booleanValue:true" as String)
         if (dashboardWithIdExists != null) {
             throw new IllegalArgumentException("Dashboard with given ID already exists.")
         }
+        // Set is_active only after all validations pass
         change is_active value { true }
     </action>
 </actions>

Likely an incorrect or invalid review comment.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_task_view_configuration.xml (6)

1-41: LGTM!

The document structure and role definitions follow standard Petri net configuration patterns with appropriate permission levels.


42-93: LGTM!

The Groovy functions correctly handle dynamic filter autocomplete and option synchronization with proper null checks and XML-encoded operators.


95-224: LGTM!

Filter configuration data fields are properly structured with appropriate validation, type restrictions, and action triggers for filter management.


226-317: LGTM!

Task view configuration fields provide comprehensive display options with proper data validation and real-time updates through immediate flags.


319-371: LGTM!

Complete i18n implementation with consistent translations for both Slovak and German locales.


373-718: LGTM!

Process flow definition with transitions, places, and arcs is properly structured with appropriate role-based access control and comprehensive UI layout configuration.

application-engine/src/main/resources/petriNets/engine-processes/dashboard_item.xml (4)

1-46: LGTM!

Document structure with appropriate role definitions and delete event handler for maintaining referential integrity.


47-65: LGTM!

The removeRefFromParent function properly maintains referential integrity by updating all dashboard_management cases that reference the deleted item.


387-441: LGTM!

Complete i18n implementation with consistent Slovak and German translations.


443-762: LGTM!

Well-structured configuration transition with comprehensive validation and proper state management through the is_active flag.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (4)

1-37: LGTM!

Good refactoring to consolidate view-related fields into ViewBody abstraction and initialize maps to prevent null pointer exceptions.


39-88: LGTM!

Well-designed constructor overloads providing flexibility while ensuring proper initialization of all required fields.


89-119: LGTM!

Methods properly handle null cases and correctly derive the useTabbedView flag from the view type.


121-184: LGTM!

Well-structured toDataSet methods with progressive enhancement through overloads and improved type safety using ToDataSetOutcome.

application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_ticket_view_configuration.xml (6)

1-51: LGTM!

Standard document structure with appropriate role definitions and async cleanup on delete.


52-90: LGTM!

Functions properly validate filter types and use async operations for non-blocking cleanup.


92-194: LGTM!

Filter configuration properly validates for Case type filters with appropriate null handling.


196-222: LGTM!

Associated view configuration supports nested view structures with dynamic option loading.


224-255: LGTM!

Minimal view configuration with complete internationalization support.


257-405: LGTM!

Well-structured transitions with proper lifecycle management for associated view configurations.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (7)

1-48: LGTM!

Well-structured service class with appropriate dependencies and Spring annotations.


49-83: LGTM!

Filter operations properly handle user context and use appropriate abstractions.


85-186: LGTM!

Comprehensive CRUD operations with proper validation, automatic parent folder creation, and flexible creation patterns.


188-239: LGTM!

Efficient search operations with proper Elasticsearch query construction and optimized existence checks.


252-252: Address the TODO comment

There's an unimplemented TODO that should be addressed or removed if no longer relevant.


241-289: LGTM!

The moveItem method properly validates cyclic paths and maintains parent-child relationships with recursive updates.


385-747: LGTM!

Comprehensive helper methods for folder management, view lifecycle, and data operations with proper error handling.

application-engine/src/main/resources/petriNets/engine-processes/menu/menu_item.xml (1)

85-93: Ensure Lucene query parameters are properly escaped
If useCase.stringId contains special Lucene characters (+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /), the unescaped string may break the query or broaden matches.

• Wrap the dynamic value in an escape helper, e.g.:

def escapedId = org.apache.lucene.queryparser.classic.QueryParser.escape(useCase.stringId)
def cases = findCasesElastic(
    "processIdentifier:\"dashboard_item\" AND dataSet.menu_items_list.keyValue:\"${escapedId}\""
)

• Alternatively, use any existing escapeLucene() or parameter-binding method provided by your Elastic service.
• Verify in ActionDelegate.findCasesElastic(…) that queries are built with escaped inputs or safe parameter binding.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (2)

1619-1628: Good refactoring to service-based approach.

The method now properly uses the FilterBody domain object and delegates to menuItemService.createFilter(). This is a clean abstraction that improves modularity and maintainability.


1879-1926: Well-structured refactoring of changeMenuItem method.

The method now properly uses the new MenuItemConstants fields and delegates URI changes to menuItemService.moveItem(). This ensures proper validation and consistency.

Comment on lines +2213 to 2217
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value))
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing .value property access on PATH_SEPARATOR constant.

The code is inconsistent with PATH_SEPARATOR usage. Based on other usages in the file, it should access the .value property.

-        if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
-            return path.replace(MenuItemConstants.PATH_SEPARATOR, "")
+        if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) == 0) {
+            return path.replace(MenuItemConstants.PATH_SEPARATOR.value, "")
         }
-        return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR))
+        return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) + 1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value))
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR))
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR.value, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) + 1)
}
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2213 to 2217, the constant MenuItemConstants.PATH_SEPARATOR is used
without accessing its .value property, which is inconsistent with other usages
in the file. Update all occurrences of MenuItemConstants.PATH_SEPARATOR in this
code block to MenuItemConstants.PATH_SEPARATOR.value to correctly access the
string value of the constant.

Comment on lines 2219 to 2224
protected String parentPath(String path) {
if (path == null || path == MenuItemConstants.PATH_SEPARATOR.value || path.length() == 0 || path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) == 0) {
return MenuItemConstants.PATH_SEPARATOR.value
if (path == null || path == MenuItemConstants.PATH_SEPARATOR || path.length() == 0 || path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return MenuItemConstants.PATH_SEPARATOR
}
return path.substring(0, path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value))
return path.substring(0, path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing .value property access on PATH_SEPARATOR constant.

Same issue as in nameFromPath method - missing .value property access.

-        if (path == null || path == MenuItemConstants.PATH_SEPARATOR || path.length() == 0 || path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
-            return MenuItemConstants.PATH_SEPARATOR
+        if (path == null || path == MenuItemConstants.PATH_SEPARATOR.value || path.length() == 0 || path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value) == 0) {
+            return MenuItemConstants.PATH_SEPARATOR.value
         }
-        return path.substring(0, path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR))
+        return path.substring(0, path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value))
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2219 to 2224, the PATH_SEPARATOR constant is used without accessing
its .value property, which is required. Update all occurrences of
MenuItemConstants.PATH_SEPARATOR to MenuItemConstants.PATH_SEPARATOR.value to
correctly reference the string value of the constant.

Comment on lines 2713 to 2716
List<String> splitUriPath(String path) {
String rootPath = MenuItemConstants.PATH_SEPARATOR.value
String[] splitPath = path.split(MenuItemConstants.PATH_SEPARATOR.value)
String rootPath = MenuItemConstants.PATH_SEPARATOR
String[] splitPath = path.split(MenuItemConstants.PATH_SEPARATOR)
if (splitPath.length == 0 && path == rootPath) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing .value property access on PATH_SEPARATOR constant.

Consistency issue with PATH_SEPARATOR usage.

-        String rootPath = MenuItemConstants.PATH_SEPARATOR
-        String[] splitPath = path.split(MenuItemConstants.PATH_SEPARATOR)
+        String rootPath = MenuItemConstants.PATH_SEPARATOR.value
+        String[] splitPath = path.split(MenuItemConstants.PATH_SEPARATOR.value)
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2713 to 2716, the PATH_SEPARATOR constant is used without accessing
its .value property, causing inconsistency. Update all occurrences of
MenuItemConstants.PATH_SEPARATOR to MenuItemConstants.PATH_SEPARATOR.value to
ensure consistent and correct usage of the constant's value.

Comment on lines 17 to 21
@RequiredArgsConstructor
class DefaultDashboardRunner implements ApplicationEngineStartupRunner {

@Autowired
private DashboardManagementService dashboardManagementService
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use consistent dependency injection pattern.

The class uses both constructor injection (@RequiredArgsConstructor) and field injection (@Autowired) which is inconsistent. Choose one pattern for clarity and maintainability.

Use constructor injection consistently:

 @Slf4j
 @Component
 @RunnerOrder(142)
-@RequiredArgsConstructor
-class DefaultDashboardRunner implements ApplicationEngineStartupRunner {
+class DefaultDashboardRunner implements ApplicationEngineStartupRunner {

-    @Autowired
-    private DashboardManagementService dashboardManagementService
+    private final DashboardManagementService dashboardManagementService
+
+    DefaultDashboardRunner(DashboardManagementService dashboardManagementService) {
+        this.dashboardManagementService = dashboardManagementService
+    }
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
around lines 17 to 21, the class mixes constructor injection
(@RequiredArgsConstructor) and field injection (@Autowired) for dependencies. To
fix this, remove the @Autowired annotation and the field injection, and instead
declare the DashboardManagementService as a final field initialized via the
constructor generated by @RequiredArgsConstructor, ensuring consistent use of
constructor injection throughout the class.

Comment on lines +64 to +69
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_ID, FieldType.TEXT, this.id);
}
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix copy-paste error in null check.

Line 67 checks this.id instead of this.name, which appears to be a copy-paste error.

 if (this.id != null) {
     outcome.putDataSetEntry(DashboardManagementConstants.FIELD_ID, FieldType.TEXT, this.id);
 }
-if (this.id != null) {
+if (this.name != null) {
     outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_ID, FieldType.TEXT, this.id);
}
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
if (this.id != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_ID, FieldType.TEXT, this.id);
}
if (this.name != null) {
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_NAME, FieldType.I18N, this.name);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
around lines 64 to 69, the null check before adding the FIELD_NAME entry
incorrectly checks this.id instead of this.name. Change the condition on line 67
to check if this.name is not null before calling outcome.putDataSetEntry for
FIELD_NAME.

}
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_SIMPLE_DASHBOARD, FieldType.BOOLEAN, this.simpleDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_PROFILE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect field value for language dashboard.

The language dashboard field is being set with profileDashboard value instead of languageDashboard.

-outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
+outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.profileDashboard);
outcome.putDataSetEntry(DashboardManagementConstants.FIELD_LANGUAGE_DASHBOARD, FieldType.BOOLEAN, this.languageDashboard);
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java
at line 75, the field for the language dashboard is incorrectly assigned the
value of profileDashboard. Replace the value passed to putDataSetEntry for
FIELD_LANGUAGE_DASHBOARD from this.profileDashboard to this.languageDashboard to
correctly reflect the language dashboard state.

Comment on lines +21 to +34
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();

fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Clarify MULTICHOICE_MAP handling logic and add documentation.

The method has a logical issue with MULTICHOICE_MAP handling and lacks documentation:

  1. Lines 25-27 set the value to an empty Set for MULTICHOICE_MAP, but line 32 immediately overwrites it with fieldValue
  2. Missing JavaDoc documentation explaining the method's purpose and parameters

Fix the MULTICHOICE_MAP logic and add documentation:

+    /**
+     * Adds a dataset entry with field type, options, and value to the dataset.
+     * @param fieldId the field identifier
+     * @param fieldType the type of the field
+     * @param options optional field options map, null will be converted to empty map
+     * @param fieldValue the field value to set
+     */
     public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
         Map<String, Object> fieldMap = new LinkedHashMap<>();

         fieldMap.put("type", fieldType.getName());
-        if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
-            fieldMap.put("value", Set.of());
-        }
         if (options == null) {
             options = new HashMap<>();
         }
         fieldMap.put("options", options);
-        fieldMap.put("value", fieldValue);
+        // Set default empty set for MULTICHOICE_MAP if fieldValue is null
+        if (fieldType.equals(FieldType.MULTICHOICE_MAP) && fieldValue == null) {
+            fieldMap.put("value", Set.of());
+        } else {
+            fieldMap.put("value", fieldValue);
+        }
         this.getDataSet().put(fieldId, fieldMap);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (fieldType.equals(FieldType.MULTICHOICE_MAP)) {
fieldMap.put("value", Set.of());
}
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
fieldMap.put("value", fieldValue);
this.getDataSet().put(fieldId, fieldMap);
}
/**
* Adds a dataset entry with field type, options, and value to the dataset.
* @param fieldId the field identifier
* @param fieldType the type of the field
* @param options optional field options map, null will be converted to empty map
* @param fieldValue the field value to set
*/
public void putDataSetEntryWithOptions(String fieldId, FieldType fieldType, @Nullable Map<String, I18nString> options, @Nullable Object fieldValue){
Map<String, Object> fieldMap = new LinkedHashMap<>();
fieldMap.put("type", fieldType.getName());
if (options == null) {
options = new HashMap<>();
}
fieldMap.put("options", options);
// Set default empty set for MULTICHOICE_MAP if fieldValue is null
if (fieldType.equals(FieldType.MULTICHOICE_MAP) && fieldValue == null) {
fieldMap.put("value", Set.of());
} else {
fieldMap.put("value", fieldValue);
}
this.getDataSet().put(fieldId, fieldMap);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardToDataSetOutcome.java
between lines 21 and 34, the MULTICHOICE_MAP handling sets the value to an empty
Set but then immediately overwrites it with fieldValue, making the initial
assignment ineffective. Fix this by setting the value to an empty Set only if
fieldValue is null or not provided for MULTICHOICE_MAP. Also, add JavaDoc
comments above the method to explain its purpose, parameters, and behavior
clearly.

Comment on lines +54 to +72
public ToDataSetOutcome toDataSet() {
ToDataSetOutcome outcome = new ToDataSetOutcome();

outcome.putDataSetEntry(FilterConstants.FILTER_TYPE_FIELD_ID, FieldType.ENUMERATION_MAP, this.type);
outcome.putDataSetEntry(FilterConstants.FILTER_VISIBILITY_FIELD_ID, FieldType.ENUMERATION_MAP, this.visibility);
outcome.putDataSetEntry(FilterConstants.FILTER_I18N_TITLE_FIELD_ID, FieldType.I18N, this.title);
Map<String, Object> metadata = this.metadata;
if (metadata == null) {
metadata = getDefaultMetadata(this.type);
}
outcome.getDataSet().put(FilterConstants.FILTER_FIELD_ID, Map.of(
"type", "filter",
"value", this.query,
"allowedNets", this.allowedNets,
"filterMetadata", metadata
));

return outcome;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation for required fields in toDataSet method.

The method converts fields to dataset entries but doesn't validate that required fields like type and query are not null or empty.

public ToDataSetOutcome toDataSet() {
+   if (this.type == null || this.type.trim().isEmpty()) {
+       throw new IllegalStateException("Filter type is required");
+   }
+   if (this.query == null || this.query.trim().isEmpty()) {
+       throw new IllegalStateException("Filter query is required");
+   }
+   
    ToDataSetOutcome outcome = new ToDataSetOutcome();
    // ... rest of the method
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public ToDataSetOutcome toDataSet() {
ToDataSetOutcome outcome = new ToDataSetOutcome();
outcome.putDataSetEntry(FilterConstants.FILTER_TYPE_FIELD_ID, FieldType.ENUMERATION_MAP, this.type);
outcome.putDataSetEntry(FilterConstants.FILTER_VISIBILITY_FIELD_ID, FieldType.ENUMERATION_MAP, this.visibility);
outcome.putDataSetEntry(FilterConstants.FILTER_I18N_TITLE_FIELD_ID, FieldType.I18N, this.title);
Map<String, Object> metadata = this.metadata;
if (metadata == null) {
metadata = getDefaultMetadata(this.type);
}
outcome.getDataSet().put(FilterConstants.FILTER_FIELD_ID, Map.of(
"type", "filter",
"value", this.query,
"allowedNets", this.allowedNets,
"filterMetadata", metadata
));
return outcome;
}
public ToDataSetOutcome toDataSet() {
if (this.type == null || this.type.trim().isEmpty()) {
throw new IllegalStateException("Filter type is required");
}
if (this.query == null || this.query.trim().isEmpty()) {
throw new IllegalStateException("Filter query is required");
}
ToDataSetOutcome outcome = new ToDataSetOutcome();
outcome.putDataSetEntry(FilterConstants.FILTER_TYPE_FIELD_ID, FieldType.ENUMERATION_MAP, this.type);
outcome.putDataSetEntry(FilterConstants.FILTER_VISIBILITY_FIELD_ID, FieldType.ENUMERATION_MAP, this.visibility);
outcome.putDataSetEntry(FilterConstants.FILTER_I18N_TITLE_FIELD_ID, FieldType.I18N, this.title);
Map<String, Object> metadata = this.metadata;
if (metadata == null) {
metadata = getDefaultMetadata(this.type);
}
outcome.getDataSet().put(FilterConstants.FILTER_FIELD_ID, Map.of(
"type", "filter",
"value", this.query,
"allowedNets", this.allowedNets,
"filterMetadata", metadata
));
return outcome;
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/FilterBody.java
between lines 54 and 72, the toDataSet method lacks validation for required
fields such as type and query. Add checks at the start of the method to ensure
that type and query are not null or empty, and throw an appropriate exception or
handle the error if they are invalid. This will prevent null or empty values
from being processed and ensure data integrity.

Comment on lines +52 to +59
public static MenuItemView fromIdentifier(String identifier) {
for (MenuItemView view : MenuItemView.values()) {
if (view.identifier.equals(identifier)) {
return view;
}
}
throw new IllegalArgumentException(identifier);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null check and improve error message.

The method should validate the input parameter and provide a more descriptive error message.

 public static MenuItemView fromIdentifier(String identifier) {
+    if (identifier == null) {
+        throw new IllegalArgumentException("Identifier cannot be null");
+    }
     for (MenuItemView view : MenuItemView.values()) {
         if (view.identifier.equals(identifier)) {
             return view;
         }
     }
-    throw new IllegalArgumentException(identifier);
+    throw new IllegalArgumentException("Unknown MenuItemView identifier: " + identifier);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static MenuItemView fromIdentifier(String identifier) {
for (MenuItemView view : MenuItemView.values()) {
if (view.identifier.equals(identifier)) {
return view;
}
}
throw new IllegalArgumentException(identifier);
}
public static MenuItemView fromIdentifier(String identifier) {
if (identifier == null) {
throw new IllegalArgumentException("Identifier cannot be null");
}
for (MenuItemView view : MenuItemView.values()) {
if (view.identifier.equals(identifier)) {
return view;
}
}
throw new IllegalArgumentException("Unknown MenuItemView identifier: " + identifier);
}
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemView.java
around lines 52 to 59, add a null check for the identifier parameter at the
start of the fromIdentifier method. If the identifier is null, throw an
IllegalArgumentException with a clear message indicating that the identifier
cannot be null. Also, improve the existing exception message to include the
invalid identifier value for better clarity.

@machacjozef machacjozef changed the base branch from release/7.0.0-rev5 to release/7.0.0-rev4 July 28, 2025 15:06
- Remove unused `uriService` references and outdated assertions.
- Simplify folder case retrieval and path handling logic.
- Adjust duplicate menu item node path creation.
- Streamline `filter_api_test.xml` to remove unnecessary node lookups.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

66-69: Extract magic string to constant

The string "_configuration" should be defined as a constant to improve maintainability and avoid typos.

+    private static final String CONFIGURATION_SUFFIX = "_configuration";
+    
     default Map<String, I18nString> getAvailableViewsAsOptions(boolean isTabbed, String viewIdentifier) {
-        int index = viewIdentifier.lastIndexOf("_configuration");
+        int index = viewIdentifier.lastIndexOf(CONFIGURATION_SUFFIX);
         if (index > 0) {
             viewIdentifier = viewIdentifier.substring(0, index);
         }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a85f22 and 490cbb7.

📒 Files selected for processing (6)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml (1 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (9 hunks)
  • application-engine/src/test/resources/petriNets/filter_api_test.xml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • application-engine/src/test/resources/petriNets/filter_api_test.xml
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

🔇 Additional comments (4)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2)

259-271: Good test coverage for validation scenarios

The test properly validates error cases for empty titles and duplicate identifiers using assertThrows. This ensures the duplication logic correctly handles invalid inputs.


330-351: Excellent test coverage for cascade deletion

The test thoroughly verifies that removing a menu item properly cascades to delete associated tabbed views (both case and task views). This ensures data consistency is maintained.

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (2)

452-466: Well-structured view lifecycle management

The handleView method and its associated must* condition checker methods provide a clear and maintainable approach to managing view lifecycle states. The separation of condition checking from action execution follows good design principles.

Also applies to: 523-545


382-392: Good defensive programming in parent-child relationship management

The method properly handles null/empty cases and maintains data consistency by updating both the child list and the has_children flag.

Comment on lines +736 to +744
protected String nameFromPath(String path) {
if (path == null || path.equals(MenuItemConstants.PATH_SEPARATOR) || path.isEmpty()) {
return "";
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR, "");
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add bounds checking for substring operation

The nameFromPath method on line 743 could throw StringIndexOutOfBoundsException if lastIndexOf returns the last position in the string.

 protected String nameFromPath(String path) {
     if (path == null || path.equals(MenuItemConstants.PATH_SEPARATOR) || path.isEmpty()) {
         return "";
     }
     if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
         return path.replace(MenuItemConstants.PATH_SEPARATOR, "");
     }
-    return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR));
+    int lastIndex = path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR);
+    return lastIndex < path.length() - 1 ? path.substring(lastIndex + 1) : "";
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected String nameFromPath(String path) {
if (path == null || path.equals(MenuItemConstants.PATH_SEPARATOR) || path.isEmpty()) {
return "";
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR, "");
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR));
}
protected String nameFromPath(String path) {
if (path == null || path.equals(MenuItemConstants.PATH_SEPARATOR) || path.isEmpty()) {
return "";
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR, "");
}
int lastIndex = path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR);
return lastIndex < path.length() - 1
? path.substring(lastIndex + 1)
: "";
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
around lines 736 to 744, the substring call uses lastIndexOf without checking if
it is the last character index, which can cause StringIndexOutOfBoundsException.
Fix this by adding bounds checking before calling substring to ensure the index
is not the last character position or adjust the substring parameters
accordingly to avoid the exception.

Comment on lines +280 to +284
String trimmed = bannedNets.value?.replaceAll("\\s","")
if (bannedNets.value != trimmed) {
change bannedNets value { trimmed }
}
</action>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Whitespace removal is too aggressive

The current implementation removes ALL whitespace including spaces within identifiers. This would transform "my net 1, my net 2" into "mynet1,mynet2" which may not be intended.

-String trimmed = bannedNets.value?.replaceAll("\\s","")
+String trimmed = bannedNets.value?.split(",").collect { it.trim() }.join(",")

The same issue applies to the default_headers field trimming on lines 364-368.

Also applies to: 364-368

🤖 Prompt for AI Agents
In
application-engine/src/main/resources/petriNets/engine-processes/menu/tabbed_case_view_configuration.xml
around lines 280 to 284 and 364 to 368, the current code removes all whitespace
characters from the bannedNets and default_headers values, which unintentionally
removes spaces within identifiers. To fix this, modify the whitespace trimming
logic to only remove leading and trailing whitespace instead of all whitespace
characters, preserving spaces inside the strings. Use a method or pattern that
trims spaces at the start and end but leaves internal spaces intact.

Case item = getMenuItem(caze)
Case filter = getFilter(caze)

Thread.sleep(4000)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace Thread.sleep with proper synchronization

Using Thread.sleep(4000) makes tests slow and potentially flaky. Consider using a polling mechanism or wait conditions to ensure the data is properly indexed.

-        Thread.sleep(4000)
+        // Wait for elastic indexing with timeout
+        def maxAttempts = 20
+        def attempt = 0
+        while (attempt < maxAttempts) {
+            def result = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER", PageRequest.of(0, 1))
+            if (!result.isEmpty()) break
+            Thread.sleep(200)
+            attempt++
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Thread.sleep(4000)
// Wait for elastic indexing with timeout
def maxAttempts = 20
def attempt = 0
while (attempt < maxAttempts) {
def result = findCasesElastic("processIdentifier:$FilterRunner.MENU_NET_IDENTIFIER", PageRequest.of(0, 1))
if (!result.isEmpty()) break
Thread.sleep(200)
attempt++
}
🤖 Prompt for AI Agents
In
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy
at line 80, replace the use of Thread.sleep(4000) with a proper synchronization
method such as a polling loop or wait condition that repeatedly checks if the
data is indexed and ready, proceeding as soon as the condition is met to avoid
unnecessary delays and reduce test flakiness.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 490cbb7 and f1981c5.

📒 Files selected for processing (7)
  • .github/workflows/nexus-release.yml (1 hunks)
  • application-engine/pom.xml (1 hunks)
  • nae-object-library/pom.xml (1 hunks)
  • nae-spring-core-adapter/pom.xml (1 hunks)
  • nae-user-ce/pom.xml (1 hunks)
  • nae-user-common/pom.xml (1 hunks)
  • pom.xml (1 hunks)
✅ Files skipped from review due to trivial changes (6)
  • nae-user-common/pom.xml
  • nae-user-ce/pom.xml
  • nae-object-library/pom.xml
  • application-engine/pom.xml
  • pom.xml
  • nae-spring-core-adapter/pom.xml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (1)
.github/workflows/nexus-release.yml (1)

52-54: Confirm server-id change aligns with <distributionManagement>

server-id is now netgrif-nexus-releases. Ensure every module’s pom.xml has a matching <id> under <distributionManagement>. Otherwise mvn deploy will skip credentials and fail.

Comment on lines +39 to +45
- name: DEBUG PRINT
run: echo "$MAVEN_USERNAME / $MAVEN_PASSWORD"
shell: bash
env:
MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Credentials echoed to logs – remove immediately

echo "$MAVEN_USERNAME / $MAVEN_PASSWORD" leaks raw credentials into the Actions log. Even if GitHub masks secrets, any mis-configuration or later copy-paste can expose them.
Delete this debug step or output only a placeholder.

-      - name: DEBUG PRINT
-        run: echo "$MAVEN_USERNAME / $MAVEN_PASSWORD"
-        shell: bash
-        env:
-          MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
-          MAVEN_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: DEBUG PRINT
run: echo "$MAVEN_USERNAME / $MAVEN_PASSWORD"
shell: bash
env:
MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
🤖 Prompt for AI Agents
In .github/workflows/nexus-release.yml around lines 39 to 45, the step that
echoes MAVEN_USERNAME and MAVEN_PASSWORD outputs sensitive credentials to the
logs. Remove the entire debug print step or replace the echo command with a
placeholder message that does not reveal any secret values to prevent credential
leakage.

- Refactor `DashboardManagementRunner` to update process descriptions for better clarity.
- Replace `@Autowired` with constructor injection in `DefaultDashboardRunner`.
- Improve javadoc comments in `DashboardManagementService` interface.
- Simplify path separator handling in `ActionDelegate`.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (4)

2735-2735: Potential query injection vulnerability.

The elastic query construction using string concatenation could be vulnerable to injection if the path parameter contains special characters or query syntax. This issue was previously identified and remains unresolved.


2213-2217: Missing .value property access on PATH_SEPARATOR constant.

The code is inconsistent with PATH_SEPARATOR usage. This issue was previously identified and remains unresolved.


2219-2224: Missing .value property access on PATH_SEPARATOR constant.

Same issue as in nameFromPath method - missing .value property access. This was previously identified.


2713-2716: Missing .value property access on PATH_SEPARATOR constant.

Consistency issue with PATH_SEPARATOR usage. This was previously identified in the review.

🧹 Nitpick comments (1)
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

1-2765: Consider breaking up this large class for better maintainability.

While the refactoring to service-based architecture is well done, the ActionDelegate class remains very large at 2700+ lines. Consider splitting it into smaller, more focused classes (e.g., FilterActionDelegate, MenuItemActionDelegate, DashboardActionDelegate) to improve maintainability and readability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f1981c5 and 84dac05.

📒 Files selected for processing (4)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (40 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy (1 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DashboardManagementRunner.groovy
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (7)
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (7)

29-31: Good architectural improvement with service-based approach.

The introduction of IMenuItemService, DashboardManagementService, and DashboardItemService properly aligns with the PR's objective to refactor menu items and dashboards into a service-based architecture. The autowiring follows Spring conventions correctly.

Also applies to: 205-213


933-936: Useful convenience method addition.

The new findCase(String stringId) method provides a cleaner API for finding cases by ID, improving code readability.


1618-1628: Well-executed refactoring to service-based architecture.

The filter and menu item creation methods have been properly refactored to use FilterBody, MenuItemBody, and the new services. The code maintains backward compatibility while improving modularity and maintainability.

Also applies to: 1733-1738, 1765-1767, 1794-1797, 1821-1826, 1862-1864


2339-2361: Clean implementation of dashboard management methods.

The new dashboard management methods properly delegate to their respective services and follow the established pattern. This maintains consistency with the menu item refactoring approach.


1722-1722: Good deprecation strategy for backward compatibility.

The deprecated methods are properly marked with @Deprecated annotations and include version information (since = "6.5.0"). They continue to work by delegating to the new service-based implementations, providing a smooth migration path.

Also applies to: 1750-1750, 1780-1780, 1809-1809, 2322-2322, 2407-2407, 2533-2533, 2575-2575, 2626-2626, 2663-2663


2110-2207: Well-structured view configuration helper methods.

The new helper methods (createSingleTaskViewBody, createDefaultViewBody, createLegacyMenuItemViews) properly encapsulate the view configuration logic and create appropriate ViewBody objects for different scenarios. The chaining of views for tabbed interfaces is handled cleanly.


2379-2382: Useful convenience overload with sensible defaults.

The new findCasesElastic overload with a default page size of 100 provides a cleaner API for common use cases.

# Conflicts:
#	application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
#	application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (2)
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (2)

2747-2757: Critical: Inconsistent PATH_SEPARATOR usage in getCorrectedUri.

Line 2748 correctly accesses PATH_SEPARATOR.value but line 2752 is missing .value, which will cause a runtime error:

-        int lastIdx = uncheckedPath.lastIndexOf(MenuItemConstants.PATH_SEPARATOR)
+        int lastIdx = uncheckedPath.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.value)

2730-2745: Incorrect property access on field constants.

Lines 2740-2741 incorrectly append .value to the field constants when accessing dataSet fields:

-                options.put(childFolderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS.value].value as String, new I18nString(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.value].value as String))
+                options.put(childFolderCase.dataSet[MenuItemConstants.FIELD_CHILD_ITEM_IDS].value as String, new I18nString(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME].value as String))

The constants should be used directly to access dataSet fields, not their .value property.

♻️ Duplicate comments (5)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

81-81: Replace Thread.sleep with proper synchronization mechanism.

This Thread.sleep(4000) makes tests slow and potentially flaky. A polling mechanism was already suggested in previous reviews to wait for elastic indexing with timeout.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (4)

2735-2735: Security: Query injection vulnerability needs to be addressed.

The elastic query construction remains vulnerable to injection attacks through the path parameter. This critical issue was previously identified and still needs to be fixed by escaping special characters.


2213-2217: Missing .value property access on PATH_SEPARATOR constant.

The PATH_SEPARATOR constant is used without accessing its .value property, which is inconsistent with other usages in the file.


2219-2224: Missing .value property access on PATH_SEPARATOR constant.

Multiple occurrences of PATH_SEPARATOR without .value property access in the parentPath method.


2713-2716: Missing .value property access on PATH_SEPARATOR constant.

The splitUriPath method uses PATH_SEPARATOR without accessing .value property.

🧹 Nitpick comments (1)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

248-248: Consider replacing Thread.sleep with proper synchronization.

Similar to line 81, this Thread.sleep(2000) can make tests slower and potentially flaky. Consider using a polling mechanism or wait condition instead.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84dac05 and 7ec0cc9.

📒 Files selected for processing (4)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (39 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (5 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (14)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (7)

10-16: LGTM! New imports support enhanced menu functionality.

The added imports align with the refactoring from preference items to menu items and support the new tabbed view configurations and utility methods.


82-88: LGTM! Correct migration to new MenuItemConstants.

The migration from old PREFERENCE_ITEM_FIELD_* constants to new FIELD_* constants is consistent with the refactoring, and the new MenuItemView.TABBED_CASE_VIEW.identifier usage properly supports the enhanced view configuration system.


95-108: LGTM! Enhanced tabbed view validation logic.

The new test logic properly validates the nested tabbed view configurations using the MenuItemUtils.getCaseIdFromCaseRef utility method and ensures correct configuration of both tabbed case and task views.


110-112: LGTM! Updated queries use correct new identifiers.

The elastic search queries correctly use the new FilterRunner.MENU_NET_IDENTIFIER and MenuItemConstants.FIELD_NODE_PATH constants, maintaining functionality while aligning with the refactoring.


128-169: LGTM! Comprehensive validation of menu item changes.

The enhanced test logic properly validates that tabbed view configurations persist correctly during menu item changes, using the MenuItemUtils.getCaseIdFromCaseRef utility method and ensuring referential integrity of nested view configurations.


279-292: LGTM! Correct validation of menu item duplication logic.

The test properly validates the duplication functionality with updated constants and correctly checks for empty string values in duplicate fields after completion, aligning with the new duplication logic.


321-352: LGTM! Comprehensive validation of cascade deletion.

The enhanced removal test properly validates that when a menu item is deleted, all associated tabbed views (both case and task views) are also properly deleted, ensuring no orphaned view configurations remain in the system.

application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (7)

933-936: Good addition of convenience method.

The new findCase(String stringId) method provides a cleaner API for finding cases by ID, complementing the existing predicate-based findCase method.


1619-1628: Clean refactoring to service-based approach.

The migration to use FilterBody and delegate to menuItemService.createFilter() properly encapsulates the filter creation logic and follows good separation of concerns.


1723-1827: Proper deprecation and migration to service-based menu item creation.

The deprecated createMenuItem methods correctly maintain backward compatibility while delegating to the new service. The consistent use of setUseTabbedView(true) indicates a standardization on tabbed views.


1879-1926: Well-structured menu item update methods.

The changeMenuItem implementation properly handles different attribute updates and delegates to appropriate services. Good use of constants for field and transition identifiers.


2339-2361: Good addition of dashboard management API methods.

The new dashboard-related methods provide a consistent API for dashboard management and properly delegate to specialized services.


2110-2207: Well-designed view configuration builder methods.

The new view creation methods properly implement the builder pattern for complex view configurations. The chained view approach allows flexible composition of case and task views.


2533-2642: Excellent deprecation strategy for menu item methods.

The deprecated methods maintain backward compatibility while properly migrating to the new service-based architecture. The consistent use of @Deprecated(since = "6.5.0") provides clear version tracking.

- Refactor user transformation logic to use `ActorTransformer.toLoggedUser` across services. Remove outdated TODO comments and unused imports.
@coderabbitai coderabbitai bot added the Medium label Jul 29, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (7)
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (2)

18-18: Remove unused Lazy import

The import org.springframework.context.annotation.Lazy is not used in any @Lazy annotations in this file. The @Lazy annotation on line 58 uses the already imported annotation.

-import org.springframework.context.annotation.Lazy;

193-193: Add pagination limits to prevent memory issues

Using FullPageRequest without limits could retrieve an unbounded number of results, potentially causing memory issues with large datasets.

-List<PetriNetReference> groupProcesses = this.petriNetService.search(processQuery, user, new FullPageRequest(), locale).getContent();
+// Limit to reasonable number of group processes
+Page<PetriNetReference> groupProcessPage = this.petriNetService.search(processQuery, user, PageRequest.of(0, 1000), locale);
+if (groupProcessPage.getTotalElements() > 1000) {
+    log.warn("Large number of group processes found: {}. Consider implementing streaming or chunked processing.", groupProcessPage.getTotalElements());
+}
+List<PetriNetReference> groupProcesses = groupProcessPage.getContent();

Also add the import:

import org.springframework.data.domain.PageRequest;
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (5)

197-199: Potential query injection vulnerability in findMenuItem.

The elastic search query directly interpolates the identifier without escaping, which could lead to query manipulation.

Escape the identifier before interpolation:

+String escapedIdentifier = identifier.replaceAll("[\\\\\"]", "\\\\$0");
 String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
-        FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, identifier);
+        FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, escapedIdentifier);

212-214: Query injection vulnerabilities in findMenuItem overload.

Both name and path parameters need escaping before interpolation.

+String escapedName = name.replaceAll("[\\\\\"]", "\\\\$0");
+String escapedPath = path.replaceAll("[\\\\\"]", "\\\\$0");
 String query = String.format("processIdentifier:%s AND title.keyword:\"%s\" AND nodePath:\"%s\"",
-        FilterRunner.MENU_NET_IDENTIFIER, name, path);
+        FilterRunner.MENU_NET_IDENTIFIER, escapedName, escapedPath);

621-659: Remove duplicate method getOrCreateFolderRecursive2.

This appears to be dead code or an experimental version. Having two methods with nearly identical names violates clean code principles and causes confusion.

Remove the entire getOrCreateFolderRecursive2 method to eliminate confusion and adhere to clean code principles.


721-727: Add null safety checks in setDataWithExecute.

The method assumes the task exists but doesn't handle the case where it might be null.

 protected Case setDataWithExecute(Case useCase, String transId, Map<String, Map<String, Object>> dataSet) throws TransitionNotExecutableException {
     AbstractUser loggedUser = userService.getLoggedOrSystem();
     String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
+    if (taskId == null) {
+        throw new IllegalStateException(String.format("Task with transition '%s' not found in case '%s'", transId, useCase.getStringId()));
+    }
     Task task = taskService.findOne(taskId);
+    if (task == null) {
+        throw new IllegalStateException(String.format("Task '%s' not found", taskId));
+    }
     task = taskService.assignTask(task, loggedUser).getTask();
     task = dataService.setData(task, ImportHelper.populateDataset((Map) dataSet)).getTask();
     return taskService.finishTask(task, loggedUser).getCase();
 }

730-738: Add bounds checking for substring operation.

The nameFromPath method could throw StringIndexOutOfBoundsException if lastIndexOf returns the last position in the string.

 protected String nameFromPath(String path) {
     if (path == null || path.equals(MenuItemConstants.PATH_SEPARATOR) || path.isEmpty()) {
         return "";
     }
     if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR) == 0) {
         return path.replace(MenuItemConstants.PATH_SEPARATOR, "");
     }
-    return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR));
+    int lastIndex = path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR);
+    return lastIndex < path.length() - 1 ? path.substring(lastIndex + 1) : "";
 }
🧹 Nitpick comments (5)
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (2)

114-116: Track the TODO for impersonation feature

There's a TODO comment indicating that impersonation functionality is not yet implemented. Consider creating a tracking issue for this feature if it's required.

Would you like me to create an issue to track the implementation of the impersonation feature?


175-180: Consider making search fields configurable

The TODO comment correctly identifies that the search fields and their boost values are hardcoded. Consider moving these to configuration properties for better flexibility.

Would you like me to help refactor this to use configuration properties for the search fields and boost values?

application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (3)

211-211: Address the TODO comment.

The TODO comment indicates retry functionality should be implemented for this method.

Would you like me to implement the retry mechanism similar to the findMenuItem(String identifier, boolean retry) method?


225-225: Address the TODO comment.

The TODO comment needs clarification or implementation.

Please clarify what specific functionality needs to be implemented for the folder case finding logic.


239-246: Inconsistent query approach in existsMenuItem.

The method uses MongoDB query while other methods use Elasticsearch. Consider consistency or document the reasoning.

Either use the commented Elasticsearch approach consistently:

-//TODO mongo
-Case menuItem = this.workflowService.searchOne(QCase.case$.processIdentifier.eq("menu_item")
-        .and(QCase.case$.dataSet.get(MenuItemConstants.FIELD_IDENTIFIER).value.eq(identifier)));
-return menuItem != null;
-//        String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
-//                FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, identifier);
-//        return countCases(FilterRunner.MENU_NET_IDENTIFIER, query) > 0;
+String escapedIdentifier = identifier.replaceAll("[\\\\\"]", "\\\\$0");
+String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
+        FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, escapedIdentifier);
+return countCases(FilterRunner.MENU_NET_IDENTIFIER, query) > 0;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ec0cc9 and a65b028.

📒 Files selected for processing (5)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

🧬 Code Graph Analysis (1)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (4)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/ActorTransformer.java (1)
  • ActorTransformer (10-131)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1)
  • MenuItemConstants (7-39)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java (1)
  • Slf4j (33-126)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1)
  • Slf4j (36-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (4)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (4)

39-50: LGTM!

The class structure, annotations, and dependency injection setup are well-implemented using Spring best practices.


57-84: LGTM!

The filter creation and update operations are well-implemented with appropriate data handling, transaction management, and logging.


429-539: LGTM!

The view and filter handling methods are well-structured with clear separation of concerns and appropriate error handling.


740-751: LGTM!

The path utility methods are well-implemented with appropriate null checks and edge case handling.

}

// TODO refactor to properties
String searchText = "*" + request.getTitle() + "*";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Sanitize search input to prevent query injection

The search text is directly concatenated with wildcards without escaping special characters. This could lead to query errors or injection issues if the title contains Elasticsearch query syntax characters.

Consider escaping special characters:

-String searchText = "*" + request.getTitle() + "*";
+String searchText = "*" + QueryStringQuery.escape(request.getTitle()) + "*";

Or use a more robust approach with match queries instead of wildcards for better performance:

-String searchText = "*" + request.getTitle() + "*";
-QueryStringQuery fullTextQuery = QueryStringQuery.of(builder -> builder.fields(fullTextFields).query(searchText));
+QueryStringQuery fullTextQuery = QueryStringQuery.of(builder -> 
+    builder.fields(fullTextFields)
+           .query(request.getTitle())
+           .defaultOperator(Operator.And)
+           .analyzeWildcard(true)
+           .fuzziness("AUTO"));

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java
at line 176, the searchText is constructed by directly concatenating wildcards
to the request title without escaping special characters, which risks query
injection or errors. Fix this by sanitizing the input string to escape
Elasticsearch special characters before adding wildcards, or refactor the query
to use a match query instead of wildcard queries for safer and more efficient
searching.

Comment on lines +257 to +295
@Override
public void moveItem(Case itemCase, String destUri) throws TransitionNotExecutableException {

log.debug("Move of menu item case [{}] started. Destination path [{}]", itemCase.getStringId(), destUri);
if (MenuItemUtils.isCyclicNodePath(itemCase, destUri)) {
throw new IllegalArgumentException(String.format("Cyclic path not supported. Destination path: %s", destUri));
}
List<Case> casesToSave = new ArrayList<>();

List<String> parentIdList = MenuItemUtils.getCaseIdsFromCaseRef(itemCase, MenuItemConstants.FIELD_PARENT_ID);
if (parentIdList != null && !parentIdList.isEmpty()) {
Case oldParent = removeChildItemFromParent(parentIdList.get(0), itemCase);
casesToSave.add(oldParent);
}

Case newParent = getOrCreateFolderItem(destUri);
if (newParent != null) {
itemCase.getDataField(MenuItemConstants.FIELD_PARENT_ID).setValue(List.of(newParent.getStringId()));
appendChildCaseIdInMemory(newParent, itemCase.getStringId());
casesToSave.add(newParent);
} else {
itemCase.getDataField(MenuItemConstants.FIELD_PARENT_ID).setValue(null);
}

resolveAndHandleNewNodePath(itemCase, destUri);
casesToSave.add(itemCase);

if (MenuItemUtils.hasFolderChildren(itemCase)) {
List<Case> childrenToSave = updateNodeInChildrenFoldersRecursive(itemCase);
casesToSave.addAll(childrenToSave);
}

for (Case useCase : casesToSave) {
if (useCase != null) {
workflowService.save(useCase);
}
}
log.debug("Moved menu item case [{}]. Destination path was [{}]", itemCase.getStringId(), destUri);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding transaction management for atomicity.

The moveItem operation involves multiple case updates that could leave the system in an inconsistent state if any step fails.

Consider wrapping the entire operation in a transaction:

@Transactional
public void moveItem(Case itemCase, String destUri) throws TransitionNotExecutableException {
    // existing implementation
}
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
around lines 257 to 295, the moveItem method updates multiple cases but lacks
transaction management, risking partial updates on failure. To fix this,
annotate the moveItem method with @Transactional to ensure all database
operations within it are atomic and rollback on exceptions, preserving data
consistency.

Comment on lines +18 to 19
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.InvalidDataAccessApiUsageException;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The annotation is presnet at line 58.

Comment on lines +45 to +46
private IPetriNetService petriNetService;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

petriNetService properties is initialized with lazy setter at line 60.

- Refactor startup runners and improve configuration handling
- Migrated Groovy-based runners to Java for consistency and maintainability.
- Introduced `MenuProcessRunner` to manage menu-related processes separately.
- Updated dashboard-related property keys and added conditional annotations for more precise feature control.
- Ensured clarity in YAML configuration with new `dashboard.enabled` property.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (2)

368-752: Helper methods provide essential functionality but past issues remain unresolved.

The helper methods support the core service functionality well, including:

  • View and filter lifecycle management
  • Recursive folder creation and management
  • Path manipulation utilities
  • Case relationship management

However, several issues flagged in previous reviews persist:

  • Unused duplicate method getOrCreateFolderRecursive2 (lines 622-660)
  • Potential StringIndexOutOfBoundsException in nameFromPath (line 738)
  • Missing null safety checks in setDataWithExecute

185-247: Query injection vulnerabilities persist from previous reviews.

The Elasticsearch query methods still directly interpolate user input without escaping, creating potential injection vulnerabilities:

  • Line 198-199: identifier parameter needs escaping
  • Line 213-214: name and path parameters need escaping

Additionally, there are unresolved TODO comments indicating incomplete implementation.

Apply proper escaping before query interpolation:

+String escapedIdentifier = identifier.replaceAll("[\\\\\"]", "\\\\$0");
 String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
-        MenuProcessRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, identifier);
+        MenuProcessRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, escapedIdentifier);
🧹 Nitpick comments (1)
application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultDashboardRunner.java (1)

1-43: LGTM! Well-designed default dashboard creation with good internationalization.

The DefaultDashboardRunner is well-implemented with:

  • Proper execution order (142) after DashboardManagementRunner
  • Good internationalization support (English, Slovak, German)
  • Sensible error handling that logs issues without breaking startup
  • Clean delegation to the service layer
  • Appropriate conditional enabling

Consider making the createMainDashboardManagementItem method private since it's only used internally:

-    Case createMainDashboardManagementItem() throws TransitionNotExecutableException {
+    private Case createMainDashboardManagementItem() throws TransitionNotExecutableException {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a65b028 and 33ff704.

📒 Files selected for processing (8)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardManagementRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultDashboardRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/MenuProcessRunner.java (1 hunks)
  • application-engine/src/main/resources/application-dev.yaml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • application-engine/src/main/resources/application-dev.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardRunner.java
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/FilterRunner.java
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: renczesstefan
PR: netgrif/application-engine#318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (1)

Learnt from: renczesstefan
PR: #318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field attributeId will be renamed to value to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (7)
application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java (5)

1-52: LGTM! Well-structured service class.

The class follows proper Spring patterns with dependency injection, logging, and clear organization. The imports are appropriate and the class structure is clean.


53-86: LGTM! Clean filter management implementation.

The filter creation and update methods follow consistent patterns with proper user handling, data transformation, and logging. The separation of concerns is well-maintained.


87-184: LGTM! Comprehensive menu item management with good API design.

The menu item creation and update methods handle complex scenarios well, including folder hierarchy management, view configuration, and identifier validation. The convenience methods (createOrUpdate, createOrIgnore) provide good API flexibility.

Note: Past reviews have flagged the need for transaction management in createMenuItem due to multiple operations that could leave the system in an inconsistent state if any step fails. This remains a valid concern for production robustness.


248-296: LGTM! Well-implemented move functionality with proper safeguards.

The moveItem method handles the complex scenario of moving menu items between folders correctly, including:

  • Cyclic path prevention
  • Parent-child relationship updates
  • Recursive node path updates for folder hierarchies
  • Efficient bulk saving approach

The implementation is thorough and handles edge cases appropriately.


297-367: LGTM! Comprehensive item duplication with recursive view handling.

The duplicateItem method handles complex duplication scenarios well, including:

  • Input validation and uniqueness checks
  • Recursive view configuration duplication
  • Proper parent-child relationship establishment
  • Dataset manipulation for the new item

The implementation is thorough and maintains data integrity during duplication.

Note: Line 336 still contains an unused method call that was flagged in previous reviews.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DashboardManagementRunner.java (1)

1-33: LGTM! Clean and well-structured startup runner implementation.

The DashboardManagementRunner follows established patterns with:

  • Proper conditional enabling via configuration property
  • Appropriate execution order (141)
  • Clean dependency injection using ImportHelper
  • Good use of constants for identifiers and file paths
  • Simple, focused responsibility for importing dashboard Petri nets

The implementation is consistent with other startup runners in the codebase.

application-engine/src/main/java/com/netgrif/application/engine/startup/runner/MenuProcessRunner.java (1)

1-52: LGTM! Excellent dynamic Petri net import implementation.

The MenuProcessRunner demonstrates excellent design with:

  • Early execution order (101) appropriate for core menu functionality
  • Clean separation between fixed import and dynamic configuration creation
  • Elegant use of streams to process MenuItemView enum values
  • Proper error handling by filtering out failed imports
  • Good maintainability - adding new menu view types only requires enum updates

The dynamic approach for configuration nets is particularly well-implemented and avoids code duplication.

- Update version to 7.0.0-SNAPSHOT and modify runners
- Bumped parent version across multiple modules to 7.0.0-SNAPSHOT.
- Made `DefaultDashboardRunner` and `DashboardManagementRunner` public for broader usage.
- Ensures proper alignment with new versioning and access changes.
@machacjozef machacjozef merged commit 19f60a7 into release/7.0.0-rev4 Jul 29, 2025
5 of 7 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 31, 2025
18 tasks
@coderabbitai coderabbitai bot mentioned this pull request Sep 5, 2025
18 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement A change that improves on an existing feature Large Medium Small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants