Skip to content

Commit 5efec1d

Browse files
svenefftingeroboquat
authored andcommitted
[dashboard] redirect when no project is found
1 parent de941d8 commit 5efec1d

File tree

8 files changed

+77
-18
lines changed

8 files changed

+77
-18
lines changed

components/dashboard/src/app/AppRoutes.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,12 @@ export const AppRoutes: FunctionComponent<AppRoutesProps> = ({ user, teams }) =>
269269
<Route path="/variables" exact>
270270
<Redirect to={settingsPathVariables} />
271271
</Route>
272-
<Route path="/tokens">
272+
<Route path="/tokens" exact>
273273
<Redirect to={settingsPathPersonalAccessTokens} />
274274
</Route>
275+
<Route path="/tokens/create" exact>
276+
<Redirect to={settingsPathPersonalAccessTokenCreate} />
277+
</Route>
275278
<Route path="/keys" exact>
276279
<Redirect to={settingsPathSSHKeys} />
277280
</Route>

components/dashboard/src/menu/OrganizationSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default function OrganizationSelector(p: OrganizationSelectorProps) {
3636
),
3737
active: team === undefined,
3838
separator: true,
39-
link: `${location.pathname}?org=0`,
39+
link: `/?org=0`,
4040
},
4141
]
4242
: []),
@@ -55,7 +55,7 @@ export default function OrganizationSelector(p: OrganizationSelectorProps) {
5555
),
5656
active: team?.id === t.id,
5757
separator: true,
58-
link: `${location.pathname}?org=${t.id}`,
58+
link: `/?org=${t.id}`,
5959
}))
6060
.sort((a, b) => (a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1)),
6161
{

components/dashboard/src/projects/Events.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
1616
import { openAuthorizeWindow } from "../provider-utils";
1717
import { useCurrentProject } from "./project-context";
1818
import { toRemoteURL } from "./render-utils";
19+
import { Redirect } from "react-router";
1920

2021
export default function () {
21-
const project = useCurrentProject();
22+
const { project, loading } = useCurrentProject();
2223

2324
const [isLoadingEvents, setIsLoadingEvents] = useState<boolean>(false);
2425
const [events, setEvents] = useState<PrebuildEvent[]>([]);
@@ -102,6 +103,10 @@ export default function () {
102103
return event.status;
103104
};
104105

106+
if (!loading && !project) {
107+
return <Redirect to="/projects" />;
108+
}
109+
105110
return (
106111
<>
107112
<Header

components/dashboard/src/projects/Prebuild.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import dayjs from "dayjs";
88
import { PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol";
99
import { useEffect, useState } from "react";
10-
import { useHistory, useParams } from "react-router";
10+
import { Redirect, useHistory, useParams } from "react-router";
1111
import Header from "../components/Header";
1212
import PrebuildLogs from "../components/PrebuildLogs";
1313
import Spinner from "../icons/Spinner.svg";
@@ -17,14 +17,18 @@ import { useCurrentProject } from "./project-context";
1717

1818
export default function () {
1919
const history = useHistory();
20-
const project = useCurrentProject();
20+
const { project, loading } = useCurrentProject();
2121

2222
const { prebuildId } = useParams<{ prebuildId: string }>();
2323

2424
const [prebuild, setPrebuild] = useState<PrebuildWithStatus | undefined>();
2525
const [isRerunningPrebuild, setIsRerunningPrebuild] = useState<boolean>(false);
2626
const [isCancellingPrebuild, setIsCancellingPrebuild] = useState<boolean>(false);
2727

28+
if (!loading && !project) {
29+
return <Redirect to={"/projects"} />;
30+
}
31+
2832
useEffect(() => {
2933
if (!project || !prebuildId) {
3034
return;

components/dashboard/src/projects/Prebuilds.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import StatusPaused from "../icons/StatusPaused.svg";
1818
import StatusRunning from "../icons/StatusRunning.svg";
1919
import { getGitpodService } from "../service/service";
2020
import { shortCommitMessage } from "./render-utils";
21-
import { Link } from "react-router-dom";
21+
import { Link, Redirect } from "react-router-dom";
2222
import { Disposable } from "vscode-jsonrpc";
2323
import { useCurrentProject } from "./project-context";
2424
import { getProjectTabs } from "./projects.routes";
2525

2626
export default function (props: { project?: Project; isAdminDashboard?: boolean }) {
2727
const currentProject = useCurrentProject();
28-
const project = props.project || currentProject;
28+
const project = props.project || currentProject.project;
2929

3030
const [searchFilter, setSearchFilter] = useState<string | undefined>();
3131
const [statusFilter, setStatusFilter] = useState<PrebuiltWorkspaceState | undefined>();
@@ -128,6 +128,10 @@ export default function (props: { project?: Project; isAdminDashboard?: boolean
128128
return date ? dayjs(date).fromNow() : "";
129129
};
130130

131+
if (!currentProject.loading && !project) {
132+
return <Redirect to="/projects" />;
133+
}
134+
131135
return (
132136
<>
133137
{!props.isAdminDashboard && (

components/dashboard/src/projects/Project.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol";
88
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
99
import dayjs from "dayjs";
1010
import { useCallback, useContext, useEffect, useState } from "react";
11-
import { useHistory } from "react-router";
11+
import { Redirect, useHistory } from "react-router";
1212
import Alert from "../components/Alert";
1313
import Header from "../components/Header";
1414
import { Item, ItemField, ItemFieldContextMenu, ItemsList } from "../components/ItemsList";
@@ -24,7 +24,7 @@ import { shortCommitMessage, toRemoteURL } from "./render-utils";
2424

2525
export default function () {
2626
const history = useHistory();
27-
const project = useCurrentProject();
27+
const { project, loading } = useCurrentProject();
2828
const { setStartWorkspaceModalProps } = useContext(StartWorkspaceModalContext);
2929

3030
const [isLoading, setIsLoading] = useState<boolean>(false);
@@ -183,10 +183,14 @@ export default function () {
183183
}
184184
};
185185

186+
if (!loading && !project) {
187+
return <Redirect to="/projects" />;
188+
}
189+
186190
return (
187191
<>
188192
<Header
189-
title={project?.name || "Unknown project"}
193+
title={project?.name || "Loading..."}
190194
subtitle={
191195
<h2 className="tracking-wide">
192196
View recent active branches for{" "}

components/dashboard/src/projects/ProjectVariables.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { Project, ProjectEnvVar } from "@gitpod/gitpod-protocol";
88
import { useEffect, useState } from "react";
9+
import { Redirect } from "react-router";
910
import Alert from "../components/Alert";
1011
import CheckBox from "../components/CheckBox";
1112
import InfoBox from "../components/InfoBox";
@@ -16,7 +17,7 @@ import { useCurrentProject } from "./project-context";
1617
import { ProjectSettingsPage } from "./ProjectSettings";
1718

1819
export default function () {
19-
const project = useCurrentProject();
20+
const { project, loading } = useCurrentProject();
2021
const [envVars, setEnvVars] = useState<ProjectEnvVar[]>([]);
2122
const [showAddVariableModal, setShowAddVariableModal] = useState<boolean>(false);
2223

@@ -39,6 +40,10 @@ export default function () {
3940
updateEnvVars();
4041
};
4142

43+
if (!loading && !project) {
44+
return <Redirect to="/projects" />;
45+
}
46+
4247
return (
4348
<ProjectSettingsPage project={project}>
4449
{showAddVariableModal && (

components/dashboard/src/projects/project-context.tsx

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import { Project } from "@gitpod/gitpod-protocol";
88
import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
9-
import { useRouteMatch } from "react-router";
9+
import { useHistory, useLocation, useRouteMatch } from "react-router";
1010
import { validate as uuidValidate } from "uuid";
1111
import { listAllProjects } from "../service/public-api";
12-
import { useCurrentTeam } from "../teams/teams-context";
12+
import { useCurrentTeam, useTeams } from "../teams/teams-context";
1313
import { useCurrentUser } from "../user-context";
1414

1515
export const ProjectContext = createContext<{
@@ -45,15 +45,26 @@ export function useProjectSlugs(): { projectSlug?: string; prebuildId?: string }
4545
}, [projectsRouteMatch?.params.projectSlug, projectsRouteMatch?.params.prebuildId]);
4646
}
4747

48-
export function useCurrentProject(): Project | undefined {
48+
export function useCurrentProject(): { project: Project | undefined; loading: boolean } {
4949
const { project, setProject } = useContext(ProjectContext);
50+
const [loading, setLoading] = useState(true);
5051
const user = useCurrentUser();
5152
const team = useCurrentTeam();
53+
const teams = useTeams();
5254
const slugs = useProjectSlugs();
55+
const location = useLocation();
56+
const history = useHistory();
5357

5458
useEffect(() => {
55-
if (!user || !slugs.projectSlug) {
59+
setLoading(true);
60+
if (!user) {
5661
setProject(undefined);
62+
// without a user we are still consider this loading
63+
return;
64+
}
65+
if (!slugs.projectSlug) {
66+
setProject(undefined);
67+
setLoading(false);
5768
return;
5869
}
5970
(async () => {
@@ -66,9 +77,32 @@ export function useCurrentProject(): Project | undefined {
6677

6778
// Find project matching with slug, otherwise with name
6879
const project = projects.find((p) => Project.slug(p) === slugs.projectSlug);
80+
if (!project && teams) {
81+
// check other orgs
82+
for (const t of teams) {
83+
if (t.id === team?.id) {
84+
continue;
85+
}
86+
const projects = await listAllProjects({ teamId: t.id });
87+
const project = projects.find((p) => Project.slug(p) === slugs.projectSlug);
88+
if (project) {
89+
// redirect to the other org
90+
history.push(location.pathname + "?org=" + t.id);
91+
}
92+
}
93+
94+
// check personal projects
95+
const projects = await listAllProjects({ userId: user.id });
96+
const project = projects.find((p) => Project.slug(p) === slugs.projectSlug);
97+
if (project) {
98+
// redirect to the other org
99+
history.push(location.pathname + "?org=0");
100+
}
101+
}
69102
setProject(project);
103+
setLoading(false);
70104
})();
71-
}, [slugs.projectSlug, setProject, team, user]);
105+
}, [slugs.projectSlug, setProject, team, user, teams, location, history]);
72106

73-
return project;
107+
return { project, loading };
74108
}

0 commit comments

Comments
 (0)