Skip to content

Commit 6216ab0

Browse files
authored
feat(ws): Notebooks 2.0 // Frontend // Workspaces details // Activity tab kubeflow#171 (kubeflow#199)
Signed-off-by: Asaad Balum <asaad.balum@gmail.com> Signed-off-by: asaadbalum <154635253+asaadbalum@users.noreply.github.com>
1 parent e5d4e41 commit 6216ab0

File tree

6 files changed

+99
-9
lines changed

6 files changed

+99
-9
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
coverage
22
results
3+
cypress/downloads/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { home } from '~/__tests__/cypress/cypress/pages/home';
2+
3+
describe('WorkspaceDetailsActivity Component', () => {
4+
beforeEach(() => {
5+
home.visit();
6+
});
7+
8+
// This tests depends on the mocked workspaces data at home page, needs revisit once workspace data fetched from BE
9+
it('open workspace details, open activity tab, check all fields match', () => {
10+
cy.findAllByTestId('table-body').first().findByTestId('action-column').click();
11+
cy.findByTestId('action-view-details').click();
12+
cy.findByTestId('activityTab').click();
13+
cy.findByTestId('lastActivity').should('have.text', '2/16/2025, 4:40:00 AM');
14+
cy.findByTestId('lastUpdate').should('have.text', '2/16/2025, 4:41:40 AM');
15+
cy.findByTestId('pauseTime').should('have.text', '2/16/2025, 4:38:20 AM');
16+
cy.findByTestId('pendingRestart').should('have.text', 'No');
17+
});
18+
});

workspaces/frontend/src/app/pages/Workspaces/Details/WorkspaceDetails.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import { Workspace } from '~/shared/types';
1616
import { WorkspaceDetailsOverview } from '~/app/pages/Workspaces/Details/WorkspaceDetailsOverview';
1717
import { WorkspaceDetailsActions } from '~/app/pages/Workspaces/Details/WorkspaceDetailsActions';
18+
import { WorkspaceDetailsActivity } from '~/app/pages/Workspaces/Details/WorkspaceDetailsActivity';
1819

1920
type WorkspaceDetailsProps = {
2021
workspace: Workspace;
@@ -39,7 +40,7 @@ export const WorkspaceDetails: React.FunctionComponent<WorkspaceDetailsProps> =
3940
};
4041

