Skip to content

Commit

Permalink
[dashboard] Allow workspace renaming
Browse files Browse the repository at this point in the history
Fixes #3946
  • Loading branch information
laushinka committed Sep 14, 2021
1 parent a45506d commit 5db390d
Showing 1 changed file with 53 additions and 9 deletions.
62 changes: 53 additions & 9 deletions components/dashboard/src/workspaces/WorkspaceEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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<HTMLInputElement>(null);
const state: WorkspaceInstancePhase = desc.latestInstance?.status?.phase || 'stopped';
const currentBranch = desc.latestInstance?.status.repo?.branch || Workspace.getBranchName(desc.workspace) || '<unknown>';
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
Expand All @@ -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',
Expand Down Expand Up @@ -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 <Item className="whitespace-nowrap py-6 px-6">
<ItemFieldIcon>
<WorkspaceStatusIndicator instance={desc?.latestInstance} />
Expand All @@ -96,7 +124,7 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) {
</Tooltip>
</ItemField>
<ItemField className="w-4/12 flex flex-col">
<div className="text-gray-500 dark:text-gray-400 overflow-ellipsis truncate">{ws.description}</div>
<div className="text-gray-500 dark:text-gray-400 overflow-ellipsis truncate">{workspaceDescription}</div>
<a href={ws.contextURL}>
<div className="text-sm text-gray-400 dark:text-gray-500 overflow-ellipsis truncate hover:text-blue-600 dark:hover:text-blue-400">{ws.contextURL}</div>
</a>
Expand All @@ -111,18 +139,34 @@ export function WorkspaceEntry({ desc, model, isAdmin, stopWorkspace }: Props) {
</Tooltip>
</ItemField>
<ItemFieldContextMenu menuEntries={menuEntries} />
{isModalVisible && <ConfirmationModal
{isDeleteModalVisible && <ConfirmationModal
title="Delete Workspace"
areYouSureText="Are you sure you want to delete this workspace?"
children={{
name: ws.id,
description: ws.description,
}}
buttonText="Delete Workspace"
visible={isModalVisible}
onClose={() => setModalVisible(false)}
visible={isDeleteModalVisible}
onClose={() => setDeleteModalVisible(false)}
onConfirm={() => model.deleteWorkspace(ws.id)}
/>}
{/*
// @ts-ignore */}
<Modal visible={isRenameModalVisible} onClose={() => setRenameModalVisible(false)} onEnter={updateWorkspaceDescription}>
<h3 className="mb-4">Rename Workspace Description</h3>
<div className="border-t border-b border-gray-200 dark:border-gray-800 -mx-6 px-6 py-4 space-y-2">
<input className="w-full" type="text" defaultValue={workspaceDescription} ref={renameInputRef} />
<div className="mt-1">
<p className="text-gray-500">You can use a friendlier name for this workspace description.</p>
<p className="text-gray-500"> Workspace URLs and endpoints will remain the same.</p>
</div>
</div>
<div className="flex justify-end mt-6">
<button className="secondary" onClick={() => setRenameModalVisible(false)}>Cancel</button>
<button className="ml-2" type="submit" onClick={updateWorkspaceDescription}>Rename</button>
</div>
</Modal>
</Item>;
}

Expand All @@ -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';
Expand Down

0 comments on commit 5db390d

Please sign in to comment.