Skip to content

Commit

Permalink
[Workspace] Add permission tab to workspace create update page (opens…
Browse files Browse the repository at this point in the history
…earch-project#6378)

* Allow workspace update with partial attirbutes

Signed-off-by: Lin Wang <wonglam@amazon.com>

* Add permissions tab for workspace creator and update page

Signed-off-by: Lin Wang <wonglam@amazon.com>

* Add change log for adding permission tab

Signed-off-by: Lin Wang <wonglam@amazon.com>

* Optimize permissions to permissions settings convertation

Signed-off-by: Lin Wang <wonglam@amazon.com>

* Address PR comments

Signed-off-by: Lin Wang <wonglam@amazon.com>

* Update comments for getPermissionModeId

Signed-off-by: Lin Wang <wonglam@amazon.com>

---------

Signed-off-by: Lin Wang <wonglam@amazon.com>
  • Loading branch information
wanglam committed Apr 17, 2024
1 parent 32fab61 commit 33768ac
Show file tree
Hide file tree
Showing 24 changed files with 1,243 additions and 428 deletions.
4 changes: 4 additions & 0 deletions src/core/types/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ export interface WorkspaceAttributeWithPermission extends WorkspaceAttribute {
export interface WorkspaceObject extends WorkspaceAttributeWithPermission {
readonly?: boolean;
}

export interface WorkspaceAttributeWithPermission extends WorkspaceAttribute {
permissions?: Permissions;
}
2 changes: 1 addition & 1 deletion src/plugins/workspace/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const WORKSPACE_LIST_APP_ID = 'workspace_list';
export const WORKSPACE_UPDATE_APP_ID = 'workspace_update';
export const WORKSPACE_OVERVIEW_APP_ID = 'workspace_overview';
// These features will be checked and disabled in checkbox on default.
export const DEFAULT_CHECKED_FEATURES_IDS = [WORKSPACE_UPDATE_APP_ID, WORKSPACE_OVERVIEW_APP_ID];
export const DEFAULT_SELECTED_FEATURES_IDS = [WORKSPACE_UPDATE_APP_ID, WORKSPACE_OVERVIEW_APP_ID];
export const WORKSPACE_FATAL_ERROR_APP_ID = 'workspace_fatal_error';
export const WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID = 'workspace';
export const WORKSPACE_CONFLICT_CONTROL_SAVED_OBJECTS_CLIENT_WRAPPER_ID =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,47 @@ describe('WorkspaceCreator', () => {
expect(notificationToastsAddDanger).not.toHaveBeenCalled();
});

it('should show danger toasts after create workspace failed', async () => {
workspaceClientCreate.mockReturnValueOnce({ result: { id: 'failResult' }, success: false });
const { getByTestId } = render(<WorkspaceCreator />);
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
});
fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).toHaveBeenCalled();
await waitFor(() => {
expect(notificationToastsAddDanger).toHaveBeenCalled();
});
expect(notificationToastsAddSuccess).not.toHaveBeenCalled();
});

it('should show danger toasts after call create workspace API failed', async () => {
workspaceClientCreate.mockImplementationOnce(async () => {
throw new Error();
});
const { getByTestId } = render(<WorkspaceCreator />);
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
});
fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).toHaveBeenCalled();
await waitFor(() => {
expect(notificationToastsAddDanger).toHaveBeenCalled();
});
expect(notificationToastsAddSuccess).not.toHaveBeenCalled();
});

it('create workspace with customized permissions', async () => {
const { getByTestId, getByText } = render(<WorkspaceCreator />);
const { getByTestId, getByText, getAllByText } = render(<WorkspaceCreator />);
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
});
fireEvent.click(getByText('Users & Permissions'));
fireEvent.click(getByTestId('workspaceForm-permissionSettingPanel-user-addNew'));
const userIdInput = getByTestId('workspaceForm-permissionSettingPanel-0-userId');
const userIdInput = getAllByText('Select')[0];
fireEvent.click(userIdInput);
fireEvent.input(getByTestId('comboBoxSearchInput'), {
target: { value: 'test user id' },
Expand All @@ -215,19 +247,4 @@ describe('WorkspaceCreator', () => {
});
expect(notificationToastsAddDanger).not.toHaveBeenCalled();
});

it('should show danger toasts after create workspace failed', async () => {
workspaceClientCreate.mockReturnValue({ result: { id: 'failResult' }, success: false });
const { getByTestId } = render(<WorkspaceCreator />);
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
});
fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).toHaveBeenCalled();
await waitFor(() => {
expect(notificationToastsAddDanger).toHaveBeenCalled();
});
expect(notificationToastsAddSuccess).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import { WorkspaceForm, WorkspaceFormSubmitData, WorkspaceOperationType } from '
import { WORKSPACE_OVERVIEW_APP_ID } from '../../../common/constants';
import { formatUrlWithWorkspaceId } from '../../../../../core/public/utils';
import { WorkspaceClient } from '../../workspace_client';
import { convertPermissionSettingsToPermissions } from '../workspace_form/utils';
import { convertPermissionSettingsToPermissions } from '../workspace_form';

