Skip to content

Commit ba5a0c6

Browse files
committed
[dashboard] In /workspaces, indicate when you have active workspaces in your teams
1 parent 3585bde commit ba5a0c6

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

components/dashboard/src/workspaces/Workspaces.tsx

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@
55
*/
66

77
import { useContext, useEffect, useState } from "react";
8-
import { Project, WhitelistedRepository, Workspace, WorkspaceInfo } from "@gitpod/gitpod-protocol";
8+
import { Project, Team, WhitelistedRepository, Workspace, WorkspaceInfo } from "@gitpod/gitpod-protocol";
99
import Header from "../components/Header";
1010
import DropDown from "../components/DropDown";
1111
import { WorkspaceModel } from "./workspace-model";
1212
import { WorkspaceEntry } from "./WorkspaceEntry";
1313
import { getGitpodService, gitpodHostUrl } from "../service/service";
1414
import { StartWorkspaceModal, WsStartEntry } from "./StartWorkspaceModal";
15-
import { Item, ItemField, ItemsList } from "../components/ItemsList";
15+
import { ItemsList } from "../components/ItemsList";
1616
import { getCurrentTeam, TeamsContext } from "../teams/teams-context";
1717
import { useLocation, useRouteMatch } from "react-router";
1818
import { toRemoteURL } from "../projects/render-utils";
19-
import { useHistory } from "react-router-dom";
19+
import { Link, useHistory } from "react-router-dom";
2020