4142
return (
42-
<DrawerPanelContent>
43+
<DrawerPanelContent data-testid="workspaceDetails">
4344
<DrawerHead>
4445
<Title headingLevel="h6">{workspace.name}</Title>
4546
<WorkspaceDetailsActions onEditClick={onEditClick} onDeleteClick={onDeleteClick} />
@@ -56,9 +57,16 @@ export const WorkspaceDetails: React.FunctionComponent<WorkspaceDetailsProps> =
5657
</TabContentBody>
5758
</TabContent>
5859
</Tab>
59-
<Tab eventKey={1} title={<TabTitleText>Activity</TabTitleText>} aria-label="Activity">
60+
<Tab
61+
eventKey={1}
62+
title={<TabTitleText>Activity</TabTitleText>}
63+
aria-label="Activity"
64+
data-testid="activityTab"
65+
>
6066
<TabContent id="activitySectionBodyPadding">
61-
<TabContentBody hasPadding>Activity</TabContentBody>
67+
<TabContentBody hasPadding>
68+
<WorkspaceDetailsActivity workspace={workspace} />
69+
</TabContentBody>
6270
</TabContent>
6371
</Tab>
6472
<Tab eventKey={2} title={<TabTitleText>Logs</TabTitleText>} aria-label="Logs">
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import {
3+
DescriptionList,
4+
DescriptionListTerm,
5+
DescriptionListGroup,
6+
DescriptionListDescription,
7+
Divider,
8+
} from '@patternfly/react-core';
9+
import { Workspace } from '~/shared/types';
10+
import { formatTimestamp } from '~/shared/utilities/WorkspaceUtils';
11+
12+
type WorkspaceDetailsActivityProps = {
13+
workspace: Workspace;
14+
};
15+
16+
export const WorkspaceDetailsActivity: React.FunctionComponent<WorkspaceDetailsActivityProps> = ({
17+
workspace,
18+
}) => {
19+
const { activity, pauseTime, pendingRestart } = workspace.status;
20+
21+
return (
22+
<DescriptionList isHorizontal>
23+
<DescriptionListGroup>
24+
<DescriptionListTerm>Last Activity</DescriptionListTerm>
25+
<DescriptionListDescription data-testid="lastActivity">
26+
{formatTimestamp(activity.lastActivity)}
27+
</DescriptionListDescription>
28+
</DescriptionListGroup>
29+
<Divider />
30+
<DescriptionListGroup>
31+
<DescriptionListTerm>Last Update</DescriptionListTerm>
32+
<DescriptionListDescription data-testid="lastUpdate">
33+
{formatTimestamp(activity.lastUpdate)}
34+
</DescriptionListDescription>
35+
</DescriptionListGroup>
36+
<Divider />
37+
<DescriptionListGroup>
38+
<DescriptionListTerm>Pause Time</DescriptionListTerm>
39+
<DescriptionListDescription data-testid="pauseTime">
40+
{formatTimestamp(pauseTime)}
41+
</DescriptionListDescription>
42+
</DescriptionListGroup>
43+
<Divider />
44+
<DescriptionListGroup>
45+
<DescriptionListTerm>Pending Restart</DescriptionListTerm>
46+
<DescriptionListDescription data-testid="pendingRestart">
47+
{pendingRestart ? 'Yes' : 'No'}
48+
</DescriptionListDescription>
49+
</DescriptionListGroup>
50+
<Divider />
51+
</DescriptionList>
52+
);
53+
};

workspaces/frontend/src/app/pages/Workspaces/Workspaces.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import { WorkspaceStartActionModal } from '~/app/pages/Workspaces/workspaceActio
4747
import { WorkspaceRestartActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceRestartActionModal';
4848
import { WorkspaceStopActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceStopActionModal';
4949
import Filter, { FilteredColumn } from 'shared/components/Filter';
50-
import { formatRam } from 'shared/utilities/WorkspaceResources';
50+
import { formatRam } from 'shared/utilities/WorkspaceUtils';
5151

5252
export enum ActionType {
5353
ViewDetails,
@@ -102,11 +102,11 @@ export const Workspaces: React.FunctionComponent = () => {
102102
},
103103
status: {
104104
activity: {
105-
lastActivity: 0,
106-
lastUpdate: 0,
105+
lastActivity: 1739673600,
106+
lastUpdate: 1739673700,
107107
},
108-
pauseTime: 0,
109-
pendingRestart: true,
108+
pauseTime: 1739673500,
109+
pendingRestart: false,
110110
podTemplateOptions: {
111111
imageConfig: {
112112
desired: '',
@@ -384,14 +384,17 @@ export const Workspaces: React.FunctionComponent = () => {
384384
const workspaceState = workspace.status.state;
385385
const workspaceActions = [
386386
{
387+
id: 'view-details',
387388
title: 'View Details',
388389
onClick: () => viewDetailsClick(workspace),
389390
},
390391
{
392+
id: 'edit',
391393
title: 'Edit',
392394
onClick: () => editAction(workspace),
393395
},
394396
{
397+
id: 'delete',
395398
title: 'Delete',
396399
onClick: () => handleDeleteClick(workspace),
397400
},
@@ -400,17 +403,20 @@ export const Workspaces: React.FunctionComponent = () => {
400403
},
401404
workspaceState !== WorkspaceState.Running
402405
? {
406+
id: 'start',
403407
title: 'Start',
404408
onClick: () => startRestartAction(workspace, ActionType.Start),
405409
}
406410
: {
411+
id: 'restart',
407412
title: 'Restart',
408413
onClick: () => startRestartAction(workspace, ActionType.Restart),
409414
},
410415
] as IActions;
411416

412417
if (workspaceState === WorkspaceState.Running) {
413418
workspaceActions.push({
419+
id: 'stop',
414420
title: 'Stop',
415421
onClick: () => stopAction(workspace),
416422
});
@@ -633,7 +639,7 @@ export const Workspaces: React.FunctionComponent = () => {
633639
<ActionsColumn
634640
items={workspaceDefaultActions(workspace).map((action) => ({
635641
...action,
636-
'data-testid': `action-${typeof action.title === 'string' ? action.title.toLowerCase() : ''}`,
642+
'data-testid': `action-${action.id || ''}`,
637643
}))}
638644
/>
639645
</Td>

workspaces/frontend/src/shared/utilities/WorkspaceResources.ts renamed to workspaces/frontend/src/shared/utilities/WorkspaceUtils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ export const formatRam = (valueInKb: number): string => {
1010

1111
return `${value.toFixed(2)} ${units[index]}`;
1212
};
13+
14+
// Helper function to format UNIX timestamps
15+
export const formatTimestamp = (timestamp: number): string =>
16+
timestamp && timestamp > 0 ? new Date(timestamp * 1000).toLocaleString() : '-';

0 commit comments

Comments
 (0)