diff --git a/components/dashboard/src/workspaces/WorkspaceEntry.tsx b/components/dashboard/src/workspaces/WorkspaceEntry.tsx index ef5e02cf5faecc..c0ddaea764f8fe 100644 --- a/components/dashboard/src/workspaces/WorkspaceEntry.tsx +++ b/components/dashboard/src/workspaces/WorkspaceEntry.tsx @@ -7,13 +7,15 @@ import { CommitContext, Workspace, WorkspaceInfo, WorkspaceInstance, WorkspaceInstanceConditions, WorkspaceInstancePhase } from '@gitpod/gitpod-protocol'; import { GitpodHostUrl } from '@gitpod/gitpod-protocol/lib/util/gitpod-host-url'; import moment from 'moment'; -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; import ConfirmationModal from '../components/ConfirmationModal'; +import Modal from '../components/Modal'; import { ContextMenuEntry } from '../components/ContextMenu'; import { Item, ItemField, ItemFieldContextMenu, ItemFieldIcon } from '../components/ItemsList'; import PendingChangesDropdown from '../components/PendingChangesDropdown'; import Tooltip from '../components/Tooltip'; import { WorkspaceModel } from './workspace-model'; +import { getGitpodService } from '../service/service'; function getLabel(state: WorkspaceInstancePhase, conditions?: WorkspaceInstanceConditions) { if (conditions?.failed) { @@ -30,10 +32,15 @@ interface Props { } export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) { - const [isModalVisible, setModalVisible] = useState(false); + const [isDeleteModalVisible, setDeleteModalVisible] = useState(false); + const [isRenameModalVisible, setRenameModalVisible] = useState(false); + const renameInputRef = useRef(null); const state: WorkspaceInstancePhase = desc.latestInstance?.status?.phase || 'stopped'; const currentBranch = desc.latestInstance?.status.repo?.branch || Workspace.getBranchName(desc.workspace) || ''; const ws = desc.workspace; + // @ts-ignore + const [workspaceDescription, setWsDescription] = useState(ws.description); + const startUrl = new GitpodHostUrl(window.location.href).with({ pathname: '/start/', hash: '#' + ws.id @@ -45,7 +52,16 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) { { title: 'Open', href: startUrl.toString() - }]; + }, + { + title: 'Rename', + href: "", + onClick: () => { + setRenameModalVisible(true); + } + }, + + ]; if (state === 'running') { menuEntries.push({ title: 'Stop', @@ -78,13 +94,25 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) { title: 'Delete', customFontStyle: 'text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300', onClick: () => { - setModalVisible(true); + setDeleteModalVisible(true); } } ); } const project = getProject(ws); + const updateWorkspaceDescription = async () => { + try { + setWsDescription(renameInputRef.current!.value); + await getGitpodService().server.setWorkspaceDescription(ws.id, renameInputRef.current!.value); + } catch (error) { + console.error(error); + } + setRenameModalVisible(false); + // Timebox TODO: error handling with toast -> another issue if it doesn't exist + return true; + } + return @@ -96,7 +124,7 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) { -
{ws.description}
+
{workspaceDescription}
{ws.contextURL}
@@ -111,7 +139,7 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) {
- {isModalVisible && setModalVisible(false)} + visible={isDeleteModalVisible} + onClose={() => setDeleteModalVisible(false)} onConfirm={() => model.deleteWorkspace(ws.id)} />} + {/* + // @ts-ignore */} + setRenameModalVisible(false)} onEnter={updateWorkspaceDescription}> +

Rename Workspace Description

+
+ +
+

You can use a friendlier name for this workspace description.

+

Workspace URLs and endpoints will remain the same.

+
+
+
+ + +
+
; } @@ -134,7 +178,7 @@ export function getProject(ws: Workspace) { } } -export function WorkspaceStatusIndicator({instance}: {instance?: WorkspaceInstance}) { +export function WorkspaceStatusIndicator({ instance }: { instance?: WorkspaceInstance }) { const state: WorkspaceInstancePhase = instance?.status?.phase || 'stopped'; const conditions = instance?.status?.conditions; let stateClassName = 'rounded-full w-3 h-3 text-sm align-middle';