2121
export interface WorkspacesProps {
2222
}
@@ -41,12 +41,22 @@ export default function () {
4141
const [repos, setRepos] = useState<WhitelistedRepository[]>([]);
4242
const [isTemplateModelOpen, setIsTemplateModelOpen] = useState<boolean>(false);
4343
const [workspaceModel, setWorkspaceModel] = useState<WorkspaceModel>();
44+
const [teamsProjects, setTeamsProjects] = useState<Project[]>([]);
45+
const [teamsWorkspaceModel, setTeamsWorkspaceModel] = useState<WorkspaceModel|undefined>();
46+
const [teamsActiveWorkspaces, setTeamsActiveWorkspaces] = useState<WorkspaceInfo[]>([]);
4447

4548
const newProjectUrl = !!team ? `/new?team=${team.slug}` : '/new';
4649
const onNewProject = () => {
4750
history.push(newProjectUrl);
4851
}
4952

53+
const fetchTeamsProjects = async () => {
54+
const projectsPerTeam = await Promise.all((teams || []).map(t => getGitpodService().server.getTeamProjects(t.id)));
55+
const allTeamsProjects = projectsPerTeam.flat(1);
56+
setTeamsProjects(allTeamsProjects);
57+
return allTeamsProjects;
58+
}
59+
5060
useEffect(() => {
5161
// only show example repos on the global user context
5262
if (!team && !projectName) {
@@ -73,6 +83,9 @@ export default function () {
7383
workspaceModel = new WorkspaceModel(setActiveWorkspaces, setInactiveWorkspaces, getGitpodService().server.getTeamProjects(team?.id).then(projects => projects.map(p => p.id)), false);
7484
} else {
7585
workspaceModel = new WorkspaceModel(setActiveWorkspaces, setInactiveWorkspaces, getGitpodService().server.getUserProjects().then(projects => projects.map(p => p.id)), true);
86+
// Don't await
87+
const teamsProjectIdsPromise = fetchTeamsProjects().then(tp => tp.map(p => p.id));
88+
setTeamsWorkspaceModel(new WorkspaceModel(setTeamsActiveWorkspaces, () => {}, teamsProjectIdsPromise, false));
7689
}
7790
setWorkspaceModel(workspaceModel);
7891
})();
@@ -156,6 +169,9 @@ export default function () {
156169
</div>
157170
<ItemsList className="lg:px-28 px-10">
158171
<div className="border-t border-gray-200 dark:border-gray-800"></div>
172+
{
173+
teamsWorkspaceModel?.initialized && <ActiveTeamWorkspaces teams={teams} teamProjects={teamsProjects} teamWorkspaces={teamsActiveWorkspaces} />
174+
}
159175
{
160176
activeWorkspaces.map(e => {
161177
return <WorkspaceEntry key={e.workspace.id} desc={e} model={workspaceModel} stopWorkspace={wsId => getGitpodService().server.stopWorkspace(wsId)} />
@@ -165,12 +181,7 @@ export default function () {
165181
activeWorkspaces.length > 0 && <div className="py-6"></div>
166182
}
167183
{
168-
inactiveWorkspaces.length === 0 ? null :
169-
<Item className="w-full bg-gray-50 py-3 px-3 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-800">
170-
<ItemField className=" flex flex-col">
171-
<div className="text-gray-400 text-sm text-center">Unpinned workspaces that have been inactive for more than 14 days will be automatically deleted. <a className="gp-link" href="https://www.gitpod.io/docs/life-of-workspace/#garbage-collection">Learn more</a></div>
172-
</ItemField>
173-
</Item>
184+
inactiveWorkspaces.length > 0 && <div className="p-3 text-gray-400 bg-gray-50 dark:bg-gray-800 rounded-xl text-sm text-center">Unpinned workspaces that have been inactive for more than 14 days will be automatically deleted. <a className="gp-link" href="https://www.gitpod.io/docs/life-of-workspace/#garbage-collection">Learn more</a></div>
174185
}
175186
{
176187
inactiveWorkspaces.map(e => {
@@ -181,8 +192,9 @@ export default function () {
181192
</>
182193
:
183194
<div className="lg:px-28 px-10 flex flex-col space-y-2">
184-
<div className="px-6 py-3 flex justify-between space-x-2 text-gray-400 border-t border-gray-200 dark:border-gray-800 h-96">
185-
<div className="flex flex-col items-center w-96 m-auto">
195+
<div className="px-6 py-3 flex flex-col text-gray-400 border-t border-gray-200 dark:border-gray-800">
196+
{teamsWorkspaceModel?.initialized && <ActiveTeamWorkspaces teams={teams} teamProjects={teamsProjects} teamWorkspaces={teamsActiveWorkspaces} />}
197+
<div className="flex flex-col items-center justify-center h-96 w-96 mx-auto">
186198
{!!team && projects.length === 0
187199
?<>
188200
<h3 className="text-center pb-3 text-gray-500 dark:text-gray-400">No Projects</h3>
@@ -216,3 +228,26 @@ export default function () {
216228
</>;
217229

218230
}
231+
232+
function ActiveTeamWorkspaces(props: { teams?: Team[], teamProjects: Project[], teamWorkspaces: WorkspaceInfo[] }) {
233+
if (!props.teams || props.teamWorkspaces.length === 0) {
234+
return <></>;
235+
}
236+
return <div className="p-3 text-gray-400 bg-gray-50 dark:bg-gray-800 rounded-xl text-sm flex items-center justify-center space-x-1">
237+
<div className="mr-2 rounded-full w-3 h-3 bg-green-500" />
238+
<span>There are currently more active workspaces in the following teams:</span>
239+
<span>{
240+
props.teams
241+
.map(t => {
242+
const projects = props.teamProjects.filter(p => p.teamId === t.id);
243+
const count = props.teamWorkspaces.filter(w => projects.some(p => p.id === w.workspace.projectId)).length;
244+
if (count < 1) {
245+
return undefined;
246+
}
247+
return <Link className="gp-link" to={`/t/${t.slug}/workspaces`}>{t.name}</Link>;
248+
})
249+
.filter(t => !!t)
250+
.map((t, i) => <>{i > 0 && <span>, </span>}{t}</>)
251+
}</span>
252+
</div>;
253+
}

0 commit comments

Comments
 (0)