1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { ContextMenuAction } from './context-menu-action-set';
6 import { ContextMenuActionNames } from 'views-components/context-menu/context-menu-action-set';
7 import { sortByProperty } from 'common/array-utils';
8 import { horizontalMenuDivider, verticalMenuDivider } from './actions/context-menu-divider';
9 import { MultiSelectMenuAction } from 'views-components/multiselect-toolbar/ms-menu-actions';
11 export enum ContextMenuKind {
12 API_CLIENT_AUTHORIZATION = "ApiClientAuthorization",
13 ROOT_PROJECT = "RootProject",
15 FILTER_GROUP = "FilterGroup",
16 READONLY_PROJECT = "ReadOnlyProject",
17 FROZEN_PROJECT = "FrozenProject",
18 FROZEN_PROJECT_ADMIN = "FrozenProjectAdmin",
19 PROJECT_ADMIN = "ProjectAdmin",
20 FILTER_GROUP_ADMIN = "FilterGroupAdmin",
21 RESOURCE = "Resource",
22 FAVORITE = "Favorite",
24 COLLECTION_FILES = "CollectionFiles",
25 COLLECTION_FILES_MULTIPLE = "CollectionFilesMultiple",
26 READONLY_COLLECTION_FILES = "ReadOnlyCollectionFiles",
27 READONLY_COLLECTION_FILES_MULTIPLE = "ReadOnlyCollectionFilesMultiple",
28 COLLECTION_FILES_NOT_SELECTED = "CollectionFilesNotSelected",
29 COLLECTION_FILE_ITEM = "CollectionFileItem",
30 COLLECTION_DIRECTORY_ITEM = "CollectionDirectoryItem",
31 READONLY_COLLECTION_FILE_ITEM = "ReadOnlyCollectionFileItem",
32 READONLY_COLLECTION_DIRECTORY_ITEM = "ReadOnlyCollectionDirectoryItem",
33 COLLECTION = "Collection",
34 COLLECTION_ADMIN = "CollectionAdmin",
35 READONLY_COLLECTION = "ReadOnlyCollection",
36 OLD_VERSION_COLLECTION = "OldVersionCollection",
37 TRASHED_COLLECTION = "TrashedCollection",
39 RUNNING_PROCESS_ADMIN = "RunningProcessAdmin",
40 PROCESS_ADMIN = "ProcessAdmin",
41 RUNNING_PROCESS_RESOURCE = "RunningProcessResource",
42 PROCESS_RESOURCE = "ProcessResource",
43 READONLY_PROCESS_RESOURCE = "ReadOnlyProcessResource",
44 PROCESS_LOGS = "ProcessLogs",
45 REPOSITORY = "Repository",
47 VIRTUAL_MACHINE = "VirtualMachine",
48 KEEP_SERVICE = "KeepService",
51 GROUP_MEMBER = "GroupMember",
52 PERMISSION_EDIT = "PermissionEdit",
54 WORKFLOW = "Workflow",
55 READONLY_WORKFLOW = "ReadOnlyWorkflow",
56 SEARCH_RESULTS = "SearchResults",
62 const processOrder = [
63 ContextMenuActionNames.VIEW_DETAILS,
64 ContextMenuActionNames.OPEN_IN_NEW_TAB,
65 ContextMenuActionNames.OUTPUTS,
66 ContextMenuActionNames.API_DETAILS,
67 ContextMenuActionNames.DIVIDER,
68 ContextMenuActionNames.EDIT_PROCESS,
69 ContextMenuActionNames.COPY_AND_RERUN_PROCESS,
70 ContextMenuActionNames.CANCEL,
71 ContextMenuActionNames.REMOVE,
72 ContextMenuActionNames.DIVIDER,
73 ContextMenuActionNames.ADD_TO_FAVORITES,
74 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
77 const projectOrder = [
78 ContextMenuActionNames.VIEW_DETAILS,
79 ContextMenuActionNames.OPEN_IN_NEW_TAB,
80 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
81 ContextMenuActionNames.OPEN_WITH_3RD_PARTY_CLIENT,
82 ContextMenuActionNames.API_DETAILS,
83 ContextMenuActionNames.DIVIDER,
84 ContextMenuActionNames.SHARE,
85 ContextMenuActionNames.NEW_PROJECT,
86 ContextMenuActionNames.EDIT_PROJECT,
87 ContextMenuActionNames.MOVE_TO,
88 ContextMenuActionNames.MOVE_TO_TRASH,
89 ContextMenuActionNames.DIVIDER,
90 ContextMenuActionNames.FREEZE_PROJECT,
91 ContextMenuActionNames.ADD_TO_FAVORITES,
92 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
95 const collectionOrder = [
96 ContextMenuActionNames.VIEW_DETAILS,
97 ContextMenuActionNames.OPEN_IN_NEW_TAB,
98 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
99 ContextMenuActionNames.OPEN_WITH_3RD_PARTY_CLIENT,
100 ContextMenuActionNames.API_DETAILS,
101 ContextMenuActionNames.DIVIDER,
102 ContextMenuActionNames.SHARE,
103 ContextMenuActionNames.EDIT_COLLECTION,
104 ContextMenuActionNames.MOVE_TO,
105 ContextMenuActionNames.MAKE_A_COPY,
106 ContextMenuActionNames.MOVE_TO_TRASH,
107 ContextMenuActionNames.DIVIDER,
108 ContextMenuActionNames.ADD_TO_FAVORITES,
109 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
112 const workflowOrder = [
113 ContextMenuActionNames.VIEW_DETAILS,
114 ContextMenuActionNames.OPEN_IN_NEW_TAB,
115 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
116 ContextMenuActionNames.API_DETAILS,
117 ContextMenuActionNames.DIVIDER,
118 ContextMenuActionNames.RUN_WORKFLOW,
119 ContextMenuActionNames.DELETE_WORKFLOW,
122 const defaultMultiOrder = [
123 ContextMenuActionNames.MOVE_TO,
124 ContextMenuActionNames.MAKE_A_COPY,
125 ContextMenuActionNames.MOVE_TO_TRASH,
128 const kindToOrder: Record<string, ContextMenuActionNames[]> = {
129 [ContextMenuKind.MULTI]: defaultMultiOrder,
131 [ContextMenuKind.PROCESS]: processOrder,
132 [ContextMenuKind.PROCESS_ADMIN]: processOrder,
133 [ContextMenuKind.PROCESS_RESOURCE]: processOrder,
134 [ContextMenuKind.RUNNING_PROCESS_ADMIN]: processOrder,
135 [ContextMenuKind.RUNNING_PROCESS_RESOURCE]: processOrder,
137 [ContextMenuKind.PROJECT]: projectOrder,
138 [ContextMenuKind.PROJECT_ADMIN]: projectOrder,
139 [ContextMenuKind.FROZEN_PROJECT]: projectOrder,
140 [ContextMenuKind.FROZEN_PROJECT_ADMIN]: projectOrder,
142 [ContextMenuKind.COLLECTION]: collectionOrder,
143 [ContextMenuKind.COLLECTION_ADMIN]: collectionOrder,
144 [ContextMenuKind.READONLY_COLLECTION]: collectionOrder,
145 [ContextMenuKind.OLD_VERSION_COLLECTION]: collectionOrder,
147 [ContextMenuKind.WORKFLOW]: workflowOrder,
148 [ContextMenuKind.READONLY_WORKFLOW]: workflowOrder,
151 export const menuDirection = {
152 VERTICAL: 'vertical',
153 HORIZONTAL: 'horizontal'
156 export const sortMenuItems = (menuKind: ContextMenuKind, menuItems: ContextMenuAction[], orthagonality: string): ContextMenuAction[] | MultiSelectMenuAction[] => {
158 const preferredOrder = kindToOrder[menuKind];
159 //if no specified order, sort by name
160 if (!preferredOrder) return menuItems.sort(sortByProperty("name"));
162 const bucketMap = new Map();
163 const leftovers: ContextMenuAction[] = [];
165 // if we have multiple dividers, we need each of them to have a different "name" property
168 preferredOrder.forEach((name) => {
169 if (name === ContextMenuActionNames.DIVIDER) {
171 bucketMap.set(`${name}-${count}`, orthagonality === menuDirection.VERTICAL ? verticalMenuDivider : horizontalMenuDivider)
173 bucketMap.set(name, null)
176 [...menuItems].forEach((item) => {
177 if (bucketMap.has(item.name)) bucketMap.set(item.name, item);
178 else leftovers.push(item);
181 return Array.from(bucketMap.values()).concat(leftovers).filter((item) => item !== null);