diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 0bd5aacf956..6679165c0b7 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -7,8 +7,6 @@
* [Event queue](events/event_queue.md)
* [Search]()
* [Elastic](search/elastic_mapping.md)
- * [Filter](search/filter.md)
- * [Import / Export](search/filter_import_export.md)
* [Permissions]()
* [User list](roles/userlist.md)
* [Permissions](roles/permissions.md)
diff --git a/docs/search/filter.md b/docs/search/filter.md
deleted file mode 100644
index 0d9924921b2..00000000000
--- a/docs/search/filter.md
+++ /dev/null
@@ -1,842 +0,0 @@
-# Developers guide to the Filter process
-
-This document contains information about the Filter process and the API provided by the application engine for
-interacting with the instances of the Filter process.
-
-## Filter data variable
-
-This data variable stores a
-generated [elastic query string query](https://www.elastic.co/guide/en/elasticsearch/reference/6.6/query-dsl-query-string-query.html)
-as it’s value.
-
-It has two additional properties that store the metadata necessary for the reconstruction of a filter.
-
-* _**allowedNets**_ - similar to the case ref data variable type, a list of identifiers of “allowed nets“ is stored in
- the filter field. The stored nets represent the nets that can be used to construct search queries within the advanced
- search component.
-* _**filterMetadata**_ - data necessary for reconstructing the state of the advanced search component. The backend
- currently does not provide any utility methods for construction of the metadata object. An interface for this object
- can be found in
- the [documentation](https://developer.netgrif.com/projects/engine-frontend/5.4.1/nae/docs/interfaces/FilterMetadata.html)
- .
-
-Beware that while a filter field does not throw an error when displayed in editable mode and changes can be made to its
-frontend representation, these changes are not propagated to backend and do not fire a set data event on the field.
-Because of this we recommend only using filter fields in visible mode, to display their values set by the frontend
-filter API.
-
-Neither title nor any other meta attribute of the filter field (such as description) is displayed as part of the filter
-field component.
-
-
-
-*an editable filter field*
-
-
-
-*a visible filter field*
-
-
-
-*an immediate filter field displayed on a panel*
-
-## Filter process
-
-The engine filter process is located under `resources/petriNets/engine-processes/filter.xml`
-
-
-
-The process is relatively simple. It stores and makes accessible the data necessary for the persistence of filters
-created by users of the application engine. All the process logic, the model contains is focussed solely on the creation
-process of the filter before it reaches its "initialized" state denoted by `p2`.
-
-The process can be overridden by the developers, by placing a net with the same file name and identifier into the
-location specified above. The process defines a “process interface” that must remain unchanged when overriding the
-process for the frontend APIs that connects to the process to work correctly. Attributes of the process that are part of
-the “process interface“ and must remain unchanged will be highlighted.
-
-### Filter process interface
-
-#### Data variables
-
-##### Filter
-
-```xml
-
- filter
- Filter
-
-```
-
-This field contains the saved filter.
-
-It must be `immediate`, have the ID `filter` and be of type `filter`.
-
-##### Filter type
-
-```xml
-
- filter_type
- Filter type
-
-
-
-
-
-```
-
-This data variable stores the type of the filter stored in the filter field of the filter process. The keys are used for
-filtering of the filter processes.
-
-It must be `immediate`, have the ID `filter_type` and be of type `enumeration_map`. The available options must have the
-keys `Case` and `Task`. The values associated with these keys are not specified by the Filter process interface and can
-therefore be freely overridden.
-
-##### Filter visibility
-
-```xml
-
- visibility
- Filter visibility
-
-
-
-
- public
-
-```
-
-This data variable can be used for filtering of the filter processes based on some internal rules. The application
-engine queries this variable when listing filter during navigation menu customisation and during filter export. Only
-public and private filters authored by the logged user are offered as options during these selection processes.
-
-No universal restriction is applied to the search queries on these instances, however. The developer must ensure that no
-inappropriate filters become available to the user during any search at their own discretion. The queries used by the
-application engine can be overridden, by extending the `IUserFiltersSearchService` interface.
-
-It must be `immediate`, have the ID `visibility` and be of type `enumeration_map`. The available options must have the
-keys `public` and `private`. The values associated with these keys are not specified by the Filter process interface and
-can therefore be freely overridden.
-
-##### Origin ViewId
-
-```xml
-
- origin_view_id
- Origin ViewId
-
-```
-
-The viewId of the view where the filter was created is stored in this data variable.
-Is only set if the filter originates from a view with an in-app filter.
-
-When the field is set an action is triggered, that resolves the parent filter (if any) and populates the data variables
-that are responsible for displaying the parent filter with the appropriate values.
-
-It must be `immediate`, have the ID `origin_view_id` and be of type `text`.
-
-##### Parent filter Id
-
-```xml
-
- parent_filter_id
- parent filter ID
-
-```
-
-The case ID of the parent filter case (if any). Is only set if the filter originates from a different filter case (usually via configurable menu).
-
-When the field is set an action is triggered, that resolves the parent filter (if any) and populates the data variables
-that are responsible for displaying the parent filter with the appropriate values.
-
-It must have the ID `parent_filter_id` and be of type `text`.
-
-##### Filter name
-
-```xml
-
- new_title
- Filter name
-
-```
-
-This data variable is used to change the title of the newly created filter case according to the wishes of the user.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### I18n filter name
-
-```xml
-
- i18n_filter_name
-
-
-```
-
-Contains the name of the filter with locale specific translations. Its value is used to generate configurable group
-navigation menu entry titles.
-
-It must be `immediate`, have the ID `i18n_filter_name` and be of type `enumeration`.
-
-The previously mentioned `new_title` data variable has a set action, that pushes its value into this variable. Since
-the `new_title` variable is a plain text field, a `I18nString` object with only its default value set is put into this
-variable. This field however does support translations, so localised menu entries can be created, or their names changed
-trough actions.
-
-##### Filter case id
-
-```xml
-
- filter_case_id
-
-
-```
-
-This variable is set during the case creation and stores the ID of this case. Since the frontend integration accesses
-the filter process mostly trough tasks, this field can be referenced in any of those tasks to grant direct access to the
-case ID, without having to execute an extra search query. The frontend integration does not use this variable currently,
-but it can be used in custom integrations.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### And me
-
-```xml
-
- and_me
- AND
-
-```
-
-Stores the translated text of the word "AND" in order to create a visual representation of the true filter content. More
-information about this can be found in the transition section.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### And view
-
-```xml
-
- and_view
- AND
-
-```
-
-Similarly to the `and_me` data variable, this too stores the translated text of the word "AND" in order to create a
-visual representation of the true filter content.
-
-This variable is referenced in the action associated with the `origin_view_id` data variable and on the `view_filter`
-and `view_as_ancestor` transitions. If it were to be removed this must be taken into the account.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### Parent filter task ref
-
-```xml
-
- taskref_and_parent
-
-
-```
-
-Similarly to the `and_view` data variable, this too is used to create the visual representation of the true filter
-content, because it stores a reference to the task in the parent filter process that contains the true visualisation of
-the parent filter.
-
-Just like the `and_view` data variable, this too is referenced in the action associated with the `origin_view_id` data
-variable and on the `t1` and `t2` transitions. If it were to be removed this must be taken into the account.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### Trimmed origin view id
-
-```xml
-
- trimmed_origin_view_id
- Filter from view with ID
-
-```
-
-Similarly to the `and_view` data variable, this too is used to create the visual representation of the true filter
-content, because it stores a trimmed version of the origin view id, that does not contain any tabbed view identifiers.
-
-Just like the `and_view` data variable, this too is referenced in the action associated with the `origin_view_id` data
-variable and on the `t1` and `t2` transitions. If it were to be removed this must be taken into the account.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted.
-
-##### Is imported
-
-```xml
-
- is_imported
-
- 0
-
-```
-
-This is the reference value for variable arc to decide, if the filter is imported by the Import filter process or is
-automatically created by the backend. When set, it sets the value of the `is_not_imported` data variable to `0`.
-
-It must have the ID `is_imported`, be of type `number` and have the initial value `0`.
-
-##### Is not imported
-
-```xml
-
- is_not_imported
-
- 1
-
-```
-
-This is the reference value for the alternative variable arc to decide, if the filter is imported by the Import filter
-process or is automatically created by the backend.
-
-It must have the ID `is_not_imported`, be of type `number` and have the initial value `1`.
-
-##### Missing allowed nets
-
-```xml
-
- missing_allowed_nets
- Missing processes
- List of missing processes for current filter
-
- htmltextarea
-
-
-```
-
-The purpose of this textarea is to show the list of missing allowed nets for the current (imported) filter. It is
-displayed in `import_filters` transition while importing new filter from XML.
-
-It must have the ID `missing_allowed_nets`, be of type `text` and have the component `htmltextarea`.
-
-##### Missing nets translations
-
-```xml
-
- missing_nets_translation
-
-
-
-
-
-
-
-```
-
-The purpose of this map filed is to translate the message in the `missing_allowed_nets` HTML textarea, because the
-message in the textarea is dynamically generated depending on the active locale.
-
-It must have the ID `missing_nets_translation` and be of type `enumeration_map`.
-
-##### My full filter
-
-```xml
-
- my_full_filter
-
-
-```
-
-This task ref holds a reference to the view_filter transition and is displayed in all tasks that should show the contents of the saved filter.
-
-It is not referenced by anything outside the process, so it can be freely modified, provided all the internal references are compatible.
-
-#### Functions
-
-##### initializeMyFullFilterTaskRef
-
-```xml
-
- {
- com.netgrif.application.engine.petrinet.domain.dataset.TaskField myFullFilter
- ->
- change myFullFilter value {return [findTask({it.caseId.eq(useCase.stringId).and(it.transitionId.eq("view_filter"))}).stringId]}
- }
-
-```
-
-This utility process-scoped function is used to set the value of the `my_full_filter` task ref data variable.
-
-It is called in a finish-post action of both the `frontend_create` and `auto_create` transitions,
-since their execution makes the searched transition (`view_filter`) executable.
-
-#### Roles
-
-##### System
-
-The system role is used to hide the `view_filter` and `view_as_ancestor` tasks from the user.
-
-The other transitions executed by the system are never searched for by the frontend API and therefore don't need to have this role assigned to them.
-
-#### Transitions
-
-The net consists of seven transitions. **Set filter metadata** and **create new filter** are used when creating filter
-from frontend filter API.
-**Automated new** is used, when creating filter from backend automatically. **Import filter** transition is used when
-importing filters in the
-_import\_filters_ process. The last three transitions **Details**, **View filter** and **View as ancestor** are used to
-display filter preview.
-
-##### Set filter metadata
-
-```xml
-
- frontend_create
-
-
-
- filter
-
- editable
-
-
-
- filter_type
-
- editable
-
-
-
- origin_view_id
-
- editable
-
-
-
-
-```
-
-This transition is executed automatically by the frontend filter API in order to set the necessary filter data into the
-process instance, when a new filter is created (saved).
-
-It must have the transition ID `frontend_create`.
-
-It must contain 4 data fields that are set via an API request:
-
-* `filter`
-* `filter_type`
-* `origin_view_id`
-* `parent_filter_id`
-
-Custom set data requests can be sent via the frontend filter API. These requests target this task. Therefore, if you
-want to set additional properties to your newly created filter instances you can do so by adding the necessary data
-variables to this task and then use the frontend API to set their values.
-
-Once it finishes the `view_filter` and `view_as_ancestor` tasks become executable.
-An action is bound to the finish of this transition, that sets the reference of the `my_full_filter` task ref.
-
-##### Create new filter
-
-```xml
-
- newFilter
- auto
-
-
-
- my_full_filter
-
- visible
-
-
-
-
-
- visibility
-
- editable
- required
-
-
-
- new_title
-
- editable
- required
-
-
-
-
-```
-
-This transition is displayed to the user in the side menu when a new filter case instance is created (a filter is saved)
-through the frontend filter API.
-
-It can reference any filter data variables. The default implementation references, the filter and its type in visible
-mode (they were set in the previous step), an editable visibility choice and an editable text field for setting the new
-filter case title (via a finish action).
-
-It must have the transition ID `newFilter`.
-
-##### Automated new filter
-
-```xml
-
- auto_create
-
-
-
- filter
-
- editable
-
-
-
- filter_type
-
- editable
-
-
-
- visibility
-
- editable
-
-
-
- origin_view_id
-
- editable
-
-
-
-
-```
-
-This transition is executed by the `DefaultFiltersRunner`, in order to set the data present in the previous two
-transitions with a single `setData` operation.
-
-It must have the transition ID `auto_create`.
-
-It must contain 5 data fields that are set via a `setData` API call.
-
-* `filter`
-* `filter_type`
-* `origin_view_id`
-* `parent_filter_id`
-* `visibility`
-
-Once it finishes the `view_filter` and `view_as_ancestor` tasks become executable.
-An action is bound to the finish of this transition, that sets the reference of the `my_full_filter` task ref.
-
-##### Import filter
-
-```xml
-
- import_filter
-
-
-
- new_title
-
- editable
-
-
-
- filter_type
-
- visible
-
-
-
- visibility
-
- editable
-
-
-
- missing_allowed_nets
-
- hidden
-
-
-
-
-
- my_full_filter
-
- visible
-
-
-
-
-```
-
-This transition is used in the `import_filters` process to allow editing of filter name and filter visibility when
-importing a new filter.
-
-It must have the transition ID `import_filter`.
-
-It should contain at least these data fields to display to the user which filter is being imported and allow them to
-change some fundamental filter properties:
-
-* `new_title` (editable)
-* `filter_type` (visible)
-* `visibility` (editable)
-* `my_full_filter` (visible)
-* `missing_allowed_nets` (hidden) - made visible by the import action if some nets are missing
-
-##### Details
-
-```xml
-
- t2
-
-
-
- filter
-
- visible
-
-
-
- filter_type
-
- visible
-
-
-
- visibility
-
- visible
-
-
-
-
-```
-
-This transition makes the filter metadata accessible to the users of the application.
-
-The Filter process interface does not specify any restrictions for this data variable, it can be freely overridden or
-omitted. Beware however, that it is referenced by the `origin_view_id` actions. This must be taken into the account when
-omitting this transition.
-
-##### View filter
-
-```xml
-
- view_filter
-
-
-
- filter
-
- visible
-
-
-
- filter_case_id
-
- hidden
-
-
-
- origin_view_id
-
- forbidden
-
-
-
- taskref_and_parent
-
- visible
-
-
-
-
- DataGroup_1
- grid
-
- and_view
-
- forbidden
-
-
-
- trimmed_origin_view_id
-
- forbidden
-
-
-
-
-```
-
-This transition displays the true content of the filter represented by the process. It can be task-reffed to show a
-referenced filter somewhere (such as in the configurable group navigation entries and filter previews). In addition to
-the filter field itself the ancestor filters are displayed here as well. Each of them is prefixed with an AND text to
-indicate that they are combined with the original filter with the **and** operator.
-
-If the root of the filter chain is a filter process (indicated by its `parent_filter_id` having a non-empty value)
-the root filters content will be the last entry displayed. If the root is a frontend filter
-(indicated by its `origin_view_id` field being set to a non-empty string) the last entry will
-contain a text indicating the view from which the filter originates. The displayed view ID excludes any tab suffixes.
-
-If the filter does not originate from a view its `origin_view_id` field must have its behavior set to `forbidden`,
-so that the frontend parsing mechanism won't find false positives during the interpretation of the filter.
-
-It must have the transition ID `view_filter`.
-
-It must contain 1 data field:
-
-* `filter`
-
-##### View as ancestor
-
-```xml
-
- view_as_ancestor
-
-
-
- and_me
-
- visible
-
-
-
- filter
-
- visible
-
-
-
- taskref_and_parent
-
- visible
-
-
-
-
- DataGroup_1
- grid
-
- and_view
-
- forbidden
-
-
-
- trimmed_origin_view_id
-
- forbidden
-
-
-
-
-```
-
-Contains the same information as the View filter task, but every row is prefixed with an AND text (including the first
-row that contains the filter field of this case).
-
-This task is referenced when resolving ancestor filters from the immediate children of this filter.
-
-## Backend filter API
-
-Since filters are implemented as Petriflow processes, they share the same API with any other process. The old filter
-related services, controllers and other classes have been deprecated in the 5.4.0 release and should no longer be used.
-
-There are a few things to keep in mind when working with filters.
-
-### Using filter fields for filtering of cases and tasks
-
-You can use the value and other attributes of a filter field to create database queries.
-
-When doing so, make sure to check if the filter has the appropriate type (that is only use Case filters to filter cases
-and Task filters to filter tasks).
-
-The value attribute of a filter field is
-an [elastic query string query](https://www.elastic.co/guide/en/elasticsearch/reference/6.6/query-dsl-query-string-query.html) (
-as mentioned above) and therefore cannot be used to filter entries from the Mongo database. It can however be turned
-into a `CaseSearchRequest` class instance, by populating the `query` attribute with the filter field value. This object
-can then be passed to the `ElasticCaseService` to find the cases that match the query. If you want to search for task
-instances then analogous classes and services exist.
-
-### Actions API
-
-Filter fields have only a limited support in the actions API.
-
-Only their value can be changed with the `change` action and this change is NOT propagated to the other filter field
-attributes (allowedNets and filterMetadata). Since these two attributes are the important part when restoring an
-advanced search component state on the frontend it can easily lead to “desynchronisation“ of these values. Changing
-these values should therefore be done cautiously.
-
-### Set data method
-
-The set data method of the `TaskDataService` can be used to modify all the attributes of a filter field. All of them
-must be set at the same time, any missing attributes will have its value set to `null`.
-
-### DefaultFiltersRunner
-
-This runner contains utility methods that can be used to create default system filter process instances. The author of
-these filters will be the system user.
-
-## Frontend filter API
-
-Since saved filters are cases you should use the existing API for interacting with cases. Utility methods exist for some
-operations. You should keep in mind however that, the frontend library does not provide a full filter persistence and
-management implementation, only the building blocks for creating one, therefore you must implement it on your own
-according to your wishes. An overview of these building blocks can be found in the following sections.
-
-### Filter constants
-
-The
-enum [UserFilterConstants](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/miscellaneous/enumerations.html#UserFilterConstants)
-contains identifiers and IDs of all parts of the filter process referenced by the frontend filters API.
-
-### UserFiltersService
-
-The [UserFiltersService](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/injectables/UserFiltersService.html)
-contains the API for saving, loading and deleting filter process instances.
-
-The search component contains buttons that trigger the save and load methods, so you do not have to use this service
-directly, but if you wish to create your own user interface you can re-use the implementation provided by this service.
-
-Injection tokens are available for the configuration of the side menu components used to save and load
-filters (`NAE_SAVE_FILTER_COMPONENT` and `NAE_LOAD_FILTER_COMPONENT`). An injection token is also available for
-configuring the filter that filters the filter process instances displayed when loading a filter (`NAE_FILTERS_FILTER`).
-
-### SearchComponent
-
-The [SearchComponent](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/classes/AbstractSearchComponent.html)
-is a wrapper for the two search mode components (fulltext and advanced)
-these components can be used independently of each other and the search component combines them into one and adds
-various control elements to them.
-
-The search component has two outputs - `filterLoaded` and `filterSaved`. These emit data related to either the saved
-filter, or the selected filter in the load pop-up. The developers must process these outputs in order to implement fully
-functional filter management.
-
-The component also has na input - `additionalFilterData`. This input can be used to modify the content of the set data
-request that is sent by the `UserFiltersService`, when a new filter is created. This way a less invasive option is
-available when overriding the default filter process and adding additional metadata necessary for your implementation of
-filter management.
-
-An injection token is available for the configuration of the search component - `NAE_SEARCH_COMPONENT_CONFIGURATION`. It
-provides
-a [SearchComponentConfiguration](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/interfaces/SearchComponentConfiguration.html)
-object that can be used to hide many elements of the search component (buttons mostly). This way you can remove the save
-and/or load filter buttons and therefore not allow the users to persist filters in some specific views.
-
-### SearchService
-
-The [SearchService](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/injectables/SearchService.html)
-provides two complementary methods - `createPredicateMetadata` and `loadFromMetadata`. These can be used to populate the
-search service with a predicate stored inside a filter field (`filterMetadata` attribute). If an advanced search
-component is connected to the search service, then it will automatically display the loaded predicate.
-
-### FilterExtractionService
-
-The [FilterExtractionService](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/injectables/FilterExtractionService.html)
-contains the functionality of extracting a frontend [Filter](https://developer.netgrif.com/projects/engine-frontend/latest/nae/docs/classes/Filter.html)
-instance from the data of a configurable navigation entry task.
\ No newline at end of file
diff --git a/docs/search/filter_import_export.md b/docs/search/filter_import_export.md
deleted file mode 100644
index cd98e559025..00000000000
--- a/docs/search/filter_import_export.md
+++ /dev/null
@@ -1,172 +0,0 @@
-# Filter import/export
-
-## User guide
-
-This guide is aimed at application users that wish to know, how to import/export selected filters from/to application.
-If you are developer that wishes to know more about the implementation and various ways the system can be interacted
-with, you can find this information in the Developer guide of filter import/export.
-
-### Overview
-
-Every user in the application have option to import/export filters. For every user in application case for import
-filters and also case for export filters exists as shown on the next image.
-
-
-
-
-
-
-
-### Processes
-
-#### Export filters
-
-After user opens **Export filters USERNAME** case, task to export filters is displayed. The task consists of three
-fields, from which only two are initially displayed to user.
-
-
-
-
-
-
-
-First field is multi choice field, which allows user to select multiple filters, which he wants to export. Filters that
-are displayed in this multi choice are all **public** filters in the application (filters which can be created by other
-users) and also all **private** filters of currently logged user. After user selects filters which he wants to export
-and clicks on the **Export filters** button, the third field is displayed.
-
-
-
-This field holds exported xml file, which contains exported filters in the custom xml format. User can download this
-file by clicking on its name. This file can be later used to import filters into the application. Users should never
-create or modify these files on their own, because of the complexity of filters format inside xml file.
-
-#### Import filters
-
-After user opens **Import filters USERNAME** case, task to import filters is displayed. The task consists of two fields,
-which are initially displayed to user and after these two fields there is one section for every imported filter.
-
-
-
-
-
-
-
-First field is file field, where user should upload xml file, that contains exported filters. After user uploads this
-xml file and clicks on **Import filters** button, application validate uploaded file against schema, which doesn't allow
-upload of files in incorrect format. If format of uploaded file is correct, application initialize creation of filters
-and displays these filters under initially displayed fields.
-
-
-
-Each section after horizontal line represents one imported filter. User can change two properties for each imported
-filter. First one is filter name and the second one is visibility of the filter. User can also see type of the filter (
-if the filter is for tasks or for cases) and also filter preview, so he can know what it is filtering.
-
-In some situation, imported filter have dependency on some processes. To correctly display preview of filter and further
-correct function of filter, all these processes need to be uploaded in application. If some of these processes are
-missing, list of missing processes is displayed inside textarea as shown on next image.
-
-
-
-When user is satisfied with imported filters, their names and visibility, he can confirm creation of these filters by
-pressing **FINISH** button on the bottom right. If the imported filters are not according to his ideas, he can abort
-further creation of these filters by pressing **CANCEL** button or deleting uploaded xml file from file field.
-
-## Developer guide
-
-This guide is aimed at developers that wish to know the implementation detail of filter import/export, so they can
-interact with or override its implementation. If you are application user and wish to know how to use the options
-available to you read the User guide of filter import/export. Please read **Filter process guide** before u start
-reading this one, because of some references on this process.
-
-### Overview
-
-The filter import and export consists of two processes, which are independent of each other. Names of processes are
-self-explaining:
-
-- **Export of filters** - serves for export of filters into xml file `export_filters.xml`
-- **Import of filters** - serves for import of filters from xml file `import_filters.xml`
-
-New schema, which describes format of xml file for exported filters, were introduced
-`filter_export_schema.xml`. All imported xml files containing filters are validated against this schema to ensure
-filters will be correctly created and working. Also, new exception class for incorrect xml file format of imported
-filters was created to throw error after validating xml file against schema `IllegalFilterFileException`.
-
-Multiple classes were added to support serialization and deserialization of filters. These classes are:
-
-- Configuration
-- FilterImportExport
-- FilterImportExportList
-- FilterMetadataExport
-- Predicate
-- PredicateArray
-- PredicateValue
-- CustomFilterDeserializer
-
-`ActionDelegate` have two new functions, which support filters import/export:
-`exportFilters(Collection filtersToExport)` and `importFilters()`. Also, new service `FilterImportExportService`
-which is called by these two functions was created and which performs most functionality in importing and exporting
-functions.
-
-When creating new user, case for importing filters and also case for exporting filters is created for this user.
-
-Also, new property was added into `application.properties`, with name `nae.filter.export.file-name`, which defines name
-of xml file that contains exported filters. This property has default string value of **filters.xml**.
-
-When filters are exported, all of their ancestors are exported as well. If the exported filters have common ancestors,
-the ancestors are only exported once. The relationships between filters are reconstructed on import based on the
-exported filters case Ids. It is assumed that parents precede their children in the imported file
-(the exported file is generated in this way). If a filter cannot find its parent on import the connection will
-be severed and an error will be logged.
-
-### Processes
-
-#### Export filters
-
-Export process consists of one task `exportFilter`, which carry out whole exporting of filters. Process and also the
-only task consist of three data fields. First one is `exportable_filters`, which is **multichoice_map** that displays
-all filters, that are exportable by currently logged user. List is loaded from `ActionDelegate`
-method `findAllFilters()` and returns all filter cases, that are public and created by any user or that are private and
-created by currently logged user.
-
-After selecting filters to export and clicking on second data field **button** with id `export_btn`, the
-method `exportFilters()` from `ActionDelegate`
-is called. This method serialize selected filters into xml file and put this file into third **file** field with
-id `export_file`.
-
-Export filters can be run any number of times so the user can export any number of filters in selected combinations into
-any number of xml files.
-
-#### Import filters
-
-Import process also consists of one task `importFilter`, which carry out whole importing of filters. There are also just
-three data fields in this process. First one is **file** field `upload_file` that serves for upload of xml file with
-filters. After uploading this file and clicking on the next **button** field `import_file`, the `importFilters()` method
-from `ActionDelegate` is called, that validates uploaded xml file against xsd schema.
-
-- If file is valid, method creates **Filter** cases via **Automated new filter** task and move them into **Import
- filter** task. Method returns list of **Import filter** task ids, that are set as value for **taskRef**
- field `imported_filters`, so the user can update some values of these filters.
-- If file is not valid, error message is thrown.
-
-Pressing **FINISH** button in this task moves imported filters into state, where they can be added into group
-navigation.
-
-Pressing **CANCEL** button or changing value to `upload_file` deletes created filters, so there will not be unworkable
-filters saved in the application database.
-
-As well as export filters, import filters can be run any number of times, so user can upload how many filters as he
-wants.
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFilterField.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFilterField.groovy
new file mode 100644
index 00000000000..38e32db0ee1
--- /dev/null
+++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/CaseFilterField.groovy
@@ -0,0 +1,23 @@
+package com.netgrif.application.engine.petrinet.domain.dataset
+
+import org.springframework.data.mongodb.core.mapping.Document
+
+@Document
+class CaseFilterField extends Field {
+
+ CaseFilterField() {
+ super()
+ }
+
+ @Override
+ FieldType getType() {
+ return FieldType.CASE_FILTER
+ }
+
+ @Override
+ Field clone() {
+ CaseFilterField clone = new CaseFilterField()
+ super.clone(clone)
+ return clone
+ }
+}
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldType.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldType.groovy
index 0b96783f52c..53ed4407918 100644
--- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldType.groovy
+++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FieldType.groovy
@@ -21,7 +21,9 @@ enum FieldType {
DATETIME("dateTime"),
BUTTON("button"),
TASK_REF("taskRef"),
- FILTER("filter"),
+ CASE_FILTER("caseFilter"),
+ TASK_FILTER("taskFilter"),
+ PROCESS_FILTER("processFilter"),
I18N("i18n"),
STRING_COLLECTION("stringCollection")
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FilterField.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FilterField.groovy
deleted file mode 100644
index a0102f21cc5..00000000000
--- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FilterField.groovy
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.netgrif.application.engine.petrinet.domain.dataset
-
-import org.springframework.data.mongodb.core.mapping.Document
-
-@Document
-class FilterField extends FieldWithAllowedNets {
-
- /**
- * Serialized information necessary for the restoration of the advanced search frontend GUI.
- *
- * Backend shouldn't need to interact with this attribute
- */
- private Map filterMetadata
-
- FilterField() {
- super()
- allowedNets = new ArrayList<>()
- filterMetadata = new HashMap<>()
- }
-
- FilterField(List allowedNets) {
- super(allowedNets)
- filterMetadata = new HashMap<>()
- }
-
- @Override
- FieldType getType() {
- return FieldType.FILTER
- }
-
- @Override
- Field clone() {
- FilterField clone = new FilterField()
- super.clone(clone)
- clone.filterMetadata = this.filterMetadata
-
- return clone
- }
-
- Map getFilterMetadata() {
- return filterMetadata
- }
-
- void setFilterMetadata(Map filterMetadata) {
- this.filterMetadata = filterMetadata
- }
-}
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ProcessFilterField.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ProcessFilterField.groovy
new file mode 100644
index 00000000000..35d238becf4
--- /dev/null
+++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/ProcessFilterField.groovy
@@ -0,0 +1,23 @@
+package com.netgrif.application.engine.petrinet.domain.dataset
+
+import org.springframework.data.mongodb.core.mapping.Document
+
+@Document
+class ProcessFilterField extends Field {
+
+ ProcessFilterField() {
+ super()
+ }
+
+ @Override
+ FieldType getType() {
+ return FieldType.PROCESS_FILTER
+ }
+
+ @Override
+ Field clone() {
+ ProcessFilterField clone = new ProcessFilterField()
+ super.clone(clone)
+ return clone
+ }
+}
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/TaskFilterField.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/TaskFilterField.groovy
new file mode 100644
index 00000000000..a54c5421b59
--- /dev/null
+++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/TaskFilterField.groovy
@@ -0,0 +1,23 @@
+package com.netgrif.application.engine.petrinet.domain.dataset
+
+import org.springframework.data.mongodb.core.mapping.Document
+
+@Document
+class TaskFilterField extends Field {
+
+ TaskFilterField() {
+ super()
+ }
+
+ @Override
+ FieldType getType() {
+ return FieldType.TASK_FILTER
+ }
+
+ @Override
+ Field clone() {
+ TaskFilterField clone = new TaskFilterField()
+ super.clone(clone)
+ return clone
+ }
+}
diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
index 26791594b3e..5fd5c9d022e 100644
--- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
+++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
@@ -26,14 +26,14 @@ import com.netgrif.application.engine.mail.interfaces.IMailService
import com.netgrif.application.engine.menu.domain.FilterBody
import com.netgrif.application.engine.menu.domain.MenuItemBody
import com.netgrif.application.engine.menu.domain.MenuItemConstants
-import com.netgrif.application.engine.menu.domain.configurations.TabbedCaseViewBody
-import com.netgrif.application.engine.menu.domain.configurations.TabbedTaskViewBody
+import com.netgrif.application.engine.menu.domain.configurations.CaseViewBody
+import com.netgrif.application.engine.menu.domain.configurations.TaskViewBody
import com.netgrif.application.engine.menu.domain.configurations.ViewBody
import com.netgrif.application.engine.menu.domain.dashboard.DashboardItemBody
import com.netgrif.application.engine.menu.domain.dashboard.DashboardManagementBody
-import com.netgrif.application.engine.menu.services.interfaces.DashboardItemService
-import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService
-import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService
+import com.netgrif.application.engine.menu.service.interfaces.DashboardItemService
+import com.netgrif.application.engine.menu.service.interfaces.DashboardManagementService
+import com.netgrif.application.engine.menu.service.interfaces.IMenuItemService
import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService
import com.netgrif.application.engine.pdf.generator.config.PdfResource
import com.netgrif.application.engine.pdf.generator.service.interfaces.IPdfGenerator
@@ -49,8 +49,6 @@ import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetServi
import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService
import com.netgrif.application.engine.petrinet.service.interfaces.IUriService
import com.netgrif.application.engine.rules.domain.RuleRepository
-import com.netgrif.application.engine.startup.DefaultFiltersRunner
-import com.netgrif.application.engine.startup.FilterRunner
import com.netgrif.application.engine.startup.ImportHelper
import com.netgrif.application.engine.utils.FullPageRequest
import com.netgrif.application.engine.workflow.domain.Case
@@ -162,18 +160,9 @@ class ActionDelegate {
@Autowired
Scheduler scheduler
- @Autowired
- IUserFilterSearchService filterSearchService
-
@Autowired
IConfigurableMenuService configurableMenuService
- @Autowired
- IMenuImportExportService menuImportExportService
-
- @Autowired
- IFilterImportExportService filterImportExportService
-
@Autowired
IExportService exportService
@@ -672,7 +661,7 @@ class ActionDelegate {
saveChangedChoices(field, targetCase, targetTask)
},
allowedNets : { cl ->
- if (!(field instanceof CaseField)) // TODO make this work with FilterField as well
+ if (!(field instanceof CaseField))
return
def allowedNets = cl()
@@ -1395,25 +1384,6 @@ class ActionDelegate {
return new DynamicValidation(rule, message)
}
- List findFilters(String userInput) {
- return filterSearchService.autocompleteFindFilters(userInput)
- }
-
- List findAllFilters() {
- return filterSearchService.autocompleteFindFilters("")
- }
-
- FileFieldValue exportFilters(Collection filtersToExport) {
- if (filtersToExport.isEmpty()) {
- return null
- }
- return filterImportExportService.exportFiltersToFile(filtersToExport)
- }
-
- List importFilters() {
- return filterImportExportService.importFilters()
- }
-
File exportCasesToFile(Closure predicate, String pathName, ExportDataConfig config = null,
int pageSize = exportConfiguration.getMongoPageSize()) {
File exportFile = new File(pathName)
@@ -1556,318 +1526,6 @@ class ActionDelegate {
return findTasks(requests, loggedUser, page, pageSize, locale, isIntersection)
}
- List findDefaultFilters() {
- if (!createDefaultFilters) {
- return []
- }
- return findCases({ it.processIdentifier.eq(FilterRunner.FILTER_PETRI_NET_IDENTIFIER).and(it.author.id.eq(userService.system.stringId)) })
- }
-
- /**
- * Creates filter instance of type {@value DefaultFiltersRunner#FILTER_TYPE_CASE}
- *
- * @param title filter case title
- * @param query elastic query for the view
- * @param icon filter case icon
- * @param allowedNets List of process identifiers
- * @param visibility Possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created {@link Case} instance of filter
- */
- @NamedVariant
- Case createCaseFilter(def title, String query, List allowedNets,
- String icon = "", String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE, def filterMetadata = null) {
- return createFilter(title, query, DefaultFiltersRunner.FILTER_TYPE_CASE, allowedNets, icon, visibility, filterMetadata)
- }
-
- /**
- * Creates filter instance of type {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- *
- * @param title filter case title
- * @param query elastic query for the view
- * @param icon filter case icon
- * @param allowedNets List of process identifiers
- * @param visibility Possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created {@link Case} instance of filter
- */
- @NamedVariant
- Case createTaskFilter(def title, String query, List allowedNets,
- String icon = "", String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE, def filterMetadata = null) {
- return createFilter(title, query, DefaultFiltersRunner.FILTER_TYPE_TASK, allowedNets, icon, visibility, filterMetadata)
- }
-
- /**
- * Creates filter instance.
- *
- * @param title filter case title
- * @param query elastic query for the view
- * @param type Filter type. Possible values: {@value DefaultFiltersRunner#FILTER_TYPE_CASE} or {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- * @param icon filter case icon
- * @param allowedNets List of process identifiers
- * @param visibility Possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created {@link Case} instance of filter
- */
- @NamedVariant
- Case createFilter(def title, String query, String type, List allowedNets,
- String icon, String visibility, def filterMetadata) {
- FilterBody body = new FilterBody()
- body.setTitle((title instanceof I18nString) ? title : new I18nString(title as String))
- body.setQuery(query)
- body.setType(type)
- body.setAllowedNets(allowedNets)
- body.setIcon(icon)
- body.setVisibility(visibility)
- body.setMetadata(filterMetadata)
- return menuItemService.createFilter(body)
- }
-
- /**
- * Changes data of provided filter instance. These attributes can be changed:
- *
changeFilter filter title { new I18nString("New title") }
- *
changeFilter filter title { "New title" }
- *
changeFilter filter icon { "filter_alt" }
- *
changeFilter filter uri { "/my_node1/my_node2" }
- *
- * @param filter {@link Case} instance of filter
- */
- def changeFilter(Case filter) {
- [query : { cl ->
- updateFilter(filter, [
- (DefaultFiltersRunner.FILTER_FIELD_ID): [
- "type" : "enumeration_map",
- "value": cl() as String
- ]
- ])
- },
- visibility : { cl ->
- updateFilter(filter, [
- (DefaultFiltersRunner.FILTER_VISIBILITY_FIELD_ID): [
- "type" : "enumeration_map",
- "value": cl() as String
- ]
- ])
- },
- allowedNets : { cl ->
- String currentQuery = workflowService.findOne(filter.stringId).dataSet[DefaultFiltersRunner.FILTER_FIELD_ID].value
- updateFilter(filter, [
- (DefaultFiltersRunner.FILTER_FIELD_ID): [
- "type" : "filter",
- "value" : currentQuery,
- "allowedNets": cl() as List
- ]
- ])
- },
- filterMetadata: { cl ->
- String currentQuery = workflowService.findOne(filter.stringId).dataSet[DefaultFiltersRunner.FILTER_FIELD_ID].value
- updateFilter(filter, [
- (DefaultFiltersRunner.FILTER_FIELD_ID): [
- "type" : "filter",
- "value" : currentQuery,
- "filterMetadata": cl() as Map
- ]
- ])
- },
- title : { cl ->
- filter = workflowService.findOne(filter.stringId)
- def value = cl()
- filter.setTitle(value as String)
- filter.dataSet[DefaultFiltersRunner.FILTER_I18N_TITLE_FIELD_ID].value = (value instanceof I18nString) ? value : new I18nString(value as String)
- workflowService.save(filter)
- },
- icon : { cl ->
- filter = workflowService.findOne(filter.stringId)
- def icon = cl() as String
- filter.setIcon(icon)
- workflowService.save(filter)
- },
- uri : { cl ->
- filter = workflowService.findOne(filter.stringId)
- def uri = cl() as String
- filter.setUriNodeId(uriService.findByUri(uri).stringId)
- workflowService.save(filter)
- }]
- }
-
- /**
- * deletes filter instance
- * Note: do not call this method if given instance is referenced in any menu_item instance
- * @param filter
- * @return
- */
- def deleteFilter(Case filter) {
- workflowService.deleteCase(filter.stringId)
- }
-
- /**
- * create menu item for given filter instance
- * @param uri
- * @param identifier - unique item identifier
- * @param filter
- * @param groupName
- * @param allowedRoles ["role_import_id": "net_import_id"]
- * @param bannedRoles ["role_import_id": "net_import_id"]
- * @return
- */
- @Deprecated
- Case createMenuItem(String uri, String identifier, Case filter, String groupName, Map allowedRoles, Map bannedRoles = [:], List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(
- uri,
- identifier,
- filter.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString,
- null
- )
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseCustomView(false)
- body.setUseTabbedView(true)
-
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
-
- return menuItemService.createMenuItem(body)
- }
-
- /**
- * create menu item for given filter instance
- * @param uri
- * @param identifier - unique item identifier
- * @param filter
- * @param groupName
- * @param allowedRoles
- * @param bannedRoles
- * @return
- */
- @Deprecated
- Case createMenuItem(String uri, String identifier, Case filter, String groupName, List allowedRoles, List bannedRoles = [], List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(
- uri,
- identifier,
- filter.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString,
- null
- )
-
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseCustomView(false)
- body.setUseTabbedView(true)
-
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
-
- return menuItemService.createMenuItem(body)
- }
-
- /**
- * create menu item for given filter instance
- * @param uri
- * @param identifier - unique item identifier
- * @param filter
- * @param groupName
- * @param allowedRoles ["role_import_id": "net_import_id"]
- * @param bannedRoles ["role_import_id": "net_import_id"]
- * @param group - if null, default group is used
- * @return
- */
- @Deprecated
- Case createMenuItem(String uri, String identifier, Case filter, Map allowedRoles, Map bannedRoles = [:], Case group = null, List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(
- uri,
- identifier,
- filter.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString,
- null
- )
-
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseCustomView(false)
- body.setUseTabbedView(true)
-
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
-
- return menuItemService.createMenuItem(body)
- }
-
- /**
- * create menu item for given filter instance
- * @param uri
- * @param identifier - unique item identifier
- * @param filter
- * @param allowedRoles
- * @param bannedRoles
- * @param group - if null, default group is used
- * @return
- */
- @Deprecated
- Case createMenuItem(String uri, String identifier, Case filter, List allowedRoles, List bannedRoles = [], Case group = null, List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(
- uri,
- identifier,
- filter.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString,
- null
- )
-
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseCustomView(false)
- body.setUseTabbedView(true)
-
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
-
- return menuItemService.createMenuItem(body)
- }
-
- /**
- * Creates item in menu with given parameters
- *
- * @param uri resource where the item is located in
- * @param identifier unique identifier of item
- * @param name displayed label in menu and tab
- * @param icon displayed icon in menu and tab
- * @param filter Case instance of filter.xml
- * @param allowedRoles Map of roles, which have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param bannedRoles Map of roles, which don't have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param caseDefaultHeaders List of headers displayed in case view
- * @param taskDefaultHeaders List of headers displayed in task view
- *
- * @return created Case of menu_item
- * */
- @NamedVariant
- Case createMenuItem(String uri, String identifier, def name, String icon = "filter_none", Case filter = null,
- Map allowedRoles = [:], Map bannedRoles = [:],
- List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(
- uri,
- identifier,
- (name instanceof I18nString) ? name : new I18nString(name as String),
- icon
- )
-
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseCustomView(false)
- body.setUseTabbedView(true)
-
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
-
- return menuItemService.createMenuItem(body)
- }
-
/**
* Changes data of provided menu_item instance. These attributes can be changed:
*
@@ -1899,31 +1557,31 @@ class ActionDelegate {
title : { cl ->
def value = cl()
I18nString newName = (value instanceof I18nString) ? value : new I18nString(value as String)
- setData(MenuItemConstants.TRANS_SETTINGS_ID, item, [
+ setData(MenuItemConstants.TRANS_SYNC_ID, item, [
(MenuItemConstants.FIELD_MENU_NAME): ["type": "i18n", "value": newName]
])
},
menuIcon : { cl ->
def value = cl()
- setData(MenuItemConstants.TRANS_SETTINGS_ID, item, [
+ setData(MenuItemConstants.TRANS_SYNC_ID, item, [
(MenuItemConstants.FIELD_MENU_ICON): ["type": "text", "value": value]
])
},
tabIcon : { cl ->
def value = cl()
- setData(MenuItemConstants.TRANS_SETTINGS_ID, item, [
+ setData(MenuItemConstants.TRANS_SYNC_ID, item, [
(MenuItemConstants.FIELD_TAB_ICON): ["type": "text", "value": value]
])
},
useCustomView : { cl ->
def value = cl()
- setData(MenuItemConstants.TRANS_SETTINGS_ID, item, [
+ setData(MenuItemConstants.TRANS_SYNC_ID, item, [
(MenuItemConstants.FIELD_USE_CUSTOM_VIEW): ["type": "boolean", "value": value]
])
},
customViewSelector: { cl ->
def value = cl()
- setData(MenuItemConstants.TRANS_SETTINGS_ID, item, [
+ setData(MenuItemConstants.TRANS_SYNC_ID, item, [
(MenuItemConstants.FIELD_CUSTOM_VIEW_SELECTOR): ["type": "text", "value": value]
])
}]
@@ -1953,178 +1611,25 @@ class ActionDelegate {
}
}
- /**
- * simplifies the process of creating a filter, menu item
- * @param uri
- * @param identifier - unique identifier of menu item
- * @param title
- * @param query
- * @param icon
- * @param type - "Case" or "Task"
- * @param allowedNets
- * @param groupName - name of group to add menu item to
- * @param allowedRoles
- * @param bannedRoles
- * @param visibility - "private" or "public"
- * @return
- */
- @Deprecated
- Case createFilterInMenu(String uri, String identifier, def title, String query, String type,
- List allowedNets,
- String groupName,
- Map allowedRoles = [:],
- Map bannedRoles = [:],
- List defaultHeaders = [],
- String icon = "",
- String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE) {
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle((title instanceof I18nString) ? title : new I18nString(title as String))
- filterBody.setQuery(query)
- filterBody.setType(type)
- filterBody.setAllowedNets(allowedNets)
- filterBody.setIcon(icon)
- filterBody.setVisibility(visibility)
- Case filter = menuItemService.createFilter(filterBody)
- Case menuItem = createMenuItem(uri, identifier, filter, groupName, allowedRoles, bannedRoles, defaultHeaders)
- return menuItem
- }
-
- /**
- * simplifies the process of creating a filter, menu item
- * @param uri
- * @param identifier - unique identifier of menu item
- * @param title
- * @param query
- * @param icon
- * @param type - "Case" or "Task"
- * @param allowedNets
- * @param allowedRoles
- * @param bannedRoles
- * @param visibility - "private" or "public"
- * @param orgGroup - group to add item to, if null default group is used
- * @return
- */
- @Deprecated
- Case createFilterInMenu(String uri, String identifier, def title, String query, String type, List allowedNets,
- Map allowedRoles = [:],
- Map bannedRoles = [:],
- List defaultHeaders,
- String icon = "",
- String visibility = DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE,
- Case orgGroup = null) {
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle((title instanceof I18nString) ? title : new I18nString(title as String))
- filterBody.setQuery(query)
- filterBody.setType(type)
- filterBody.setAllowedNets(allowedNets)
- filterBody.setIcon(icon)
- filterBody.setVisibility(visibility)
- Case filter = menuItemService.createFilter(filterBody)
- Case menuItem = createMenuItem(uri, identifier, filter, allowedRoles, bannedRoles, orgGroup, defaultHeaders)
- return menuItem
- }
-
- /**
- * Creates filter and menu_item instances with given parameters.
- *
- * @param uri resource where the item is located in
- * @param itemIdentifier unique identifier of item
- * @param itemAndFilterName displayed label in menu and tab
- * @param filterQuery elastic query for filter
- * @param filterType type of filter. Possible values: {@value DefaultFiltersRunner#FILTER_TYPE_CASE} or
- * {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- * @param filterVisibility possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or
- * {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterAllowedNets List of allowed nets. Element of list is process identifier
- * @param itemAndFilterIcon displayed icon in menu and tab
- * @param itemAllowedRoles Map of roles, which have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param itemBannedRoles Map of roles, which don't have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param itemCaseDefaultHeaders List of headers displayed in case view
- * @param itemTaskDefaultHeaders List of headers displayed in task view
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created {@link Case} instance of menu_item
- * */
- @NamedVariant
- Case createFilterInMenu(String uri, String itemIdentifier, def itemAndFilterName, String filterQuery,
- String filterType, String filterVisibility, List filterAllowedNets = [],
- String itemAndFilterIcon = "filter_none", Map itemAllowedRoles = [:],
- Map itemBannedRoles = [:], List itemCaseDefaultHeaders = [],
- List itemTaskDefaultHeaders = [], def filterMetadata = null) {
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle((itemAndFilterName instanceof I18nString) ? itemAndFilterName : new I18nString(itemAndFilterName as String))
- filterBody.setQuery(filterQuery)
- filterBody.setType(filterType)
- filterBody.setAllowedNets(filterAllowedNets)
- filterBody.setIcon(itemAndFilterIcon)
- filterBody.setVisibility(filterVisibility)
- filterBody.setMetadata(filterMetadata as Map)
- Case filter = menuItemService.createFilter(filterBody)
- Case menuItem = createMenuItem(uri, itemIdentifier, itemAndFilterName, itemAndFilterIcon, filter, itemAllowedRoles,
- itemBannedRoles, itemCaseDefaultHeaders, itemTaskDefaultHeaders)
- return menuItem
- }
-
- /**
- * Creates filter and menu_item instances with given parameters.
- *
- * @param body configuration class for menu item creation
- * @param filterQuery elastic query for filter
- * @param filterType type of filter. Possible values: {@value DefaultFiltersRunner#FILTER_TYPE_CASE} or
- * {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- * @param filterVisibility possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or
- * {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterAllowedNets List of allowed nets. Element of list is process identifier
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created {@link Case} instance of menu_item
- * */
- Case createFilterInMenu(MenuItemBody body, String filterQuery, String filterType, String filterVisibility,
- List filterAllowedNets = [], def filterMetadata = null) {
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle(body.menuName)
- filterBody.setQuery(filterQuery)
- filterBody.setType(filterType)
- filterBody.setAllowedNets(filterAllowedNets)
- filterBody.setIcon(body.menuIcon)
- filterBody.setVisibility(filterVisibility)
- filterBody.setMetadata(filterMetadata as Map)
-
- body.setView(createLegacyMenuItemViews(filterBody))
- body.setUseTabbedView(true)
-
- Case menuItem = createMenuItem(body)
- return menuItem
- }
-
Case createMenuItem(MenuItemBody body) {
return menuItemService.createMenuItem(body)
}
- protected ViewBody createLegacyMenuItemViews(Case filterCase, List caseDefaultHeaders = null,
- List taskDefaultHeaders = null) {
- FilterBody body = new FilterBody(filterCase)
- body.setType((String) filterCase?.getFieldValue("filter_type"))
- return createLegacyMenuItemViews(body, caseDefaultHeaders, taskDefaultHeaders)
- }
-
protected ViewBody createLegacyMenuItemViews(FilterBody filterBody, List caseDefaultHeaders = null,
List taskDefaultHeaders = null) {
if (filterBody.getType() == "Case") {
- ViewBody caseView = new TabbedCaseViewBody()
+ ViewBody caseView = new CaseViewBody()
caseView.setFilterBody(filterBody)
caseView.setDefaultHeaders(caseDefaultHeaders)
caseView.setRequireTitleInCreation(true)
- ViewBody taskView = new TabbedTaskViewBody()
+ ViewBody taskView = new TaskViewBody()
taskView.setDefaultHeaders(taskDefaultHeaders)
caseView.setChainedView(taskView)
return caseView
} else if (filterBody.getType() == "Task") {
- ViewBody taskView = new TabbedTaskViewBody()
+ ViewBody taskView = new TaskViewBody()
taskView.setFilterBody(filterBody)
taskView.setDefaultHeaders(taskDefaultHeaders)
return taskView
@@ -2162,17 +1667,6 @@ class ActionDelegate {
return menuItemService.duplicateItem(originItem, newTitle, newIdentifier)
}
- /**
- * Finds filter by name
- *
- * @param name Title of the filter
- *
- * @return found filter instance. Can be null
- */
- Case findFilter(String name) {
- return findCaseElastic("processIdentifier:$FilterRunner.FILTER_PETRI_NET_IDENTIFIER AND title.keyword:\"$name\"" as String)
- }
-
/**
* Finds menu item by unique identifier
*
@@ -2346,158 +1840,10 @@ class ActionDelegate {
} as Map
}
- private void updateFilter(Case filter, Map dataSet) {
- setData(DefaultFiltersRunner.DETAILS_TRANSITION, filter, dataSet)
- }
-
I18nString i18n(String value, Map translations) {
return new I18nString(value, translations)
}
- @Deprecated
- Map createMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, Map roles, Map bannedRoles = [:], Case group = null, List defaultHeaders = []) {
- if (existsMenuItem(id)) {
- log.info("$id menu exists")
- return null
- }
- Case filter = createCaseFilter(title, query, allowedNets, icon, DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE)
- Case menu = createMenuItem(uri, id, filter, roles, bannedRoles, group, defaultHeaders)
- return [
- "filter" : filter,
- "menuItem": menu
- ]
- }
-
- @Deprecated
- Map createTaskMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, Map roles, Case group = null, List defaultHeaders = []) {
- if (existsMenuItem(id)) {
- log.info("$id menu exists")
- return null
- }
- Case filter = createTaskFilter(title, query, allowedNets, icon, DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE)
- Case menu = createMenuItem(uri, id, filter, roles, [:], group, defaultHeaders)
- return [
- "filter" : filter,
- "menuItem": menu
- ]
- }
-
- @Deprecated
- Case createOrUpdateCaseMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, Map roles = [:], Map bannedRoles = [:], Case group = null, List defaultHeaders = []) {
- return createOrUpdateMenuItemAndFilter(uri, id, title, query, DefaultFiltersRunner.FILTER_TYPE_CASE,
- DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE, allowedNets, icon, roles, bannedRoles, defaultHeaders)
- }
-
- @Deprecated
- Case createOrUpdateTaskMenuItem(String id, String uri, String query, String icon, String title, List allowedNets, Map roles = [:], Map bannedRoles = [:], Case group = null, List defaultHeaders = []) {
- return createOrUpdateMenuItemAndFilter(uri, id, title, query, DefaultFiltersRunner.FILTER_TYPE_TASK,
- DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE, allowedNets, icon, roles, bannedRoles, defaultHeaders)
- }
-
- @Deprecated
- Case createOrUpdateMenuItem(String id, String uri, String type, String query, String icon, String title, List allowedNets,
- Map roles = [:], Map bannedRoles = [:], Case group = null,
- List defaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(uri, id, title, icon)
- body.setAllowedRoles(collectRolesForPreferenceItem(roles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseTabbedView(true)
-
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle(new I18nString(title as String))
- filterBody.setQuery(query)
- filterBody.setType(type)
- filterBody.setAllowedNets(allowedNets)
- filterBody.setIcon(icon)
- filterBody.setVisibility(DefaultFiltersRunner.FILTER_VISIBILITY_PRIVATE)
-
- body.setView(createLegacyMenuItemViews(filterBody, defaultHeaders))
- return menuItemService.createOrUpdateMenuItem(body)
- }
-
- /**
- * Creates or updates menu item with given identifier.
- *
- * @param uri resource where the item is located in
- * @param identifier unique identifier of item
- * @param name displayed label in menu and tab
- * @param icon displayed icon in menu and tab
- * @param filter Case instance of filter.xml
- * @param allowedRoles Map of roles, which have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param bannedRoles Map of roles, which don't have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param caseDefaultHeaders List of headers displayed in case view
- * @param taskDefaultHeaders List of headers displayed in task view
- *
- * @return created or updated menu item instance
- * */
- @Deprecated(since = "6.5.0")
- Case createOrUpdateMenuItem(String uri, String identifier, def name, String icon = "filter_none", Case filter = null,
- Map allowedRoles = [:], Map bannedRoles = [:],
- List caseDefaultHeaders = [], List taskDefaultHeaders = []) {
- MenuItemBody body = new MenuItemBody(uri, identifier, name, icon)
- body.setAllowedRoles(collectRolesForPreferenceItem(allowedRoles))
- body.setBannedRoles(collectRolesForPreferenceItem(bannedRoles))
- body.setUseTabbedView(true)
- if (filter == null) {
- body.setView(createLegacyMenuItemViews(new FilterBody(null), caseDefaultHeaders, taskDefaultHeaders))
- } else {
- body.setView(createLegacyMenuItemViews(filter, caseDefaultHeaders, taskDefaultHeaders))
- }
-
- return createOrUpdateMenuItem(body)
- }
-
- /**
- * Creates or updates menu item with given identifier along with the filter instance. It's safe to use on existing
- * menu item instance, that doesn't contain filter. In such case, missing filter will be created with provided
- * parameters.
- *
- * @param uri resource where the item is located in
- * @param itemIdentifier unique identifier of item
- * @param itemAndFilterName displayed label in menu and tab
- * @param filterQuery elastic query for filter
- * @param filterType type of filter. Possible values: {@value DefaultFiltersRunner#FILTER_TYPE_CASE} or
- * {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- * @param filterVisibility possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or
- * {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterAllowedNets List of allowed nets. Element of list is process identifier
- * @param itemAndFilterIcon displayed icon in menu and tab
- * @param itemAllowedRoles Map of roles, which have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param itemBannedRoles Map of roles, which don't have access to the item. Key is role_id in XML and value is process
- * identifier where the role exists
- * @param itemCaseDefaultHeaders List of headers displayed in case view
- * @param itemTaskDefaultHeaders List of headers displayed in task view
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created or updated menu item instance along with the actual filter
- * */
- @Deprecated(since = "6.5.0")
- Case createOrUpdateMenuItemAndFilter(String uri, String itemIdentifier, def itemAndFilterName, String filterQuery,
- String filterType, String filterVisibility, List filterAllowedNets = [],
- String itemAndFilterIcon = "filter_none", Map itemAllowedRoles = [:],
- Map itemBannedRoles = [:], List itemCaseDefaultHeaders = [],
- List itemTaskDefaultHeaders = [], def filterMetadata = null) {
- MenuItemBody body = new MenuItemBody(uri, itemIdentifier, itemAndFilterName, itemAndFilterIcon)
- body.allowedRoles = collectRolesForPreferenceItem(itemAllowedRoles)
- body.bannedRoles = collectRolesForPreferenceItem(itemBannedRoles)
- body.setUseTabbedView(true)
-
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle((itemAndFilterName instanceof I18nString) ? itemAndFilterName : new I18nString(itemAndFilterName as String))
- filterBody.setQuery(filterQuery)
- filterBody.setType(filterType)
- filterBody.setAllowedNets(filterAllowedNets)
- filterBody.setIcon(itemAndFilterIcon)
- filterBody.setVisibility(filterVisibility)
- filterBody.setMetadata(filterMetadata as Map)
- body.setView(createLegacyMenuItemViews(filterBody, itemCaseDefaultHeaders, itemTaskDefaultHeaders))
-
- return menuItemService.createOrUpdateMenuItem(body)
- }
-
/**
* Creates or updates menu item with given identifier.
*
@@ -2509,40 +1855,6 @@ class ActionDelegate {
return menuItemService.createOrUpdateMenuItem(body)
}
- /**
- * Creates or updates menu item with given identifier along with the filter instance. It's safe to use on existing
- * menu item instance, that doesn't contain filter. In such case, missing filter will be created with provided
- * parameters.
- *
- * @param body data for menu item
- * @param filterQuery elastic query for filter
- * @param filterType type of filter. Possible values: {@value DefaultFiltersRunner#FILTER_TYPE_CASE} or
- * {@value DefaultFiltersRunner#FILTER_TYPE_TASK}
- * @param filterVisibility possible values: {@value DefaultFiltersRunner#FILTER_VISIBILITY_PRIVATE} or
- * {@value DefaultFiltersRunner#FILTER_VISIBILITY_PUBLIC}
- * @param filterAllowedNets List of allowed nets. Element of list is process identifier
- * @param filterMetadata metadata for filter. If no value is provided, then default value is used: {@link #defaultFilterMetadata(String)}
- *
- * @return created or updated menu item instance along with the actual filter
- * */
- @Deprecated(since = "6.5.0")
- Case createOrUpdateMenuItemAndFilter(MenuItemBody body, String filterQuery, String filterType, String filterVisibility,
- List filterAllowedNets = [], def filterMetadata = null) {
- body.setUseTabbedView(true)
-
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle(body.getMenuName())
- filterBody.setQuery(filterQuery)
- filterBody.setType(filterType)
- filterBody.setAllowedNets(filterAllowedNets)
- filterBody.setIcon(body.getMenuIcon())
- filterBody.setVisibility(filterVisibility)
- filterBody.setMetadata(filterMetadata as Map)
- body.setView(createLegacyMenuItemViews(filterBody))
-
- return menuItemService.createOrUpdateMenuItem(body)
- }
-
/**
* Creates menu item or ignores it if already exists
*
@@ -2554,33 +1866,6 @@ class ActionDelegate {
return menuItemService.createOrIgnoreMenuItem(body)
}
- /**
- * Creates menu item or ignores it if already exists. If existing item does not contain filter, the filter instance
- * is created by provided parameters.
- *
- * @param body configuration class for menu item
- *
- * @return created or existing menu item instance
- * */
- @Deprecated(since = "6.5.0")
- Case createOrIgnoreMenuItemAndFilter(MenuItemBody body, String filterQuery, String filterType, String filterVisibility,
- List filterAllowedNets = [], def filterMetadata = null) {
- body.setUseTabbedView(true)
-
- FilterBody filterBody = new FilterBody()
- filterBody.setTitle(body.getMenuName())
- filterBody.setQuery(filterQuery)
- filterBody.setType(filterType)
- filterBody.setAllowedNets(filterAllowedNets)
- filterBody.setIcon(body.getMenuIcon())
- filterBody.setVisibility(filterVisibility)
- filterBody.setMetadata(filterMetadata as Map)
-
- body.setView(createLegacyMenuItemViews(filterBody))
-
- return menuItemService.createOrIgnoreMenuItem(body)
- }
-
/**
* Updates existing menu item with provided values.
*
@@ -2593,10 +1878,6 @@ class ActionDelegate {
return menuItemService.updateMenuItem(item, body)
}
- static Map defaultFilterMetadata(String type) {
- return FilterBody.getDefaultMetadata(type)
- }
-
void removeChildItemFromParent(String folderId, Case childItem) {
menuItemService.removeChildItemFromParent(folderId, childItem)
}
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
index 7e5475ef098..1e580755668 100644
--- a/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
+++ b/src/main/groovy/com/netgrif/application/engine/startup/DefaultDashboardRunner.groovy
@@ -2,7 +2,7 @@ package com.netgrif.application.engine.startup
import com.netgrif.application.engine.menu.domain.dashboard.DashboardManagementBody
-import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService
+import com.netgrif.application.engine.menu.service.interfaces.DashboardManagementService
import com.netgrif.application.engine.petrinet.domain.I18nString
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy
deleted file mode 100644
index 3f2f1e2b371..00000000000
--- a/src/main/groovy/com/netgrif/application/engine/startup/DefaultFiltersRunner.groovy
+++ /dev/null
@@ -1,314 +0,0 @@
-package com.netgrif.application.engine.startup
-
-import com.netgrif.application.engine.auth.service.interfaces.IUserService
-import com.netgrif.application.engine.petrinet.domain.I18nString
-import com.netgrif.application.engine.petrinet.domain.PetriNet
-import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService
-import com.netgrif.application.engine.workflow.domain.Case
-import com.netgrif.application.engine.workflow.domain.QCase
-import com.netgrif.application.engine.workflow.domain.QTask
-import com.netgrif.application.engine.workflow.domain.Task
-import com.netgrif.application.engine.workflow.service.interfaces.IDataService
-import com.netgrif.application.engine.workflow.service.interfaces.ITaskService
-import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService
-import lombok.extern.slf4j.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import org.springframework.beans.factory.annotation.Value
-
-@Slf4j
-@Component
-class DefaultFiltersRunner extends AbstractOrderedCommandLineRunner {
-
- public static final String AUTO_CREATE_TRANSITION = "auto_create"
- public static final String DETAILS_TRANSITION = "t2"
-
- public static final String FILTER_TYPE_FIELD_ID = "filter_type"
- public static final String FILTER_ORIGIN_VIEW_ID_FIELD_ID = "origin_view_id"
- public static final String FILTER_PARENT_CASE_ID_FIELD_ID = "parent_filter_id"
- public static final String FILTER_VISIBILITY_FIELD_ID = "visibility"
- public static final String FILTER_FIELD_ID = "filter"
- public static final String FILTER_I18N_TITLE_FIELD_ID = "i18n_filter_name"
- public static final String GERMAN_ISO_3166_CODE = "de"
- public static final String SLOVAK_ISO_3166_CODE = "sk"
- public static final String IS_IMPORTED = "is_imported"
-
- public static final String FILTER_TYPE_CASE = "Case"
- public static final String FILTER_TYPE_TASK = "Task"
-
- public static final String FILTER_VISIBILITY_PRIVATE = "private"
- public static final String FILTER_VISIBILITY_PUBLIC = "public"
-
- @Value('${nae.create.default.filters:false}')
- private Boolean createDefaultFilters
-
- @Autowired
- private IPetriNetService petriNetService
-
- @Autowired
- private IWorkflowService workflowService
-
- @Autowired
- private IUserService userService
-
- @Autowired
- private ITaskService taskService
-
- @Autowired
- private IDataService dataService
-
- @Override
- void run(String... args) throws Exception {
- if (createDefaultFilters) {
- createCaseFilter("All cases", "assignment", FILTER_VISIBILITY_PUBLIC, "", [], [
- "predicateMetadata": [],
- "searchCategories" : []
- ], [
- (GERMAN_ISO_3166_CODE): "Alle Fälle",
- (SLOVAK_ISO_3166_CODE): "Všetky prípady"
- ])
- createCaseFilter("My cases", "assignment_ind", FILTER_VISIBILITY_PUBLIC, "(author:<>)", [], [
- "predicateMetadata": [[["category": "case_author", "configuration": ["operator": "equals"], "values": [["text": "search.category.userMe", value: ["<>"]]]]]],
- "searchCategories" : ["case_author"]
- ], [
- (GERMAN_ISO_3166_CODE): "Meine Fälle",
- (SLOVAK_ISO_3166_CODE): "Moje prípady"
- ])
-
- createTaskFilter("All tasks", "library_add_check", FILTER_VISIBILITY_PUBLIC, "", [], [
- "predicateMetadata": [],
- "searchCategories" : []
- ], [
- (GERMAN_ISO_3166_CODE): "Alle Aufgaben",
- (SLOVAK_ISO_3166_CODE): "Všetky úlohy"
- ])
- createTaskFilter("My tasks", "account_box", FILTER_VISIBILITY_PUBLIC, "(userId:<>)", [], [
- "predicateMetadata": [[["category": "task_assignee", "configuration": ["operator": "equals"], "values": [["text": "search.category.userMe", value: ["<>"]]]]]],
- "searchCategories" : ["task_assignee"]
- ], [
- (GERMAN_ISO_3166_CODE): "Meine Aufgaben",
- (SLOVAK_ISO_3166_CODE): "Moje úlohy"
- ])
- }
- }
-
- /**
- * Creates a new case filter filter process instance
- * @param title unique title of the default filter
- * @param icon material icon identifier of the default filter
- * @param filterVisibility filter visibility
- * @param filterQuery the elastic query string query used by the filter
- * @param allowedNets list of process identifiers allowed for search categories metadata generation
- * @param filterMetadata metadata of the serialised filter as generated by the frontend
- * @param titleTranslations a map of locale codes to translated strings for the filter title
- * @param withDefaultCategories whether the default search categories should be merged with the search categories specified in the metadata
- * @param inheritBaseAllowedNets whether the base allowed nets should be merged with the allowed nets specified in the filter field
- * @param originId the ID of the parent if any
- * @param viewOrigin true if the parent was a view. false if the parent was another filter
- * @param isImported whether the filter is being created by importing it from na XML file
- * @return an empty Optional if the filter process does not exist. An existing filter process instance if a filter process instance with the same name already exists. A new filter process instance if not.
- */
- Optional createCaseFilter(
- String title,
- String icon,
- String filterVisibility,
- String filterQuery,
- List allowedNets,
- Map filterMetadata,
- Map titleTranslations,
- boolean withDefaultCategories = true,
- boolean inheritBaseAllowedNets = true,
- String originId = null,
- boolean viewOrigin = false,
- boolean isImported = false
- ) {
- return createFilter(
- title,
- icon,
- FILTER_TYPE_CASE,
- filterVisibility,
- filterQuery,
- allowedNets,
- filterMetadata,
- titleTranslations,
- withDefaultCategories,
- inheritBaseAllowedNets,
- originId,
- viewOrigin,
- isImported
- )
- }
-
- /**
- * Creates a new task filter filter process instance
- * @param title unique title of the default filter
- * @param icon material icon identifier of the default filter
- * @param filterVisibility filter visibility
- * @param filterQuery the elastic query string query used by the filter
- * @param allowedNets list of process identifiers allowed for search categories metadata generation
- * @param filterMetadata metadata of the serialised filter as generated by the frontend
- * @param titleTranslations a map of locale codes to translated strings for the filter title
- * @param withDefaultCategories whether the default search categories should be merged with the search categories specified in the metadata
- * @param inheritBaseAllowedNets whether the base allowed nets should be merged with the allowed nets specified in the filter field
- * @param originId the ID of the parent if any
- * @param viewOrigin true if the parent was a view. false if the parent was another filter
- * @param isImported whether the filter is being created by importing it from na XML file
- * @return an empty Optional if the filter process does not exist. An existing filter process instance if a filter process instance with the same name already exists. A new filter process instance if not.
- */
- Optional createTaskFilter(
- String title,
- String icon,
- String filterVisibility,
- String filterQuery,
- List allowedNets,
- Map filterMetadata,
- Map titleTranslations,
- boolean withDefaultCategories = true,
- boolean inheritBaseAllowedNets = true,
- String originId = null,
- boolean viewOrigin = false,
- boolean isImported = false
- ) {
- return createFilter(
- title,
- icon,
- FILTER_TYPE_TASK,
- filterVisibility,
- filterQuery,
- allowedNets,
- filterMetadata,
- titleTranslations,
- withDefaultCategories,
- inheritBaseAllowedNets,
- originId,
- viewOrigin,
- isImported
- )
- }
-
- /**
- * Creates a new filter process instance of the provided type
- * @param title unique title of the default filter
- * @param icon material icon identifier of the default filter
- * @param filterType the type of the filter
- * @param filterVisibility filter visibility
- * @param filterQuery the elastic query string query used by the filter
- * @param allowedNets list of process identifiers allowed for search categories metadata generation
- * @param filterMetadata metadata of the serialised filter as generated by the frontend
- * @param titleTranslations a map of locale codes to translated strings for the filter title
- * @param withDefaultCategories whether the default search categories should be merged with the search categories specified in the metadata
- * @param inheritBaseAllowedNets whether the base allowed nets should be merged with the allowed nets specified in the filter field
- * @param originId the ID of the parent if any
- * @param viewOrigin true if the parent was a view. false if the parent was another filter
- * @param isImported whether the filter is being created by importing it from na XML file
- * @return an empty Optional if the filter process does not exist. An existing filter process instance if a filter process instance with the same name already exists. A new filter process instance if not.
- */
- Optional createFilter(
- String title,
- String icon,
- String filterType,
- String filterVisibility,
- String filterQuery,
- List allowedNets,
- Map filterMetadata,
- Map titleTranslations,
- boolean withDefaultCategories,
- boolean inheritBaseAllowedNets,
- String originId = null,
- boolean viewOrigin = false,
- boolean isImported = false
- ) {
- return createFilterCase(
- title,
- icon,
- filterType,
- filterVisibility,
- filterQuery,
- allowedNets,
- filterMetadata << ["filterType": filterType, "defaultSearchCategories": withDefaultCategories, "inheritAllowedNets": inheritBaseAllowedNets],
- titleTranslations,
- originId,
- viewOrigin,
- isImported
- )
- }
-
- private Optional createFilterCase(
- String title,
- String icon,
- String filterType,
- String filterVisibility,
- String filterQuery,
- List allowedNets,
- Map filterMetadata,
- Map titleTranslations,
- String originId,
- boolean viewOrigin,
- boolean isImported
- ) {
- PetriNet filterNet = this.petriNetService.getNewestVersionByIdentifier('filter')
- if (filterNet == null) {
- return Optional.empty()
- }
-
- def loggedUser = this.userService.getLoggedOrSystem()
-
- if (loggedUser.getStringId() == this.userService.getSystem().getStringId()) {
- Case filterCase = this.workflowService.searchOne(QCase.case$.processIdentifier.eq("filter").and(QCase.case$.title.eq(title)).and(QCase.case$.author.id.eq(userService.getSystem().getStringId())))
- if (filterCase != null) {
- return Optional.of(filterCase)
- }
- }
-
- Case filterCase = this.workflowService.createCase(filterNet.getStringId(), title, null, loggedUser.transformToLoggedUser()).getCase()
- filterCase.setIcon(icon)
- filterCase = this.workflowService.save(filterCase)
- Task newFilterTask = this.taskService.searchOne(QTask.task.transitionId.eq(AUTO_CREATE_TRANSITION).and(QTask.task.caseId.eq(filterCase.getStringId())))
- this.taskService.assignTask(newFilterTask, this.userService.getLoggedOrSystem())
-
- def setDataMap = [
- (FILTER_TYPE_FIELD_ID): [
- "type": "enumeration_map",
- "value": filterType
- ],
- (FILTER_VISIBILITY_FIELD_ID): [
- "type": "enumeration_map",
- "value": filterVisibility
- ],
- (FILTER_FIELD_ID): [
- "type": "filter",
- "value": filterQuery,
- "allowedNets": allowedNets,
- "filterMetadata": filterMetadata
- ]
- ]
-
- if (originId != null) {
- setDataMap.put(viewOrigin ? FILTER_ORIGIN_VIEW_ID_FIELD_ID : FILTER_PARENT_CASE_ID_FIELD_ID, [
- "type": "text",
- "value": originId
- ])
- }
-
-
- this.dataService.setData(newFilterTask, ImportHelper.populateDataset(setDataMap))
- if (isImported) {
- this.dataService.setData(newFilterTask, ImportHelper.populateDataset([
- (IS_IMPORTED): [
- "type": "number",
- "value": 1
- ]
- ]))
- }
-
- I18nString translatedTitle = new I18nString(title)
- titleTranslations.forEach({locale, translation -> translatedTitle.addTranslation(locale, translation)})
-
- filterCase = this.workflowService.findOne(filterCase.getStringId())
- filterCase.dataSet[FILTER_I18N_TITLE_FIELD_ID].value = translatedTitle
- workflowService.save(filterCase)
-
- this.taskService.finishTask(newFilterTask, this.userService.getLoggedOrSystem())
- return Optional.of(this.workflowService.findOne(filterCase.getStringId()))
- }
-}
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy
deleted file mode 100644
index fe45689889b..00000000000
--- a/src/main/groovy/com/netgrif/application/engine/startup/FilterRunner.groovy
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.netgrif.application.engine.startup
-
-import com.netgrif.application.engine.menu.domain.MenuItemView
-import com.netgrif.application.engine.petrinet.domain.PetriNet
-import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-
-@Slf4j
-@Component
-class FilterRunner extends AbstractOrderedCommandLineRunner {
-
- @Autowired
- private ImportHelper helper
-
- @Autowired
- private IPetriNetService petriNetService
-
- @Autowired
- private SystemUserRunner systemCreator
-
- private static final String FILTER_FILE_NAME = "engine-processes/filter.xml"
- public static final String FILTER_PETRI_NET_IDENTIFIER = "filter"
-
- private static final String MENU_ITEM_FILE_NAME = "engine-processes/menu/menu_item.xml"
- public static final String MENU_NET_IDENTIFIER = "menu_item"
-
- private static final String EXPORT_FILTER_FILE_NAME = "engine-processes/export_filters.xml"
- private static final String EXPORT_NET_IDENTIFIER = "export_filters"
-
- private static final String IMPORT_FILTER_FILE_NAME = "engine-processes/import_filters.xml"
- private static final String IMPORT_NET_IDENTIFIER = "import_filters"
-
- @Override
- void run(String... args) throws Exception {
- helper.importProcess("Petri net for filters", FILTER_PETRI_NET_IDENTIFIER, FILTER_FILE_NAME)
- createConfigurationNets()
- helper.importProcess("Petri net for filter preferences", MENU_NET_IDENTIFIER, MENU_ITEM_FILE_NAME)
- createImportFiltersNet()
- createExportFiltersNet()
- }
-
- Optional createImportFiltersNet() {
- helper.importProcess("Petri net for importing filters", IMPORT_NET_IDENTIFIER, IMPORT_FILTER_FILE_NAME)
- }
-
- Optional createExportFiltersNet() {
- helper.importProcess("Petri net for exporting filters", EXPORT_NET_IDENTIFIER, EXPORT_FILTER_FILE_NAME)
- }
-
- private List createConfigurationNets() {
- return MenuItemView.values().each { view ->
- String processIdentifier = view.getIdentifier() + "_configuration"
- String filePath = String.format("engine-processes/menu/%s.xml", processIdentifier)
- helper.importProcess(String.format("Petri net for %s", processIdentifier), processIdentifier, filePath)
- }.collect()
- }
-}
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/MenuRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/MenuRunner.groovy
new file mode 100644
index 00000000000..472d9bb5a79
--- /dev/null
+++ b/src/main/groovy/com/netgrif/application/engine/startup/MenuRunner.groovy
@@ -0,0 +1,39 @@
+package com.netgrif.application.engine.startup
+
+import com.netgrif.application.engine.menu.domain.MenuItemConstants
+import com.netgrif.application.engine.menu.domain.MenuItemViewType
+import com.netgrif.application.engine.petrinet.domain.PetriNet
+import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService
+import groovy.util.logging.Slf4j
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+
+@Slf4j
+@Component
+class MenuRunner extends AbstractOrderedCommandLineRunner {
+
+ private static final String MENU_ITEM_FILE_NAME = "engine-processes/menu/menu_item.xml"
+
+ @Autowired
+ private ImportHelper helper
+
+ @Autowired
+ private IPetriNetService petriNetService
+
+ @Autowired
+ private SystemUserRunner systemCreator
+
+ @Override
+ void run(String... args) throws Exception {
+ createConfigurationNets()
+ helper.importProcess("Petri net for menu item", MenuItemConstants.PROCESS_IDENTIFIER, MENU_ITEM_FILE_NAME)
+ }
+
+ private void createConfigurationNets() {
+ MenuItemViewType.values().each { view ->
+ String processIdentifier = view.getIdentifier() + "_configuration"
+ String filePath = String.format("engine-processes/menu/%s.xml", processIdentifier)
+ helper.importProcess(String.format("Petri net for %s", processIdentifier), processIdentifier, filePath)
+ }.collect()
+ }
+}
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy
index 4fac0dc985e..670b97b214a 100644
--- a/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy
+++ b/src/main/groovy/com/netgrif/application/engine/startup/MongoDbRunner.groovy
@@ -1,10 +1,11 @@
package com.netgrif.application.engine.startup
+
+import com.netgrif.application.engine.menu.service.interfaces.IMenuItemService
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
-import org.springframework.context.annotation.Profile
import org.springframework.data.mapping.context.MappingContext
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.index.IndexOperations
@@ -16,7 +17,6 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty
import org.springframework.stereotype.Component
@Component
-@Profile("!test")
class MongoDbRunner extends AbstractOrderedCommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(MongoDbRunner)
@@ -24,6 +24,9 @@ class MongoDbRunner extends AbstractOrderedCommandLineRunner {
@Autowired
private MongoTemplate mongoTemplate
+ @Autowired
+ private IMenuItemService menuItemService
+
@Value('${spring.data.mongodb.database}')
private String name
@@ -48,23 +51,25 @@ class MongoDbRunner extends AbstractOrderedCommandLineRunner {
if (host != null && port != null)
log.info("Dropping Mongo database ${host}:${port}/${name}")
else if (uri != null)
- log.info("Droppiung Mongo database ${uri}")
+ log.info("Dropping Mongo database ${uri}")
mongoTemplate.getDb().drop()
}
if (resolveIndexesOnStartup) {
+ log.info("Ensuring Mongo indexes")
resolveIndexes()
}
}
- void resolveIndexes() {
+ private void resolveIndexes() {
MappingContext extends MongoPersistentEntity>, MongoPersistentProperty> mappingContext = mongoTemplate.getConverter().getMappingContext()
IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext)
mappingContext.getPersistentEntities()
.stream()
.filter(it -> it.isAnnotationPresent(Document.class))
.forEach(it -> {
- IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
- resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
+ IndexOperations indexOps = mongoTemplate.indexOps(it.getType())
+ resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex)
})
+ menuItemService.ensureDatabaseIndexes()
}
}
\ No newline at end of file
diff --git a/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy b/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy
index 14c9c83b234..fd7444cc20b 100644
--- a/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy
+++ b/src/main/groovy/com/netgrif/application/engine/startup/RunnerController.groovy
@@ -16,9 +16,8 @@ class RunnerController {
SystemUserRunner,
UriRunner,
FunctionsCacheRunner,
- FilterRunner,
+ MenuRunner,
GroupRunner,
- DefaultFiltersRunner,
ImpersonationRunner,
DashboardRunner,
DashboardManagementRunner,
diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java
index b31836c11b9..cf74d3c5d43 100755
--- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java
+++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java
@@ -10,7 +10,6 @@
import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService;
import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService;
import com.netgrif.application.engine.startup.SystemUserRunner;
-import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
@@ -50,9 +49,6 @@ public class UserService extends AbstractUserService {
@Autowired
private GroupConfigurationProperties groupProperties;
- @Autowired
- private IFilterImportExportService filterImportExportService;
-
@Override
public IUser saveNewAndAuthenticate(IUser user) {
return saveNew(user, true);
@@ -70,8 +66,6 @@ private IUser saveNew(IUser user, boolean login) {
addDefaultAuthorities(user);
User savedUser = userRepository.save((User) user);
- filterImportExportService.createFilterImport(user);
- filterImportExportService.createFilterExport(user);
if (groupProperties.isDefaultEnabled())
groupService.createGroup(user);
diff --git a/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java b/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java
index 4ac4a03c32c..850e4dbe0be 100644
--- a/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java
+++ b/src/main/java/com/netgrif/application/engine/importer/service/FieldFactory.java
@@ -197,8 +197,8 @@ public static String parseEnumerationMapValue(Case useCase, String fieldId) {
}
// TODO: refactor this shit
- Field getField(Data data, Importer importer) throws IllegalArgumentException, MissingIconKeyException {
- Field field;
+ Field> getField(Data data, Importer importer) throws IllegalArgumentException, MissingIconKeyException {
+ Field> field;
switch (data.getType()) {
case TEXT:
field = buildTextField(data);
@@ -248,8 +248,15 @@ Field getField(Data data, Importer importer) throws IllegalArgumentException, Mi
case MULTICHOICE_MAP:
field = buildMultichoiceMapField(data, importer);
break;
- case FILTER:
- field = buildFilterField(data);
+ case FILTER: // "FILTER" is deprecated
+ case CASE_FILTER:
+ field = buildCaseFilterField(data);
+ break;
+ case TASK_FILTER:
+ field = buildTaskFilterField(data);
+ break;
+ case PROCESS_FILTER:
+ field = buildProcessFilterField(data);
break;
case I_18_N:
field = buildI18nField(data, importer);
@@ -549,13 +556,22 @@ private FileListField buildFileListField(Data data) {
return fileListField;
}
- private FilterField buildFilterField(Data data) {
- AllowedNets nets = data.getAllowedNets();
- if (nets == null) {
- return new FilterField();
- } else {
- return new FilterField(new ArrayList<>(nets.getAllowedNet()));
- }
+ private CaseFilterField buildCaseFilterField(Data data) {
+ CaseFilterField field = new CaseFilterField();
+ setDefaultValue(field, data, field::setDefaultValue);
+ return field;
+ }
+
+ private TaskFilterField buildTaskFilterField(Data data) {
+ TaskFilterField field = new TaskFilterField();
+ setDefaultValue(field, data, field::setDefaultValue);
+ return field;
+ }
+
+ private ProcessFilterField buildProcessFilterField(Data data) {
+ ProcessFilterField field = new ProcessFilterField();
+ setDefaultValue(field, data, field::setDefaultValue);
+ return field;
}
private I18nField buildI18nField(Data data, Importer importer) {
@@ -611,8 +627,6 @@ private Field buildField(Case useCase, String fieldId, boolean withValidation, S
resolveMapOptions((MapOptionsField) field, useCase);
if (field instanceof FieldWithAllowedNets)
resolveAllowedNets((FieldWithAllowedNets) field, useCase);
- if (field instanceof FilterField)
- resolveFilterMetadata((FilterField) field, useCase);
if (withValidation)
resolveValidations(field, useCase);
return field;
@@ -661,13 +675,6 @@ private void resolveAllowedNets(FieldWithAllowedNets field, Case useCase) {
field.setAllowedNets(allowedNets);
}
- private void resolveFilterMetadata(FilterField field, Case useCase) {
- Map metadata = useCase.getDataField(field.getImportId()).getFilterMetadata();
- if (metadata == null)
- return;
- field.setFilterMetadata(metadata);
- }
-
public Field buildImmediateField(Case useCase, String fieldId) {
Field field = useCase.getPetriNet().getDataSet().get(fieldId).clone();
resolveDataValues(field, useCase, fieldId);
@@ -788,14 +795,10 @@ private void parseFileListValue(FileListField field, Case useCase, String fieldI
private void resolveAttributeValues(Field field, Case useCase, String fieldId) {
DataField dataField = useCase.getDataSet().get(fieldId);
- if (field.getType().equals(FieldType.CASE_REF) || field.getType().equals(FieldType.FILTER)) {
+ if (field.getType().equals(FieldType.CASE_REF)) {
List allowedNets = new ArrayList<>(dataField.getAllowedNets());
((FieldWithAllowedNets) field).setAllowedNets(allowedNets);
}
- if (field.getType().equals(FieldType.FILTER)) {
- Map filterMetadata = new HashMap<>(dataField.getFilterMetadata());
- ((FilterField) field).setFilterMetadata(filterMetadata);
- }
}
private void setDefaultValue(Field field, Data data, Consumer setDefault) {
diff --git a/src/main/java/com/netgrif/application/engine/importer/service/Importer.java b/src/main/java/com/netgrif/application/engine/importer/service/Importer.java
index 596db2e301f..c333a31bf9c 100644
--- a/src/main/java/com/netgrif/application/engine/importer/service/Importer.java
+++ b/src/main/java/com/netgrif/application/engine/importer/service/Importer.java
@@ -39,7 +39,6 @@
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -123,7 +122,6 @@ public class Importer {
@Autowired
private ILogicValidator logicValidator;
- @Transactional
public Optional importPetriNet(InputStream xml) throws MissingPetriNetMetaDataException, MissingIconKeyException {
try {
initialize();
@@ -135,7 +133,6 @@ public Optional importPetriNet(InputStream xml) throws MissingPetriNet
return Optional.empty();
}
- @Transactional
public Optional importPetriNet(File xml) throws MissingPetriNetMetaDataException, MissingIconKeyException {
try {
return importPetriNet(new FileInputStream(xml));
@@ -159,7 +156,6 @@ protected void initialize() {
this.functions = new LinkedList<>();
}
- @Transactional
protected void unmarshallXml(InputStream xml) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
@@ -167,7 +163,6 @@ protected void unmarshallXml(InputStream xml) throws JAXBException {
document = (Document) jaxbUnmarshaller.unmarshal(xml);
}
- @Transactional
public Path saveNetFile(PetriNet net, InputStream xmlFile) throws IOException {
File savedFile = new File(fileStorageConfiguration.getStorageArchived() + net.getStringId() + "-" + net.getTitle() + FILE_EXTENSION);
savedFile.getParentFile().mkdirs();
@@ -176,7 +171,6 @@ public Path saveNetFile(PetriNet net, InputStream xmlFile) throws IOException {
return savedFile.toPath();
}
- @Transactional
protected Optional createPetriNet() throws MissingPetriNetMetaDataException, MissingIconKeyException {
net = new PetriNet();
@@ -225,7 +219,6 @@ protected Optional createPetriNet() throws MissingPetriNetMetaDataExce
return Optional.of(net);
}
- @Transactional
protected void resolveRoleRef(CaseRoleRef roleRef) {
CaseLogic logic = roleRef.getCaseLogic();
String roleId = getRole(roleRef.getId()).getStringId();
@@ -240,7 +233,6 @@ protected void resolveRoleRef(CaseRoleRef roleRef) {
net.addPermission(roleId, roleFactory.getProcessPermissions(logic));
}
- @Transactional
protected void createFunction(com.netgrif.application.engine.importer.model.Function function) {
com.netgrif.application.engine.petrinet.domain.Function fun = functionFactory.getFunction(function);
@@ -248,8 +240,7 @@ protected void createFunction(com.netgrif.application.engine.importer.model.Func
functions.add(fun);
}
- @Transactional
- protected void resolveUserRef(CaseUserRef userRef) {
+ protected void resolveUserRef(CaseActorRef userRef) {
CaseLogic logic = userRef.getCaseLogic();
String usersId = userRef.getId();
@@ -260,21 +251,18 @@ protected void resolveUserRef(CaseUserRef userRef) {
net.addUserPermission(usersId, roleFactory.getProcessPermissions(logic));
}
- @Transactional
protected void resolveProcessEvents(ProcessEvents processEvents) {
if (processEvents != null && processEvents.getEvent() != null) {
net.setProcessEvents(createProcessEventsMap(processEvents.getEvent()));
}
}
- @Transactional
protected void resolveCaseEvents(CaseEvents caseEvents) {
if (caseEvents != null && caseEvents.getEvent() != null) {
net.setCaseEvents(createCaseEventsMap(caseEvents.getEvent()));
}
}
- @Transactional
protected void evaluateFunctions() {
try {
actionsCacheService.evaluateFunctions(functions);
@@ -283,7 +271,6 @@ protected void evaluateFunctions() {
}
}
- @Transactional
protected void evaluateActions(String s, Action action) {
try {
actionsRunner.getActionCode(action, functions, true);
@@ -292,7 +279,6 @@ protected void evaluateActions(String s, Action action) {
}
}
- @Transactional
protected void resolveActionRefs(String actionId, Action action) {
Action referenced = actions.get(actionId);
if (referenced == null) {
@@ -302,13 +288,11 @@ protected void resolveActionRefs(String actionId, Action action) {
action.setTrigger(referenced.getTrigger());
}
- @Transactional
protected void addI18N(I18N importI18N) {
String locale = importI18N.getLocale();
importI18N.getI18NString().forEach(translation -> addTranslation(translation, locale));
}
- @Transactional
protected void addTranslation(I18NStringType i18NStringType, String locale) {
String name = i18NStringType.getName();
I18nString translation = getI18n(name);
@@ -319,7 +303,6 @@ protected void addTranslation(I18NStringType i18NStringType, String locale) {
translation.addTranslation(locale, i18NStringType.getValue());
}
- @Transactional
protected void applyMapping(Mapping mapping) throws MissingIconKeyException {
Transition transition = getTransition(mapping.getTransitionRef());
mapping.getRoleRef().forEach(roleRef -> addRoleLogic(transition, roleRef));
@@ -330,7 +313,6 @@ protected void applyMapping(Mapping mapping) throws MissingIconKeyException {
mapping.getTrigger().forEach(trigger -> addTrigger(transition, trigger));
}
- @Transactional
protected void resolveDataActions(Data data) {
String fieldId = data.getId();
if (data.getEvent() != null && !data.getEvent().isEmpty()) {
@@ -368,7 +350,6 @@ private void addActionsToEvent(List actions, DataEventType type, Map actions = buildActionRefs(data.getActionRef());
@@ -388,7 +369,6 @@ protected Action fromActionRef(ActionRef actionRef) {
return placeholder;
}
- @Transactional
protected void resolveTransitionActions(com.netgrif.application.engine.importer.model.Transition trans) {
if (trans.getDataRef() != null) {
resolveDataRefActions(trans.getDataRef(), trans);
@@ -402,7 +382,6 @@ protected void resolveTransitionActions(com.netgrif.application.engine.importer.
}
}
- @Transactional
protected void resolveDataRefActions(List dataRef, com.netgrif.application.engine.importer.model.Transition trans) {
dataRef.forEach(ref -> {
String fieldId = getField(ref.getId()).getStringId();
@@ -449,7 +428,6 @@ protected DataEvent createDefaultEvent(List actions, DataEventType type)
return event;
}
- @Transactional
protected void createArc(com.netgrif.application.engine.importer.model.Arc importArc) {
Arc arc = arcFactory.getArc(importArc);
arc.setImportId(importArc.getId());
@@ -477,15 +455,13 @@ protected void createArc(com.netgrif.application.engine.importer.model.Arc impor
net.addArc(arc);
}
- @Transactional
protected void createDataSet(Data importData) throws MissingIconKeyException {
- Field field = fieldFactory.getField(importData, this);
+ Field> field = fieldFactory.getField(importData, this);
net.addDataSetField(field);
fields.put(importData.getId(), field);
}
- @Transactional
protected void createTransition(com.netgrif.application.engine.importer.model.Transition importTransition) throws MissingIconKeyException {
transitionValidator.checkConflictingAttributes(importTransition, importTransition.getUsersRef(), importTransition.getUserRef(), "usersRef", "userRef");
transitionValidator.checkDeprecatedAttributes(importTransition);
@@ -558,7 +534,6 @@ protected void createTransition(com.netgrif.application.engine.importer.model.Tr
transitions.put(importTransition.getId(), transition);
}
- @Transactional
protected void addAssignedUserPolicy(com.netgrif.application.engine.importer.model.Transition importTransition, Transition transition) {
if (importTransition.getAssignedUser().isCancel() != null) {
transition.getAssignedUserPolicy().put("cancel", importTransition.getAssignedUser().isCancel());
@@ -568,7 +543,6 @@ protected void addAssignedUserPolicy(com.netgrif.application.engine.importer.mod
}
}
- @Transactional
protected com.netgrif.application.engine.petrinet.domain.events.Event addEvent(String transitionId, com.netgrif.application.engine.importer.model.Event imported) {
com.netgrif.application.engine.petrinet.domain.events.Event event = new com.netgrif.application.engine.petrinet.domain.events.Event();
event.setImportId(imported.getId());
@@ -581,7 +555,6 @@ protected com.netgrif.application.engine.petrinet.domain.events.Event addEvent(S
return event;
}
- @Transactional
protected com.netgrif.application.engine.petrinet.domain.events.ProcessEvent addProcessEvent(com.netgrif.application.engine.importer.model.ProcessEvent imported) {
com.netgrif.application.engine.petrinet.domain.events.ProcessEvent event = new com.netgrif.application.engine.petrinet.domain.events.ProcessEvent();
event.setMessage(toI18NString(imported.getMessage()));
@@ -593,7 +566,6 @@ protected com.netgrif.application.engine.petrinet.domain.events.ProcessEvent add
return event;
}
- @Transactional
protected com.netgrif.application.engine.petrinet.domain.events.CaseEvent addCaseEvent(com.netgrif.application.engine.importer.model.CaseEvent imported) {
com.netgrif.application.engine.petrinet.domain.events.CaseEvent event = new com.netgrif.application.engine.petrinet.domain.events.CaseEvent();
event.setMessage(toI18NString(imported.getMessage()));
@@ -644,7 +616,6 @@ protected List parsePhaseActions(String fieldId, EventPhaseType phase, D
return actionList;
}
- @Transactional
protected void addDefaultRole(Transition transition) {
if (!net.isDefaultRoleEnabled() || isDefaultRoleReferenced(transition)) {
return;
@@ -656,7 +627,6 @@ protected void addDefaultRole(Transition transition) {
transition.addRole(defaultRole.getStringId(), roleFactory.getPermissions(logic));
}
- @Transactional
protected void addAnonymousRole(Transition transition) {
if (!net.isAnonymousRoleEnabled() || isAnonymousRoleReferenced(transition)) {
return;
@@ -667,7 +637,6 @@ protected void addAnonymousRole(Transition transition) {
transition.addRole(anonymousRole.getStringId(), roleFactory.getPermissions(logic));
}
- @Transactional
protected void addDefaultPermissions() {
if (!net.isDefaultRoleEnabled() || isDefaultRoleReferencedOnNet()) {
return;
@@ -680,7 +649,6 @@ protected void addDefaultPermissions() {
net.addPermission(defaultRole.getStringId(), roleFactory.getProcessPermissions(logic));
}
- @Transactional
protected void addAnonymousPermissions() {
if (!net.isAnonymousRoleEnabled() || isAnonymousRoleReferencedOnNet()) {
return;
@@ -692,7 +660,6 @@ protected void addAnonymousPermissions() {
net.addPermission(anonymousRole.getStringId(), roleFactory.getProcessPermissions(logic));
}
- @Transactional
protected void addDataWithDefaultGroup(Transition transition, DataRef dataRef) throws MissingIconKeyException {
DataGroup dataGroup = new DataGroup();
dataGroup.setImportId(transition.getImportId() + "_" + dataRef.getId() + "_" + System.currentTimeMillis());
@@ -709,7 +676,6 @@ protected void addDataWithDefaultGroup(Transition transition, DataRef dataRef) t
addDataComponent(transition, dataRef);
}
- @Transactional
protected void addDataGroup(Transition transition, com.netgrif.application.engine.importer.model.DataGroup importDataGroup, int index) throws MissingIconKeyException {
String alignment = importDataGroup.getAlignment() != null ? importDataGroup.getAlignment().value() : "";
DataGroup dataGroup = new DataGroup();
@@ -738,7 +704,6 @@ protected void addDataGroup(Transition transition, com.netgrif.application.engin
}
}
- @Transactional
protected void addToTransaction(Transition transition, TransactionRef transactionRef) {
Transaction transaction = getTransaction(transactionRef.getId());
if (transaction == null) {
@@ -747,7 +712,6 @@ protected void addToTransaction(Transition transition, TransactionRef transactio
transaction.addTransition(transition);
}
- @Transactional
protected void addRoleLogic(Transition transition, RoleRef roleRef) {
Logic logic = roleRef.getLogic();
String roleId = getRole(roleRef.getId()).getStringId();
@@ -765,8 +729,7 @@ protected void addRoleLogic(Transition transition, RoleRef roleRef) {
transition.addRole(roleId, roleFactory.getPermissions(logic));
}
- @Transactional
- protected void addUserLogic(Transition transition, UserRef userRef) {
+ protected void addUserLogic(Transition transition, ActorRef userRef) {
Logic logic = userRef.getLogic();
String userRefId = userRef.getId();
@@ -780,7 +743,6 @@ protected void addUserLogic(Transition transition, UserRef userRef) {
transition.addUserRef(userRefId, roleFactory.getPermissions(logic));
}
- @Transactional
protected void addDataLogic(Transition transition, DataRef dataRef) {
Logic logic = dataRef.getLogic();
try {
@@ -800,7 +762,6 @@ protected void addDataLogic(Transition transition, DataRef dataRef) {
}
}
- @Transactional
protected void addDataLayout(Transition transition, DataRef dataRef) {
Layout layout = dataRef.getLayout();
try {
@@ -831,7 +792,6 @@ protected void addDataLayout(Transition transition, DataRef dataRef) {
}
}
- @Transactional
protected void addDataComponent(Transition transition, DataRef dataRef) throws MissingIconKeyException {
String fieldId = getField(dataRef.getId()).getStringId();
Component component = null;
@@ -841,7 +801,6 @@ protected void addDataComponent(Transition transition, DataRef dataRef) throws M
transition.addDataSet(fieldId, null, null, null, component);
}
- @Transactional
protected Map buildEvents(String fieldId, List events, String transitionId) {
Map parsedEvents = new HashMap<>();
@@ -897,7 +856,6 @@ protected com.netgrif.application.engine.petrinet.domain.events.DataEvent create
return dataEvent;
}
- @Transactional
protected List buildActions(List imported, String fieldId, String transitionId) {
return imported.stream()
.map(action -> parseAction(fieldId, transitionId, action))
@@ -964,7 +922,6 @@ protected boolean containsParams(String definition) {
return definition.matches("[\\W\\w\\s]*[\\w]*:[\\s]*[ft].[\\w]+;[\\w\\W\\s]*");
}
- @Transactional
protected void parseObjectIds(Action action, String fieldId, String transitionId, String definition) {
try {
Map ids = parseParams(definition);
@@ -1020,14 +977,12 @@ protected String getFieldId(String importId) {
}
}
- @Transactional
protected void addTrigger(Transition transition, com.netgrif.application.engine.importer.model.Trigger importTrigger) {
Trigger trigger = triggerFactory.buildTrigger(importTrigger);
transition.addTrigger(trigger);
}
- @Transactional
protected void createPlace(com.netgrif.application.engine.importer.model.Place importPlace) {
Place place = new Place();
place.setImportId(importPlace.getId());
@@ -1044,7 +999,6 @@ protected void createPlace(com.netgrif.application.engine.importer.model.Place i
places.put(importPlace.getId(), place);
}
- @Transactional
protected void createRole(Role importRole) {
if (importRole.getId().equals(ProcessRole.DEFAULT_ROLE)) {
throw new IllegalArgumentException("Role ID '" + ProcessRole.DEFAULT_ROLE + "' is a reserved identifier, roles with this ID cannot be defined!");
@@ -1115,7 +1069,6 @@ protected Map mapping;
+
+ public ConfigurationTemplateOutcome() {
+ this.mapping = new HashMap<>();
+ }
+
+ public ConfigurationTemplateOutcome(ToDataSetOutcome toDataSetOutcome) {
+ this();
+ if (toDataSetOutcome != null) {
+ toDataSetOutcome.getDataSet()
+ .forEach((fieldId, fieldMap) -> this.mapping.put(fieldId, fieldMap.get("value")));
+ }
+ }
+
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/FilterBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/FilterBody.java
index de048064e33..bfa7f29634c 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/FilterBody.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/FilterBody.java
@@ -1,74 +1,33 @@
package com.netgrif.application.engine.menu.domain;
-import com.netgrif.application.engine.petrinet.domain.I18nString;
import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
-import com.netgrif.application.engine.startup.DefaultFiltersRunner;
-import com.netgrif.application.engine.workflow.domain.Case;
import com.netgrif.application.engine.workflow.service.interfaces.IDataService;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
@Data
@NoArgsConstructor
public class FilterBody {
- private Case filter;
- private I18nString title;
private String query;
- private String type;
- private List allowedNets;
- private String icon;
- private String visibility;
- private Map metadata;
-
- public FilterBody(Case filterCase) {
- this.filter = filterCase;
- }
-
- /**
- * Gets default metadata with provided filter type
- *
- * @param type type of the filter
- *
- * @return metadata containing filter type as map
- * */
- public static Map getDefaultMetadata(String type) {
- Map 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);
-
- return resultMap;
- }
+ private FieldType type;
/**
* Transforms attributes into dataSet for {@link IDataService#setData}
*
* @return {@link ToDataSetOutcome} object with dataSet
* */
- public ToDataSetOutcome toDataSet() {
- ToDataSetOutcome outcome = new ToDataSetOutcome();
-
- outcome.putDataSetEntry(DefaultFiltersRunner.FILTER_TYPE_FIELD_ID, FieldType.ENUMERATION_MAP, this.type);
- outcome.putDataSetEntry(DefaultFiltersRunner.FILTER_VISIBILITY_FIELD_ID, FieldType.ENUMERATION_MAP, this.visibility);
- outcome.putDataSetEntry(DefaultFiltersRunner.FILTER_I18N_TITLE_FIELD_ID, FieldType.I18N, this.title);
- Map metadata = this.metadata;
- if (metadata == null) {
- metadata = getDefaultMetadata(this.type);
+ public ToDataSetOutcome toDataSet(ToDataSetOutcome viewDataSetOutcome, String filterFieldId) {
+ Map dataSetValues = new HashMap<>();
+ if (this.type == null) {
+ throw new IllegalArgumentException("Filter type is not provided");
}
- outcome.getDataSet().put(DefaultFiltersRunner.FILTER_FIELD_ID, Map.of(
- "type", "filter",
- "value", this.query,
- "allowedNets", this.allowedNets,
- "filterMetadata", metadata
- ));
+ dataSetValues.put("type", this.type.getName());
+ dataSetValues.put("value", this.query);
+ viewDataSetOutcome.getDataSet().put(filterFieldId, dataSetValues);
- return outcome;
+ return viewDataSetOutcome;
}
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java
index 9637f9ddeb8..02dde589073 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemBody.java
@@ -22,6 +22,7 @@
public class MenuItemBody {
private String uri;
private String identifier;
+ private String configurationTemplateIdentifier;
private String menuIcon = "filter_none";
private I18nString menuName;
@@ -31,7 +32,7 @@ public class MenuItemBody {
private String customViewSelector;
private boolean isAutoSelect = false;
- private boolean useTabbedView;
+ private boolean useTabbedView = true;
private String tabIcon;
private boolean useTabIcon = true;
private I18nString tabName;
@@ -108,8 +109,14 @@ public void setTabName(String name) {
}
public void setView(ViewBody viewBody) {
- this.view = viewBody;
- this.useTabbedView = viewBody == null || viewBody.getViewType().isTabbed();
+ if (viewBody != null) {
+ this.view = viewBody;
+ MenuItemViewType viewType = viewBody.getViewType();
+ if (viewType.isTabbed() != viewType.isUntabbed()) {
+ // if isTabbed == isUntabbed we cannot determine the result value
+ this.useTabbedView = viewType.isTabbed();
+ }
+ }
}
/**
@@ -157,10 +164,16 @@ public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCas
if (nodePath != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_NODE_PATH, FieldType.TEXT, nodePath);
}
- outcome.putDataSetEntry(MenuItemConstants.FIELD_MENU_NAME, FieldType.I18N, this.menuName);
+ if (this.menuName == null) {
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_MENU_NAME, FieldType.I18N, new I18nString(this.identifier));
+ } else {
+ 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);
+ if (this.tabName != null) {
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_TAB_NAME, FieldType.I18N, this.tabName);
+ }
outcome.putDataSetEntry(MenuItemConstants.FIELD_TAB_ICON, FieldType.TEXT, this.tabIcon);
if (this.identifier != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_IDENTIFIER, FieldType.TEXT, this.getIdentifier());
@@ -173,7 +186,27 @@ public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCas
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);
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_CONFIGURATION_TEMPLATES, FieldType.ENUMERATION_MAP, this.configurationTemplateIdentifier);
+
+ outcome = toDataSetWithView(viewCase, outcome);
+ return outcome;
+ }
+
+ /**
+ * Transforms minimal attributes into dataSet for view configuration by template.
+ *
+ * @param viewCase case instance of view
+ * @return {@link ToDataSetOutcome} object with dataSet containing only view-related fields
+ */
+ public ToDataSetOutcome toDataSetByConfigTemplate(Case viewCase) {
+ ToDataSetOutcome outcome = new ToDataSetOutcome();
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_USE_TABBED_VIEW, FieldType.BOOLEAN, this.useTabbedView);
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_USE_CUSTOM_VIEW, FieldType.BOOLEAN, this.useCustomView);
+ return toDataSetWithView(viewCase, outcome);
+ }
+
+ protected ToDataSetOutcome toDataSetWithView(Case viewCase, ToDataSetOutcome outcome) {
if (viewCase != null) {
outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_TYPE, FieldType.ENUMERATION_MAP,
this.view.getViewType().getIdentifier());
@@ -181,8 +214,9 @@ public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCas
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));
+ String allDataTaskId = MenuItemUtils.findTaskIdInCase(viewCase, ViewConstants.TRANS_ALL_MENU_DATA_ID);
+ outcome.putDataSetEntry(MenuItemConstants.FIELD_VIEW_CONFIGURATION_ALL_DATA_FORM, FieldType.TASK_REF, List.of(allDataTaskId));
}
-
return outcome;
}
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java
index d6ac1a37afc..60992401417 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemConstants.java
@@ -28,8 +28,17 @@ public class MenuItemConstants {
public static final String FIELD_IS_AUTO_SELECT = "is_auto_select";
public static final String FIELD_VIEW_CONFIGURATION_ID = "view_configuration_id";
public static final String FIELD_VIEW_CONFIGURATION_FORM = "view_configuration_form";
+ public static final String FIELD_VIEW_CONFIGURATION_ALL_DATA_FORM = "view_configuration_all_data_form";
+ public static final String FIELD_CONFIGURATION_TEMPLATES = "configuration_templates";
public static final String TRANS_SETTINGS_ID = "item_settings";
+ public static final String TRANS_SYS_INIT_ID = "system_initialize";
public static final String TRANS_INIT_ID = "initialize";
public static final String TRANS_SYNC_ID = "data_sync";
+ public static final String TRANS_ALL_MENU_DATA = "all_menu_data";
+
+ public static final String PROCESS_IDENTIFIER = "menu_item";
+
+ public static final String IDENTIFIER_INDEX_NAME = "menuItemIdentifierIdx";
+ public static final String NODE_PATH_INDEX_NAME = "menuItemNodePathIdx";
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemView.java b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemViewType.java
similarity index 54%
rename from src/main/java/com/netgrif/application/engine/menu/domain/MenuItemView.java
rename to src/main/java/com/netgrif/application/engine/menu/domain/MenuItemViewType.java
index 1bdf5a43d54..bdf38961bee 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemView.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/MenuItemViewType.java
@@ -13,17 +13,19 @@
* Here is listed and configured every configuration process available for menu items.
* */
@Getter
-public enum MenuItemView {
- TABBED_CASE_VIEW(new I18nString("Tabbed case view", Map.of("sk", "Zobrazenie prípadov v taboch",
- "de", "Fallansicht mit Registerkarten")), "tabbed_case_view", List.of("tabbed_task_view"),
- true, true),
- TABBED_TASK_VIEW(new I18nString("Tabbed task view", Map.of("sk", "Zobrazenie úloh v taboch",
- "de", "Aufgabenansicht mit Registerkarten")), "tabbed_task_view", List.of(), true, true),
- TABBED_TICKET_VIEW(new I18nString("Tabbed ticket view", Map.of("sk", "Tiketové zobrazenie v taboch",
- "de", "Ticketansicht mit Registerkarten")), "tabbed_ticket_view",
- List.of("tabbed_single_task_view"), true, true),
- TABBED_SINGLE_TASK_VIEW(new I18nString("Tabbed single task view", Map.of("sk", "Zobrazenie jednej úlohy v taboch",
- "de", "Einzelaufgabenansicht mit Registerkarten")), "tabbed_single_task_view", List.of(), true, false);
+public enum MenuItemViewType {
+ CASE_VIEW(new I18nString("Case view",
+ Map.of("sk", "Zobrazenie prípadov", "de", "Fallansicht")),
+ "case_view", List.of("task_view"), true, true, true),
+ TASK_VIEW(new I18nString("Task view",
+ Map.of("sk", "Zobrazenie úloh", "de", "Aufgabenansicht")),
+ "task_view", List.of(), true, true, true),
+ TABBED_TICKET_VIEW(new I18nString("Tabbed ticket view",
+ Map.of("sk", "Tiketové zobrazenie v taboch", "de", "Ticketansicht mit Registerkarten")),
+ "tabbed_ticket_view", List.of("single_task_view"), true, false, true),
+ SINGLE_TASK_VIEW(new I18nString("Single task view",
+ Map.of("sk", "Zobrazenie jednej úlohy", "de", "Einzelaufgabenansicht")),
+ "single_task_view", List.of(), true, true, true);
private final I18nString name;
private final String identifier;
@@ -32,25 +34,28 @@ public enum MenuItemView {
* */
private final List allowedAssociatedViews;
private final boolean isTabbed;
+ private final boolean isUntabbed;
/**
* if false, the view cannot be used as first configuration of the menu_item, but can be used as secondary
* (associated to another view)
* */
private final boolean isPrimary;
- MenuItemView(I18nString name, String identifier, List allowedAssociatedViews, boolean isTabbed, boolean isPrimary) {
+ MenuItemViewType(I18nString name, String identifier, List allowedAssociatedViews, boolean isTabbed,
+ boolean isUntabbed, boolean isPrimary) {
this.name = name;
this.identifier = identifier;
this.allowedAssociatedViews = allowedAssociatedViews;
this.isTabbed = isTabbed;
+ this.isUntabbed = isUntabbed;
this.isPrimary = isPrimary;
}
/**
* Builds enum value by the view identifier
* */
- public static MenuItemView fromIdentifier(String identifier) {
- for (MenuItemView view : MenuItemView.values()) {
+ public static MenuItemViewType fromIdentifier(String identifier) {
+ for (MenuItemViewType view : MenuItemViewType.values()) {
if (view.identifier.equals(identifier)) {
return view;
}
@@ -66,9 +71,9 @@ public static MenuItemView fromIdentifier(String identifier) {
*
* @return List of views based on {@link #isTabbed}
* */
- public static List findAllByIsTabbedAndIsPrimary(boolean isTabbed, boolean isPrimary) {
- return Arrays.stream(MenuItemView.values())
- .filter(view -> view.isTabbed == isTabbed && view.isPrimary == isPrimary)
+ public static List findAllByIsTabbedAndIsPrimary(boolean isTabbed, boolean isPrimary) {
+ return Arrays.stream(MenuItemViewType.values())
+ .filter(view -> (view.isTabbed == isTabbed || view.isUntabbed != isTabbed) && view.isPrimary == isPrimary)
.collect(Collectors.toList());
}
@@ -80,10 +85,10 @@ public static List findAllByIsTabbedAndIsPrimary(boolean isTabbed,
*
* @return List of views based on {@link #isTabbed} and {@link #allowedAssociatedViews}
* */
- public static List findAllByIsTabbedAndParentIdentifier(boolean isTabbed, String parentIdentifier) {
- MenuItemView parentView = fromIdentifier(parentIdentifier);
- return Arrays.stream(MenuItemView.values())
- .filter(view -> view.isTabbed == isTabbed
+ public static List findAllByIsTabbedAndParentIdentifier(boolean isTabbed, String parentIdentifier) {
+ MenuItemViewType parentView = fromIdentifier(parentIdentifier);
+ return Arrays.stream(MenuItemViewType.values())
+ .filter(view -> (view.isTabbed == isTabbed || view.isUntabbed != isTabbed)
&& parentView.getAllowedAssociatedViews().contains(view.identifier))
.collect(Collectors.toList());
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewBody.java
new file mode 100644
index 00000000000..6a47b3b45b3
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewBody.java
@@ -0,0 +1,114 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
+import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CaseViewBody extends ViewBody {
+ private String viewSearchType = "fulltext_advanced";
+ private I18nString createCaseButtonTitle;
+ private String createCaseButtonIcon = "add";
+ private boolean requireTitleInCreation = true;
+ private boolean showCreateCaseButton = true;
+ private String bannedNetsInCreation;
+ private boolean showMoreMenu = false;
+ private boolean allowHeaderTableMode = true;
+ private List headersMode = new ArrayList<>(List.of("sort", "edit", "search"));
+ private String headersDefaultMode = "sort";
+ private List defaultHeaders;
+ private boolean headerModeChangeable = true;
+ private boolean useDefaultHeaders = true;
+ private I18nString emptyContentText;
+ private String emptyContentIcon;
+ private boolean allowExport;
+ private boolean allAllowedNets = true;
+ private List allowedNets;
+ private boolean inheritAllowedNets = true;
+
+ private ViewBody chainedView;
+
+ @Override
+ public ViewBody getAssociatedViewBody() {
+ return this.chainedView;
+ }
+
+ @Override
+ public MenuItemViewType getViewType() {
+ return MenuItemViewType.CASE_VIEW;
+ }
+
+ @Override
+ public String getFilterFieldId() {
+ return CaseViewConstants.FIELD_FILTER;
+ }
+
+ @Override
+ public FieldType getFilterType() {
+ return FieldType.CASE_FILTER;
+ }
+
+ @Override
+ protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
+
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
+ this.viewSearchType);
+ if (this.createCaseButtonTitle != null) {
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_CREATE_CASE_BUTTON_TITLE, FieldType.I18N,
+ this.createCaseButtonTitle);
+ }
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_CREATE_CASE_BUTTON_ICON, FieldType.TEXT,
+ this.createCaseButtonIcon);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_REQUIRE_TITLE_IN_CREATION, FieldType.BOOLEAN,
+ this.requireTitleInCreation);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_SHOW_CREATE_CASE_BUTTON, FieldType.BOOLEAN,
+ this.showCreateCaseButton);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_BANNED_NETS_IN_CREATION, FieldType.TEXT,
+ this.bannedNetsInCreation);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_SHOW_MORE_MENU, FieldType.BOOLEAN,
+ this.showMoreMenu);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
+ this.allowHeaderTableMode);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
+ this.headersMode == null ? new ArrayList<>() : this.headersMode);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
+ this.headersDefaultMode);
+ if (this.defaultHeaders != null) {
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_DEFAULT_HEADERS, FieldType.STRING_COLLECTION,
+ this.defaultHeaders);
+ }
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
+ this.headerModeChangeable);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_USE_DEFAULT_HEADERS, FieldType.BOOLEAN,
+ this.useDefaultHeaders);
+ if (this.emptyContentText != null) {
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_EMPTY_CONTENT_TEXT, FieldType.I18N,
+ this.emptyContentText);
+ }
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_EMPTY_CONTENT_ICON, FieldType.TEXT,
+ this.emptyContentIcon);
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_ALLOW_EXPORT, FieldType.BOOLEAN,
+ this.allowExport);
+
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_ALL_ALLOWED_NETS, FieldType.BOOLEAN,
+ this.allAllowedNets);
+ if (this.allowedNets != null) {
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_ALLOWED_NETS, FieldType.STRING_COLLECTION,
+ this.allowedNets);
+ }
+ outcome.putDataSetEntry(CaseViewConstants.FIELD_INHERIT_ALLOWED_NETS, FieldType.BOOLEAN,
+ this.inheritAllowedNets);
+
+ return outcome;
+ }
+}
+
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewConstants.java
new file mode 100644
index 00000000000..44db426e1b5
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/CaseViewConstants.java
@@ -0,0 +1,27 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+/**
+ * Here are declared constants of process case_view_configuration.xml.
+ */
+public class CaseViewConstants extends ViewConstants {
+ public static final String FIELD_DEFAULT_HEADERS = "case_default_headers";
+ public static final String FIELD_REQUIRE_TITLE_IN_CREATION = "require_title_in_creation";
+ public static final String FIELD_VIEW_SEARCH_TYPE = "case_view_search_type";
+ public static final String FIELD_CREATE_CASE_BUTTON_TITLE = "create_case_button_title";
+ public static final String FIELD_CREATE_CASE_BUTTON_ICON = "create_case_button_icon";
+ public static final String FIELD_BANNED_NETS_IN_CREATION = "banned_nets_in_creation";
+ public static final String FIELD_SHOW_CREATE_CASE_BUTTON = "show_create_case_button";
+ public static final String FIELD_SHOW_MORE_MENU = "case_show_more_menu";
+ public static final String FIELD_ALLOW_HEADER_TABLE_MODE = "case_allow_header_table_mode";
+ public static final String FIELD_HEADERS_MODE = "case_headers_mode";
+ public static final String FIELD_HEADERS_DEFAULT_MODE = "case_headers_default_mode";
+ public static final String FIELD_IS_HEADER_MODE_CHANGEABLE = "case_is_header_mode_changeable";
+ public static final String FIELD_USE_DEFAULT_HEADERS = "use_case_default_headers";
+ public static final String FIELD_EMPTY_CONTENT_TEXT = "case_empty_content_text";
+ public static final String FIELD_EMPTY_CONTENT_ICON = "case_empty_content_icon";
+ public static final String FIELD_FILTER = "case_filter";
+ public static final String FIELD_ALLOW_EXPORT = "case_allow_export";
+ public static final String FIELD_ALL_ALLOWED_NETS = "case_all_allowed_nets";
+ public static final String FIELD_ALLOWED_NETS = "case_allowed_nets";
+ public static final String FIELD_INHERIT_ALLOWED_NETS = "case_inherit_allowed_nets";
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewBody.java
new file mode 100644
index 00000000000..1b4e3531adb
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewBody.java
@@ -0,0 +1,43 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
+import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
+import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SingleTaskViewBody extends ViewBody {
+ private boolean showPageHeader = true;
+ private boolean showPageFooter = false;
+
+ @Override
+ public ViewBody getAssociatedViewBody() {
+ return null;
+ }
+
+ @Override
+ public MenuItemViewType getViewType() {
+ return MenuItemViewType.SINGLE_TASK_VIEW;
+ }
+
+ @Override
+ public String getFilterFieldId() {
+ return SingleTaskViewConstants.FIELD_FILTER;
+ }
+
+ @Override
+ public FieldType getFilterType() {
+ return FieldType.TASK_FILTER;
+ }
+
+ @Override
+ protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
+ outcome.putDataSetEntry(SingleTaskViewConstants.FIELD_SHOW_PAGE_HEADER, FieldType.BOOLEAN, this.showPageHeader);
+ outcome.putDataSetEntry(SingleTaskViewConstants.FIELD_SHOW_PAGE_FOOTER, FieldType.BOOLEAN, this.showPageFooter);
+ return outcome;
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewConstants.java
new file mode 100644
index 00000000000..d251523ae8f
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/SingleTaskViewConstants.java
@@ -0,0 +1,7 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+public class SingleTaskViewConstants extends ViewConstants {
+ public static final String FIELD_SHOW_PAGE_HEADER = "show_page_header";
+ public static final String FIELD_SHOW_PAGE_FOOTER = "show_page_footer";
+ public static final String FIELD_FILTER = "task_filter";
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewBody.java
deleted file mode 100644
index 5f18b2920cb..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewBody.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-import com.netgrif.application.engine.menu.domain.MenuItemView;
-import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
-import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Data
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-public class TabbedCaseViewBody extends ViewBody {
- private String viewSearchType = "fulltext_advanced";
- private String createCaseButtonTitle;
- private String createCaseButtonIcon = "add";
- private boolean requireTitleInCreation = true;
- private boolean showCreateCaseButton = true;
- private String bannedNetsInCreation;
- private boolean showMoreMenu = false;
- private boolean allowHeaderTableMode = true;
- private List headersMode = new ArrayList<>(List.of("sort", "edit", "search"));
- private String headersDefaultMode = "sort";
- private List defaultHeaders;
- private boolean isHeaderModeChangeable = true;
- private boolean useDefaultHeaders = true;
-
- private ViewBody chainedView;
-
- @Override
- public ViewBody getAssociatedViewBody() {
- return this.chainedView;
- }
-
- @Override
- public MenuItemView getViewType() {
- return MenuItemView.TABBED_CASE_VIEW;
- }
-
- @Override
- protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
-
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
- this.viewSearchType);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_CREATE_CASE_BUTTON_TITLE, FieldType.TEXT,
- this.createCaseButtonTitle);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_CREATE_CASE_BUTTON_ICON, FieldType.TEXT,
- this.createCaseButtonIcon);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_REQUIRE_TITLE_IN_CREATION, FieldType.BOOLEAN,
- this.requireTitleInCreation);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_SHOW_CREATE_CASE_BUTTON, FieldType.BOOLEAN,
- this.showCreateCaseButton);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_BANNED_NETS_IN_CREATION, FieldType.TEXT,
- this.bannedNetsInCreation);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_SHOW_MORE_MENU, FieldType.BOOLEAN,
- this.showMoreMenu);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
- this.allowHeaderTableMode);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
- this.headersMode == null ? new ArrayList<>() : this.headersMode);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
- this.headersDefaultMode);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_DEFAULT_HEADERS, FieldType.TEXT,
- this.defaultHeaders != null ? String.join(",", this.defaultHeaders) : null);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
- this.isHeaderModeChangeable);
- outcome.putDataSetEntry(TabbedCaseViewConstants.FIELD_USE_CASE_DEFAULT_HEADERS, FieldType.BOOLEAN,
- this.useDefaultHeaders);
-
- return outcome;
- }
-}
-
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewConstants.java
deleted file mode 100644
index b5c8ef2361b..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedCaseViewConstants.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-/**
- * Here are declared constants of process tabbed_case_view_configuration.xml.
- */
-public class TabbedCaseViewConstants extends ViewConstants {
- 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_REQUIRE_TITLE_IN_CREATION = "require_title_in_creation";
- public static final String FIELD_VIEW_SEARCH_TYPE = "view_search_type";
- public static final String FIELD_CREATE_CASE_BUTTON_TITLE = "create_case_button_title";
- public static final String FIELD_CREATE_CASE_BUTTON_ICON = "create_case_button_icon";
- public static final String FIELD_BANNED_NETS_IN_CREATION = "banned_nets_in_creation";
- public static final String FIELD_SHOW_CREATE_CASE_BUTTON = "show_create_case_button";
- public static final String FIELD_SHOW_MORE_MENU = "show_more_menu";
- public static final String FIELD_ALLOW_HEADER_TABLE_MODE = "allow_header_table_mode";
- public static final String FIELD_HEADERS_MODE = "headers_mode";
- public static final String FIELD_HEADERS_DEFAULT_MODE = "headers_default_mode";
- public static final String FIELD_IS_HEADER_MODE_CHANGEABLE = "is_header_mode_changeable";
- public static final String FIELD_USE_CASE_DEFAULT_HEADERS = "use_case_default_headers";
-}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewBody.java
deleted file mode 100644
index fa58689c976..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewBody.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-import com.netgrif.application.engine.menu.domain.MenuItemView;
-import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
-import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-@Data
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-public class TabbedSingleTaskViewBody extends ViewBody {
- private String transitionId;
-
- @Override
- public ViewBody getAssociatedViewBody() {
- return null;
- }
-
- @Override
- public MenuItemView getViewType() {
- return MenuItemView.TABBED_SINGLE_TASK_VIEW;
- }
-
- @Override
- protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
- outcome.putDataSetEntry(TabbedSingleTaskViewConstants.FIELD_TRANSITION_ID, FieldType.TEXT, this.transitionId);
- return outcome;
- }
-}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewConstants.java
deleted file mode 100644
index c0d6949b328..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedSingleTaskViewConstants.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-public class TabbedSingleTaskViewConstants extends ViewConstants {
- public static final String FIELD_TRANSITION_ID = "transition_id";
-}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewBody.java
deleted file mode 100644
index 0fabe6940fe..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewBody.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-import com.netgrif.application.engine.menu.domain.MenuItemView;
-import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
-import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
-import com.netgrif.application.engine.workflow.domain.Case;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Data
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-public class TabbedTaskViewBody extends ViewBody {
- private Case filter;
- private boolean mergeFilters = true;
- private String viewSearchType = "fulltext_advanced";
- private List headersMode = new ArrayList<>(List.of("sort", "edit"));
- private String headersDefaultMode = "sort";
- private boolean isHeaderModeChangeable = true;
- private boolean allowHeaderTableMode = true;
- private boolean useDefaultHeaders = true;
- private List defaultHeaders;
- private boolean showMoreMenu = true;
-
- @Override
- public ViewBody getAssociatedViewBody() {
- return null;
- }
-
- @Override
- public MenuItemView getViewType() {
- return MenuItemView.TABBED_TASK_VIEW;
- }
-
- @Override
- protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
-
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_MERGE_FILTERS, FieldType.BOOLEAN,
- this.mergeFilters);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
- this.viewSearchType);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
- this.headersMode == null ? new ArrayList<>() : this.headersMode);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
- this.headersDefaultMode);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
- this.isHeaderModeChangeable);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
- this.allowHeaderTableMode);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_USE_DEFAULT_HEADERS, FieldType.BOOLEAN,
- this.useDefaultHeaders);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_DEFAULT_HEADERS, FieldType.TEXT,
- this.defaultHeaders != null ? String.join(",", this.defaultHeaders) : null);
- outcome.putDataSetEntry(TabbedTaskViewConstants.FIELD_SHOW_MORE_MENU, FieldType.BOOLEAN,
- this.showMoreMenu);
-
- return outcome;
- }
-}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewConstants.java
deleted file mode 100644
index f895558fa77..00000000000
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTaskViewConstants.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.netgrif.application.engine.menu.domain.configurations;
-
-/**
- * Here are declared constants of process tabbed_task_view_configuration.xml.
- */
-public class TabbedTaskViewConstants extends ViewConstants {
- 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_HEADERS_DEFAULT_MODE = "headers_default_mode";
- public static final String FIELD_IS_HEADER_MODE_CHANGEABLE = "is_header_mode_changeable";
- public static final String FIELD_ALLOW_HEADER_TABLE_MODE = "allow_header_table_mode";
- public static final String FIELD_USE_DEFAULT_HEADERS = "use_default_headers";
- public static final String FIELD_SHOW_MORE_MENU = "show_more_menu";
-}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTicketViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTicketViewBody.java
index f0aafd54b65..7f898695be2 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTicketViewBody.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TabbedTicketViewBody.java
@@ -1,7 +1,8 @@
package com.netgrif.application.engine.menu.domain.configurations;
-import com.netgrif.application.engine.menu.domain.MenuItemView;
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
+import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@@ -19,8 +20,18 @@ public ViewBody getAssociatedViewBody() {
}
@Override
- public MenuItemView getViewType() {
- return MenuItemView.TABBED_TICKET_VIEW;
+ public MenuItemViewType getViewType() {
+ return MenuItemViewType.TABBED_TICKET_VIEW;
+ }
+
+ @Override
+ public String getFilterFieldId() {
+ return "";
+ }
+
+ @Override
+ public FieldType getFilterType() {
+ return null;
}
@Override
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewBody.java
new file mode 100644
index 00000000000..4e8e09456bd
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewBody.java
@@ -0,0 +1,94 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
+import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class TaskViewBody extends ViewBody {
+ private boolean mergeFilters = true;
+ private String viewSearchType = "fulltext_advanced";
+ private List headersMode = new ArrayList<>(List.of("sort", "edit"));
+ private String headersDefaultMode = "sort";
+ private boolean isHeaderModeChangeable = true;
+ private boolean allowHeaderTableMode = true;
+ private boolean useDefaultHeaders = true;
+ private List defaultHeaders;
+ private boolean showMoreMenu = true;
+ private I18nString emptyContentText;
+ private String emptyContentIcon;
+ private boolean allAllowedNets = true;
+ private List allowedNets;
+ private boolean inheritAllowedNets = true;
+
+ @Override
+ public ViewBody getAssociatedViewBody() {
+ return null;
+ }
+
+ @Override
+ public MenuItemViewType getViewType() {
+ return MenuItemViewType.TASK_VIEW;
+ }
+
+ @Override
+ public String getFilterFieldId() {
+ return TaskViewConstants.FIELD_FILTER;
+ }
+
+ @Override
+ public FieldType getFilterType() {
+ return FieldType.TASK_FILTER;
+ }
+
+ @Override
+ protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
+
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_MERGE_FILTERS, FieldType.BOOLEAN,
+ this.mergeFilters);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_VIEW_SEARCH_TYPE, FieldType.ENUMERATION_MAP,
+ this.viewSearchType);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_HEADERS_MODE, FieldType.MULTICHOICE_MAP,
+ this.headersMode == null ? new ArrayList<>() : this.headersMode);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
+ this.headersDefaultMode);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_IS_HEADER_MODE_CHANGEABLE, FieldType.BOOLEAN,
+ this.isHeaderModeChangeable);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_ALLOW_HEADER_TABLE_MODE, FieldType.BOOLEAN,
+ this.allowHeaderTableMode);
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_USE_DEFAULT_HEADERS, FieldType.BOOLEAN,
+ this.useDefaultHeaders);
+ if (this.defaultHeaders != null) {
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_DEFAULT_HEADERS, FieldType.STRING_COLLECTION,
+ this.defaultHeaders);
+ }
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_SHOW_MORE_MENU, FieldType.BOOLEAN,
+ this.showMoreMenu);
+ if (this.emptyContentText != null) {
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_EMPTY_CONTENT_TEXT, FieldType.I18N,
+ this.emptyContentText);
+ }
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_EMPTY_CONTENT_ICON, FieldType.TEXT,
+ this.emptyContentIcon);
+
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_ALL_ALLOWED_NETS, FieldType.BOOLEAN,
+ this.allAllowedNets);
+ if (this.allowedNets != null) {
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_ALLOWED_NETS, FieldType.STRING_COLLECTION,
+ this.allowedNets);
+ }
+ outcome.putDataSetEntry(TaskViewConstants.FIELD_INHERIT_ALLOWED_NETS, FieldType.BOOLEAN,
+ this.inheritAllowedNets);
+
+ return outcome;
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewConstants.java
new file mode 100644
index 00000000000..c9acf6f9e54
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/TaskViewConstants.java
@@ -0,0 +1,22 @@
+package com.netgrif.application.engine.menu.domain.configurations;
+
+/**
+ * Here are declared constants of process task_view_configuration.xml.
+ */
+public class TaskViewConstants extends ViewConstants {
+ public static final String FIELD_MERGE_FILTERS = "merge_filters";
+ public static final String FIELD_FILTER = "task_filter";
+ public static final String FIELD_VIEW_SEARCH_TYPE = "task_view_search_type";
+ public static final String FIELD_DEFAULT_HEADERS = "task_default_headers";
+ public static final String FIELD_HEADERS_MODE = "task_headers_mode";
+ public static final String FIELD_HEADERS_DEFAULT_MODE = "task_headers_default_mode";
+ public static final String FIELD_IS_HEADER_MODE_CHANGEABLE = "task_is_header_mode_changeable";
+ public static final String FIELD_ALLOW_HEADER_TABLE_MODE = "task_allow_header_table_mode";
+ public static final String FIELD_USE_DEFAULT_HEADERS = "use_task_default_headers";
+ public static final String FIELD_SHOW_MORE_MENU = "task_show_more_menu";
+ public static final String FIELD_EMPTY_CONTENT_TEXT = "task_empty_content_text";
+ public static final String FIELD_EMPTY_CONTENT_ICON = "task_empty_content_icon";
+ public static final String FIELD_ALL_ALLOWED_NETS = "task_all_allowed_nets";
+ public static final String FIELD_ALLOWED_NETS = "task_allowed_nets";
+ public static final String FIELD_INHERIT_ALLOWED_NETS = "task_inherit_allowed_nets";
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewBody.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewBody.java
index d636b6e60b1..58c8edf0c0f 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewBody.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewBody.java
@@ -1,7 +1,7 @@
package com.netgrif.application.engine.menu.domain.configurations;
import com.netgrif.application.engine.menu.domain.FilterBody;
-import com.netgrif.application.engine.menu.domain.MenuItemView;
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
import com.netgrif.application.engine.menu.utils.MenuItemUtils;
import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
@@ -23,7 +23,9 @@ public abstract class ViewBody {
protected FilterBody filterBody;
public abstract ViewBody getAssociatedViewBody();
- public abstract MenuItemView getViewType();
+ public abstract MenuItemViewType getViewType();
+ public abstract String getFilterFieldId();
+ public abstract FieldType getFilterType();
/**
* Internal method, that must transform data in concrete class and add them into received outcome. Method must return
* the updated outcome.
@@ -52,18 +54,17 @@ public String getViewProcessIdentifier() {
* @return {@link ToDataSetOutcome} object containing dataSet
* */
public ToDataSetOutcome toDataSet() {
- return toDataSet(null, null);
+ return toDataSet(null);
};
/**
* Transforms data of this class into {@link ToDataSetOutcome}, which contains prepared data for the {@link IDataService#setData}
*
* @param associatedViewCase case instance of associated view. If provided, caseRef and taskRef are initialized.
- * @param filterCase case instance of filter. If provided, caseRef is initialized
*
* @return {@link ToDataSetOutcome} object containing dataSet
* */
- public ToDataSetOutcome toDataSet(Case associatedViewCase, Case filterCase) {
+ public ToDataSetOutcome toDataSet(Case associatedViewCase) {
ToDataSetOutcome outcome = new ToDataSetOutcome();
if (associatedViewCase != null) {
@@ -73,9 +74,12 @@ public ToDataSetOutcome toDataSet(Case associatedViewCase, Case filterCase) {
List.of(associatedViewCase.getStringId()));
String taskId = MenuItemUtils.findTaskIdInCase(associatedViewCase, ViewConstants.TRANS_SETTINGS_ID);
outcome.putDataSetEntry(ViewConstants.FIELD_VIEW_CONFIGURATION_FORM, FieldType.TASK_REF, List.of(taskId));
+ String allDataTaskId = MenuItemUtils.findTaskIdInCase(associatedViewCase, ViewConstants.TRANS_ALL_MENU_DATA_ID);
+ outcome.putDataSetEntry(ViewConstants.FIELD_VIEW_CONFIGURATION_ALL_DATA_FORM, FieldType.TASK_REF, List.of(allDataTaskId));
}
- if (filterCase != null) {
- outcome.putDataSetEntry(ViewConstants.FIELD_VIEW_FILTER_CASE, FieldType.CASE_REF, List.of(filterCase.getStringId()));
+ if (filterBody != null) {
+ filterBody.setType(getFilterType());
+ outcome = filterBody.toDataSet(outcome, getFilterFieldId());
}
return toDataSetInternal(outcome);
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewConstants.java b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewConstants.java
index 74c38803f06..d27bfa83e03 100644
--- a/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewConstants.java
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/configurations/ViewConstants.java
@@ -7,10 +7,10 @@ public class ViewConstants {
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 FIELD_VIEW_CONFIGURATION_FORM = "view_configuration_form";
- public static final String FIELD_VIEW_CONTAINS_FILTER = "contains_filter";
- public static final String FIELD_VIEW_FILTER_CASE = "filter_case";
+ public static final String FIELD_VIEW_CONFIGURATION_ALL_DATA_FORM = "view_configuration_all_data_form";
public static final String TRANS_INIT_ID = "initialize";
public static final String TRANS_SETTINGS_ID = "settings";
+ public static final String TRANS_ALL_MENU_DATA_ID = "all_menu_data";
public static final String TRANS_SYNC_ID = "data_sync";
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/CustomViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/CustomViewTemplate.java
new file mode 100644
index 00000000000..ac5970868b7
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/CustomViewTemplate.java
@@ -0,0 +1,37 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class CustomViewTemplate implements Template {
+ public static final String IDENTIFIER = "custom_view";
+
+ private static final I18nString NAME = new I18nString("Custom view",
+ Map.of("sk", "Vlastné zobrazenie", "de", "Benutzerdefinierte Ansicht"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(false);
+ menuItemBody.setUseCustomView(true);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/README.md b/src/main/java/com/netgrif/application/engine/menu/domain/templates/README.md
new file mode 100644
index 00000000000..7dd8af166fa
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/README.md
@@ -0,0 +1,48 @@
+# Menu Item Template Creation Guide
+
+## Overview
+
+Templates provide predefined configurations for menu items that can be reused throughout the application. Each template
+encapsulates a complete menu item structure with its associated views and filters.
+
+## Template Structure
+
+A template must implement the `Template` interface with three core components:
+
+- **Identifier**: A unique string constant that identifies the template
+- **Name**: An internationalized string (I18nString) providing the display name in multiple languages
+- **Template Body**: A MenuItemBody instance containing the complete menu item configuration
+
+## Creation Steps
+
+1. **Create Template Class**
+ - Implement the `Template` interface
+ - Define a unique public static IDENTIFIER constant
+ - Create a private static I18nString NAME with translations
+ - Declare a private static MenuItemBody TEMPLATE field
+
+2. **Build Template Configuration**
+ - Implement a private static `buildTemplate()` method
+ - Instantiate MenuItemBody and configure its properties
+ - Create and configure the appropriate view body (CaseViewBody, TaskViewBody, ...)
+ - Set up FilterBody for data filtering requirements
+ - Configure chained views if needed (e.g., TaskViewBody within CaseViewBody)
+ - Wire all components together through setter methods
+
+3. **Implement Interface Methods**
+ - Return IDENTIFIER from `getIdentifier()`
+ - Return NAME from `getName()`
+ - Return TEMPLATE from `getTemplate()`
+
+4. **Register Template**
+ - Add the template to the `MenuItemTemplateHolder.templates` map
+ - Use the template's IDENTIFIER as the key
+ - Instantiate the template class as the value
+
+## Best Practices
+
+- Keep identifiers lowercase with underscores for consistency
+- Provide translations for all supported languages in the NAME field
+- Build template configuration statically to ensure immutability
+- Ensure all required view and filter configurations are properly initialized
+- Use descriptive identifiers that reflect the template's purpose
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleCaseViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleCaseViewTemplate.java
new file mode 100644
index 00000000000..59a99ffd44d
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleCaseViewTemplate.java
@@ -0,0 +1,42 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.CaseViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class SimpleCaseViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "simple_case_view";
+
+ private static final I18nString NAME = new I18nString("Simple case view",
+ Map.of("sk", "Zobrazenie prípadov", "de", "Fallansicht"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(false);
+
+ CaseViewBody caseViewBody = new CaseViewBody();
+ caseViewBody.setFilterBody(Template.defaultCaseFilterBody());
+ menuItemBody.setView(caseViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleTaskViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleTaskViewTemplate.java
new file mode 100644
index 00000000000..e636d1fc466
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SimpleTaskViewTemplate.java
@@ -0,0 +1,42 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.TaskViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class SimpleTaskViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "simple_task_view";
+
+ private static final I18nString NAME = new I18nString("Simple task view",
+ Map.of("sk", "Zobrazenie úloh", "de", "Aufgabenansicht"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(false);
+
+ TaskViewBody taskViewBody = new TaskViewBody();
+ taskViewBody.setFilterBody(Template.defaultTaskFilterBody());
+ menuItemBody.setView(taskViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/SingleTaskViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SingleTaskViewTemplate.java
new file mode 100644
index 00000000000..aa77e986bff
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/SingleTaskViewTemplate.java
@@ -0,0 +1,42 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.SingleTaskViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class SingleTaskViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "single_task_view";
+
+ private static final I18nString NAME = new I18nString("Single task view",
+ Map.of("sk", "Zobrazenie jednej úlohy", "de", "Anzeige einer Aufgabe"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(false);
+
+ SingleTaskViewBody singleTaskViewBody = new SingleTaskViewBody();
+ singleTaskViewBody.setFilterBody(Template.defaultTaskFilterBody());
+ menuItemBody.setView(singleTaskViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedCaseViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedCaseViewTemplate.java
new file mode 100644
index 00000000000..ecfc1d93f16
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedCaseViewTemplate.java
@@ -0,0 +1,45 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.CaseViewBody;
+import com.netgrif.application.engine.menu.domain.configurations.TaskViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class TabbedCaseViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "tabbed_case_view";
+
+ private static final I18nString NAME = new I18nString("Tabbed case view",
+ Map.of("sk", "Zobrazenie prípadov v záložkách", "de", "Registerkartenansicht für Fälle"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(true);
+
+ CaseViewBody caseViewBody = new CaseViewBody();
+
+ caseViewBody.setFilterBody(Template.defaultCaseFilterBody());
+ caseViewBody.setChainedView(new TaskViewBody());
+ menuItemBody.setView(caseViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTaskViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTaskViewTemplate.java
new file mode 100644
index 00000000000..cc3135c3b27
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTaskViewTemplate.java
@@ -0,0 +1,43 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.TaskViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class TabbedTaskViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "tabbed_task_view";
+
+ private static final I18nString NAME = new I18nString("Tabbed task view",
+ Map.of("sk", "Zobrazenie úloh v záložkách", "de", "Aufgabenansicht in Registerkarten"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(true);
+
+ TaskViewBody taskViewBody = new TaskViewBody();
+
+ taskViewBody.setFilterBody(Template.defaultTaskFilterBody());
+ menuItemBody.setView(taskViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTicketViewTemplate.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTicketViewTemplate.java
new file mode 100644
index 00000000000..4221d963dbf
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/TabbedTicketViewTemplate.java
@@ -0,0 +1,46 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.configurations.SingleTaskViewBody;
+import com.netgrif.application.engine.menu.domain.configurations.TabbedTicketViewBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+
+public class TabbedTicketViewTemplate implements Template {
+
+ public static final String IDENTIFIER = "tabbed_ticket_view";
+
+ private static final I18nString NAME = new I18nString("Tabbed ticket view",
+ Map.of("sk", "Tiketové zobrazenie", "de", "Ticketansicht"));
+
+ private static MenuItemBody buildTemplate() {
+ MenuItemBody menuItemBody = new MenuItemBody();
+ menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
+ menuItemBody.setUseTabbedView(true);
+
+ TabbedTicketViewBody tabbedTicketViewBody = new TabbedTicketViewBody();
+
+ SingleTaskViewBody singleTaskViewBody = new SingleTaskViewBody();
+ singleTaskViewBody.setFilterBody(Template.defaultTaskFilterBody());
+ tabbedTicketViewBody.setChainedView(singleTaskViewBody);
+ menuItemBody.setView(tabbedTicketViewBody);
+
+ return menuItemBody;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return IDENTIFIER;
+ }
+
+ @Override
+ public I18nString getName() {
+ return NAME;
+ }
+
+ @Override
+ public MenuItemBody getTemplate() {
+ return buildTemplate();
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/domain/templates/Template.java b/src/main/java/com/netgrif/application/engine/menu/domain/templates/Template.java
new file mode 100644
index 00000000000..2cd42e6b846
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/domain/templates/Template.java
@@ -0,0 +1,26 @@
+package com.netgrif.application.engine.menu.domain.templates;
+
+import com.netgrif.application.engine.menu.domain.FilterBody;
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
+
+public interface Template {
+ String getIdentifier();
+ I18nString getName();
+ MenuItemBody getTemplate();
+
+ static FilterBody defaultTaskFilterBody() {
+ FilterBody filterBody = new FilterBody();
+ filterBody.setType(FieldType.TASK_FILTER);
+ filterBody.setQuery("*");
+ return filterBody;
+ }
+
+ static FilterBody defaultCaseFilterBody() {
+ FilterBody filterBody = new FilterBody();
+ filterBody.setType(FieldType.CASE_FILTER);
+ filterBody.setQuery("*");
+ return filterBody;
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java b/src/main/java/com/netgrif/application/engine/menu/service/DashboardItemServiceImpl.java
similarity index 97%
rename from src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java
rename to src/main/java/com/netgrif/application/engine/menu/service/DashboardItemServiceImpl.java
index cd8b2c3a09c..20dbb8dbe18 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/DashboardItemServiceImpl.java
@@ -1,4 +1,4 @@
-package com.netgrif.application.engine.menu.services;
+package com.netgrif.application.engine.menu.service;
import com.netgrif.application.engine.auth.domain.IUser;
import com.netgrif.application.engine.auth.domain.LoggedUser;
@@ -8,7 +8,7 @@
import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardItemBody;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardItemConstants;
-import com.netgrif.application.engine.menu.services.interfaces.DashboardItemService;
+import com.netgrif.application.engine.menu.service.interfaces.DashboardItemService;
import com.netgrif.application.engine.menu.utils.MenuItemUtils;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService;
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java b/src/main/java/com/netgrif/application/engine/menu/service/DashboardManagementServiceImpl.java
similarity index 98%
rename from src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
rename to src/main/java/com/netgrif/application/engine/menu/service/DashboardManagementServiceImpl.java
index c35ce0267f8..944270d33e5 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/DashboardManagementServiceImpl.java
@@ -1,4 +1,4 @@
-package com.netgrif.application.engine.menu.services;
+package com.netgrif.application.engine.menu.service;
import com.netgrif.application.engine.auth.domain.IUser;
import com.netgrif.application.engine.auth.domain.LoggedUser;
@@ -9,7 +9,7 @@
import com.netgrif.application.engine.menu.domain.dashboard.DashboardItemConstants;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardManagementBody;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardManagementConstants;
-import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService;
+import com.netgrif.application.engine.menu.service.interfaces.DashboardManagementService;
import com.netgrif.application.engine.menu.utils.MenuItemUtils;
import com.netgrif.application.engine.petrinet.domain.I18nString;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemService.java
similarity index 63%
rename from src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
rename to src/main/java/com/netgrif/application/engine/menu/service/MenuItemService.java
index 23f18825609..062dc9f1cbd 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemService.java
@@ -1,26 +1,23 @@
-package com.netgrif.application.engine.menu.services;
+package com.netgrif.application.engine.menu.service;
import com.netgrif.application.engine.auth.domain.IUser;
import com.netgrif.application.engine.auth.domain.LoggedUser;
import com.netgrif.application.engine.auth.service.interfaces.IUserService;
import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService;
import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest;
-import com.netgrif.application.engine.menu.domain.FilterBody;
-import com.netgrif.application.engine.menu.domain.MenuItemBody;
-import com.netgrif.application.engine.menu.domain.MenuItemConstants;
-import com.netgrif.application.engine.menu.domain.ToDataSetOutcome;
+import com.netgrif.application.engine.menu.domain.*;
import com.netgrif.application.engine.menu.domain.configurations.ViewBody;
import com.netgrif.application.engine.menu.domain.configurations.ViewConstants;
-import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService;
+import com.netgrif.application.engine.menu.domain.templates.Template;
+import com.netgrif.application.engine.menu.service.interfaces.IMenuItemService;
import com.netgrif.application.engine.menu.utils.MenuItemUtils;
-import com.netgrif.application.engine.petrinet.domain.I18nString;
-import com.netgrif.application.engine.petrinet.domain.UriContentType;
-import com.netgrif.application.engine.petrinet.domain.UriNode;
+import com.netgrif.application.engine.petrinet.domain.*;
import com.netgrif.application.engine.petrinet.domain.dataset.FieldType;
+import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
+import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService;
+import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService;
import com.netgrif.application.engine.petrinet.service.interfaces.IUriService;
-import com.netgrif.application.engine.startup.DefaultFiltersRunner;
-import com.netgrif.application.engine.startup.FilterRunner;
import com.netgrif.application.engine.startup.ImportHelper;
import com.netgrif.application.engine.workflow.domain.Case;
import com.netgrif.application.engine.workflow.domain.Task;
@@ -29,7 +26,13 @@
import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.bson.types.ObjectId;
import org.springframework.data.domain.*;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.index.CompoundIndexDefinition;
+import org.springframework.data.mongodb.core.index.IndexDefinition;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.*;
@@ -44,47 +47,42 @@ public class MenuItemService implements IMenuItemService {
protected final IUserService userService;
protected final IUriService uriService;
protected final IElasticCaseService elasticCaseService;
+ protected final MongoTemplate mongoTemplate;
+ protected final IPetriNetService petriNetService;
+ protected final IProcessRoleService processRoleService;
+
+ protected Boolean existDatabaseIndexes;
protected static final String DEFAULT_FOLDER_ICON = "folder";
+ protected static final String GLOBAL_ROLE = "GLOBAL_ROLE";
+ protected static final Map CUSTOM_MENU_ITEM_INDEXES = Map.of(
+ String.format("dataSet.%s.value", MenuItemConstants.FIELD_IDENTIFIER), MenuItemConstants.IDENTIFIER_INDEX_NAME,
+ String.format("dataSet.%s.value", MenuItemConstants.FIELD_NODE_PATH), MenuItemConstants.NODE_PATH_INDEX_NAME
+ );
- /**
- * Creates new filter case
- *
- * @param body filter data used for creation
- *
- * @return initialized filter case instance with the provided data
- * */
- @Override
- public Case createFilter(FilterBody body) throws TransitionNotExecutableException {
- IUser loggedUser = userService.getLoggedOrSystem();
- Case filterCase = createCase(FilterRunner.FILTER_PETRI_NET_IDENTIFIER, body.getTitle().getDefaultValue(), loggedUser.transformToLoggedUser());
- filterCase.setIcon(body.getIcon());
- filterCase = workflowService.save(filterCase);
- ToDataSetOutcome dataSetOutcome = body.toDataSet();
- filterCase = setDataWithExecute(filterCase, DefaultFiltersRunner.AUTO_CREATE_TRANSITION, dataSetOutcome.getDataSet());
- log.trace("Created filter case [{}][{}]", filterCase.getStringId(), body.getTitle().getDefaultValue());
- return filterCase;
- }
/**
- * Updates existing filter case
+ * Ensures custom MongoDB compound indexes for menu items are created on the Case collection.
+ * Creates background indexes combining processIdentifier with menu item identifier
+ * and node path fields to optimize menu item queries.
*
- * @param filterCase filter to be updated
- * @param body data values used for update
- *
- * @return updated filter case instance
- * */
+ * @see #CUSTOM_MENU_ITEM_INDEXES
+ */
@Override
- public Case updateFilter(Case filterCase, FilterBody body) {
- filterCase.setIcon(body.getIcon());
- filterCase = workflowService.save(filterCase);
- ToDataSetOutcome dataSetOutcome = body.toDataSet();
- filterCase = setData(filterCase, DefaultFiltersRunner.DETAILS_TRANSITION, dataSetOutcome.getDataSet());
- log.trace("Updated filter case [{}][{}]", filterCase.getStringId(), body.getTitle().getDefaultValue());
- return filterCase;
+ public void ensureDatabaseIndexes() {
+ log.info("Ensuring Mongo database menu item indexes");
+ CUSTOM_MENU_ITEM_INDEXES.forEach( (indexKey, indexName) -> {
+ org.bson.Document keys = new org.bson.Document()
+ .append("processIdentifier", 1)
+ .append(indexKey, 1);
+ IndexDefinition index = new CompoundIndexDefinition(keys)
+ .named(indexName)
+ .background();
+ mongoTemplate.indexOps(Case.class).ensureIndex(index);
+ });
+ existDatabaseIndexes = Boolean.TRUE;
}
-
/**
* Creates menu item case and it's configuration cases
*
@@ -96,12 +94,13 @@ public Case updateFilter(Case filterCase, FilterBody body) {
* */
@Override
public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
+ validateMenuItemBody(body);
+
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));
+ if (existsMenuItem(body.getIdentifier())) {
+ throw new IllegalArgumentException(String.format("Menu item identifier %s is not unique!", body.getIdentifier()));
}
Case parentItemCase = getOrCreateFolderItem(body.getUri());
@@ -109,47 +108,44 @@ public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableExce
if (newName == null) {
newName = new I18nString(body.getIdentifier());
}
- Case menuItemCase = createCase(FilterRunner.MENU_NET_IDENTIFIER, newName.getDefaultValue(),
+ Case menuItemCase = createCase(MenuItemConstants.PROCESS_IDENTIFIER, newName.getDefaultValue(),
loggedUser.transformToLoggedUser());
menuItemCase.setUriNodeId(uriService.findByUri(body.getUri()).getStringId());
menuItemCase = workflowService.save(menuItemCase);
parentItemCase = appendChildCaseIdAndSave(parentItemCase, menuItemCase.getStringId());
- String nodePath = createNodePath(body.getUri(), sanitizedIdentifier);
+ String nodePath = createNodePath(body.getUri(), body.getIdentifier());
uriService.getOrCreate(nodePath, UriContentType.CASE);
Case viewCase = null;
if (body.hasView()) {
- viewCase = createView(body.getView());
+ viewCase = createView(body.getView(), body.isUseTabbedView());
}
ToDataSetOutcome dataSetOutcome = body.toDataSet(parentItemCase.getStringId(), nodePath, viewCase);
- menuItemCase = setDataWithExecute(menuItemCase, MenuItemConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
+ menuItemCase = setDataWithExecute(menuItemCase, MenuItemConstants.TRANS_SYS_INIT_ID, dataSetOutcome.getDataSet());
log.debug("Created menu item case [{}] with identifier [{}].", menuItemCase.getStringId(), body.getIdentifier());
return menuItemCase;
}
/**
- * Updates menu item case and it's configuration cases
+ * Updates menu item case and it's configuration cases (recreates)
*
* @param itemCase menu item case to be updated
* @param body data used for update
*
- * @return updated menu item case (configuration cases are updated, but not returned)
+ * @return recreated menu item case (configuration cases are recreated, but not returned)
* */
@Override
public Case updateMenuItem(Case itemCase, MenuItemBody body) throws TransitionNotExecutableException {
- log.debug("Update of menu item case with identifier [{}] started.", body.getIdentifier());
- String actualUriNodeId = uriService.findByUri(body.getUri()).getStringId();
- if (!itemCase.getUriNodeId().equals(actualUriNodeId)) {
- itemCase.setUriNodeId(actualUriNodeId);
- itemCase = workflowService.save(itemCase);
+ validateMenuItemBody(body);
+ if (itemCase == null) {
+ throw new IllegalArgumentException("Menu item case is null. Cannot update");
}
- Case viewCase = findView(itemCase);
- viewCase = handleView(viewCase, body.getView());
- ToDataSetOutcome dataSetOutcome = body.toDataSet(viewCase);
- itemCase = setData(itemCase, MenuItemConstants.TRANS_SYNC_ID, dataSetOutcome.getDataSet());
+ log.debug("Update of menu item case with identifier [{}] started.", body.getIdentifier());
+ workflowService.deleteCase(itemCase);
+ itemCase = createMenuItem(body);
log.debug("Updated menu item case [{}] with identifier [{}].", itemCase.getStringId(), body.getIdentifier());
return itemCase;
}
@@ -164,6 +160,9 @@ public Case updateMenuItem(Case itemCase, MenuItemBody body) throws TransitionNo
* */
@Override
public Case createOrUpdateMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
+ if (body == null) {
+ throw new IllegalArgumentException("Menu item body cannot be null");
+ }
Case itemCase = findMenuItem(MenuItemUtils.sanitize(body.getIdentifier()));
if (itemCase != null) {
return updateMenuItem(itemCase, body);
@@ -182,10 +181,14 @@ public Case createOrUpdateMenuItem(MenuItemBody body) throws TransitionNotExecut
* */
@Override
public Case createOrIgnoreMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
- Case itemCase = findMenuItem(body.getIdentifier());
+ if (body == null) {
+ throw new IllegalArgumentException("Menu item body cannot be null");
+ }
+ String sanitizedIdentifier = MenuItemUtils.sanitize(body.getIdentifier());
+ Case itemCase = findMenuItem(sanitizedIdentifier);
if (itemCase != null) {
log.debug("Ignored creation or update of menu item case [{}] with identifier [{}].", itemCase.getStringId(),
- body.getIdentifier());
+ sanitizedIdentifier);
return itemCase;
} else {
return createMenuItem(body);
@@ -201,9 +204,17 @@ public Case createOrIgnoreMenuItem(MenuItemBody body) throws TransitionNotExecut
* */
@Override
public Case findMenuItem(String identifier) {
- String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
- FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_IDENTIFIER, identifier);
- return findCase(FilterRunner.MENU_NET_IDENTIFIER, query);
+ Query query = Query.query(
+ Criteria.where("processIdentifier").is(MenuItemConstants.PROCESS_IDENTIFIER)
+ .and(String.format("dataSet.%s.value", MenuItemConstants.FIELD_IDENTIFIER)).is(identifier)
+ );
+ if (existDatabaseIndexes == null || !existDatabaseIndexes) {
+ ensureDatabaseIndexes();
+ }
+ query.withHint(MenuItemConstants.IDENTIFIER_INDEX_NAME);
+ List caseAsList = mongoTemplate.find(query, Case.class);
+ Optional caseOptional = caseAsList.stream().findFirst();
+ return caseOptional.map(aCase -> workflowService.findOne(aCase.getStringId())).orElse(null);
}
/**
@@ -218,8 +229,8 @@ public Case findMenuItem(String identifier) {
public Case findMenuItem(String uri, String name) {
UriNode uriNode = uriService.findByUri(uri);
String query = String.format("processIdentifier:%s AND title.keyword:\"%s\" AND uriNodeId:\"%s\"",
- FilterRunner.MENU_NET_IDENTIFIER, name, uriNode.getStringId());
- return findCase(FilterRunner.MENU_NET_IDENTIFIER, query);
+ MenuItemConstants.PROCESS_IDENTIFIER, name, uriNode.getStringId());
+ return findCase(MenuItemConstants.PROCESS_IDENTIFIER, query);
}
/**
@@ -231,9 +242,20 @@ public Case findMenuItem(String uri, String name) {
* */
@Override
public Case findFolderCase(UriNode node) {
- String query = String.format("processIdentifier:%s AND dataSet.%s.textValue.keyword:\"%s\"",
- FilterRunner.MENU_NET_IDENTIFIER, MenuItemConstants.FIELD_NODE_PATH, node.getUriPath());
- return findCase(FilterRunner.MENU_NET_IDENTIFIER, query);
+ if (node == null) {
+ throw new IllegalArgumentException("Node cannot be null");
+ }
+ Query query = Query.query(
+ Criteria.where("processIdentifier").is(MenuItemConstants.PROCESS_IDENTIFIER)
+ .and(String.format("dataSet.%s.value", MenuItemConstants.FIELD_NODE_PATH)).is(node.getUriPath())
+ );
+ if (existDatabaseIndexes == null || !existDatabaseIndexes) {
+ ensureDatabaseIndexes();
+ }
+ query.withHint(MenuItemConstants.NODE_PATH_INDEX_NAME);
+ List caseAsList = mongoTemplate.find(query, Case.class);
+ Optional caseOptional = caseAsList.stream().findFirst();
+ return caseOptional.map(aCase -> workflowService.findOne(aCase.getStringId())).orElse(null);
}
/**
@@ -245,9 +267,7 @@ public Case findFolderCase(UriNode node) {
* */
@Override
public boolean existsMenuItem(String identifier) {
- 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;
+ return findMenuItem(identifier) != null;
}
/**
@@ -262,20 +282,28 @@ public boolean existsMenuItem(String identifier) {
* */
@Override
public void moveItem(Case itemCase, String destUri) throws TransitionNotExecutableException {
+ if (destUri == null) {
+ throw new IllegalArgumentException("Destination path cannot be null");
+ }
+ if (itemCase == null) {
+ throw new IllegalArgumentException("Item case cannot be null");
+ }
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 casesToSave = new ArrayList<>();
- List parentIdList = MenuItemUtils.getCaseIdsFromCaseRef(itemCase, MenuItemConstants.FIELD_PARENT_ID);
- if (parentIdList != null && !parentIdList.isEmpty()) {
- Case oldParent = removeChildItemFromParent(parentIdList.get(0), itemCase);
- casesToSave.add(oldParent);
- }
+ List oldParentIdAsList = MenuItemUtils.getCaseIdsFromCaseRef(itemCase, MenuItemConstants.FIELD_PARENT_ID);
UriNode destNode = uriService.getOrCreate(destUri, UriContentType.CASE);
Case newParent = getOrCreateFolderItem(destNode.getUriPath());
+
+ if (oldParentIdAsList != null && !oldParentIdAsList.isEmpty()) {
+ Case oldParent = removeChildItemFromParent(oldParentIdAsList.get(0), itemCase);
+ casesToSave.add(oldParent);
+ }
+
if (newParent != null) {
itemCase.getDataField(MenuItemConstants.FIELD_PARENT_ID).setValue(List.of(newParent.getStringId()));
appendChildCaseIdInMemory(newParent, itemCase.getStringId());
@@ -336,7 +364,7 @@ public Case duplicateItem(Case originItem, I18nString newTitle, String newIdenti
duplicatedViewCase = duplicateView(originViewCase);
}
- Case duplicated = createCase(FilterRunner.MENU_NET_IDENTIFIER, newTitle.getDefaultValue(),
+ Case duplicated = createCase(MenuItemConstants.PROCESS_IDENTIFIER, newTitle.getDefaultValue(),
userService.getLoggedOrSystem().transformToLoggedUser());
duplicated.setUriNodeId(originItem.getUriNodeId());
duplicated.setDataSet(originItem.getDataSet());
@@ -365,7 +393,7 @@ public Case duplicateItem(Case originItem, I18nString newTitle, String newIdenti
addConfigurationIntoDataSet(duplicatedViewCase, dataSet);
}
- setDataWithExecute(duplicated, MenuItemConstants.TRANS_INIT_ID, dataSet);
+ setDataWithExecute(duplicated, MenuItemConstants.TRANS_SYS_INIT_ID, dataSet);
List parentIdAsList = MenuItemUtils.getCaseIdsFromCaseRef(originItem, MenuItemConstants.FIELD_PARENT_ID);
if (parentIdAsList != null && !parentIdAsList.isEmpty()) {
@@ -398,6 +426,137 @@ public Case removeChildItemFromParent(String folderId, Case childItem) {
return workflowService.save(parentFolder);
}
+ /**
+ * Retrieves menu item data groups for the specified case and locale.
+ *
+ * @param caseId identifier of the menu item case
+ * @param locale locale to use for retrieving localized data
+ * @return list of data groups from the menu item case
+ */
+ @Override
+ public List getMenuItemData(String caseId, Locale locale) {
+ Case menuItemCase = workflowService.findOne(caseId);
+ String taskId = MenuItemUtils.findTaskIdInCase(menuItemCase, MenuItemConstants.TRANS_ALL_MENU_DATA);
+ return dataService.getDataGroups(taskId, locale).getData();
+ }
+
+ /**
+ * Handles the application of a configuration template to a menu item case.
+ *
+ * This method retrieves the selected configuration template from the menu item case,
+ * loads the corresponding template definition, and applies it by creating or updating
+ * the associated view configuration. If no template is selected, the method returns
+ * without making any changes.
+ *
+ *
+ * @param menuItemCase the menu item case to which the configuration template should be applied
+ * @return a ConfigurationTemplateOutcome containing the dataSet outcome from applying the template,
+ * or an empty outcome if no template was selected
+ * @throws TransitionNotExecutableException if the workflow transition required for applying the template configuration cannot be executed
+ * @throws IllegalArgumentException if the selected template identifier does not correspond to any registered template
+ */
+ @Override
+ public ConfigurationTemplateOutcome handleConfigurationTemplate(Case menuItemCase) throws TransitionNotExecutableException {
+ String selectedTemplate = (String) menuItemCase.getFieldValue(MenuItemConstants.FIELD_CONFIGURATION_TEMPLATES);
+ if (selectedTemplate == null || selectedTemplate.isEmpty()) {
+ return new ConfigurationTemplateOutcome();
+ }
+
+ String menuItemIdentifier = (String) menuItemCase.getFieldValue(MenuItemConstants.FIELD_IDENTIFIER);
+ log.debug("Handling configuration template selection for menu item: [{}, {}] and configuration template: {}",
+ menuItemCase.getStringId(), menuItemIdentifier, selectedTemplate);
+ Optional menuItemBodyOpt = MenuItemTemplateHolder.get(selectedTemplate);
+ if (menuItemBodyOpt.isEmpty()) {
+ throw new IllegalArgumentException(String.format("No configuration template found with name: %s", selectedTemplate));
+ }
+
+ MenuItemBody menuItemBody = menuItemBodyOpt.get();
+ Case viewCase = null;
+ if (menuItemBody.hasView()) {
+ viewCase = createView(menuItemBody.getView(), menuItemBody.isUseTabbedView());
+ }
+ ToDataSetOutcome dataSetOutcome = menuItemBody.toDataSetByConfigTemplate(viewCase);
+ log.debug("For menu item: [{}. {}] was used configuration template: {}", menuItemCase.getStringId(),
+ menuItemIdentifier, selectedTemplate);
+ return new ConfigurationTemplateOutcome(dataSetOutcome);
+ }
+
+ @Override
+ public Map collectRoles(List roles) {
+ // todo rework authorization
+ Map roleMap = new HashMap<>();
+ for (ProcessRole role : roles) {
+ String key;
+ I18nString displayName;
+
+ if (role.isGlobal()) {
+ key = role.getImportId() + ":" + GLOBAL_ROLE;
+ displayName = new I18nString(role.getName() + " (🌍 Global role)");
+ } else {
+ PetriNet net = petriNetService.get(new ObjectId(role.getNetId()));
+ key = role.getImportId() + ":" + net.getIdentifier();
+ displayName = new I18nString(role.getName() + " (" + net.getTitle() + ")");
+ }
+
+ roleMap.put(key, displayName);
+ }
+ return roleMap;
+ }
+
+ @Override
+ public Map collectRoles(Map roles) {
+ // todo rework authorization
+ Map temp = new HashMap<>();
+ Map result = new HashMap<>();
+
+ for (Map.Entry entry : roles.entrySet()) {
+ if (GLOBAL_ROLE.equals(entry.getValue())) {
+ Set findGlobalRole = processRoleService.findAllByImportId(ProcessRole.GLOBAL + entry.getKey());
+ if (findGlobalRole == null || findGlobalRole.isEmpty()) {
+ continue;
+ }
+ Optional roleOpt = findGlobalRole.stream()
+ .filter(ProcessRole::isGlobal)
+ .findFirst();
+ if (roleOpt.isEmpty()) {
+ continue;
+ }
+ result.put(roleOpt.get().getImportId() + ":" + GLOBAL_ROLE,
+ new I18nString(roleOpt.get().getName() + " (🌍 Global role)"));
+ } else {
+ if (!temp.containsKey(entry.getValue())) {
+ temp.put(entry.getValue(), petriNetService.getNewestVersionByIdentifier(entry.getValue()));
+ }
+ PetriNet net = temp.get(entry.getValue());
+ Optional roleOpt = net.getRoles().values().stream()
+ .filter(r -> r.getImportId().equals(entry.getKey()))
+ .findFirst();
+ roleOpt.ifPresent(processRole -> result.put(processRole.getImportId() + ":" + net.getIdentifier(),
+ new I18nString(processRole.getName() + " (" + net.getTitle() + ")")));
+ }
+ }
+
+ return result;
+ }
+
+ protected void validateMenuItemBody(MenuItemBody body) {
+ if (body == null) {
+ throw new IllegalArgumentException("Input data cannot be null");
+ }
+ if (body.getIdentifier() == null) {
+ throw new IllegalArgumentException("Identifier cannot be null");
+ }
+ if (body.getUri() == null || body.getUri().isBlank()) {
+ throw new IllegalArgumentException("Uri cannot be null");
+ } else {
+ body.setUri(MenuItemUtils.sanitizeUriSegments(body.getUri(), uriService));
+ List uriSegments = List.of(body.getUri().split(uriService.getUriSeparator()));
+ if (uriSegments.contains(body.getIdentifier())) {
+ throw new IllegalArgumentException("Uri cannot contain this identifier");
+ }
+ }
+ }
+
protected Case findCase(String processIdentifier, String query) {
CaseSearchRequest request = CaseSearchRequest.builder()
.process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier)))
@@ -409,15 +568,6 @@ protected Case findCase(String processIdentifier, String query) {
return resultPage.hasContent() ? resultPage.getContent().get(0) : null;
}
- protected long countCases(String processIdentifier, String query) {
- CaseSearchRequest request = CaseSearchRequest.builder()
- .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier)))
- .query(query)
- .build();
- return elasticCaseService.count(List.of(request), userService.getLoggedOrSystem().transformToLoggedUser(),
- Locale.getDefault(), false);
- }
-
protected Case duplicateView(Case viewCase) throws TransitionNotExecutableException {
Case duplicatedAssociatedViewCase = null;
if (MenuItemUtils.hasView(viewCase)) {
@@ -436,60 +586,20 @@ protected Case duplicateView(Case viewCase) throws TransitionNotExecutableExcept
addConfigurationIntoDataSet(duplicatedAssociatedViewCase, dataSet);
}
- return setDataWithExecute(duplicatedViewCase, MenuItemConstants.TRANS_INIT_ID, dataSet);
+ return setDataWithExecute(duplicatedViewCase, ViewConstants.TRANS_INIT_ID, dataSet);
}
- protected Case findView(Case itemOrViewCase) {
- return findCaseInCaseRef(itemOrViewCase, MenuItemConstants.FIELD_VIEW_CONFIGURATION_ID);
- }
-
- protected Case findFilter(Case viewCase) {
- return findCaseInCaseRef(viewCase, ViewConstants.FIELD_VIEW_FILTER_CASE);
- }
-
- protected Case findCaseInCaseRef(Case useCase, String caseRefId) {
- try {
- String caseId = MenuItemUtils.getCaseIdFromCaseRef(useCase, caseRefId);
- return workflowService.findOne(caseId);
- } catch (IllegalArgumentException | NullPointerException ignore) {
- return null;
- }
- }
-
- protected Case handleView(Case existingViewCase, ViewBody body) throws TransitionNotExecutableException {
- if (mustUpdateView(existingViewCase, body)) {
- return updateView(existingViewCase, body);
- } else if (mustCreateView(existingViewCase, body)) {
- return createView(body);
- } else if (mustRemoveView(existingViewCase, body)) {
- removeView(existingViewCase);
- return null;
- } else if (mustRemoveAndCreateView(existingViewCase, body)) {
- removeView(existingViewCase);
- return createView(body);
- } else {
- return null;
- }
- }
-
- protected Case createView(ViewBody body) throws TransitionNotExecutableException {
+ protected Case createView(ViewBody body, boolean isTabbed) throws TransitionNotExecutableException {
IUser loggedUser = userService.getLoggedOrSystem();
Case viewCase = createCase(body.getViewProcessIdentifier(), body.getViewProcessIdentifier(),
- loggedUser.transformToLoggedUser());
+ loggedUser.transformToLoggedUser(), isTabbed);
Case associatedViewCase = null;
if (body.hasAssociatedView()) {
- associatedViewCase = createView(body.getAssociatedViewBody());
- }
- Case filterCase = null;
- if (body.getFilterBody() != null) {
- if (body.getFilterBody().getFilter() != null) {
- filterCase = body.getFilterBody().getFilter();
- } else {
- filterCase = createFilter(body.getFilterBody());
- }
+ associatedViewCase = createView(body.getAssociatedViewBody(), isTabbed);
}
- ToDataSetOutcome dataSetOutcome = body.toDataSet(associatedViewCase, filterCase);
+
+ ToDataSetOutcome dataSetOutcome = body.toDataSet(associatedViewCase);
viewCase = setDataWithExecute(viewCase, ViewConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
log.trace("Created configuration view case [{}] of identifier [{}]", viewCase.getStringId(),
@@ -497,60 +607,6 @@ protected Case createView(ViewBody body) throws TransitionNotExecutableException
return viewCase;
}
- protected Case updateView(Case viewCase, ViewBody body) throws TransitionNotExecutableException {
- Case filterCase = findFilter(viewCase);
- filterCase = handleFilter(filterCase, body.getFilterBody());
-
- Case associatedViewCase = findView(viewCase);
- associatedViewCase = handleView(associatedViewCase, body.getAssociatedViewBody());
-
- ToDataSetOutcome outcome = body.toDataSet(associatedViewCase, filterCase);
- viewCase = setData(viewCase, ViewConstants.TRANS_SYNC_ID, outcome.getDataSet());
-
- log.trace("Updated configuration view case [{}] of identifier [{}]", viewCase.getStringId(),
- body.getViewProcessIdentifier());
- return viewCase;
- }
-
- protected void removeView(Case viewCase) {
- workflowService.deleteCase(viewCase);
- log.trace("Removed configuration view case [{}].", viewCase.getStringId());
- }
-
- protected Case handleFilter(Case filterCase, FilterBody body) throws TransitionNotExecutableException {
- if (mustCreateFilter(filterCase, body)) {
- return createFilter(body);
- } else if (mustUpdateFilter(filterCase, body)) {
- return updateFilter(filterCase, body);
- } else {
- return filterCase;
- }
- }
-
- protected boolean mustUpdateView(Case useCase, ViewBody body) {
- return body != null && useCase != null && useCase.getProcessIdentifier().equals(body.getViewProcessIdentifier());
- }
-
- protected boolean mustRemoveAndCreateView(Case useCase, ViewBody body) {
- return body != null && useCase != null && !useCase.getProcessIdentifier().equals(body.getViewProcessIdentifier());
- }
-
- protected boolean mustRemoveView(Case useCase, ViewBody body) {
- return body == null && useCase != null;
- }
-
- protected boolean mustCreateView(Case useCase, ViewBody body) {
- return body != null && useCase == null;
- }
-
- protected boolean mustCreateFilter(Case filterCase, FilterBody body) {
- return filterCase == null && body != null;
- }
-
- protected boolean mustUpdateFilter(Case filterCase, FilterBody body) {
- return filterCase != null && body != null;
- }
-
protected List updateNodeInChildrenFoldersRecursive(Case parentFolder) {
List childItemIds = MenuItemUtils.getCaseIdsFromCaseRef(parentFolder, MenuItemConstants.FIELD_CHILD_ITEM_IDS);
if (childItemIds == null || childItemIds.isEmpty()) {
@@ -575,6 +631,9 @@ protected List updateNodeInChildrenFoldersRecursive(Case parentFolder) {
protected void resolveAndHandleNewNodePath(Case folderItem, String destUri) {
String newNodePath = resolveNewNodePath(folderItem, destUri);
+ if (newNodePath.startsWith("//")) {
+ newNodePath = newNodePath.replace("//", uriService.getUriSeparator());
+ }
UriNode newNode = uriService.getOrCreate(newNodePath, UriContentType.CASE);
folderItem.getDataField(MenuItemConstants.FIELD_NODE_PATH).setValue(newNode.getUriPath());
}
@@ -611,7 +670,7 @@ protected Case getOrCreateFolderRecursive(UriNode node, MenuItemBody body, Case
return folderCase;
}
- folderCase = createCase(FilterRunner.MENU_NET_IDENTIFIER, body.getMenuName().getDefaultValue(),
+ folderCase = createCase(MenuItemConstants.PROCESS_IDENTIFIER, body.getMenuName().getDefaultValue(),
loggedUser.transformToLoggedUser());
folderCase.setUriNodeId(node.getParentId());
folderCase = workflowService.save(folderCase);
@@ -628,7 +687,7 @@ protected Case getOrCreateFolderRecursive(UriNode node, MenuItemBody body, Case
Case parentFolderCase = getOrCreateFolderRecursive(parentNode, body, folderCase);
dataSetOutcome.putDataSetEntry(MenuItemConstants.FIELD_PARENT_ID, FieldType.CASE_REF, List.of(parentFolderCase.getStringId()));
}
- folderCase = setDataWithExecute(folderCase, MenuItemConstants.TRANS_INIT_ID, dataSetOutcome.getDataSet());
+ folderCase = setDataWithExecute(folderCase, MenuItemConstants.TRANS_SYS_INIT_ID, dataSetOutcome.getDataSet());
log.trace("Created folder menu item [{}] with identifier [{}]", folderCase.getStringId(), body.getIdentifier());
return folderCase;
@@ -671,12 +730,20 @@ protected void addConfigurationIntoDataSet(Case configurationCase, Map> dataSet) {
String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId);
return setData(taskId, dataSet);
diff --git a/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java
new file mode 100644
index 00000000000..48f27d931ac
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/service/MenuItemTemplateHolder.java
@@ -0,0 +1,121 @@
+package com.netgrif.application.engine.menu.service;
+
+import com.netgrif.application.engine.menu.domain.MenuItemBody;
+import com.netgrif.application.engine.menu.domain.templates.*;
+import com.netgrif.application.engine.menu.utils.MenuItemUtils;
+import com.netgrif.application.engine.petrinet.domain.I18nString;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Holder class that manages predefined menu item templates.
+ *
+ * This class provides a central registry for menu item templates that can be used
+ * throughout the application. Templates are identified by unique string identifiers
+ * and can be retrieved or transformed into user-selectable options.
+ *
+ */
+public class MenuItemTemplateHolder {
+ /**
+ * Map of available menu item templates indexed by their unique identifiers.
+ *
+ * Each entry maps a template identifier to its corresponding Template instance.
+ * This map is immutable and initialized with predefined templates.
+ * The key is the template identifier (String), and the value is the Template instance.
+ *
+ */
+ private final static Map templates = Map.of(
+ TabbedCaseViewTemplate.IDENTIFIER, new TabbedCaseViewTemplate(),
+ TabbedTaskViewTemplate.IDENTIFIER, new TabbedTaskViewTemplate(),
+ SimpleCaseViewTemplate.IDENTIFIER, new SimpleCaseViewTemplate(),
+ SimpleTaskViewTemplate.IDENTIFIER, new SimpleTaskViewTemplate(),
+ SingleTaskViewTemplate.IDENTIFIER, new SingleTaskViewTemplate(),
+ TabbedTicketViewTemplate.IDENTIFIER, new TabbedTicketViewTemplate(),
+ CustomViewTemplate.IDENTIFIER, new CustomViewTemplate()
+ );
+
+
+ /**
+ * Retrieves a template by its unique identifier.
+ *
+ * This method looks up and returns the Template instance associated with the
+ * provided identifier from the templates registry.
+ *
+ *
+ * @param identifier the unique identifier of the template to retrieve
+ * @return an Optional containing the MenuItemBody instance if found, or empty Optional if no template exists for the given identifier
+ */
+ public static Optional get(String identifier) {
+ return Optional.ofNullable(templates.get(identifier)).map(Template::getTemplate);
+ }
+
+ /**
+ * Retrieves a template by its unique identifier and configures it with the provided URI and menu item identifier.
+ *
+ * This method looks up the Template instance associated with the provided identifier from the templates registry,
+ * and then configures the template's body with the specified URI and menu item identifier.
+ *
+ *
+ * @param identifier the unique identifier of the template to retrieve
+ * @param uri the URI to set on the template's body
+ * @param menuItemIdentifier the menu item identifier to set on the template's body
+ * @return an Optional containing the configured MenuItemBody instance if found, or empty Optional if no template exists for the given identifier
+ */
+ public static Optional get(String identifier, String uri, String menuItemIdentifier) {
+ return get(identifier).map(body -> {
+ body.setUri(uri);
+ body.setIdentifier(menuItemIdentifier);
+ return body;
+ });
+ }
+
+ /**
+ * Retrieves a template by its unique identifier and configures it with the provided URI and menu name.
+ *
+ * This method looks up the Template instance associated with the provided identifier from the templates registry,
+ * and then configures the template's body with the specified URI and internationalized menu name.
+ * The menu item identifier is automatically generated by sanitizing the default menu name value.
+ * If the default value is null or blank, the first available translation is used instead.
+ *
+ *
+ * @param identifier the unique identifier of the template to retrieve
+ * @param uri the URI to set on the template's body
+ * @param menuName the internationalized menu name to set on the template's body
+ * @return an Optional containing the configured MenuItemBody instance if found, or empty Optional if no template exists for the given identifier
+ * @throws IllegalArgumentException if the menu name has no default value or translations
+ */
+ public static Optional get(String identifier, String uri, I18nString menuName) {
+ return get(identifier).map(body -> {
+ body.setUri(uri);
+ body.setMenuName(menuName);
+ String defaultName = menuName.getDefaultValue();
+ if (defaultName == null || defaultName.isBlank()) {
+ defaultName = menuName.getTranslations().values().stream()
+ .findAny()
+ .orElseThrow(() -> new IllegalArgumentException("Please provide a name for the menu item"));
+ }
+ body.setIdentifier(MenuItemUtils.sanitize(defaultName));
+ return body;
+ });
+ }
+
+ /**
+ * Transforms the available templates into a map of selectable options.
+ *
+ * This method converts the templates map into a format suitable for displaying
+ * as user-selectable options, where the key is the template identifier and the
+ * value is the internationalized name of the template.
+ *
+ *
+ * @return a map where keys are template identifiers and values are internationalized template names
+ */
+ public static Map transformToOptions() {
+ return templates.entrySet().stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> entry.getValue().getName()
+ ));
+ }
+}
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardItemService.java
similarity index 88%
rename from src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java
rename to src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardItemService.java
index 6555ad2c04f..3dd698d53c1 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardItemService.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardItemService.java
@@ -1,4 +1,4 @@
-package com.netgrif.application.engine.menu.services.interfaces;
+package com.netgrif.application.engine.menu.service.interfaces;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardItemBody;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardManagementService.java
similarity index 89%
rename from src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java
rename to src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardManagementService.java
index 01efb79d055..e5765ddbf3b 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/DashboardManagementService.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/DashboardManagementService.java
@@ -1,4 +1,4 @@
-package com.netgrif.application.engine.menu.services.interfaces;
+package com.netgrif.application.engine.menu.service.interfaces;
import com.netgrif.application.engine.menu.domain.dashboard.DashboardManagementBody;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
diff --git a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/IMenuItemService.java
similarity index 64%
rename from src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java
rename to src/main/java/com/netgrif/application/engine/menu/service/interfaces/IMenuItemService.java
index 9de2a7f2308..4a90a0e1043 100644
--- a/src/main/java/com/netgrif/application/engine/menu/services/interfaces/IMenuItemService.java
+++ b/src/main/java/com/netgrif/application/engine/menu/service/interfaces/IMenuItemService.java
@@ -1,21 +1,24 @@
-package com.netgrif.application.engine.menu.services.interfaces;
+package com.netgrif.application.engine.menu.service.interfaces;
-import com.netgrif.application.engine.menu.domain.FilterBody;
+import com.netgrif.application.engine.menu.domain.ConfigurationTemplateOutcome;
import com.netgrif.application.engine.menu.domain.MenuItemBody;
-import com.netgrif.application.engine.menu.domain.MenuItemView;
+import com.netgrif.application.engine.menu.domain.MenuItemViewType;
+import com.netgrif.application.engine.petrinet.domain.DataGroup;
import com.netgrif.application.engine.petrinet.domain.I18nString;
import com.netgrif.application.engine.petrinet.domain.UriNode;
+import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole;
import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException;
import com.netgrif.application.engine.workflow.domain.Case;
import com.netgrif.application.engine.petrinet.domain.dataset.MapOptionsField;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
public interface IMenuItemService {
- Case createFilter(FilterBody body) throws TransitionNotExecutableException;
- Case updateFilter(Case filterCase, FilterBody body);
+ void ensureDatabaseIndexes();
Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException;
Case updateMenuItem(Case itemCase, MenuItemBody body) throws TransitionNotExecutableException;
Case createOrUpdateMenuItem(MenuItemBody body) throws TransitionNotExecutableException;
@@ -27,6 +30,10 @@ public interface IMenuItemService {
void moveItem(Case item, String destUri) throws TransitionNotExecutableException;
Case duplicateItem(Case originItem, I18nString newTitle, String newIdentifier) throws TransitionNotExecutableException;
Case removeChildItemFromParent(String folderId, Case childItem);
+ List getMenuItemData(String caseId, Locale locale);
+ ConfigurationTemplateOutcome handleConfigurationTemplate(Case menuItemCase) throws TransitionNotExecutableException;
+ Map collectRoles(List roles);
+ Map collectRoles(Map roles);
/**
* Gets all tabbed or non-tabbed views
@@ -34,21 +41,21 @@ public interface IMenuItemService {
* @param isTabbed if true, only tabbed views will be returned
* @param isPrimary if true, only views accessible directly from the menu_item will be returned
*
- * @return All available views defined in {@link MenuItemView} in consideration of input value. Views are returned as
+ * @return All available views defined in {@link MenuItemViewType} in consideration of input value. Views are returned as
* options for {@link MapOptionsField}
* */
default Map getAvailableViewsAsOptions(boolean isTabbed, boolean isPrimary) {
- return MenuItemView.findAllByIsTabbedAndIsPrimary(isTabbed, isPrimary).stream()
- .collect(Collectors.toMap(MenuItemView::getIdentifier, MenuItemView::getName));
+ return MenuItemViewType.findAllByIsTabbedAndIsPrimary(isTabbed, isPrimary).stream()
+ .collect(Collectors.toMap(MenuItemViewType::getIdentifier, MenuItemViewType::getName));
}
/**
* Gets all tabbed or non-tabbed views
*
* @param isTabbed if true, only tabbed views will be returned
- * @param viewIdentifier identifier of view (defined in {@link MenuItemView}), which is parent to returned views
+ * @param viewIdentifier identifier of view (defined in {@link MenuItemViewType}), which is parent to returned views
*
- * @return All available views defined in {@link MenuItemView} in consideration of input values. Views are returned as
+ * @return All available views defined in {@link MenuItemViewType} in consideration of input values. Views are returned as
* options for {@link MapOptionsField}
* */
default Map getAvailableViewsAsOptions(boolean isTabbed, String viewIdentifier) {
@@ -56,8 +63,8 @@ default Map getAvailableViewsAsOptions(boolean isTabbed, Str
if (index > 0) {
viewIdentifier = viewIdentifier.substring(0, index);
}
- return MenuItemView.findAllByIsTabbedAndParentIdentifier(isTabbed, viewIdentifier).stream()
- .collect(Collectors.toMap(MenuItemView::getIdentifier, MenuItemView::getName));
+ return MenuItemViewType.findAllByIsTabbedAndParentIdentifier(isTabbed, viewIdentifier).stream()
+ .collect(Collectors.toMap(MenuItemViewType::getIdentifier, MenuItemViewType::getName));
}
}
diff --git a/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java b/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java
index d1fcaf8e590..b7b3107a8b6 100644
--- a/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java
+++ b/src/main/java/com/netgrif/application/engine/menu/utils/MenuItemUtils.java
@@ -1,9 +1,10 @@
package com.netgrif.application.engine.menu.utils;
import com.netgrif.application.engine.menu.domain.MenuItemConstants;
+import com.netgrif.application.engine.petrinet.service.interfaces.IUriService;
import com.netgrif.application.engine.workflow.domain.Case;
import com.netgrif.application.engine.workflow.domain.TaskPair;
-import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService;
+import com.netgrif.application.engine.menu.service.interfaces.IMenuItemService;
import java.text.Normalizer;
import java.util.List;
@@ -29,6 +30,33 @@ public static String sanitize(String input) {
.toLowerCase();
}
+ /**
+ * Sanitizes each segment of a URI path by removing diacritical marks, replacing special characters with
+ * delimiters, and converting to lowercase. The URI is split by the separator defined in the provided
+ * {@link IUriService}, each segment is sanitized individually, and then the segments are concatenated back
+ * together.
+ *
+ * @param uri the URI string to be sanitized
+ * @param uriService the service providing the URI separator configuration
+ *
+ * @return sanitized URI string with all segments processed, or null if input URI is null
+ * */
+ public static String sanitizeUriSegments(String uri, IUriService uriService) {
+ if (uri == null) {
+ return null;
+ }
+ String[] uriSegments = uri.split(uriService.getUriSeparator());
+ if (uriSegments.length == 0) {
+ return uriService.getRoot().getUriPath();
+ }
+ StringBuilder sanitizedUriBuilder = new StringBuilder();
+ for (String uriSegment : uriSegments) {
+ sanitizedUriBuilder.append(uriService.getUriSeparator());
+ sanitizedUriBuilder.append(MenuItemUtils.sanitize(uriSegment));
+ }
+ return sanitizedUriBuilder.toString().replaceAll("//", uriService.getUriSeparator());
+ }
+
/**
* Finds task id in the provided case instance by transition id
*
@@ -64,7 +92,7 @@ public static String findTaskIdInCase(Case useCase, String transId) {
* */
public static boolean isCyclicNodePath(Case folderItem, String destUri) {
String oldNodePath = (String) folderItem.getFieldValue(MenuItemConstants.FIELD_NODE_PATH);
- return destUri.contains(oldNodePath);
+ return oldNodePath != null && destUri.contains(oldNodePath);
}
/**
diff --git a/src/main/java/com/netgrif/application/engine/menu/web/MenuController.java b/src/main/java/com/netgrif/application/engine/menu/web/MenuController.java
new file mode 100644
index 00000000000..070e5e06615
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/web/MenuController.java
@@ -0,0 +1,52 @@
+package com.netgrif.application.engine.menu.web;
+
+import com.netgrif.application.engine.menu.service.interfaces.IMenuItemService;
+import com.netgrif.application.engine.menu.web.responsebodies.MenuItemDataResponse;
+import com.netgrif.application.engine.petrinet.domain.DataGroup;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.hateoas.MediaTypes;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.util.Base64;
+import java.util.List;
+import java.util.Locale;
+
+@Slf4j
+@RestController
+@Tag(name = "Menu")
+@RequiredArgsConstructor
+@RequestMapping("/api/menu")
+public class MenuController {
+
+ private final IMenuItemService menuItemService;
+
+ // todo menu item authorization
+ @Operation(summary = "Get relevant data for the menu item", security = {@SecurityRequirement(name = "BasicAuth")})
+ @GetMapping(value = "/{encodedCaseId}", produces = MediaTypes.HAL_JSON_VALUE)
+ public EntityModel getMenuItemData(@PathVariable("encodedCaseId") String encodedCaseId, Locale locale) {
+ try {
+ String caseId = new String(Base64.getDecoder().decode(encodedCaseId));
+ List dataGroups = menuItemService.getMenuItemData(caseId, locale);
+ return EntityModel.of(new MenuItemDataResponse(dataGroups));
+ } catch (IllegalArgumentException e) {
+ log.warn("Requested with invalid input", e);
+ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Requested with invalid input");
+ } catch (Exception e) {
+ log.error("Getting menu item data failed", e);
+ throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Getting menu item data failed");
+ }
+ }
+
+ // todo search with authorization
+}
+
diff --git a/src/main/java/com/netgrif/application/engine/menu/web/responsebodies/MenuItemDataResponse.java b/src/main/java/com/netgrif/application/engine/menu/web/responsebodies/MenuItemDataResponse.java
new file mode 100644
index 00000000000..57669493c74
--- /dev/null
+++ b/src/main/java/com/netgrif/application/engine/menu/web/responsebodies/MenuItemDataResponse.java
@@ -0,0 +1,17 @@
+package com.netgrif.application.engine.menu.web.responsebodies;
+
+import com.netgrif.application.engine.petrinet.domain.DataGroup;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+@RequiredArgsConstructor
+public class MenuItemDataResponse {
+
+ /**
+ * List of data groups containing menu item data.
+ */
+ @Getter
+ private final List data;
+}
diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java b/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java
index 039f6db8b7d..10e26d1b94b 100644
--- a/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java
+++ b/src/main/java/com/netgrif/application/engine/workflow/domain/Case.java
@@ -104,7 +104,7 @@ public class Case implements Serializable {
@Getter
@Setter
@Transient
- private List immediateData;
+ private List> immediateData;
@Getter
@Setter
@@ -251,9 +251,6 @@ public void populateDataSet(IInitValueExpressionEvaluator initValueExpressionEva
if (field instanceof FieldWithAllowedNets) {
this.dataSet.get(key).setAllowedNets(((FieldWithAllowedNets) field).getAllowedNets());
}
- if (field instanceof FilterField) {
- this.dataSet.get(key).setFilterMetadata(((FilterField) field).getFilterMetadata());
- }
if (field instanceof MapOptionsField && ((MapOptionsField) field).isDynamic()) {
dynamicOptionsFields.add((MapOptionsField) field);
}
diff --git a/src/main/java/com/netgrif/application/engine/workflow/domain/DataField.java b/src/main/java/com/netgrif/application/engine/workflow/domain/DataField.java
index 5734a9b3e93..5a122c2c2b3 100644
--- a/src/main/java/com/netgrif/application/engine/workflow/domain/DataField.java
+++ b/src/main/java/com/netgrif/application/engine/workflow/domain/DataField.java
@@ -43,9 +43,6 @@ public class DataField implements Referencable, Serializable {
@Getter
private List validations;
- @Getter
- private Map filterMetadata;
-
@Getter
@Setter
@JsonIgnore
@@ -115,11 +112,6 @@ public void setAllowedNets(List allowedNets) {
update();
}
- public void setFilterMetadata(Map filterMetadata) {
- this.filterMetadata = filterMetadata;
- update();
- }
-
public void setOptions(Map options) {
setOptions(options, true);
}
diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java b/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java
index 548ee926a2b..77a6cffdf34 100644
--- a/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java
+++ b/src/main/java/com/netgrif/application/engine/workflow/service/DataService.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.netgrif.application.engine.auth.domain.IUser;
import com.netgrif.application.engine.auth.service.interfaces.IUserService;
@@ -291,12 +292,6 @@ public SetDataEventOutcome setData(Task task, ObjectNode values, Map filterMetadata = parseFilterMetadataValue((ObjectNode) entry.getValue(), fieldType);
- if (filterMetadata != null) {
- dataField.setFilterMetadata(filterMetadata);
- changedField.addAttribute("filterMetadata", filterMetadata);
- modified = true;
- }
Map options = parseOptionsNode(entry.getValue(), fieldType);
if (options != null) {
setDataFieldOptions(options, dataField, changedField, fieldType);
@@ -1010,7 +1005,7 @@ private List parseListLongValues(ObjectNode node) {
private List parseAllowedNetsValue(JsonNode jsonNode) {
ObjectNode node = (ObjectNode) jsonNode;
String fieldType = getFieldTypeFromNode(node);
- if (Objects.equals(fieldType, FieldType.CASE_REF.getName()) || Objects.equals(fieldType, FieldType.FILTER.getName())) {
+ if (Objects.equals(fieldType, FieldType.CASE_REF.getName())) {
return parseListStringAllowedNets(node);
}
return null;
@@ -1021,10 +1016,11 @@ private List parseListStringAllowedNets(ObjectNode node) {
}
private List parseListString(ObjectNode node, String attributeKey) {
- ArrayNode arrayNode = (ArrayNode) node.get(attributeKey);
- if (arrayNode == null) {
+ Object objectNode = node.get(attributeKey);
+ if (objectNode == null || objectNode instanceof NullNode) {
return null;
}
+ ArrayNode arrayNode = (ArrayNode) objectNode;
ArrayList list = new ArrayList<>();
arrayNode.forEach(string -> list.add(string.asText()));
return list;
@@ -1053,19 +1049,6 @@ private String getFieldTypeFromNode(ObjectNode node) {
return node.get("type").asText();
}
- private Map parseFilterMetadataValue(ObjectNode node, String fieldType) {
- if (Objects.equals(fieldType, FieldType.FILTER.getName())) {
- JsonNode filterMetadata = node.get("filterMetadata");
- if (filterMetadata == null) {
- return null;
- }
- ObjectMapper mapper = new ObjectMapper();
- return mapper.convertValue(filterMetadata, new TypeReference