Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2486,7 +2486,11 @@ class ActionDelegate {
if (!childrenIds.isEmpty()) {
for (String id : childrenIds) {
UriNode childNode = uriService.findById(id)
options.put(childNode.name, new I18nString(childNode.name))
Case folderCase = menuItemService.findFolderCase(childNode)
if (folderCase != null) {
I18nString name = (I18nString) folderCase.getFieldValue(MenuItemConstants.FIELD_MENU_NAME)
options.put(childNode.name, name)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class MenuItemBody {
private boolean useCustomView = false;
private String customViewSelector;
private boolean isAutoSelect = false;
private boolean isFolder = false;

private boolean useTabbedView = true;
private String tabIcon;
Expand Down Expand Up @@ -109,16 +110,29 @@ public void setTabName(String name) {
}

public void setView(ViewBody viewBody) {
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();
}
if (viewBody == null) {
return;
}
if (this.isFolder) {
throw new IllegalArgumentException("Folder cannot have view");
}
this.view = viewBody;
MenuItemViewType viewType = viewBody.getViewType();
if (viewType.getViewType() == ViewType.ONLY_TABBED) {
this.useTabbedView = true;
} else if (viewType.getViewType() == ViewType.ONLY_UNTABBED) {
this.useTabbedView = false;
}
}

public void setIsFolder(boolean isFolder) {
if (isFolder && this.view != null) {
throw new IllegalArgumentException("Folder cannot have view");
}
this.isFolder = isFolder;
}


/**
* @return true if the menu item contains view
* */
Expand Down Expand Up @@ -187,6 +201,7 @@ public ToDataSetOutcome toDataSet(String parentId, String nodePath, Case viewCas
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.putDataSetEntry(MenuItemConstants.FIELD_IS_FOLDER, FieldType.BOOLEAN, this.isFolder);

outcome = toDataSetWithView(viewCase, outcome);

Expand All @@ -203,6 +218,7 @@ 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);
outcome.putDataSetEntry(MenuItemConstants.FIELD_IS_FOLDER, FieldType.BOOLEAN, this.isFolder);
return toDataSetWithView(viewCase, outcome);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class MenuItemConstants {
public static final String FIELD_PARENT_ID = "parentId";
public static final String FIELD_CHILD_ITEM_IDS = "childItemIds";
public static final String FIELD_HAS_CHILDREN = "hasChildren";
public static final String FIELD_IS_FOLDER = "is_folder";
public static final String FIELD_IDENTIFIER = "menu_item_identifier";
public static final String FIELD_APPEND_MENU_ITEM = "append_menu_item_stringId";
public static final String FIELD_ALLOWED_ROLES = "allowed_roles";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,52 @@
import java.util.Map;
import java.util.stream.Collectors;

import static com.netgrif.application.engine.menu.domain.ViewType.*;


/**
* Here is listed and configured every configuration process available for menu items.
* Here is listed and described every configuration process available for menu items.
* */
@Getter
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),
"case_view", List.of("task_view"), TABBED_AND_UNTABBED, true),
TASK_VIEW(new I18nString("Task view",
Map.of("sk", "Zobrazenie úloh", "de", "Aufgabenansicht")),
"task_view", List.of(), true, true, true),
"task_view", List.of(), TABBED_AND_UNTABBED, 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),
"tabbed_ticket_view", List.of("single_task_view"), ONLY_TABBED, 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);
"single_task_view", List.of(), TABBED_AND_UNTABBED, true);

private final I18nString name;
private final String identifier;

/**
* List of view identifiers of views, that can be associated with the view
* */
private final List<String> allowedAssociatedViews;
private final boolean isTabbed;
private final boolean isUntabbed;

/**
* Specifies whether this view type can be used in tabbed menu items, untabbed menu items, or both.
* This determines the context in which the view can be displayed in the menu structure.
* */
private final ViewType viewType;

