Merge branch '17782-react-scripts-ts-migration' into main. Closes #17782
[arvados-workbench2.git] / 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     PROCESS_LOGS: `/process-logs/:id(${RESOURCE_UUID_PATTERN})`,
29     REPOSITORIES: '/repositories',
30     SHARED_WITH_ME: '/shared-with-me',
31     RUN_PROCESS: '/run-process',
32     VIRTUAL_MACHINES_ADMIN: '/virtual-machines-admin',
33     VIRTUAL_MACHINES_USER: '/virtual-machines-user',
34     WORKFLOWS: '/workflows',
35     SEARCH_RESULTS: '/search-results',
36     SSH_KEYS_ADMIN: `/ssh-keys-admin`,
37     SSH_KEYS_USER: `/ssh-keys-user`,
38     SITE_MANAGER: `/site-manager`,
39     MY_ACCOUNT: '/my-account',
40     LINK_ACCOUNT: '/link_account',
41     KEEP_SERVICES: `/keep-services`,
42     COMPUTE_NODES: `/nodes`,
43     USERS: '/users',
44     API_CLIENT_AUTHORIZATIONS: `/api_client_authorizations`,
45     GROUPS: '/groups',
46     GROUP_DETAILS: `/group/:id(${RESOURCE_UUID_PATTERN})`,
47     LINKS: '/links',
48     PUBLIC_FAVORITES: '/public-favorites',
49     COLLECTIONS_CONTENT_ADDRESS: `/collections/:id(${PORTABLE_DATA_HASH_PATTERN})`,
50     ALL_PROCESSES: '/all_processes',
51     NO_MATCH: '*',
52 };
53
54 export const getResourceUrl = (uuid: string) => {
55     const kind = extractUuidKind(uuid);
56     switch (kind) {
57         case ResourceKind.PROJECT:
58             return getProjectUrl(uuid);
59         case ResourceKind.USER:
60             return getProjectUrl(uuid);
61         case ResourceKind.COLLECTION:
62             return getCollectionUrl(uuid);
63         case ResourceKind.PROCESS:
64             return getProcessUrl(uuid);
65         default:
66             return undefined;
67     }
68 };
69
70 export const getNavUrl = (uuid: string, config: FederationConfig) => {
71     const path = getResourceUrl(uuid) || "";
72     const cls = uuid.substr(0, 5);
73     if (cls === config.localCluster || extractUuidKind(uuid) === ResourceKind.USER || COLLECTION_PDH_REGEX.exec(uuid)) {
74         return path;
75     } else if (config.remoteHostsConfig[cls]) {
76         let u: URL;
77         if (config.remoteHostsConfig[cls].workbench2Url) {
78             /* NOTE: wb2 presently doesn't support passing api_token
79                to arbitrary page to set credentials, only through
80                api-token route.  So for navigation to work, user needs
81                to already be logged in.  In the future we want to just
82                request the records and display in the current
83                workbench instance making this redirect unnecessary. */
84             u = new URL(config.remoteHostsConfig[cls].workbench2Url);
85         } else {
86             u = new URL(config.remoteHostsConfig[cls].workbenchUrl);
87             u.search = "api_token=" + config.sessions.filter((s) => s.clusterId === cls)[0].token;
88         }
89         u.pathname = path;
90         return u.toString();
91     } else {
92         return "";
93     }
94 };
95
96
97 export const getProcessUrl = (uuid: string) => `/processes/${uuid}`;
98
99 export const getProcessLogUrl = (uuid: string) => `/process-logs/${uuid}`;
100
101 export const getGroupUrl = (uuid: string) => `/group/${uuid}`;
102
103 export interface ResourceRouteParams {
104     id: string;
105 }
106
107 export const matchRootRoute = (route: string) =>
108     matchPath(route, { path: Routes.ROOT, exact: true });
109
110 export const matchFavoritesRoute = (route: string) =>
111     matchPath(route, { path: Routes.FAVORITES });
112
113 export const matchTrashRoute = (route: string) =>
114     matchPath(route, { path: Routes.TRASH });
115
116 export const matchAllProcessesRoute = (route: string) =>
117     matchPath(route, { path: Routes.ALL_PROCESSES });
118
119 export const matchProjectRoute = (route: string) =>
120     matchPath<ResourceRouteParams>(route, { path: Routes.PROJECTS });
121
122 export const matchCollectionRoute = (route: string) =>
123     matchPath<ResourceRouteParams>(route, { path: Routes.COLLECTIONS });
124
125 export const matchProcessRoute = (route: string) =>
126     matchPath<ResourceRouteParams>(route, { path: Routes.PROCESSES });
127
128 export const matchProcessLogRoute = (route: string) =>
129     matchPath<ResourceRouteParams>(route, { path: Routes.PROCESS_LOGS });
130
131 export const matchSharedWithMeRoute = (route: string) =>
132     matchPath(route, { path: Routes.SHARED_WITH_ME });
133
134 export const matchRunProcessRoute = (route: string) =>
135     matchPath(route, { path: Routes.RUN_PROCESS });
136
137 export const matchWorkflowRoute = (route: string) =>
138     matchPath<ResourceRouteParams>(route, { path: Routes.WORKFLOWS });
139
140 export const matchSearchResultsRoute = (route: string) =>
141     matchPath<ResourceRouteParams>(route, { path: Routes.SEARCH_RESULTS });
142
143 export const matchUserVirtualMachineRoute = (route: string) =>
144     matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_USER });
145
146 export const matchAdminVirtualMachineRoute = (route: string) =>
147     matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_ADMIN });
148
149 export const matchRepositoriesRoute = (route: string) =>
150     matchPath<ResourceRouteParams>(route, { path: Routes.REPOSITORIES });
151
152 export const matchSshKeysUserRoute = (route: string) =>
153     matchPath(route, { path: Routes.SSH_KEYS_USER });
154
155 export const matchSshKeysAdminRoute = (route: string) =>
156     matchPath(route, { path: Routes.SSH_KEYS_ADMIN });
157
158 export const matchSiteManagerRoute = (route: string) =>
159     matchPath(route, { path: Routes.SITE_MANAGER });
160
161 export const matchMyAccountRoute = (route: string) =>
162     matchPath(route, { path: Routes.MY_ACCOUNT });
163
164 export const matchLinkAccountRoute = (route: string) =>
165     matchPath(route, { path: Routes.LINK_ACCOUNT });
166
167 export const matchKeepServicesRoute = (route: string) =>
168     matchPath(route, { path: Routes.KEEP_SERVICES });
169
170 export const matchTokenRoute = (route: string) =>
171     matchPath(route, { path: Routes.TOKEN });
172
173 export const matchFedTokenRoute = (route: string) =>
174     matchPath(route, { path: Routes.FED_LOGIN });
175
176 export const matchUsersRoute = (route: string) =>
177     matchPath(route, { path: Routes.USERS });
178
179 export const matchComputeNodesRoute = (route: string) =>
180     matchPath(route, { path: Routes.COMPUTE_NODES });
181
182 export const matchApiClientAuthorizationsRoute = (route: string) =>
183     matchPath(route, { path: Routes.API_CLIENT_AUTHORIZATIONS });
184
185 export const matchGroupsRoute = (route: string) =>
186     matchPath(route, { path: Routes.GROUPS });
187
188 export const matchGroupDetailsRoute = (route: string) =>
189     matchPath<ResourceRouteParams>(route, { path: Routes.GROUP_DETAILS });
190
191 export const matchLinksRoute = (route: string) =>
192     matchPath(route, { path: Routes.LINKS });
193
194 export const matchPublicFavoritesRoute = (route: string) =>
195     matchPath(route, { path: Routes.PUBLIC_FAVORITES });
196
197 export const matchCollectionsContentAddressRoute = (route: string) =>
198     matchPath(route, { path: Routes.COLLECTIONS_CONTENT_ADDRESS });