export const WorkspaceCreator = () => {
const {
services: { application, notifications, http, workspaceClient },
} = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>();

const isPermissionEnabled = application?.capabilities.workspaces.permissionEnabled;

const handleWorkspaceFormSubmit = useCallback(
async (data: WorkspaceFormSubmitData) => {
let result;
Expand All @@ -28,6 +28,29 @@ export const WorkspaceCreator = () => {
attributes,
convertPermissionSettingsToPermissions(permissionSettings)
);
if (result?.success) {
notifications?.toasts.addSuccess({
title: i18n.translate('workspace.create.success', {
defaultMessage: 'Create workspace successfully',
}),
});
if (application && http) {
const newWorkspaceId = result.result.id;
// Redirect page after one second, leave one second time to show create successful toast.
window.setTimeout(() => {
window.location.href = formatUrlWithWorkspaceId(
application.getUrlForApp(WORKSPACE_OVERVIEW_APP_ID, {
absolute: true,
}),
newWorkspaceId,
http.basePath
);
}, 1000);
}
return;
} else {
throw new Error(result?.error ? result?.error : 'create workspace failed');
}
} catch (error) {
notifications?.toasts.addDanger({
title: i18n.translate('workspace.create.failed', {
Expand All @@ -37,33 +60,6 @@ export const WorkspaceCreator = () => {
});
return;
}
if (result?.success) {
notifications?.toasts.addSuccess({
title: i18n.translate('workspace.create.success', {
defaultMessage: 'Create workspace successfully',
}),
});
if (application && http) {
const newWorkspaceId = result.result.id;
// Redirect page after one second, leave one second time to show create successful toast.
window.setTimeout(() => {
window.location.href = formatUrlWithWorkspaceId(
application.getUrlForApp(WORKSPACE_OVERVIEW_APP_ID, {
absolute: true,
}),
newWorkspaceId,
http.basePath
);
}, 1000);
}
return;
}
notifications?.toasts.addDanger({
title: i18n.translate('workspace.create.failed', {
defaultMessage: 'Failed to create workspace',
}),
text: result?.error,
});
},
[notifications?.toasts, http, application, workspaceClient]
);
Expand Down
22 changes: 11 additions & 11 deletions src/plugins/workspace/public/components/workspace_form/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@
import { i18n } from '@osd/i18n';
import { WorkspacePermissionMode } from '../../../common/constants';

export enum WorkspaceOperationType {
Create = 'create',
Update = 'update',
}

export enum WorkspaceFormTabs {
NotSelected,
FeatureVisibility,
UsersAndPermissions,
}

export enum WorkspacePermissionItemType {
User = 'user',
Group = 'group',
Expand Down Expand Up @@ -51,14 +62,3 @@ export const optionIdToWorkspacePermissionModesMap: {
],
[PermissionModeId.Admin]: [WorkspacePermissionMode.LibraryWrite, WorkspacePermissionMode.Write],
};

export enum WorkspaceOperationType {
Create = 'create',
Update = 'update',
}

export enum WorkspaceFormTabs {
NotSelected,
FeatureVisibility,
UsersAndPermissions,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
export { WorkspaceForm } from './workspace_form';
export { WorkspaceFormSubmitData } from './types';
export { WorkspaceOperationType } from './constants';
export {
convertPermissionsToPermissionSettings,
convertPermissionSettingsToPermissions,
} from './utils';
29 changes: 18 additions & 11 deletions src/plugins/workspace/public/components/workspace_form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,29 @@
* SPDX-License-Identifier: Apache-2.0
*/

import type { WorkspacePermissionItemType, WorkspaceOperationType } from './constants';
import type { WorkspacePermissionMode } from '../../../common/constants';
import type { ApplicationStart } from '../../../../../core/public';
import type { WorkspacePermissionMode } from '../../../common/constants';
import type { WorkspaceOperationType, WorkspacePermissionItemType } from './constants';

export type WorkspacePermissionSetting =
| { type: WorkspacePermissionItemType.User; userId: string; modes: WorkspacePermissionMode[] }
| { type: WorkspacePermissionItemType.Group; group: string; modes: WorkspacePermissionMode[] };
| {
id: number;
type: WorkspacePermissionItemType.User;
userId: string;
modes: WorkspacePermissionMode[];
}
| {
id: number;
type: WorkspacePermissionItemType.Group;
group: string;
modes: WorkspacePermissionMode[];
};

export interface WorkspaceFormSubmitData {
name: string;
description?: string;
features?: string[];
color?: string;
icon?: string;
defaultVISTheme?: string;
permissionSettings?: WorkspacePermissionSetting[];
}

Expand All @@ -36,11 +44,10 @@ export interface WorkspaceFeatureGroup {
features: WorkspaceFeature[];
}

export type WorkspaceFormErrors = Omit<
{ [key in keyof WorkspaceFormData]?: string },
'permissions'
> & {
permissions?: string[];
export type WorkspaceFormErrors = {
[key in keyof Omit<WorkspaceFormData, 'permissionSettings'>]?: string;
} & {
permissionSettings?: { [key: number]: string };
};

export interface WorkspaceFormProps {
Expand Down
Loading

0 comments on commit 33768ac

Please sign in to comment.