diff --git a/changelogs/fragments/8529.yml b/changelogs/fragments/8529.yml new file mode 100644 index 000000000000..4f57759a9e40 --- /dev/null +++ b/changelogs/fragments/8529.yml @@ -0,0 +1,2 @@ +fix: +- Update the title of header recent menu ([#8529](/~https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8529)) \ No newline at end of file diff --git a/changelogs/fragments/8543.yml b/changelogs/fragments/8543.yml new file mode 100644 index 000000000000..06bade085a1d --- /dev/null +++ b/changelogs/fragments/8543.yml @@ -0,0 +1,2 @@ +refactor: +- Update workspace collaborator table UI ([#8543](/~https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8543)) \ No newline at end of file diff --git a/src/core/public/chrome/ui/header/recent_items.tsx b/src/core/public/chrome/ui/header/recent_items.tsx index ee0554ece08d..7efd276b8fa9 100644 --- a/src/core/public/chrome/ui/header/recent_items.tsx +++ b/src/core/public/chrome/ui/header/recent_items.tsx @@ -276,7 +276,11 @@ export const RecentItems = ({ style={{ maxHeight: '35vh', overflow: 'auto' }} > -

Recent

+

+ {i18n.translate('core.header.recent.title', { + defaultMessage: 'Recent assets', + })} +

{selectedRecentsItems.length > 0 ? ( diff --git a/src/plugins/workspace/public/assets/background_pic.tsx b/src/plugins/workspace/public/assets/background_pic.tsx new file mode 100644 index 000000000000..5dab33d11d38 --- /dev/null +++ b/src/plugins/workspace/public/assets/background_pic.tsx @@ -0,0 +1,1942 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; + +export const BackgroundPic = () => ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+); diff --git a/src/plugins/workspace/public/components/workspace_detail_app.tsx b/src/plugins/workspace/public/components/workspace_detail_app.tsx index a393026552a5..b67d0eef6544 100644 --- a/src/plugins/workspace/public/components/workspace_detail_app.tsx +++ b/src/plugins/workspace/public/components/workspace_detail_app.tsx @@ -140,7 +140,7 @@ export const WorkspaceDetailApp = (props: WorkspaceDetailPropsWithOnAppLeave) => ); }, 1000); } - return; + return result; } else { setIsFormSubmitting(false); throw new Error(result?.error ? result?.error : 'update workspace failed'); diff --git a/src/plugins/workspace/public/components/workspace_form/__snapshots__/add_collaborator_button.test.tsx.snap b/src/plugins/workspace/public/components/workspace_form/__snapshots__/add_collaborator_button.test.tsx.snap index 98482f3f71b1..33aaf83531e2 100644 --- a/src/plugins/workspace/public/components/workspace_form/__snapshots__/add_collaborator_button.test.tsx.snap +++ b/src/plugins/workspace/public/components/workspace_form/__snapshots__/add_collaborator_button.test.tsx.snap @@ -19,17 +19,21 @@ Object { type="button" > Add collaborators +    + @@ -52,17 +56,21 @@ Object { type="button" > Add collaborators +    + diff --git a/src/plugins/workspace/public/components/workspace_form/add_collaborator_button.tsx b/src/plugins/workspace/public/components/workspace_form/add_collaborator_button.tsx index fe957574603b..c7360d173e02 100644 --- a/src/plugins/workspace/public/components/workspace_form/add_collaborator_button.tsx +++ b/src/plugins/workspace/public/components/workspace_form/add_collaborator_button.tsx @@ -4,7 +4,13 @@ */ import React, { useState, useRef, useCallback } from 'react'; -import { EuiPopover, EuiContextMenu, EuiButton, EuiContextMenuPanelDescriptor } from '@elastic/eui'; +import { + EuiPopover, + EuiContextMenu, + EuiSmallButton, + EuiContextMenuPanelDescriptor, + EuiIcon, +} from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { WorkspaceCollaboratorType } from '../../services/workspace_collaborator_types_service'; import { WorkspaceCollaborator } from '../../types'; @@ -66,18 +72,19 @@ export const AddCollaboratorButton = ({ id="add-collaborator-popover" data-test-subj="add-collaborator-popover" button={ - setIsPopoverOpen((prev) => !prev)} - size="s" data-test-subj="add-collaborator-button" > {i18n.translate('workspace.workspaceDetail.collaborator.add', { defaultMessage: 'Add collaborators', })} - +    + + } isOpen={isPopoverOpen} closePopover={() => setIsPopoverOpen(false)} diff --git a/src/plugins/workspace/public/components/workspace_form/types.ts b/src/plugins/workspace/public/components/workspace_form/types.ts index 43c960f274d5..7cc6dbb4c300 100644 --- a/src/plugins/workspace/public/components/workspace_form/types.ts +++ b/src/plugins/workspace/public/components/workspace_form/types.ts @@ -79,7 +79,10 @@ export type WorkspaceFormErrors = { export interface WorkspaceFormProps { application: ApplicationStart; savedObjects: SavedObjectsStart; - onSubmit?: (formData: WorkspaceFormSubmitData, refresh?: boolean) => void; + onSubmit?: ( + formData: WorkspaceFormSubmitData, + refresh?: boolean + ) => Promise<{ result: boolean; success: true } | undefined>; defaultValues?: Partial; operationType: WorkspaceOperationType; permissionEnabled?: boolean; diff --git a/src/plugins/workspace/public/components/workspace_form/use_workspace_form.test.ts b/src/plugins/workspace/public/components/workspace_form/use_workspace_form.test.ts index 52d65091cb89..ecb36acaa125 100644 --- a/src/plugins/workspace/public/components/workspace_form/use_workspace_form.test.ts +++ b/src/plugins/workspace/public/components/workspace_form/use_workspace_form.test.ts @@ -10,9 +10,18 @@ import { WorkspacePermissionMode } from '../../../common/constants'; import { WorkspaceOperationType, WorkspacePermissionItemType } from './constants'; import { WorkspaceFormSubmitData, WorkspaceFormErrorCode } from './types'; import { useWorkspaceForm } from './use_workspace_form'; +import { waitFor } from '@testing-library/dom'; -const setup = (defaultValues?: WorkspaceFormSubmitData, permissionEnabled = false) => { - const onSubmitMock = jest.fn(); +const setup = ({ + defaultValues, + permissionEnabled = false, + onSubmit, +}: { + defaultValues: WorkspaceFormSubmitData; + permissionEnabled?: boolean; + onSubmit?: jest.Mock; +}) => { + const onSubmitMock = onSubmit ?? jest.fn(); const renderResult = renderHook(useWorkspaceForm, { initialProps: { application: applicationServiceMock.createStartContract(), @@ -31,8 +40,10 @@ const setup = (defaultValues?: WorkspaceFormSubmitData, permissionEnabled = fals describe('useWorkspaceForm', () => { it('should return invalid workspace name error and not call onSubmit when invalid name', async () => { const { renderResult, onSubmitMock } = setup({ - id: 'foo', - name: '~', + defaultValues: { + id: 'foo', + name: '~', + }, }); expect(renderResult.result.current.formErrors).toEqual({}); @@ -51,8 +62,9 @@ describe('useWorkspaceForm', () => { }); it('should return "Use case is required. Select a use case." and not call onSubmit', async () => { const { renderResult, onSubmitMock } = setup({ - id: 'foo', - name: 'test-workspace-name', + defaultValues: { + name: 'test-workspace-name', + }, }); expect(renderResult.result.current.formErrors).toEqual({}); @@ -70,13 +82,13 @@ describe('useWorkspaceForm', () => { expect(onSubmitMock).not.toHaveBeenCalled(); }); it('should return "Add workspace owner." and not call onSubmit', async () => { - const { renderResult, onSubmitMock } = setup( - { + const { renderResult, onSubmitMock } = setup({ + defaultValues: { id: 'foo', name: 'test-workspace-name', }, - true - ); + permissionEnabled: true, + }); expect(renderResult.result.current.formErrors).toEqual({}); act(() => { @@ -111,9 +123,11 @@ describe('useWorkspaceForm', () => { }); it('should call onSubmit with workspace name and features', async () => { const { renderResult, onSubmitMock } = setup({ - id: 'foo', - name: 'test-workspace-name', - features: ['use-case-observability'], + defaultValues: { + id: 'foo', + name: 'test-workspace-name', + features: ['use-case-observability'], + }, }); expect(renderResult.result.current.formErrors).toEqual({}); @@ -130,9 +144,11 @@ describe('useWorkspaceForm', () => { }); it('should update selected use case', () => { const { renderResult } = setup({ - id: 'foo', - name: 'test-workspace-name', - features: ['use-case-observability'], + defaultValues: { + id: 'foo', + name: 'test-workspace-name', + features: ['use-case-observability'], + }, }); expect(renderResult.result.current.formData.useCase).toBe('observability'); @@ -144,9 +160,11 @@ describe('useWorkspaceForm', () => { it('should reset workspace form', () => { const { renderResult } = setup({ - id: 'test', - name: 'current-workspace-name', - features: ['use-case-observability'], + defaultValues: { + id: 'test', + name: 'current-workspace-name', + features: ['use-case-observability'], + }, }); expect(renderResult.result.current.formData.name).toBe('current-workspace-name'); @@ -160,4 +178,22 @@ describe('useWorkspaceForm', () => { }); expect(renderResult.result.current.formData.name).toBe('current-workspace-name'); }); + + it('should call setPermissionSettings if onSubmit successfully', async () => { + const onSubmitMock = jest.fn().mockResolvedValue({ success: true }); + const { renderResult } = setup({ + defaultValues: { + id: 'test', + name: 'current-workspace-name', + features: ['use-case-observability'], + }, + onSubmit: onSubmitMock, + }); + act(() => { + renderResult.result.current.handleSubmitPermissionSettings([]); + }); + await waitFor(() => { + expect(renderResult.result.current.formData.permissionSettings).toStrictEqual([]); + }); + }); }); diff --git a/src/plugins/workspace/public/components/workspace_form/use_workspace_form.ts b/src/plugins/workspace/public/components/workspace_form/use_workspace_form.ts index cac2c02bc414..70fe9fdb2c81 100644 --- a/src/plugins/workspace/public/components/workspace_form/use_workspace_form.ts +++ b/src/plugins/workspace/public/components/workspace_form/use_workspace_form.ts @@ -122,10 +122,9 @@ export const useWorkspaceForm = ({ [onSubmit, permissionEnabled] ); - const handleSubmitPermissionSettings = (settings: WorkspacePermissionSetting[]) => { - setPermissionSettings(settings); + const handleSubmitPermissionSettings = async (settings: WorkspacePermissionSetting[]) => { const currentFormData = getFormDataRef.current(); - onSubmit?.( + const result = await onSubmit?.( { name: currentFormData.name!, description: currentFormData.description, @@ -136,6 +135,9 @@ export const useWorkspaceForm = ({ }, false ); + if (result) { + setPermissionSettings(settings); + } }; const handleColorChange = useCallback['onChange']>((text) => { diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_collaborator_table.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_collaborator_table.tsx index ce0a40a4b0b1..f87ee2e894c5 100644 --- a/src/plugins/workspace/public/components/workspace_form/workspace_collaborator_table.tsx +++ b/src/plugins/workspace/public/components/workspace_form/workspace_collaborator_table.tsx @@ -17,6 +17,8 @@ import { EuiEmptyPrompt, EuiContextMenuPanelDescriptor, EuiText, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { WorkspacePermissionSetting } from './types'; @@ -31,6 +33,7 @@ import { accessLevelNameToWorkspacePermissionModesMap, } from '../../constants'; import { WorkspaceCollaborator, WorkspaceCollaboratorAccessLevel } from '../../types'; +import { BackgroundPic } from '../../assets/background_pic'; export type PermissionSetting = Pick & Partial; @@ -116,27 +119,34 @@ export const WorkspaceCollaboratorTable = ({ const emptyStateMessage = useMemo(() => { return ( - - {i18n.translate('workspace.workspaceDetail.collaborator.emptyState.title', { - defaultMessage: 'Your workspace doesn’t have any collaborators.', + + + + {i18n.translate('workspace.workspaceDetail.collaborator.emptyState.title', { + defaultMessage: 'Your workspace doesn’t have any collaborators.', + })} + + } + titleSize="s" + body={i18n.translate('workspace.workspaceDetail.collaborator.emptyState.body', { + defaultMessage: + 'Currently you’re the only user who has access to the workspace as an owner. Share this workspace by adding collaborators.', })} - - } - titleSize="s" - body={i18n.translate('workspace.workspaceDetail.collaborator.emptyState.body', { - defaultMessage: - 'Currently you’re the only user who has access to the workspace as an owner. Share this workspace by adding collaborators.', - })} - actions={ - + } /> - } - /> + + + + + ); }, [displayedCollaboratorTypes, permissionSettings, handleSubmitPermissionSettings]);