21842: list styling
[arvados.git] / services / workbench2 / src / routes / routes.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { matchPath } from 'react-router';
6 import { ResourceKind, RESOURCE_UUID_PATTERN, extractUuidKind, COLLECTION_PDH_REGEX, PORTABLE_DATA_HASH_PATTERN } from 'models/resource';
7 import { getProjectUrl } from 'models/project';
8 import { getCollectionUrl } from 'models/collection';
9 import { Config } from 'common/config';
10 import { Session } from "models/session";
11
12 export interface FederationConfig {
13     localCluster: string;
14     remoteHostsConfig: { [key: string]: Config };
15     sessions: Session[];
16 }
17
18 export const Routes = {
19     ROOT: '/',
20     TOKEN: '/token',
21     FED_LOGIN: '/fedtoken',
22     ADD_SESSION: '/add-session',
23     PROJECTS: `/projects/:id(${RESOURCE_UUID_PATTERN})`,
24     COLLECTIONS: `/collections/:id(${RESOURCE_UUID_PATTERN})`,
25     PROCESSES: `/processes/:id(${RESOURCE_UUID_PATTERN})`,
26     FAVORITES: '/favorites',
27     TRASH: '/trash',
28     REPOSITORIES: '/repositories',
29     SHARED_WITH_ME: '/shared-with-me',
30     RUN_PROCESS: '/run-process',
31     VIRTUAL_MACHINES_ADMIN: '/virtual-machines-admin',
32     VIRTUAL_MACHINES_USER: '/virtual-machines-user',
33     WORKFLOWS: '/workflows',
34     REGISTEREDWORKFLOW: `/workflows/:id(${RESOURCE_UUID_PATTERN})`,
35     SEARCH_RESULTS: '/search-results',
36     SSH_KEYS_ADMIN: `/ssh-keys-admin`,
37     SSH_KEYS_USER: `/ssh-keys-user`,
38     INSTANCE_TYPES: `/instance-types`,
39     SITE_MANAGER: `/site-manager`,
40     MY_ACCOUNT: '/my-account',
41     LINK_ACCOUNT: '/link_account',
42     KEEP_SERVICES: `/keep-services`,
43     USERS: '/users',
44     USER_PROFILE: `/user/:id(${RESOURCE_UUID_PATTERN})`,
45     API_CLIENT_AUTHORIZATIONS: `/api_client_authorizations`,
46     GROUPS: '/groups',
47     GROUP_DETAILS: `/group/:id(${RESOURCE_UUID_PATTERN})`,
48     LINKS: '/links',
49     PUBLIC_FAVORITES: '/public-favorites',
50     COLLECTIONS_CONTENT_ADDRESS: `/collections/:id(${PORTABLE_DATA_HASH_PATTERN})`,
51     ALL_PROCESSES: '/all_processes',
52     NO_MATCH: '*',
53 };
54
55 export const getResourceUrl = (uuid: string) => {
56     const kind = extractUuidKind(uuid);
57     switch (kind) {
58         case ResourceKind.PROJECT:
59             return getProjectUrl(uuid);
60         case ResourceKind.USER:
61             return getProjectUrl(uuid);
62         case ResourceKind.COLLECTION:
63             return getCollectionUrl(uuid);
64         case ResourceKind.PROCESS:
65             return getProcessUrl(uuid);
66         case ResourceKind.WORKFLOW:
67             return getWorkflowUrl(uuid);
68         default:
69             return undefined;
70     }
71 };
72
73 /**
74  * @returns A relative or federated url for the given uuid, with a token for federated WB1 urls
75  */
76 export const getNavUrl = (uuid: string, config: FederationConfig, includeToken: boolean = true): string => {
77     const path = getResourceUrl(uuid) || "";
78     const cls = uuid.substring(0, 5);
79     if (cls === config.localCluster || extractUuidKind(uuid) === ResourceKind.USER || COLLECTION_PDH_REGEX.exec(uuid)) {
80         return path;
81     } else if (config.remoteHostsConfig[cls]) {
82         let u: URL;
83         if (config.remoteHostsConfig[cls].workbench2Url) {
84             /* NOTE: wb2 presently doesn't support passing api_token
85                to arbitrary page to set credentials, only through
86                api-token route.  So for navigation to work, user needs
87                to already be logged in.  In the future we want to just
88                request the records and display in the current
89                workbench instance making this redirect unnecessary. */
90             u = new URL(config.remoteHostsConfig[cls].workbench2Url);
91         } else {
92             u = new URL(config.remoteHostsConfig[cls].workbenchUrl);
93             if (includeToken) {
94                 u.search = "api_token=" + config.sessions.filter((s) => s.clusterId === cls)[0].token;
95             }
96         }
97         u.pathname = path;
98         return u.toString();
99     } else {
100         return "";
101     }
102 };
103
104
105 export const getProcessUrl = (uuid: string) => `/processes/${uuid}`;
106
107 export const getWorkflowUrl = (uuid: string) => `/workflows/${uuid}`;
108
109 export const getGroupUrl = (uuid: string) => `/group/${uuid}`;
110
111 export const getUserProfileUrl = (uuid: string) => `/user/${uuid}`;
112
113 export interface ResourceRouteParams {
114     id: string;
115 }
116
117 export const matchRootRoute = (route: string) =>
118     matchPath(route, { path: Routes.ROOT, exact: true });
119
120 export const matchFavoritesRoute = (route: string) =>
121     matchPath(route, { path: Routes.FAVORITES });
122
123 export const matchTrashRoute = (route: string) =>
124     matchPath(route, { path: Routes.TRASH });
125
126 export const matchAllProcessesRoute = (route: string) =>
127     matchPath(route, { path: Routes.ALL_PROCESSES });
128
129 export const matchRegisteredWorkflowRoute = (route: string) =>
130     matchPath<ResourceRouteParams>(route, { path: Routes.REGISTEREDWORKFLOW });
131
132 export const matchProjectRoute = (route: string) =>
133     matchPath<ResourceRouteParams>(route, { path: Routes.PROJECTS });
134
135 export const matchCollectionRoute = (route: string) =>
136     matchPath<ResourceRouteParams>(route, { path: Routes.COLLECTIONS });
137
138 export const matchProcessRoute = (route: string) =>
139     matchPath<ResourceRouteParams>(route, { path: Routes.PROCESSES });
140
141 export const matchSharedWithMeRoute = (route: string) =>
142     matchPath(route, { path: Routes.SHARED_WITH_ME });
143
144 export const matchRunProcessRoute = (route: string) =>
145     matchPath(route, { path: Routes.RUN_PROCESS });
146
147 export const matchWorkflowRoute = (route: string) =>
148     matchPath<ResourceRouteParams>(route, { path: Routes.WORKFLOWS });
149
150 export const matchSearchResultsRoute = (route: string) =>
151     matchPath<ResourceRouteParams>(route, { path: Routes.SEARCH_RESULTS });
152
153 export const matchUserVirtualMachineRoute = (route: string) =>
154     matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_USER });
155
156 export const matchAdminVirtualMachineRoute = (route: string) =>
157     matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_ADMIN });
158
159 export const matchRepositoriesRoute = (route: string) =>
160     matchPath<ResourceRouteParams>(route, { path: Routes.REPOSITORIES });
161
162 export const matchSshKeysUserRoute = (route: string) =>
163     matchPath(route, { path: Routes.SSH_KEYS_USER });
164
165     export const matchSshKeysAdminRoute = (route: string) =>
166     matchPath(route, { path: Routes.SSH_KEYS_ADMIN });
167
168 export const matchInstanceTypesRoute = (route: string) =>
169     matchPath(route, { path: Routes.INSTANCE_TYPES });
170
171 export const matchSiteManagerRoute = (route: string) =>
172     matchPath(route, { path: Routes.SITE_MANAGER });
173
174 export const matchMyAccountRoute = (route: string) =>
175     matchPath(route, { path: Routes.MY_ACCOUNT });
176
177 export const matchLinkAccountRoute = (route: string) =>
178     matchPath(route, { path: Routes.LINK_ACCOUNT });
179
180 export const matchKeepServicesRoute = (route: string) =>
181     matchPath(route, { path: Routes.KEEP_SERVICES });
182
183 export const matchTokenRoute = (route: string) =>
184     matchPath(route, { path: Routes.TOKEN });
185
186 export const matchFedTokenRoute = (route: string) =>
187     matchPath(route, { path: Routes.FED_LOGIN });
188
189 export const matchUsersRoute = (route: string) =>
190     matchPath(route, { path: Routes.USERS });
191
192 export const matchUserProfileRoute = (route: string) =>
193     matchPath<ResourceRouteParams>(route, { path: Routes.USER_PROFILE });
194
195 export const matchApiClientAuthorizationsRoute = (route: string) =>
196     matchPath(route, { path: Routes.API_CLIENT_AUTHORIZATIONS });
197
198 export const matchGroupsRoute = (route: string) =>
199     matchPath(route, { path: Routes.GROUPS });
200
201 export const matchGroupDetailsRoute = (route: string) =>
202     matchPath<ResourceRouteParams>(route, { path: Routes.GROUP_DETAILS });
203
204 export const matchLinksRoute = (route: string) =>
205     matchPath(route, { path: Routes.LINKS });
206
207 export const matchPublicFavoritesRoute = (route: string) =>
208     matchPath(route, { path: Routes.PUBLIC_FAVORITES });
209
210 export const matchCollectionsContentAddressRoute = (route: string) =>
211     matchPath(route, { path: Routes.COLLECTIONS_CONTENT_ADDRESS });