Skip to content

Commit

Permalink
feat: Add copy task id to task list (#10058)
Browse files Browse the repository at this point in the history
  • Loading branch information
gt2345 authored Oct 17, 2024
1 parent 2e822b7 commit 472baf9
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 2 deletions.
16 changes: 15 additions & 1 deletion webui/react/src/components/TaskActionDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Button from 'hew/Button';
import Dropdown, { MenuItem } from 'hew/Dropdown';
import Icon from 'hew/Icon';
import { useModal } from 'hew/Modal';
import { useToast } from 'hew/Toast';
import useConfirm from 'hew/useConfirm';
import React, { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
Expand All @@ -12,6 +13,7 @@ import usePermissions from 'hooks/usePermissions';
import { paths, serverAddress } from 'routes/utils';
import { killTask } from 'services/api';
import { TaskAction as Action, CommandState, CommandTask, CommandType, DetailedUser } from 'types';
import { copyToClipboard } from 'utils/dom';
import handleError, { ErrorLevel, ErrorType } from 'utils/error';
import { capitalize } from 'utils/string';
import { isTaskKillable } from 'utils/task';
Expand All @@ -26,6 +28,7 @@ interface Props {

const TaskActionDropdown: React.FC<Props> = ({ task, onComplete, children }: Props) => {
const { canModifyWorkspaceNSC } = usePermissions();
const { openToast } = useToast();
const TaskConnectModal = useModal(TaskConnectModalComponent);

const isConnectable = (task: CommandTask): boolean => {
Expand Down Expand Up @@ -62,6 +65,10 @@ const TaskActionDropdown: React.FC<Props> = ({ task, onComplete, children }: Pro
key: Action.ViewLogs,
label: 'View Logs',
},
{
key: Action.CopyTaskID,
label: 'Copy Task ID',
},
];
if (isTaskKillable(task, canModifyWorkspaceNSC({ workspace: { id: task.workspaceId } }))) {
items.push({ key: Action.Kill, label: 'Kill' });
Expand All @@ -74,7 +81,7 @@ const TaskActionDropdown: React.FC<Props> = ({ task, onComplete, children }: Pro

const navigate = useNavigate();

const handleDropdown = (key: string) => {
const handleDropdown = async (key: string) => {
try {
switch (key) {
case Action.Connect:
Expand All @@ -97,6 +104,13 @@ const TaskActionDropdown: React.FC<Props> = ({ task, onComplete, children }: Pro
onComplete?.(key);
navigate(paths.taskLogs(task));
break;
case Action.CopyTaskID:
await copyToClipboard(task.id);
openToast({
severity: 'Confirm',
title: 'Task ID has been copied to clipboard.',
});
break;
}
} catch (e) {
handleError(e, {
Expand Down
1 change: 1 addition & 0 deletions webui/react/src/components/TaskList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ const TaskList: React.FC<Props> = ({ workspace }: Props) => {
dataIndex: 'id',
defaultWidth: DEFAULT_COLUMN_WIDTHS['id'],
key: 'id',
onCell: () => ({ 'data-testid': 'taskID' }),
render: taskIdRenderer,
sorter: (a: CommandTask, b: CommandTask): number => alphaNumericSorter(a.id, b.id),
title: 'Short ID',
Expand Down
5 changes: 5 additions & 0 deletions webui/react/src/e2e/models/components/TaskList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ class TaskRow extends Row {
parent: this,
selector: '[data-testid="state"]',
});
readonly taskID = new BaseComponent({
parent: this,
selector: '[data-testid="taskID"]',
});
}

/**
* Represents the TaskActionDropdown from src/components/TaskActionDropdown.tsx
*/
class TaskActionDropdown extends DropdownMenu {
readonly kill = this.menuItem(TaskAction.Kill);
readonly copy = this.menuItem(TaskAction.CopyTaskID);
readonly viewLogs = this.menuItem(TaskAction.ViewLogs);
readonly connect = this.menuItem(TaskAction.Connect);
}
Expand Down
16 changes: 15 additions & 1 deletion webui/react/src/e2e/tests/workspaceTasks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { validate } from 'uuid';

import { expect, test } from 'e2e/fixtures/global-fixtures';
import { TaskLogs } from 'e2e/models/pages/TaskLogs';
import { WorkspaceDetails } from 'e2e/models/pages/WorkspaceDetails';
Expand Down Expand Up @@ -27,10 +29,22 @@ test.describe('Workspace Tasks', () => {

await workspaceDetails.taskList.taskKillModal.pwLocator.waitFor();
await workspaceDetails.taskList.taskKillModal.killButton.pwLocator.click();

await expect(firstRow.state.pwLocator).toHaveText('Terminated');
});

await test.step('Copy task ID', async () => {
try {
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
} catch {
return;
}

await (await firstRow.actions.open()).copy.pwLocator.click();
const handle = await authedPage.evaluateHandle(() => navigator.clipboard.readText());
const clipboard = await handle.jsonValue();
expect(validate(clipboard)).toBeTruthy();
});

await test.step('View logs', async () => {
await (await firstRow.actions.open()).viewLogs.pwLocator.click();

Expand Down
1 change: 1 addition & 0 deletions webui/react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,7 @@ export interface CommandTask extends Task {

export const TaskAction = {
Connect: 'Connect',
CopyTaskID: 'Copy Task ID',
Kill: 'Kill',
ViewLogs: 'View Logs',
} as const;
Expand Down

0 comments on commit 472baf9

Please sign in to comment.