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 COLLECTION = "Collection",
14 COLLECTION_ADMIN = "CollectionAdmin",
15 COLLECTION_DIRECTORY_ITEM = "CollectionDirectoryItem",
16 COLLECTION_FILE_ITEM = "CollectionFileItem",
17 COLLECTION_FILES = "CollectionFiles",
18 COLLECTION_FILES_MULTIPLE = "CollectionFilesMultiple",
19 COLLECTION_FILES_NOT_SELECTED = "CollectionFilesNotSelected",
20 FAVORITE = "Favorite",
21 FILTER_GROUP = "FilterGroup",
22 FILTER_GROUP_ADMIN = "FilterGroupAdmin",
23 FROZEN_MANAGEABLE_PROJECT = "FrozenManageableProject",
24 FROZEN_PROJECT = "FrozenProject",
25 FROZEN_PROJECT_ADMIN = "FrozenProjectAdmin",
27 GROUP_MEMBER = "GroupMember",
28 KEEP_SERVICE = "KeepService",
30 MANAGEABLE_PROJECT = "ManageableProject",
32 OLD_VERSION_COLLECTION = "OldVersionCollection",
33 PERMISSION_EDIT = "PermissionEdit",
35 PROCESS_ADMIN = "ProcessAdmin",
36 PROCESS_LOGS = "ProcessLogs",
37 PROCESS_RESOURCE = "ProcessResource",
39 PROJECT_ADMIN = "ProjectAdmin",
40 READONLY_COLLECTION = "ReadOnlyCollection",
41 READONLY_COLLECTION_DIRECTORY_ITEM = "ReadOnlyCollectionDirectoryItem",
42 READONLY_COLLECTION_FILE_ITEM = "ReadOnlyCollectionFileItem",
43 READONLY_COLLECTION_FILES = "ReadOnlyCollectionFiles",
44 READONLY_COLLECTION_FILES_MULTIPLE = "ReadOnlyCollectionFilesMultiple",
45 READONLY_PROCESS_RESOURCE = "ReadOnlyProcessResource",
46 READONLY_PROJECT = "ReadOnlyProject",
47 READONLY_WORKFLOW = "ReadOnlyWorkflow",
48 REPOSITORY = "Repository",
49 RESOURCE = "Resource",
50 ROOT_PROJECT = "RootProject",
51 ROOT_PROJECT_ADMIN = "RootProjectAdmin",
52 RUNNING_PROCESS_ADMIN = "RunningProcessAdmin",
53 RUNNING_PROCESS_RESOURCE = "RunningProcessResource",
54 SEARCH_RESULTS = "SearchResults",
57 TRASHED_COLLECTION = "TrashedCollection",
59 USER_DETAILS = "UserDetails",
60 VIRTUAL_MACHINE = "VirtualMachine",
61 WORKFLOW = "Workflow",
62 WRITEABLE_COLLECTION = "WriteableCollection",
63 WRITEABLE_PROJECT = "WriteableProject",
66 const processOrder = [
67 ContextMenuActionNames.VIEW_DETAILS,
68 ContextMenuActionNames.OPEN_IN_NEW_TAB,
69 ContextMenuActionNames.COPY_UUID,
70 ContextMenuActionNames.COPY_AND_RERUN_PROCESS,
71 ContextMenuActionNames.CANCEL,
72 ContextMenuActionNames.EDIT_PROCESS,
73 ContextMenuActionNames.REMOVE,
74 ContextMenuActionNames.DIVIDER,
75 ContextMenuActionNames.OUTPUTS,
76 ContextMenuActionNames.ADD_TO_FAVORITES,
77 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
78 ContextMenuActionNames.DIVIDER,
79 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
80 ContextMenuActionNames.API_DETAILS,
83 const projectOrder = [
84 ContextMenuActionNames.VIEW_DETAILS,
85 ContextMenuActionNames.OPEN_IN_NEW_TAB,
86 ContextMenuActionNames.COPY_UUID,
87 ContextMenuActionNames.SHARE,
88 ContextMenuActionNames.EDIT_PROJECT,
89 ContextMenuActionNames.MOVE_TO_TRASH,
90 ContextMenuActionNames.DIVIDER,
91 ContextMenuActionNames.NEW_PROJECT,
92 ContextMenuActionNames.MOVE_TO,
93 ContextMenuActionNames.FREEZE_PROJECT,
94 ContextMenuActionNames.ADD_TO_FAVORITES,
95 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
96 ContextMenuActionNames.DIVIDER,
97 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
98 ContextMenuActionNames.OPEN_WITH_3RD_PARTY_CLIENT,
99 ContextMenuActionNames.API_DETAILS,
102 const collectionOrder = [
103 ContextMenuActionNames.VIEW_DETAILS,
104 ContextMenuActionNames.OPEN_IN_NEW_TAB,
105 ContextMenuActionNames.COPY_UUID,
106 ContextMenuActionNames.SHARE,
107 ContextMenuActionNames.EDIT_COLLECTION,
108 ContextMenuActionNames.MOVE_TO_TRASH,
109 ContextMenuActionNames.DIVIDER,
110 ContextMenuActionNames.MAKE_A_COPY,
111 ContextMenuActionNames.MOVE_TO,
112 ContextMenuActionNames.ADD_TO_FAVORITES,
113 ContextMenuActionNames.ADD_TO_PUBLIC_FAVORITES,
114 ContextMenuActionNames.DIVIDER,
115 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
116 ContextMenuActionNames.OPEN_WITH_3RD_PARTY_CLIENT,
117 ContextMenuActionNames.API_DETAILS,
120 const workflowOrder = [
121 ContextMenuActionNames.VIEW_DETAILS,
122 ContextMenuActionNames.OPEN_IN_NEW_TAB,
123 ContextMenuActionNames.COPY_UUID,
124 ContextMenuActionNames.RUN_WORKFLOW,
125 ContextMenuActionNames.DELETE_WORKFLOW,
126 ContextMenuActionNames.DIVIDER,
127 ContextMenuActionNames.COPY_LINK_TO_CLIPBOARD,
128 ContextMenuActionNames.API_DETAILS,
131 const rootProjectOrder = [
132 ContextMenuActionNames.VIEW_DETAILS,
133 ContextMenuActionNames.USER_ACCOUNT,
134 ContextMenuActionNames.API_DETAILS,
137 const defaultMultiOrder = [
138 ContextMenuActionNames.MOVE_TO,
139 ContextMenuActionNames.MAKE_A_COPY,
140 ContextMenuActionNames.MOVE_TO_TRASH,
143 const kindToOrder: Record<string, ContextMenuActionNames[]> = {
144 [ContextMenuKind.MULTI]: defaultMultiOrder,
146 [ContextMenuKind.PROCESS]: processOrder,
147 [ContextMenuKind.PROCESS_ADMIN]: processOrder,
148 [ContextMenuKind.PROCESS_RESOURCE]: processOrder,
149 [ContextMenuKind.RUNNING_PROCESS_ADMIN]: processOrder,
150 [ContextMenuKind.RUNNING_PROCESS_RESOURCE]: processOrder,
151 [ContextMenuKind.READONLY_PROCESS_RESOURCE]: processOrder,
153 [ContextMenuKind.PROJECT]: projectOrder,
154 [ContextMenuKind.PROJECT_ADMIN]: projectOrder,
155 [ContextMenuKind.READONLY_PROJECT]: projectOrder,
156 [ContextMenuKind.FROZEN_PROJECT]: projectOrder,
157 [ContextMenuKind.FROZEN_PROJECT_ADMIN]: projectOrder,
158 [ContextMenuKind.WRITEABLE_PROJECT]: projectOrder,
159 [ContextMenuKind.MANAGEABLE_PROJECT]: projectOrder,
160 [ContextMenuKind.FROZEN_MANAGEABLE_PROJECT]: projectOrder,
162 [ContextMenuKind.COLLECTION]: collectionOrder,
163 [ContextMenuKind.COLLECTION_ADMIN]: collectionOrder,
164 [ContextMenuKind.READONLY_COLLECTION]: collectionOrder,
165 [ContextMenuKind.WRITEABLE_COLLECTION]: collectionOrder,
166 [ContextMenuKind.OLD_VERSION_COLLECTION]: collectionOrder,
168 [ContextMenuKind.WORKFLOW]: workflowOrder,
169 [ContextMenuKind.READONLY_WORKFLOW]: workflowOrder,
171 [ContextMenuKind.GROUPS]: projectOrder,
173 [ContextMenuKind.FILTER_GROUP]: projectOrder,
174 [ContextMenuKind.FILTER_GROUP_ADMIN]: projectOrder,
176 [ContextMenuKind.ROOT_PROJECT]: rootProjectOrder,
177 [ContextMenuKind.ROOT_PROJECT_ADMIN]: rootProjectOrder,
180 export const menuDirection = {
181 VERTICAL: 'vertical',
182 HORIZONTAL: 'horizontal'
185 export const sortMenuItems = (menuKind: ContextMenuKind, menuItems: ContextMenuAction[], orthagonality: string): ContextMenuAction[] | MultiSelectMenuAction[] => {
186 const preferredOrder = kindToOrder[menuKind];
187 //if no specified order, sort by name
188 if (!preferredOrder) return menuItems.sort(sortByProperty("name"));
190 const bucketMap = new Map();
191 const leftovers: ContextMenuAction[] = [];
193 // if we have multiple dividers, we need each of them to have a different "name" property
196 preferredOrder.forEach((name) => {
197 if (name === ContextMenuActionNames.DIVIDER) {
199 bucketMap.set(`${name}-${count}`, orthagonality === menuDirection.VERTICAL ? verticalMenuDivider : horizontalMenuDivider)
201 bucketMap.set(name, null)
204 [...menuItems].forEach((item) => {
205 if (bucketMap.has(item.name)) bucketMap.set(item.name, item);
206 else leftovers.push(item);
209 const result = Array.from(bucketMap.values()).concat(leftovers).filter((item) => item !== null).reduce((acc, val)=>{
210 return acc.at(-1)?.name === "Divider" && val.name === "Divider" ? acc : acc.concat(val)
213 console.log('>>>SORT', menuKind);
215 return result.at(-1)?.name === "Divider" ? result.slice(0, -1) : result;