/**
* 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;

MenuItemViewType(I18nString name, String identifier, List<String> allowedAssociatedViews, boolean isTabbed,
boolean isUntabbed, boolean isPrimary) {
MenuItemViewType(I18nString name, String identifier, List<String> allowedAssociatedViews, ViewType viewType, boolean isPrimary) {
this.name = name;
this.identifier = identifier;
this.allowedAssociatedViews = allowedAssociatedViews;
this.isTabbed = isTabbed;
this.isUntabbed = isUntabbed;
this.viewType = viewType;
this.isPrimary = isPrimary;
}

Expand All @@ -64,32 +70,29 @@ public static MenuItemViewType fromIdentifier(String identifier) {
}

/**
* Finds all enum values, that are tabbed or non-tabbed
* Finds all enum values, that are / are not primary
*
* @param isTabbed if true, only tabbed values will be returned
* @param isPrimary if true, only views accessible directly from the menu_item will be returned
*
* @return List of views based on {@link #isTabbed}
* @return List of views based on {@link #isPrimary}
* */
public static List<MenuItemViewType> findAllByIsTabbedAndIsPrimary(boolean isTabbed, boolean isPrimary) {
public static List<MenuItemViewType> findAllByIsPrimary(boolean isPrimary) {
return Arrays.stream(MenuItemViewType.values())
.filter(view -> (view.isTabbed == isTabbed || view.isUntabbed != isTabbed) && view.isPrimary == isPrimary)
.filter(view -> view.isPrimary == isPrimary)
.collect(Collectors.toList());
}

/**
* Finds all enum values, that are tabbed or non-tabbed and are defined in parent view as {@link #allowedAssociatedViews}
* Finds all enum values, that are are defined in parent view as {@link #allowedAssociatedViews}
*
* @param isTabbed if true, set of views is reduced to only tabbed views
* @param parentIdentifier identifier of the view, that contains returned views in {@link #allowedAssociatedViews}
*
* @return List of views based on {@link #isTabbed} and {@link #allowedAssociatedViews}
* @return List of views based on {@link #allowedAssociatedViews}
* */
public static List<MenuItemViewType> findAllByIsTabbedAndParentIdentifier(boolean isTabbed, String parentIdentifier) {
public static List<MenuItemViewType> findAllByParentIdentifier(String parentIdentifier) {
MenuItemViewType parentView = fromIdentifier(parentIdentifier);
return Arrays.stream(MenuItemViewType.values())
.filter(view -> (view.isTabbed == isTabbed || view.isUntabbed != isTabbed)
&& parentView.getAllowedAssociatedViews().contains(view.identifier))
.filter(view -> parentView.getAllowedAssociatedViews().contains(view.identifier))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.netgrif.application.engine.menu.domain;

public enum ViewType {
ONLY_TABBED,
ONLY_UNTABBED,
TABBED_AND_UNTABBED
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class CaseViewBody extends ViewBody {
private boolean allowHeaderTableMode = true;
private List<String> headersMode = new ArrayList<>(List.of("sort", "edit", "search"));
private String headersDefaultMode = "sort";
private String headersSortModeActive;
private String headersSortModeDirection = "desc";
private List<String> defaultHeaders;
private boolean headerModeChangeable = true;
private boolean useDefaultHeaders = true;
Expand Down Expand Up @@ -82,6 +84,10 @@ protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
this.headersMode == null ? new ArrayList<>() : this.headersMode);
outcome.putDataSetEntry(CaseViewConstants.FIELD_HEADERS_DEFAULT_MODE, FieldType.ENUMERATION_MAP,
this.headersDefaultMode);
outcome.putDataSetEntry(CaseViewConstants.FIELD_HEADERS_SORT_MODE_ACTIVE, FieldType.TEXT,
this.headersSortModeActive);
outcome.putDataSetEntry(CaseViewConstants.FIELD_HEADERS_SORT_MODE_DIRECTION, FieldType.ENUMERATION_MAP,
this.headersSortModeDirection);
if (this.defaultHeaders != null) {
outcome.putDataSetEntry(CaseViewConstants.FIELD_DEFAULT_HEADERS, FieldType.STRING_COLLECTION,
this.defaultHeaders);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class CaseViewConstants extends ViewConstants {
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_HEADERS_SORT_MODE_ACTIVE = "case_headers_sort_mode_active";
public static final String FIELD_HEADERS_SORT_MODE_DIRECTION = "case_headers_sort_mode_direction";
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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class TaskViewBody extends ViewBody {
private String viewSearchType = "fulltext_advanced";
private List<String> headersMode = new ArrayList<>(List.of("sort", "edit"));
private String headersDefaultMode = "sort";
private String headersSortModeActive;
private String headersSortModeDirection = "desc";
private boolean isHeaderModeChangeable = true;
private boolean allowHeaderTableMode = true;
private boolean useDefaultHeaders = true;
Expand Down Expand Up @@ -71,6 +73,10 @@ protected ToDataSetOutcome toDataSetInternal(ToDataSetOutcome outcome) {
outcome.putDataSetEntry(TaskViewConstants.FIELD_DEFAULT_HEADERS, FieldType.STRING_COLLECTION,
this.defaultHeaders);
}
outcome.putDataSetEntry(TaskViewConstants.FIELD_HEADERS_SORT_MODE_ACTIVE, FieldType.TEXT,
this.headersSortModeActive);
outcome.putDataSetEntry(TaskViewConstants.FIELD_HEADERS_SORT_MODE_DIRECTION, FieldType.ENUMERATION_MAP,
this.headersSortModeDirection);
outcome.putDataSetEntry(TaskViewConstants.FIELD_SHOW_MORE_MENU, FieldType.BOOLEAN,
this.showMoreMenu);
if (this.emptyContentText != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class TaskViewConstants extends ViewConstants {
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_HEADERS_SORT_MODE_ACTIVE = "task_headers_sort_mode_active";
public static final String FIELD_HEADERS_SORT_MODE_DIRECTION = "task_headers_sort_mode_direction";
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";
Expand Down
Original file line number Diff line number Diff line change
@@ -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 FolderTemplate implements Template {

public static final String IDENTIFIER = "folder";

private static final I18nString NAME = new I18nString("Folder without view",
Map.of("sk", "Priečinok bez zobrazenia", "de", "Ordner ohne Ansicht"));

private static MenuItemBody buildTemplate() {
MenuItemBody menuItemBody = new MenuItemBody();
menuItemBody.setConfigurationTemplateIdentifier(IDENTIFIER);
menuItemBody.setUseTabbedView(false);
menuItemBody.setIsFolder(true);
return menuItemBody;
}

@Override
public String getIdentifier() {
return IDENTIFIER;
}

@Override
public I18nString getName() {
return NAME;
}

@Override
public MenuItemBody getTemplate() {
return buildTemplate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public void ensureDatabaseIndexes() {
*
* @throws IllegalArgumentException if the provided menu identifier already exists
* */
// todo: should be transactional
@Override
public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException {
validateMenuItemBody(body);
Expand Down Expand Up @@ -247,6 +248,7 @@ public Case findFolderCase(UriNode node) {
Query query = Query.query(
Criteria.where("processIdentifier").is(MenuItemConstants.PROCESS_IDENTIFIER)
.and(String.format("dataSet.%s.value", MenuItemConstants.FIELD_NODE_PATH)).is(node.getUriPath())
.and(String.format("dataSet.%s.value", MenuItemConstants.FIELD_IS_FOLDER)).is(true)
);
if (existDatabaseIndexes == null || !existDatabaseIndexes) {
ensureDatabaseIndexes();
Expand Down Expand Up @@ -291,11 +293,11 @@ public void moveItem(Case itemCase, String destUri) throws TransitionNotExecutab
if (MenuItemUtils.isCyclicNodePath(itemCase, destUri)) {
throw new IllegalArgumentException(String.format("Cyclic path not supported. Destination path: %s", destUri));
}
List<Case> casesToSave = new ArrayList<>();

List<String> oldParentIdAsList = MenuItemUtils.getCaseIdsFromCaseRef(itemCase, MenuItemConstants.FIELD_PARENT_ID);

UriNode destNode = uriService.getOrCreate(destUri, UriContentType.CASE);

List<Case> casesToSave = new ArrayList<>();
List<String> oldParentIdAsList = MenuItemUtils.getCaseIdsFromCaseRef(itemCase, MenuItemConstants.FIELD_PARENT_ID);
Case newParent = getOrCreateFolderItem(destNode.getUriPath());

if (oldParentIdAsList != null && !oldParentIdAsList.isEmpty()) {
Expand Down Expand Up @@ -421,7 +423,6 @@ public Case removeChildItemFromParent(String folderId, Case childItem) {
}
childIds.remove(childItem.getStringId());
parentFolder.getDataField(MenuItemConstants.FIELD_CHILD_ITEM_IDS).setValue(childIds);
parentFolder.getDataField(MenuItemConstants.FIELD_HAS_CHILDREN).setValue(MenuItemUtils.hasFolderChildren(parentFolder));
return workflowService.save(parentFolder);
}

Expand Down Expand Up @@ -540,6 +541,9 @@ protected void validateMenuItemBody(MenuItemBody body) {
throw new IllegalArgumentException("Uri cannot contain this identifier");
}
}
if (body.isFolder() && body.getView() != null) {
throw new IllegalArgumentException("Folder cannot have view");
}
}

protected Case findCase(String processIdentifier, String query) {
Expand Down Expand Up @@ -638,6 +642,8 @@ protected String createNodePath(String uri, String identifier) {
protected Case getOrCreateFolderItem(String uri) throws TransitionNotExecutableException {
UriNode node = uriService.getOrCreate(uri, UriContentType.CASE);
MenuItemBody body = new MenuItemBody(new I18nString(node.getName()), DEFAULT_FOLDER_ICON);
body.setIdentifier(MenuItemUtils.sanitize(node.getName()));
body.setIsFolder(true);
return getOrCreateFolderRecursive(node, body);
}

Expand All @@ -655,6 +661,10 @@ protected Case getOrCreateFolderRecursive(UriNode node, MenuItemBody body, Case
return folderCase;
}

if (existsMenuItem(body.getIdentifier())) {
throw new IllegalArgumentException(String.format("Menu item with identifier '%s' is not folder", body.getIdentifier()));
}

folderCase = createCase(MenuItemConstants.PROCESS_IDENTIFIER, body.getMenuName().getDefaultValue(),
loggedUser.transformToLoggedUser());
folderCase.setUriNodeId(node.getParentId());
Expand All @@ -668,6 +678,8 @@ protected Case getOrCreateFolderRecursive(UriNode node, MenuItemBody body, Case
if (node.getParentId() != null) {
UriNode parentNode = uriService.findById(node.getParentId());
body = new MenuItemBody(new I18nString(parentNode.getName()), DEFAULT_FOLDER_ICON);
body.setIdentifier(MenuItemUtils.sanitize(parentNode.getName()));
body.setIsFolder(true);

Case parentFolderCase = getOrCreateFolderRecursive(parentNode, body, folderCase);
dataSetOutcome.putDataSetEntry(MenuItemConstants.FIELD_PARENT_ID, FieldType.CASE_REF, List.of(parentFolderCase.getStringId()));
Expand All @@ -688,8 +700,6 @@ protected void appendChildCaseIdInDataSet(Case folderCase, String childItemCaseI

dataSet.put(MenuItemConstants.FIELD_CHILD_ITEM_IDS, Map.of("type", FieldType.CASE_REF.getName(),
"value", childIds));
dataSet.put(MenuItemConstants.FIELD_HAS_CHILDREN, Map.of("type", FieldType.BOOLEAN.getName(),
"value", !childIds.isEmpty()));
}

protected void appendChildCaseIdInMemory(Case folderCase, String childItemCaseId) {
Expand All @@ -700,7 +710,6 @@ protected void appendChildCaseIdInMemory(Case folderCase, String childItemCaseId
childIds.add(childItemCaseId);
folderCase.getDataField(MenuItemConstants.FIELD_CHILD_ITEM_IDS).setValue(childIds);
}
folderCase.getDataField(MenuItemConstants.FIELD_HAS_CHILDREN).setValue(MenuItemUtils.hasFolderChildren(folderCase));
}

protected Case appendChildCaseIdAndSave(Case folderCase, String childItemCaseId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ SimpleCaseViewTemplate.IDENTIFIER, new SimpleCaseViewTemplate(),
SimpleTaskViewTemplate.IDENTIFIER, new SimpleTaskViewTemplate(),
SingleTaskViewTemplate.IDENTIFIER, new SingleTaskViewTemplate(),
TabbedTicketViewTemplate.IDENTIFIER, new TabbedTicketViewTemplate(),
CustomViewTemplate.IDENTIFIER, new CustomViewTemplate()
CustomViewTemplate.IDENTIFIER, new CustomViewTemplate(),
FolderTemplate.IDENTIFIER, new FolderTemplate()
);


Expand Down
Loading
Loading