diff --git a/changelogs/fragments/7652.yml b/changelogs/fragments/7652.yml new file mode 100644 index 000000000000..132afc64c12c --- /dev/null +++ b/changelogs/fragments/7652.yml @@ -0,0 +1,2 @@ +feat: +- Update permission settings appearance ([#7652](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7652)) \ No newline at end of file diff --git a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx index e3463bc7d9f5..f42665acd1d1 100644 --- a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx +++ b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx @@ -252,7 +252,7 @@ describe('WorkspaceCreator', () => { target: { value: 'test workspace name' }, }); fireEvent.click(getByTestId('workspaceUseCase-observability')); - fireEvent.click(getByTestId('workspaceForm-permissionSettingPanel-user-addNew')); + fireEvent.click(getByTestId('workspaceForm-permissionSettingPanel-addNew')); fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton')); expect(workspaceClientCreate).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/src/plugins/workspace/public/components/workspace_form/constants.ts b/src/plugins/workspace/public/components/workspace_form/constants.ts index a69afeacbbbc..1224d5abb0ec 100644 --- a/src/plugins/workspace/public/components/workspace_form/constants.ts +++ b/src/plugins/workspace/public/components/workspace_form/constants.ts @@ -49,6 +49,11 @@ export const usersAndPermissionsTitle = i18n.translate('workspace.form.usersAndP defaultMessage: 'Workspaces access', }); +export const usersAndPermissionsCreatePageTitle = i18n.translate( + 'workspace.form.usersAndPermissions.createPage.title', + { defaultMessage: 'Add collaborators' } +); + export const detailsName = i18n.translate('workspace.form.workspaceDetails.name.label', { defaultMessage: 'Name', }); diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx index a968f560fb03..04e232736e2a 100644 --- a/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx +++ b/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx @@ -4,8 +4,8 @@ */ import React, { useRef } from 'react'; -import { EuiPanel, EuiSpacer, EuiTitle, EuiForm } from '@elastic/eui'; - +import { EuiPanel, EuiSpacer, EuiTitle, EuiForm, EuiText } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; import { WorkspaceFormProps } from './types'; import { useWorkspaceForm } from './use_workspace_form'; import { WorkspacePermissionSettingPanel } from './workspace_permission_setting_panel'; @@ -16,7 +16,7 @@ import { SelectDataSourcePanel } from './select_data_source_panel'; import { EnterDetailsPanel } from './workspace_enter_details_panel'; import { selectDataSourceTitle, - usersAndPermissionsTitle, + usersAndPermissionsCreatePageTitle, workspaceDetailsTitle, workspaceUseCaseTitle, } from './constants'; @@ -36,7 +36,6 @@ export const WorkspaceForm = (props: WorkspaceFormProps) => { formData, formErrors, numberOfErrors, - numberOfChanges, setName, setDescription, handleFormSubmit, @@ -95,8 +94,15 @@ export const WorkspaceForm = (props: WorkspaceFormProps) => { {permissionEnabled && ( -

{usersAndPermissionsTitle}

+

{usersAndPermissionsCreatePageTitle}

+ + + {i18n.translate('workspace.form.usersAndPermissions.description', { + defaultMessage: + 'You will be added as an owner to the workspace. Select additional users and user groups as workspace collaborators with different access levels.', + })} + ) => { const onGroupOrUserIdChangeMock = jest.fn(); const onPermissionModesChangeMock = jest.fn(); const onDeleteMock = jest.fn(); + const onTypeChangeMock = jest.fn(); const renderResult = render( ) => { onGroupOrUserIdChange={onGroupOrUserIdChangeMock} onPermissionModesChange={onPermissionModesChangeMock} onDelete={onDeleteMock} + onTypeChange={onTypeChangeMock} {...options} /> ); @@ -32,10 +34,41 @@ const setup = (options?: Partial) => { onGroupOrUserIdChangeMock, onPermissionModesChangeMock, onDeleteMock, + onTypeChangeMock, }; }; describe('WorkspacePermissionSettingInput', () => { + const originalOffsetHeight = Object.getOwnPropertyDescriptor( + HTMLElement.prototype, + 'offsetHeight' + ); + const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth'); + + beforeEach(() => { + Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { + configurable: true, + value: 600, + }); + Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { + configurable: true, + value: 600, + }); + }); + + afterEach(() => { + Object.defineProperty( + HTMLElement.prototype, + 'offsetHeight', + originalOffsetHeight as PropertyDescriptor + ); + Object.defineProperty( + HTMLElement.prototype, + 'offsetWidth', + originalOffsetWidth as PropertyDescriptor + ); + }); + it('should render consistent user id and permission modes', () => { const { renderResult } = setup({ userId: 'foo', @@ -44,9 +77,6 @@ describe('WorkspacePermissionSettingInput', () => { expect(renderResult.getByText('foo')).toBeInTheDocument(); expect(renderResult.getByText('Read')).toBeInTheDocument(); - expect( - renderResult.getByText('Read').closest('.euiButtonGroupButton-isSelected') - ).toBeInTheDocument(); }); it('should render consistent group id and permission modes', () => { const { renderResult } = setup({ @@ -57,19 +87,16 @@ describe('WorkspacePermissionSettingInput', () => { expect(renderResult.getByText('bar')).toBeInTheDocument(); expect(renderResult.getByText('Read & Write')).toBeInTheDocument(); - expect( - renderResult.getByText('Read & Write').closest('.euiButtonGroupButton-isSelected') - ).toBeInTheDocument(); }); it('should call onGroupOrUserIdChange with user id', () => { const { renderResult, onGroupOrUserIdChangeMock } = setup(); expect(onGroupOrUserIdChangeMock).not.toHaveBeenCalled(); fireEvent.click(renderResult.getByText('Select a user')); - fireEvent.input(renderResult.getByTestId('comboBoxSearchInput'), { + fireEvent.input(renderResult.getAllByTestId('comboBoxSearchInput')[0], { target: { value: 'user1' }, }); - fireEvent.blur(renderResult.getByTestId('comboBoxSearchInput')); + fireEvent.blur(renderResult.getAllByTestId('comboBoxSearchInput')[0]); expect(onGroupOrUserIdChangeMock).toHaveBeenCalledWith({ type: 'user', userId: 'user1' }, 0); }); it('should call onGroupOrUserIdChange with group', () => { @@ -79,10 +106,10 @@ describe('WorkspacePermissionSettingInput', () => { expect(onGroupOrUserIdChangeMock).not.toHaveBeenCalled(); fireEvent.click(renderResult.getByText('Select a user group')); - fireEvent.input(renderResult.getByTestId('comboBoxSearchInput'), { + fireEvent.input(renderResult.getAllByTestId('comboBoxSearchInput')[0], { target: { value: 'group' }, }); - fireEvent.blur(renderResult.getByTestId('comboBoxSearchInput')); + fireEvent.blur(renderResult.getAllByTestId('comboBoxSearchInput')[0]); expect(onGroupOrUserIdChangeMock).toHaveBeenCalledWith({ type: 'group', group: 'group' }, 0); }); @@ -100,6 +127,10 @@ describe('WorkspacePermissionSettingInput', () => { const { renderResult, onPermissionModesChangeMock } = setup({}); expect(onPermissionModesChangeMock).not.toHaveBeenCalled(); + const permissionToggleListButton = within( + renderResult.getAllByTestId('workspace-permissionModeOptions')[0] + ).getByTestId('comboBoxToggleListButton'); + fireEvent.click(permissionToggleListButton); fireEvent.click(renderResult.getByText('Owner')); expect(onPermissionModesChangeMock).toHaveBeenCalledWith(['library_write', 'write'], 0); }); @@ -111,4 +142,13 @@ describe('WorkspacePermissionSettingInput', () => { fireEvent.click(renderResult.getByLabelText('Delete permission setting')); expect(onDeleteMock).toHaveBeenCalledWith(0); }); + + it('should call onTypeChange with types after types changed', () => { + const { renderResult, onTypeChangeMock } = setup({}); + expect(onTypeChangeMock).not.toHaveBeenCalled(); + + fireEvent.click(renderResult.getByTestId('workspace-typeOptions')); + fireEvent.click(renderResult.getByText('Group')); + expect(onTypeChangeMock).toHaveBeenCalledWith('group', 0); + }); }); diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_input.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_input.tsx index 40165530c3b2..96c79b5b26da 100644 --- a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_input.tsx +++ b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_input.tsx @@ -3,14 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { EuiFlexGroup, - EuiCompressedComboBox, EuiFlexItem, + EuiComboBox, + EuiPopover, EuiButtonIcon, - EuiButtonGroup, - EuiText, + EuiButtonEmpty, + EuiSelectable, + EuiComboBoxOptionOption, + EuiSelectableOption, } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { WorkspacePermissionMode } from '../../../common/constants'; @@ -23,37 +26,25 @@ import { getPermissionModeId } from './utils'; const permissionModeOptions = [ { - id: PermissionModeId.Read, - label: ( - - {i18n.translate('workspace.form.permissionSettingPanel.permissionModeOptions.read', { - defaultMessage: 'Read', - })} - - ), + value: PermissionModeId.Read, + label: i18n.translate('workspace.form.permissionSettingPanel.permissionModeOptions.read', { + defaultMessage: 'Read', + }), }, { - id: PermissionModeId.ReadAndWrite, - label: ( - - {i18n.translate( - 'workspace.form.permissionSettingPanel.permissionModeOptions.readAndWrite', - { - defaultMessage: 'Read & Write', - } - )} - + value: PermissionModeId.ReadAndWrite, + label: i18n.translate( + 'workspace.form.permissionSettingPanel.permissionModeOptions.readAndWrite', + { + defaultMessage: 'Read & Write', + } ), }, { - id: PermissionModeId.Owner, - label: ( - - {i18n.translate('workspace.form.permissionSettingPanel.permissionModeOptions.owner', { - defaultMessage: 'Owner', - })} - - ), + value: PermissionModeId.Owner, + label: i18n.translate('workspace.form.permissionSettingPanel.permissionModeOptions.owner', { + defaultMessage: 'Owner', + }), }, ]; @@ -67,13 +58,14 @@ export interface WorkspacePermissionSettingInputProps { deletable?: boolean; userOrGroupDisabled: boolean; onGroupOrUserIdChange: ( - groupOrUserId: + id: | { type: WorkspacePermissionItemType.User; userId?: string } | { type: WorkspacePermissionItemType.Group; group?: string }, index: number ) => void; - onPermissionModesChange: ( - WorkspacePermissionMode: WorkspacePermissionMode[], + onPermissionModesChange: (modes: WorkspacePermissionMode[], index: number) => void; + onTypeChange: ( + type: WorkspacePermissionItemType.User | WorkspacePermissionItemType.Group, index: number ) => void; onDelete: (index: number) => void; @@ -91,13 +83,43 @@ export const WorkspacePermissionSettingInput = ({ onDelete, onGroupOrUserIdChange, onPermissionModesChange, + onTypeChange, }: WorkspacePermissionSettingInputProps) => { const groupOrUserIdSelectedOptions = useMemo( () => (group || userId ? [{ label: (group || userId) as string }] : []), [group, userId] ); - const permissionModesSelectedId = useMemo(() => getPermissionModeId(modes ?? []), [modes]); + const [isTypeListOpen, setIsTypeListOpen] = useState(false); + + const typeOptions = useMemo>>( + () => [ + { + value: WorkspacePermissionItemType.User, + label: i18n.translate('workspace.form.permissionSettingPanel.typeOptions.user', { + defaultMessage: 'User', + }), + checked: type === WorkspacePermissionItemType.User ? 'on' : undefined, + }, + { + value: WorkspacePermissionItemType.Group, + label: i18n.translate('workspace.form.permissionSettingPanel.typeOptions.group', { + defaultMessage: 'Group', + }), + checked: type === WorkspacePermissionItemType.Group ? 'on' : undefined, + }, + ], + [type] + ); + + const permissionModesSelected = useMemo(() => { + const idSelected = getPermissionModeId(modes ?? []); + const permissionModeSelected = permissionModeOptions.find( + (option) => option.value === idSelected + ); + return permissionModeSelected ? [permissionModeSelected] : []; + }, [modes]); + const handleGroupOrUserIdCreate = useCallback( (groupOrUserId) => { onGroupOrUserIdChange( @@ -111,7 +133,7 @@ export const WorkspacePermissionSettingInput = ({ ); const handleGroupOrUserIdChange = useCallback( - (options) => { + (options: Array>) => { if (options.length === 0) { onGroupOrUserIdChange({ type }, index); } @@ -120,23 +142,40 @@ export const WorkspacePermissionSettingInput = ({ ); const handlePermissionModeOptionChange = useCallback( - (id: string) => { - if (optionIdToWorkspacePermissionModesMap[id]) { - onPermissionModesChange([...optionIdToWorkspacePermissionModesMap[id]], index); + (option: Array>) => { + if (option.length > 0) { + const id = option[0].value; + if (optionIdToWorkspacePermissionModesMap[id]) { + onPermissionModesChange([...optionIdToWorkspacePermissionModesMap[id]], index); + } } }, [index, onPermissionModesChange] ); + const handleTypeChange = useCallback( + (options: Array>) => { + for (const option of options) { + if (option.checked === 'on') { + onTypeChange(option.value, index); + setIsTypeListOpen(false); + return; + } + } + }, + [index, onTypeChange] + ); + const handleDelete = useCallback(() => { onDelete(index); }, [index, onDelete]); return ( - + - setIsTypeListOpen((current) => !current)} + data-test-subj="workspace-typeOptions" + isDisabled={userOrGroupDisabled || !isEditing} + > + {type === WorkspacePermissionItemType.User + ? typeOptions[0].label + : typeOptions[1].label} + + } + isOpen={isTypeListOpen} + closePopover={() => setIsTypeListOpen(false)} + panelPaddingSize="none" + > + + {(list) => list} + + + } /> - - + @@ -170,7 +242,7 @@ export const WorkspacePermissionSettingInput = ({ color="danger" aria-label="Delete permission setting" iconType="trash" - display="base" + display="empty" size="m" onClick={handleDelete} isDisabled={!deletable} diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.test.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.test.tsx index 6e8a3ffb62dc..5dccb1831339 100644 --- a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.test.tsx +++ b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.test.tsx @@ -4,7 +4,7 @@ */ import React from 'react'; -import { fireEvent, render } from '@testing-library/react'; +import { fireEvent, render, waitFor, within } from '@testing-library/react'; import { WorkspacePermissionSettingPanel, WorkspacePermissionSettingPanelProps, @@ -43,25 +43,55 @@ const setup = (options?: Partial) => { }; describe('WorkspacePermissionSettingInput', () => { + const originalOffsetHeight = Object.getOwnPropertyDescriptor( + HTMLElement.prototype, + 'offsetHeight' + ); + const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth'); + + beforeEach(() => { + Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { + configurable: true, + value: 600, + }); + Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { + configurable: true, + value: 600, + }); + }); + + afterEach(() => { + Object.defineProperty( + HTMLElement.prototype, + 'offsetHeight', + originalOffsetHeight as PropertyDescriptor + ); + Object.defineProperty( + HTMLElement.prototype, + 'offsetWidth', + originalOffsetWidth as PropertyDescriptor + ); + }); + it('should render consistent user and group permissions', () => { const { renderResult } = setup(); expect(renderResult.getByText('foo')).toBeInTheDocument(); - expect( - renderResult.getAllByText('Read')[0].closest('.euiButtonGroupButton-isSelected') - ).toBeInTheDocument(); + expect(renderResult.getByText('Read')).toBeInTheDocument(); expect(renderResult.getByText('bar')).toBeInTheDocument(); - expect( - renderResult.getAllByText('Read & Write')[1].closest('.euiButtonGroupButton-isSelected') - ).toBeInTheDocument(); + expect(renderResult.getByText('Read & Write')).toBeInTheDocument(); }); it('should call onChange with new user permission modes', () => { const { renderResult, onChangeMock } = setup(); expect(onChangeMock).not.toHaveBeenCalled(); - fireEvent.click(renderResult.getAllByText('Read & Write')[0]); + const permissionToggleListButton = within( + renderResult.getAllByTestId('workspace-permissionModeOptions')[0] + ).getByTestId('comboBoxToggleListButton'); + fireEvent.click(permissionToggleListButton); + fireEvent.click(renderResult.getAllByText('Read & Write')[1]); expect(onChangeMock).toHaveBeenCalledWith([ { id: 0, @@ -81,7 +111,11 @@ describe('WorkspacePermissionSettingInput', () => { const { renderResult, onChangeMock } = setup(); expect(onChangeMock).not.toHaveBeenCalled(); - fireEvent.click(renderResult.getAllByText('Owner')[1]); + const permissionToggleListButton = within( + renderResult.getAllByTestId('workspace-permissionModeOptions')[1] + ).getByTestId('comboBoxToggleListButton'); + fireEvent.click(permissionToggleListButton); + fireEvent.click(renderResult.getByText('Owner')); expect(onChangeMock).toHaveBeenCalledWith([ { id: 0, @@ -97,6 +131,50 @@ describe('WorkspacePermissionSettingInput', () => { }, ]); }); + it('should call onChange with new user type', () => { + const { renderResult, onChangeMock } = setup(); + expect(onChangeMock).not.toHaveBeenCalled(); + + waitFor(() => { + fireEvent.click(renderResult.getAllByTestId('workspace-typeOptions')[1]); + fireEvent.click(renderResult.getAllByText('User')[1]); + expect(onChangeMock).toHaveBeenCalledWith([ + { + id: 0, + type: WorkspacePermissionItemType.User, + userId: 'foo', + modes: ['library_read', 'read'], + }, + { + id: 1, + type: WorkspacePermissionItemType.User, + modes: ['library_write', 'read'], + }, + ]); + }); + }); + it('should call onChange with new group type', () => { + const { renderResult, onChangeMock } = setup(); + + expect(onChangeMock).not.toHaveBeenCalled(); + waitFor(() => { + fireEvent.click(renderResult.getAllByTestId('workspace-typeOptions')[0]); + fireEvent.click(renderResult.getAllByText('Group')[0]); + expect(onChangeMock).toHaveBeenCalledWith([ + { + id: 0, + type: WorkspacePermissionItemType.Group, + modes: ['library_read', 'read'], + }, + { + id: 1, + type: WorkspacePermissionItemType.Group, + group: 'bar', + modes: ['library_write', 'read'], + }, + ]); + }); + }); it('should call onChange with new user permission setting after add new button click', () => { const { renderResult, onChangeMock } = setup({ @@ -104,7 +182,7 @@ describe('WorkspacePermissionSettingInput', () => { }); expect(onChangeMock).not.toHaveBeenCalled(); - fireEvent.click(renderResult.getByTestId('workspaceForm-permissionSettingPanel-user-addNew')); + fireEvent.click(renderResult.getByTestId('workspaceForm-permissionSettingPanel-addNew')); expect(onChangeMock).toHaveBeenCalledWith([ { id: 0, @@ -114,22 +192,29 @@ describe('WorkspacePermissionSettingInput', () => { ]); }); - it('should call onChange with new group permission setting after add new button click', () => { - const { renderResult, onChangeMock } = setup({ - permissionSettings: [], - }); + it('should call onChange with user permission setting after delete button click', () => { + const { renderResult, onChangeMock } = setup(); expect(onChangeMock).not.toHaveBeenCalled(); - fireEvent.click(renderResult.getByTestId('workspaceForm-permissionSettingPanel-group-addNew')); + fireEvent.click(renderResult.getAllByLabelText('Delete permission setting')[0]); expect(onChangeMock).toHaveBeenCalledWith([ { - id: 0, + id: 1, type: WorkspacePermissionItemType.Group, - modes: [WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.Read], + group: 'bar', + modes: [WorkspacePermissionMode.LibraryWrite, WorkspacePermissionMode.Read], }, ]); }); + it('should call onGroupOrUserIdChange without user id after clear button clicked', () => { + const { renderResult, onChangeMock } = setup(); + + expect(onChangeMock).not.toHaveBeenCalled(); + fireEvent.click(renderResult.getAllByTestId('comboBoxClearButton')[0]); + expect(onChangeMock).toHaveBeenCalled(); + }); + it('should not able to edit user or group when disabled', () => { const { renderResult } = setup({ permissionSettings: [ diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.tsx index b9027697dee4..951615279d94 100644 --- a/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.tsx +++ b/src/plugins/workspace/public/components/workspace_form/workspace_permission_setting_panel.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useCallback, useEffect, useMemo, useRef } from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; import { EuiSmallButton, EuiFlexGroup, @@ -36,57 +36,74 @@ export interface WorkspacePermissionSettingPanelProps { isEditing?: boolean; } -interface UserOrGroupSectionProps extends WorkspacePermissionSettingPanelProps { - type: WorkspacePermissionItemType; - nextIdGenerator: () => number; -} - -const UserOrGroupSection = ({ - type, +export const WorkspacePermissionSettingPanel = ({ errors, onChange, - isEditing, - nextIdGenerator, + isEditing = true, permissionSettings, disabledUserOrGroupInputIds, -}: UserOrGroupSectionProps) => { +}: WorkspacePermissionSettingPanelProps) => { + const nextIdRef = useRef(generateNextPermissionSettingsId(permissionSettings)); + + const handlePermissionSettingsChange = useCallback( + (newSettings) => { + onChange?.([...newSettings]); + }, + [onChange] + ); + + const nextIdGenerator = useCallback(() => { + const nextId = nextIdRef.current; + nextIdRef.current++; + return nextId; + }, []); + + useEffect(() => { + nextIdRef.current = Math.max( + nextIdRef.current, + generateNextPermissionSettingsId(permissionSettings) + ); + }, [permissionSettings]); + // default permission mode is read const handleAddNewOne = useCallback(() => { - onChange?.([ + handlePermissionSettingsChange?.([ ...permissionSettings, { id: nextIdGenerator(), - type, + type: WorkspacePermissionItemType.User, modes: optionIdToWorkspacePermissionModesMap[PermissionModeId.Read], }, ]); - }, [onChange, type, permissionSettings, nextIdGenerator]); + }, [handlePermissionSettingsChange, permissionSettings, nextIdGenerator]); const handleDelete = useCallback( (index: number) => { - onChange?.(permissionSettings.filter((_item, itemIndex) => itemIndex !== index)); + handlePermissionSettingsChange?.( + permissionSettings.filter((_item, itemIndex) => itemIndex !== index) + ); }, - [onChange, permissionSettings] + [handlePermissionSettingsChange, permissionSettings] ); const handlePermissionModesChange = useCallback< WorkspacePermissionSettingInputProps['onPermissionModesChange'] >( (modes, index) => { - onChange?.( + handlePermissionSettingsChange?.( permissionSettings.map((item, itemIndex) => index === itemIndex ? { ...item, modes } : item ) ); }, - [onChange, permissionSettings] + [handlePermissionSettingsChange, permissionSettings] ); const handleGroupOrUserIdChange = useCallback< WorkspacePermissionSettingInputProps['onGroupOrUserIdChange'] >( (userOrGroupIdWithType, index) => { - onChange?.( + handlePermissionSettingsChange?.( permissionSettings.map((item, itemIndex) => index === itemIndex ? { @@ -98,7 +115,18 @@ const UserOrGroupSection = ({ ) ); }, - [onChange, permissionSettings] + [handlePermissionSettingsChange, permissionSettings] + ); + + const handleTypeChange = useCallback( + (type, index) => { + handlePermissionSettingsChange?.( + permissionSettings.map((item, itemIndex) => + index === itemIndex ? { id: item.id, type, modes: item.modes } : item + ) + ); + }, + [handlePermissionSettingsChange, permissionSettings] ); return ( @@ -106,15 +134,9 @@ const UserOrGroupSection = ({ <> @@ -122,7 +144,7 @@ const UserOrGroupSection = ({ <> @@ -139,12 +161,13 @@ const UserOrGroupSection = ({ > @@ -154,94 +177,15 @@ const UserOrGroupSection = ({ - {type === WorkspacePermissionItemType.User - ? i18n.translate('workspace.form.permissionSettingPanel.addUser', { - defaultMessage: 'Add user', - }) - : i18n.translate('workspace.form.permissionSettingPanel.addUserGroup', { - defaultMessage: 'Add user group', - })} + {i18n.translate('workspace.form.permissionSettingPanel.addCollaborator', { + defaultMessage: 'Add collaborator', + })} )} ); }; - -export const WorkspacePermissionSettingPanel = ({ - errors, - onChange, - permissionSettings, - disabledUserOrGroupInputIds, - isEditing = true, -}: WorkspacePermissionSettingPanelProps) => { - const userPermissionSettings = useMemo( - () => - permissionSettings?.filter( - (permissionSettingItem) => permissionSettingItem.type === WorkspacePermissionItemType.User - ) ?? [], - [permissionSettings] - ); - const groupPermissionSettings = useMemo( - () => - permissionSettings?.filter( - (permissionSettingItem) => permissionSettingItem.type === WorkspacePermissionItemType.Group - ) ?? [], - [permissionSettings] - ); - - const nextIdRef = useRef(generateNextPermissionSettingsId(permissionSettings)); - - const handleUserPermissionSettingsChange = useCallback( - (newSettings) => { - onChange?.([...newSettings, ...groupPermissionSettings]); - }, - [groupPermissionSettings, onChange] - ); - - const handleGroupPermissionSettingsChange = useCallback( - (newSettings) => { - onChange?.([...userPermissionSettings, ...newSettings]); - }, - [userPermissionSettings, onChange] - ); - - const nextIdGenerator = useCallback(() => { - const nextId = nextIdRef.current; - nextIdRef.current++; - return nextId; - }, []); - - useEffect(() => { - nextIdRef.current = Math.max( - nextIdRef.current, - generateNextPermissionSettingsId(permissionSettings) - ); - }, [permissionSettings]); - - return ( -
- - - -
- ); -};