e.stopPropagation()}>
{props.closeable !== false && (
-
diff --git a/components/dashboard/src/workspaces/WorkspaceEntry.tsx b/components/dashboard/src/workspaces/WorkspaceEntry.tsx
index 521f6bce3862db..1af14ec22c816c 100644
--- a/components/dashboard/src/workspaces/WorkspaceEntry.tsx
+++ b/components/dashboard/src/workspaces/WorkspaceEntry.tsx
@@ -9,7 +9,7 @@ import { MouseEvent, useState } from 'react';
import { WorkspaceModel } from './workspace-model';
-export function WorkspaceEntry({desc, model}: {desc: WorkspaceInfo, model: WorkspaceModel}) {
+export function WorkspaceEntry({ desc, model }: { desc: WorkspaceInfo, model: WorkspaceModel }) {
const [isModalVisible, setModalVisible] = useState(false);
const [isChangesModalVisible, setChangesModalVisible] = useState(false);
const state: WorkspaceInstancePhase = desc.latestInstance?.status?.phase || 'stopped';
@@ -46,14 +46,21 @@ export function WorkspaceEntry({desc, model}: {desc: WorkspaceInfo, model: Works
pathname: '/start/',
hash: '#' + ws.id
});
- const downloadURL = new GitpodHostUrl(window.location.href).with({
- pathname: `/workspace-download/get/${ws.id}`
+ const downloadURL = new GitpodHostUrl(window.location.href).with({
+ pathname: `/workspace-download/get/${ws.id}`
}).toString();
const menuEntries: ContextMenuEntry[] = [
{
title: 'Open',
href: startUrl.toString()
- },
+ }];
+ if (state === 'running') {
+ menuEntries.push({
+ title: 'Stop',
+ onClick: () => getGitpodService().server.stopWorkspace(ws.id)
+ });
+ }
+ menuEntries.push(
{
title: 'Download',
href: downloadURL
@@ -80,63 +87,66 @@ export function WorkspaceEntry({desc, model}: {desc: WorkspaceInfo, model: Works
setModalVisible(true);
}
}
- ];
+ );
const project = getProject(ws);
- const startWsOnClick = (event: MouseEvent) => {
- window.location.href = startUrl.toString();
- }
const showChanges = (event: MouseEvent) => {
+ event.preventDefault();
setChangesModalVisible(true);
}
- return
-
-
-
+ return
-
-
-
-
{ws.description}
-
{ws.contextURL}
+
+
+
{ws.description}
+
{ws.contextURL}
+
+
+
0 ? showChanges : undefined}>
+
+
{currentBranch}
+ {
+ numberOfChanges > 0 ?
+
{changesLabel}
+ :
+
No Changes
+ }
+
-
-
0 ? showChanges: startWsOnClick}>
-
-
{currentBranch}
- {
- numberOfChanges > 0 ?
-
{changesLabel}
- :
-
No Changes
- }
-
setChangesModalVisible(false)}>
- {getChangesPopup(pendingChanges)}
-
+
+
{moment(WorkspaceInfo.lastActiveISODate(desc)).fromNow()}
-
-
-
{moment(WorkspaceInfo.lastActiveISODate(desc)).fromNow()}
-
-
-
-
-
-
-
setModalVisible(false)}>
+
+
+
+
+
+
+ setChangesModalVisible(false)}>
+ {getChangesPopup(pendingChanges)}
+
+ setModalVisible(false)} onEnter={() => {model.deleteWorkspace(ws.id); return true;}}>
-
Delete {ws.id}
-
-
Do you really want to delete this workspace?
+
Delete Workspace
+
+
Are you sure you want to delete this workspace?
+
+
{ws.id}
+
{ws.description}
+
-
-
+
diff --git a/components/dashboard/src/workspaces/Workspaces.tsx b/components/dashboard/src/workspaces/Workspaces.tsx
index bb77d05efb28b4..fff7ddcf6e98f9 100644
--- a/components/dashboard/src/workspaces/Workspaces.tsx
+++ b/components/dashboard/src/workspaces/Workspaces.tsx
@@ -89,7 +89,7 @@ export class Workspaces extends React.Component
Name
Context
Pending Changes
-
Last Active
+
Last Start
{
diff --git a/components/dashboard/src/workspaces/workspace-model.ts b/components/dashboard/src/workspaces/workspace-model.ts
index fad617b2ce5ec1..aab4627f36d47a 100644
--- a/components/dashboard/src/workspaces/workspace-model.ts
+++ b/components/dashboard/src/workspaces/workspace-model.ts
@@ -2,7 +2,7 @@ import { Disposable, DisposableCollection, GitpodClient, WorkspaceInfo, Workspac
import { getGitpodService } from "../service/service";
export class WorkspaceModel implements Disposable, Partial {
-
+
protected workspaces = new Map();
protected currentlyFetching = new Set();
protected disposables = new DisposableCollection();
@@ -15,7 +15,7 @@ export class WorkspaceModel implements Disposable, Partial {
constructor(protected setWorkspaces: (ws: WorkspaceInfo[]) => void) {
this.internalRefetch();
}
-
+
protected internalRefetch() {
this.disposables.dispose();
this.disposables = new DisposableCollection();
@@ -27,17 +27,17 @@ export class WorkspaceModel implements Disposable, Partial {
});
this.disposables.push(getGitpodService().registerClient(this));
}
-
+
protected updateMap(workspaces: WorkspaceInfo[]) {
for (const ws of workspaces) {
this.workspaces.set(ws.workspace.id, ws);
}
}
-
+
dispose(): void {
this.disposables.dispose();
}
-
+
async onInstanceUpdate(instance: WorkspaceInstance) {
if (this.workspaces) {
if (this.workspaces.has(instance.workspaceId)) {
@@ -58,7 +58,13 @@ export class WorkspaceModel implements Disposable, Partial {
}
}
}
-
+
+ async deleteWorkspace(id: string): Promise {
+ await getGitpodService().server.deleteWorkspace(id);
+ this.workspaces.delete(id);
+ this.notifyWorkpaces();
+ }
+
protected internalActive = true;
get active() {
return this.internalActive;