Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/app/AppRoutes.tsx
2499 views
1
/**
2
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import React from "react";
8
import { Redirect, Route, Switch, useLocation } from "react-router";
9
import OAuthClientApproval from "../OauthClientApproval";
10
import Menu from "../menu/Menu";
11
import { parseProps } from "../start/StartWorkspace";
12
import {
13
settingsPathAccount,
14
settingsPathIntegrations,
15
settingsPathMain,
16
settingsPathNotifications,
17
settingsPathPersonalAccessTokenCreate,
18
settingsPathPersonalAccessTokenEdit,
19
settingsPathPersonalAccessTokens,
20
settingsPathPlans,
21
settingsPathPreferences,
22
settingsPathSSHKeys,
23
settingsPathVariables,
24
switchToPAYGPathMain,
25
usagePathMain,
26
} from "../user-settings/settings.routes";
27
import { getURLHash, isGitpodIo } from "../utils";
28
import { workspacesPathMain } from "../workspaces/workspaces.routes";
29
import { AdminRoute } from "./AdminRoute";
30
import { Blocked } from "./Blocked";
31
32
// TODO: Can we bundle-split/lazy load these like other pages?
33
import { BlockedRepositories } from "../admin/BlockedRepositories";
34
import PersonalAccessTokenCreateView from "../user-settings/PersonalAccessTokensCreateView";
35
import { CreateWorkspacePage } from "../workspaces/CreateWorkspacePage";
36
import { BlockedEmailDomains } from "../admin/BlockedEmailDomains";
37
import { AppNotifications } from "../AppNotifications";
38
import { projectsPathInstallGitHubApp } from "../projects/projects.routes";
39
import { Heading1, Subheading } from "@podkit/typography/Headings";
40
import { PrebuildDetailPage } from "../prebuilds/detail/PrebuildDetailPage";
41
42
const Workspaces = React.lazy(() => import(/* webpackPrefetch: true */ "../workspaces/Workspaces"));
43
const Account = React.lazy(() => import(/* webpackPrefetch: true */ "../user-settings/Account"));
44
const Notifications = React.lazy(() => import(/* webpackPrefetch: true */ "../user-settings/Notifications"));
45
const EnvironmentVariables = React.lazy(
46
() => import(/* webpackPrefetch: true */ "../user-settings/EnvironmentVariables"),
47
);
48
const SSHKeys = React.lazy(() => import(/* webpackPrefetch: true */ "../user-settings/SSHKeys"));
49
const Integrations = React.lazy(() => import(/* webpackPrefetch: true */ "../user-settings/Integrations"));
50
const Preferences = React.lazy(() => import(/* webpackPrefetch: true */ "../user-settings/Preferences"));
51
const PersonalAccessTokens = React.lazy(
52
() => import(/* webpackPrefetch: true */ "../user-settings/PersonalAccessTokens"),
53
);
54
const StartWorkspace = React.lazy(() => import(/* webpackPrefetch: true */ "../start/StartWorkspace"));
55
const NewTeam = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/NewTeam"));
56
const JoinTeam = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/JoinTeam"));
57
const Members = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/Members"));
58
const TeamSettings = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamSettings"));
59
const TeamUsageBasedBilling = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamUsageBasedBilling"));
60
const SSO = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/SSO"));
61
const TeamGitIntegrations = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/GitIntegrationsPage"));
62
const TeamPolicies = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamPolicies"));
63
const TeamOnboarding = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamOnboarding"));
64
const TeamNetworking = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamNetworking"));
65
const TeamAuthentication = React.lazy(() => import(/* webpackPrefetch: true */ "../teams/TeamAuthentication"));
66
const InstallGitHubApp = React.lazy(() => import(/* webpackPrefetch: true */ "../projects/InstallGitHubApp"));
67
const FromReferrer = React.lazy(() => import(/* webpackPrefetch: true */ "../FromReferrer"));
68
const UserSearch = React.lazy(() => import(/* webpackPrefetch: true */ "../admin/UserSearch"));
69
const WorkspacesSearch = React.lazy(() => import(/* webpackPrefetch: true */ "../admin/WorkspacesSearch"));
70
const ProjectsSearch = React.lazy(() => import(/* webpackPrefetch: true */ "../admin/ProjectsSearch"));
71
const TeamsSearch = React.lazy(() => import(/* webpackPrefetch: true */ "../admin/TeamsSearch"));
72
const Usage = React.lazy(() => import(/* webpackPrefetch: true */ "../Usage"));
73
const Insights = React.lazy(() => import(/* webpackPrefetch: true */ "../Insights"));
74
const ConfigurationListPage = React.lazy(
75
() => import(/* webpackPrefetch: true */ "../repositories/list/RepositoryList"),
76
);
77
const ConfigurationDetailPage = React.lazy(
78
() => import(/* webpackPrefetch: true */ "../repositories/detail/ConfigurationDetailPage"),
79
);
80
81
const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ "../prebuilds/list/PrebuildListPage"));
82
const AdminPage = React.lazy(() => import(/* webpackPrefetch: true */ "../org-admin/AdminPage"));
83
84
export const AppRoutes = () => {
85
const hash = getURLHash();
86
const location = useLocation();
87
88
// TODO: Add a Route for this instead of inspecting location manually
89
if (location.pathname.startsWith("/blocked")) {
90
return <Blocked />;
91
}
92
93
// TODO: Add a Route for this instead of inspecting location manually
94
if (location.pathname.startsWith("/oauth-approval")) {
95
return <OAuthClientApproval />;
96
}
97
98
// TODO: Try and encapsulate this in a route for "/" (check for hash in route component, render or redirect accordingly)
99
const isCreation = location.pathname === "/" && hash !== "";
100
if (isCreation) {
101
return <Redirect to={"/new" + location.pathname + location.search + location.hash} />;
102
}
103
104
// TODO: Try and make this a <Route/> entry instead
105
const isWsStart = /\/start\/?/.test(window.location.pathname) && hash !== "";
106
if (isWsStart) {
107
return <StartWorkspace {...parseProps(hash, window.location.search)} />;
108
}
109
110
// TODO: Add some context to what this logic is for
111
if (/^(github|gitlab)\.com\/.+?/i.test(window.location.pathname)) {
112
let url = new URL(window.location.href);
113
url.hash = url.pathname;
114
url.pathname = "/";
115
window.location.replace(url);
116
return <div></div>;
117
}
118
119
return (
120
<Route>
121
<Switch>
122
<Route path="/new" exact component={CreateWorkspacePage} />
123
<Route path="*">
124
<div className="container">
125
<Menu />
126
<AppNotifications />
127
<Switch>
128
<Route path="/open">
129
<Redirect to="/new" />
130
</Route>
131
<Route
132
path={[
133
switchToPAYGPathMain,
134
settingsPathPlans,
135
"/old-team-plans",
136
"/teams",
137
"/subscription",
138
"/upgrade-subscription",
139
"/plans",
140
]}
141
exact
142
>
143
<Redirect to={"/billing"} />
144
</Route>
145
<Route path={workspacesPathMain} exact component={Workspaces} />
146
<Route path={settingsPathAccount} exact component={Account} />
147
<Route path={usagePathMain} exact component={Usage} />
148
<Route path={"/insights"} exact component={Insights} />
149
<Route path={settingsPathIntegrations} exact component={Integrations} />
150
<Route path={settingsPathNotifications} exact component={Notifications} />
151
<Route path={settingsPathVariables} exact component={EnvironmentVariables} />
152
<Route path={settingsPathSSHKeys} exact component={SSHKeys} />
153
<Route path={settingsPathPersonalAccessTokens} exact component={PersonalAccessTokens} />
154
<Route
155
path={settingsPathPersonalAccessTokenCreate}
156
exact
157
component={PersonalAccessTokenCreateView}
158
/>
159
<Route
160
path={settingsPathPersonalAccessTokenEdit + "/:tokenId"}
161
exact
162
component={PersonalAccessTokenCreateView}
163
/>
164
<Route path={settingsPathPreferences} exact component={Preferences} />
165
<Route path={projectsPathInstallGitHubApp} exact component={InstallGitHubApp} />
166
<Route path="/from-referrer" exact component={FromReferrer} />
167
168
<AdminRoute path="/admin/users" component={UserSearch} />
169
<AdminRoute path="/admin/orgs" component={TeamsSearch} />
170
<AdminRoute path="/admin/workspaces" component={WorkspacesSearch} />
171
<AdminRoute path="/admin/projects" component={ProjectsSearch} />
172
<AdminRoute path="/admin/blocked-repositories" component={BlockedRepositories} />
173
<AdminRoute path="/admin/blocked-email-domains" component={BlockedEmailDomains} />
174
175
<Route path={["/", "/login", "/login/:orgSlug"]} exact>
176
<Redirect to={workspacesPathMain} />
177
</Route>
178
<Route path={[settingsPathMain]} exact>
179
<Redirect to={settingsPathAccount} />
180
</Route>
181
<Route path={["/access-control"]} exact>
182
<Redirect to={settingsPathIntegrations} />
183
</Route>
184
<Route path={["/admin"]} exact>
185
<Redirect to="/admin/users" />
186
</Route>
187
<Route path="/sorry" exact>
188
<div className="mt-48 text-center">
189
<Heading1>Oh, no! Something went wrong!</Heading1>
190
<Subheading className="mt-4 text-gitpod-red">
191
{decodeURIComponent(getURLHash())}
192
</Subheading>
193
</div>
194
</Route>
195
<Route exact path="/orgs/new" component={NewTeam} />
196
<Route exact path="/orgs/join" component={JoinTeam} />
197
198
{/* These routes that require a selected organization, otherwise they redirect to "/" */}
199
<Route exact path="/members" component={Members} />
200
<Route exact path="/settings" component={TeamSettings} />
201
<Route exact path="/settings/git" component={TeamGitIntegrations} />
202
<Route exact path="/settings/policy" component={TeamPolicies} />
203
<Route exact path="/settings/onboarding" component={TeamOnboarding} />
204
<Route exact path="/settings/networking" component={TeamNetworking} />
205
<Route exact path="/settings/auth" component={TeamAuthentication} />
206
{/* TODO: migrate other org settings pages underneath /settings prefix so we can utilize nested routes */}
207
<Route exact path="/billing" component={TeamUsageBasedBilling} />
208
<Route exact path="/sso" component={SSO} />
209
<Route exact path="/org-admin" component={AdminPage} />
210
211
<Route exact path={`/prebuilds`} component={PrebuildListPage} />
212
<Route path="/prebuilds/:prebuildId" component={PrebuildDetailPage} />
213
<Route exact path="/repositories" component={ConfigurationListPage} />
214
{/* Handles all /repositories/:id/* routes in a nested router */}
215
<Route path="/repositories/:id" component={ConfigurationDetailPage} />
216
217
{/* basic redirect for old team slugs */}
218
<Route path={"/t/"} exact>
219
<Redirect to="/repositories" />
220
</Route>
221
<Route path={"/projects/"}>
222
<Redirect to="/repositories" />
223
</Route>
224
{/* redirect for old user settings slugs */}
225
<Route path="/account" exact>
226
<Redirect to={settingsPathAccount} />
227
</Route>
228
<Route path="/integrations" exact>
229
<Redirect to={settingsPathIntegrations} />
230
</Route>
231
<Route path="/notifications" exact>
232
<Redirect to={settingsPathNotifications} />
233
</Route>
234
<Route path="/user/billing" exact>
235
<Redirect to={"/billing"} />
236
</Route>
237
<Route path="/preferences" exact>
238
<Redirect to={settingsPathPreferences} />
239
</Route>
240
<Route path="/variables" exact>
241
<Redirect to={settingsPathVariables} />
242
</Route>
243
<Route path="/tokens" exact>
244
<Redirect to={settingsPathPersonalAccessTokens} />
245
</Route>
246
<Route path="/tokens/create" exact>
247
<Redirect to={settingsPathPersonalAccessTokenCreate} />
248
</Route>
249
<Route path="/keys" exact>
250
<Redirect to={settingsPathSSHKeys} />
251
</Route>
252
<Route
253
path="*"
254
render={(_match) => {
255
// delegate to our website to handle the request
256
if (isGitpodIo()) {
257
window.location.host = "www.gitpod.io";
258
}
259
260
return (
261
<div className="mt-48 text-center">
262
<Heading1>404</Heading1>
263
<Subheading className="mt-4">Page not found.</Subheading>
264
</div>
265
);
266
}}
267
/>
268
</Switch>
269
</div>
270
</Route>
271
</Switch>
272
</Route>
273
);
274
};
275
276