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]);