Skip to content

Commit 763eddb

Browse files
gaobinlongruanyl
authored andcommitted
Add update workspace page (opensearch-project#25)
Signed-off-by: gaobinlong <gbinlong@amazon.com>
1 parent a28e12d commit 763eddb

File tree

7 files changed

+179
-10
lines changed

7 files changed

+179
-10
lines changed

src/plugins/workspace/common/constants.ts

+3
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ export const WORKSPACE_ID_IN_SESSION_STORAGE = '_workspace_id_';
1010
export const PATHS = {
1111
create: '/create',
1212
overview: '/overview',
13+
update: '/update',
1314
};
15+
export const WORKSPACE_OP_TYPE_CREATE = 'create';
16+
export const WORKSPACE_OP_TYPE_UPDATE = 'update';

src/plugins/workspace/public/components/routes.ts

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { PATHS } from '../../common/constants';
77

88
import { WorkspaceCreator } from './workspace_creator';
9+
import { WorkspaceUpdater } from './workspace_updater';
910
import { WorkspaceOverview } from './workspace_overview';
1011

1112
export interface RouteConfig {
@@ -26,4 +27,9 @@ export const ROUTES: RouteConfig[] = [
2627
Component: WorkspaceOverview,
2728
label: 'Overview',
2829
},
30+
{
31+
path: PATHS.update,
32+
Component: WorkspaceUpdater,
33+
label: 'Update',
34+
},
2935
];

src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { i18n } from '@osd/i18n';
1010
import { useOpenSearchDashboards } from '../../../../../plugins/opensearch_dashboards_react/public';
1111

1212
import { WorkspaceForm, WorkspaceFormData } from './workspace_form';
13+
import { WORKSPACE_OP_TYPE_CREATE } from '../../../common/constants';
1314

1415
export const WorkspaceCreator = () => {
1516
const {
@@ -61,7 +62,11 @@ export const WorkspaceCreator = () => {
6162
style={{ width: '100%', maxWidth: 1000 }}
6263
>
6364
{application && (
64-
<WorkspaceForm application={application} onSubmit={handleWorkspaceFormSubmit} />
65+
<WorkspaceForm
66+
application={application}
67+
onSubmit={handleWorkspaceFormSubmit}
68+
opType={WORKSPACE_OP_TYPE_CREATE}
69+
/>
6570
)}
6671
</EuiPageContent>
6772
</EuiPageBody>

src/plugins/workspace/public/components/workspace_creator/workspace_form.tsx

+20-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
import { WorkspaceTemplate } from '../../../../../core/types';
3333
import { AppNavLinkStatus, ApplicationStart } from '../../../../../core/public';
3434
import { useApplications, useWorkspaceTemplate } from '../../hooks';
35+
import { WORKSPACE_OP_TYPE_CREATE, WORKSPACE_OP_TYPE_UPDATE } from '../../../common/constants';
3536

3637
interface WorkspaceFeature {
3738
id: string;
@@ -62,8 +63,14 @@ interface WorkspaceFormProps {
6263
application: ApplicationStart;
6364
onSubmit?: (formData: WorkspaceFormData) => void;
6465
defaultValues?: WorkspaceFormData;
66+
opType?: string;
6567
}
66-
export const WorkspaceForm = ({ application, onSubmit, defaultValues }: WorkspaceFormProps) => {
68+
export const WorkspaceForm = ({
69+
application,
70+
onSubmit,
71+
defaultValues,
72+
opType,
73+
}: WorkspaceFormProps) => {
6774
const { workspaceTemplates, templateFeatureMap } = useWorkspaceTemplate(application);
6875
const applications = useApplications(application);
6976

@@ -199,7 +206,7 @@ export const WorkspaceForm = ({ application, onSubmit, defaultValues }: Workspac
199206
</EuiTitle>
200207
<EuiSpacer />
201208
<EuiFormRow label="Name" isInvalid={!!formErrors.name} error={formErrors.name}>
202-
<EuiFieldText onChange={handleNameInputChange} />
209+
<EuiFieldText value={name} onChange={handleNameInputChange} />
203210
</EuiFormRow>
204211
<EuiFormRow
205212
label={
@@ -208,7 +215,7 @@ export const WorkspaceForm = ({ application, onSubmit, defaultValues }: Workspac
208215
</>
209216
}
210217
>
211-
<EuiFieldText onChange={handleDescriptionInputChange} />
218+
<EuiFieldText value={description} onChange={handleDescriptionInputChange} />
212219
</EuiFormRow>
213220
</EuiPanel>
214221
<EuiSpacer />
@@ -329,9 +336,16 @@ export const WorkspaceForm = ({ application, onSubmit, defaultValues }: Workspac
329336
</EuiPanel>
330337
<EuiSpacer />
331338
<EuiText textAlign="right">
332-
<EuiButton form={formIdRef.current} type="submit" fill>
333-
Create workspace
334-
</EuiButton>
339+
{opType === WORKSPACE_OP_TYPE_CREATE && (
340+
<EuiButton form={formIdRef.current} type="submit" fill>
341+
Create workspace
342+
</EuiButton>
343+
)}
344+
{opType === WORKSPACE_OP_TYPE_UPDATE && (
345+
<EuiButton form={formIdRef.current} type="submit" fill>
346+
Update workspace
347+
</EuiButton>
348+
)}
335349
</EuiText>
336350
</EuiForm>
337351
);

src/plugins/workspace/public/components/workspace_overview.tsx

+21-3
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,43 @@ import React from 'react';
77
import { EuiPageHeader, EuiButton, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
88
import { useObservable } from 'react-use';
99
import { of } from 'rxjs';
10+
import { i18n } from '@osd/i18n';
11+
import { PATHS } from '../../common/constants';
12+
import { ApplicationStart } from '../../../../core/public';
13+
import { WORKSPACE_APP_ID, WORKSPACE_ID_IN_SESSION_STORAGE } from '../../common/constants';
1014

1115
import { useOpenSearchDashboards } from '../../../../../src/plugins/opensearch_dashboards_react/public';
1216

1317
export const WorkspaceOverview = () => {
1418
const {
15-
services: { workspaces },
16-
} = useOpenSearchDashboards();
19+
services: { workspaces, application, notifications },
20+
} = useOpenSearchDashboards<{ application: ApplicationStart }>();
1721

1822
const currentWorkspace = useObservable(
1923
workspaces ? workspaces.client.currentWorkspace$ : of(null)
2024
);
2125

26+
const onUpdateWorkspaceClick = () => {
27+
if (!currentWorkspace || !currentWorkspace.id) {
28+
notifications?.toasts.addDanger({
29+
title: i18n.translate('Cannot find current workspace', {
30+
defaultMessage: 'Cannot update workspace',
31+
}),
32+
});
33+
return;
34+
}
35+
application.navigateToApp(WORKSPACE_APP_ID, {
36+
path: PATHS.update + '?' + WORKSPACE_ID_IN_SESSION_STORAGE + '=' + currentWorkspace.id,
37+
});
38+
};
39+
2240
return (
2341
<>
2442
<EuiPageHeader
2543
pageTitle="Overview"
2644
rightSideItems={[
2745
<EuiButton color="danger">Delete</EuiButton>,
28-
<EuiButton>Update</EuiButton>,
46+
<EuiButton onClick={onUpdateWorkspaceClick}>Update</EuiButton>,
2947
]}
3048
/>
3149
<EuiPanel>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export { WorkspaceUpdater } from './workspace_updater';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import React, { useCallback, useEffect, useState } from 'react';
7+
import { EuiPage, EuiPageBody, EuiPageHeader, EuiPageContent } from '@elastic/eui';
8+
import { useObservable } from 'react-use';
9+
import { i18n } from '@osd/i18n';
10+
import { of } from 'rxjs';
11+
12+
import { WorkspaceAttribute } from 'opensearch-dashboards/public';
13+
import { useOpenSearchDashboards } from '../../../../../../src/plugins/opensearch_dashboards_react/public';
14+
15+
import { PATHS } from '../../../common/constants';
16+
import { WorkspaceForm, WorkspaceFormData } from '../workspace_creator/workspace_form';
17+
import {
18+
WORKSPACE_APP_ID,
19+
WORKSPACE_ID_IN_SESSION_STORAGE,
20+
WORKSPACE_OP_TYPE_UPDATE,
21+
} from '../../../common/constants';
22+
import { ApplicationStart } from '../../../../../core/public';
23+
24+
export const WorkspaceUpdater = () => {
25+
const {
26+
services: { application, workspaces, notifications },
27+
} = useOpenSearchDashboards<{ application: ApplicationStart }>();
28+
29+
const currentWorkspace = useObservable(
30+
workspaces ? workspaces.client.currentWorkspace$ : of(null)
31+
);
32+
33+
const excludedAttribute = 'id';
34+
const { [excludedAttribute]: removedProperty, ...otherAttributes } =
35+
currentWorkspace || ({} as WorkspaceAttribute);
36+
37+
const [currentWorkspaceFormData, setCurrentWorkspaceFormData] = useState<
38+
Omit<WorkspaceAttribute, 'id'>
39+
>(otherAttributes);
40+
41+
useEffect(() => {
42+
const { id, ...others } = currentWorkspace || ({} as WorkspaceAttribute);
43+
setCurrentWorkspaceFormData(others);
44+
}, [workspaces, currentWorkspace, excludedAttribute]);
45+
46+
const handleWorkspaceFormSubmit = useCallback(
47+
async (data: WorkspaceFormData) => {
48+
let result;
49+
if (!currentWorkspace) {
50+
notifications?.toasts.addDanger({
51+
title: i18n.translate('Cannot find current workspace', {
52+
defaultMessage: 'Cannot update workspace',
53+
}),
54+
});
55+
return;
56+
}
57+
try {
58+
result = await workspaces?.client.update(currentWorkspace?.id, data);
59+
} catch (error) {
60+
notifications?.toasts.addDanger({
61+
title: i18n.translate('workspace.update.failed', {
62+
defaultMessage: 'Failed to update workspace',
63+
}),
64+
text: error instanceof Error ? error.message : JSON.stringify(error),
65+
});
66+
return;
67+
}
68+
if (result?.success) {
69+
notifications?.toasts.addSuccess({
70+
title: i18n.translate('workspace.update.success', {
71+
defaultMessage: 'Update workspace successfully',
72+
}),
73+
});
74+
application.navigateToApp(WORKSPACE_APP_ID, {
75+
path: PATHS.overview + '?' + WORKSPACE_ID_IN_SESSION_STORAGE + '=' + currentWorkspace.id,
76+
});
77+
return;
78+
}
79+
notifications?.toasts.addDanger({
80+
title: i18n.translate('workspace.update.failed', {
81+
defaultMessage: 'Failed to update workspace',
82+
}),
83+
text: result?.error,
84+
});
85+
},
86+
[notifications?.toasts, workspaces?.client, currentWorkspace, application]
87+
);
88+
89+
if (!currentWorkspaceFormData.name) {
90+
return null;
91+
}
92+
93+
return (
94+
<EuiPage paddingSize="none">
95+
<EuiPageBody panelled>
96+
<EuiPageHeader restrictWidth pageTitle="Update Workspace" />
97+
<EuiPageContent
98+
verticalPosition="center"
99+
horizontalPosition="center"
100+
paddingSize="none"
101+
color="subdued"
102+
hasShadow={false}
103+
style={{ width: '100%', maxWidth: 1000 }}
104+
>
105+
{application && (
106+
<WorkspaceForm
107+
application={application}
108+
onSubmit={handleWorkspaceFormSubmit}
109+
defaultValues={currentWorkspaceFormData}
110+
opType={WORKSPACE_OP_TYPE_UPDATE}
111+
/>
112+
)}
113+
</EuiPageContent>
114+
</EuiPageBody>
115+
</EuiPage>
116+
);
117+
};

0 commit comments

Comments
 (0)