From 43acbfb6d20382491a63cd6aaa1177c8ee1416df Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Mon, 9 Oct 2023 14:09:54 +0800
Subject: [PATCH 01/22] feat: enable workspace id in basePath
Signed-off-by: SuZhou-Joe
---
src/plugins/workspace/server/plugin.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts
index d926727fd569..9e9d3517593c 100644
--- a/src/plugins/workspace/server/plugin.ts
+++ b/src/plugins/workspace/server/plugin.ts
@@ -72,6 +72,8 @@ export class WorkspacePlugin implements Plugin<{}, {}> {
this.proxyWorkspaceTrafficToRealHandler(core);
+ this.proxyWorkspaceTrafficToRealHandler(core);
+
registerRoutes({
http: core.http,
logger: this.logger,
From 3c128d177d38134298222c90da41fd6eb33a64fe Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Tue, 10 Oct 2023 14:29:01 +0800
Subject: [PATCH 02/22] feat: add unit test
Signed-off-by: SuZhou-Joe
---
src/core/public/http/base_path.test.ts | 32 +++
src/core/public/http/http_service.test.ts | 26 +++
src/core/public/utils/workspace.test.ts | 16 ++
.../workspace_fatal_error.test.tsx.snap | 182 ++++++++++++++++++
.../workspace_fatal_error.test.tsx | 21 ++
src/plugins/workspace/public/plugin.test.ts | 112 +++++++++++
.../workspace/public/workspace_client.mock.ts | 25 +++
7 files changed, 414 insertions(+)
create mode 100644 src/core/public/utils/workspace.test.ts
create mode 100644 src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
create mode 100644 src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
create mode 100644 src/plugins/workspace/public/plugin.test.ts
create mode 100644 src/plugins/workspace/public/workspace_client.mock.ts
diff --git a/src/core/public/http/base_path.test.ts b/src/core/public/http/base_path.test.ts
index 27cfa9bf0581..f80d41631b9b 100644
--- a/src/core/public/http/base_path.test.ts
+++ b/src/core/public/http/base_path.test.ts
@@ -110,4 +110,36 @@ describe('BasePath', () => {
expect(new BasePath('/foo/bar', '/foo').serverBasePath).toEqual('/foo');
});
});
+
+ describe('workspaceBasePath', () => {
+ it('get path with workspace', () => {
+ expect(new BasePath('/foo/bar', '/foo/bar', '/workspace').get()).toEqual(
+ '/foo/bar/workspace'
+ );
+ });
+
+ it('getBasePath with workspace provided', () => {
+ expect(new BasePath('/foo/bar', '/foo/bar', '/workspace').getBasePath()).toEqual('/foo/bar');
+ });
+
+ it('prepend with workspace provided', () => {
+ expect(new BasePath('/foo/bar', '/foo/bar', '/workspace').prepend('/prepend')).toEqual(
+ '/foo/bar/workspace/prepend'
+ );
+ });
+
+ it('prepend with workspace provided but calls without workspace', () => {
+ expect(
+ new BasePath('/foo/bar', '/foo/bar', '/workspace').prepend('/prepend', {
+ withoutWorkspace: true,
+ })
+ ).toEqual('/foo/bar/prepend');
+ });
+
+ it('remove with workspace provided', () => {
+ expect(
+ new BasePath('/foo/bar', '/foo/bar', '/workspace').remove('/foo/bar/workspace/remove')
+ ).toEqual('/remove');
+ });
+ });
});
diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts
index e60e506dfc0a..5671064e4c52 100644
--- a/src/core/public/http/http_service.test.ts
+++ b/src/core/public/http/http_service.test.ts
@@ -74,6 +74,32 @@ describe('#setup()', () => {
// We don't verify that this Observable comes from Fetch#getLoadingCount$() to avoid complex mocking
expect(loadingServiceSetup.addLoadingCountSource).toHaveBeenCalledWith(expect.any(Observable));
});
+
+ it('setup basePath without workspaceId provided in window.location.href', () => {
+ const injectedMetadata = injectedMetadataServiceMock.createSetupContract();
+ const fatalErrors = fatalErrorsServiceMock.createSetupContract();
+ const httpService = new HttpService();
+ const setupResult = httpService.setup({ fatalErrors, injectedMetadata });
+ expect(setupResult.basePath.get()).toEqual('');
+ });
+
+ it('setup basePath with workspaceId provided in window.location.href', () => {
+ const windowSpy = jest.spyOn(window, 'window', 'get');
+ windowSpy.mockImplementation(
+ () =>
+ ({
+ location: {
+ href: 'http://localhost/w/workspaceId/app',
+ },
+ } as any)
+ );
+ const injectedMetadata = injectedMetadataServiceMock.createSetupContract();
+ const fatalErrors = fatalErrorsServiceMock.createSetupContract();
+ const httpService = new HttpService();
+ const setupResult = httpService.setup({ fatalErrors, injectedMetadata });
+ expect(setupResult.basePath.get()).toEqual('/w/workspaceId');
+ windowSpy.mockRestore();
+ });
});
describe('#stop()', () => {
diff --git a/src/core/public/utils/workspace.test.ts b/src/core/public/utils/workspace.test.ts
new file mode 100644
index 000000000000..ab15152ddf04
--- /dev/null
+++ b/src/core/public/utils/workspace.test.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { getWorkspaceIdFromUrl } from './workspace';
+
+describe('#getWorkspaceIdFromUrl', () => {
+ it('return workspace when there is a match', () => {
+ expect(getWorkspaceIdFromUrl('/w/foo')).toEqual('foo');
+ });
+
+ it('return empty when there is not a match', () => {
+ expect(getWorkspaceIdFromUrl('/w2/foo')).toEqual('');
+ });
+});
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap b/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
new file mode 100644
index 000000000000..df744cde09c8
--- /dev/null
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
@@ -0,0 +1,182 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` render error with callout 1`] = `
+
+
+
+
+
+
+
+
+
+ Something went wrong
+
+
+
+
+
+
+
+ The workspace you want to go can not be found, try go back to home.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[` render normally 1`] = `
+
+
+
+
+
+
+
+
+
+ Something went wrong
+
+
+
+
+
+
+
+ The workspace you want to go can not be found, try go back to home.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
new file mode 100644
index 000000000000..f69007cb381a
--- /dev/null
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
@@ -0,0 +1,21 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { WorkspaceFatalError } from './workspace_fatal_error';
+describe('', () => {
+ it('render normally', async () => {
+ const { findByText, container } = render();
+ await findByText('Something went wrong');
+ expect(container).toMatchSnapshot();
+ });
+
+ it('render error with callout', async () => {
+ const { findByText, container } = render();
+ await findByText('errorInCallout');
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/workspace/public/plugin.test.ts b/src/plugins/workspace/public/plugin.test.ts
new file mode 100644
index 000000000000..4deb3ebce359
--- /dev/null
+++ b/src/plugins/workspace/public/plugin.test.ts
@@ -0,0 +1,112 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { workspaceClientMock, WorkspaceClientMock } from './workspace_client.mock';
+import { applicationServiceMock, chromeServiceMock, coreMock } from '../../../core/public/mocks';
+import { WorkspacePlugin } from './plugin';
+import { WORKSPACE_FATAL_ERROR_APP_ID, WORKSPACE_OVERVIEW_APP_ID } from '../common/constants';
+import { Observable, Subscriber } from 'rxjs';
+
+describe('Workspace plugin', () => {
+ beforeEach(() => {
+ WorkspaceClientMock.mockClear();
+ Object.values(workspaceClientMock).forEach((item) => item.mockClear());
+ });
+ it('#setup', async () => {
+ const setupMock = coreMock.createSetup();
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ expect(setupMock.application.register).toBeCalledTimes(1);
+ expect(setupMock.workspaces.workspaceEnabled$.getValue()).toEqual(true);
+ expect(WorkspaceClientMock).toBeCalledTimes(1);
+ expect(workspaceClientMock.enterWorkspace).toBeCalledTimes(0);
+ });
+
+ it('#setup when workspace id is in url and enterWorkspace return error', async () => {
+ const windowSpy = jest.spyOn(window, 'window', 'get');
+ windowSpy.mockImplementation(
+ () =>
+ ({
+ location: {
+ href: 'http://localhost/w/workspaceId/app',
+ },
+ } as any)
+ );
+ workspaceClientMock.enterWorkspace.mockResolvedValue({
+ success: false,
+ error: 'error',
+ });
+ const setupMock = coreMock.createSetup();
+ const applicationStartMock = applicationServiceMock.createStartContract();
+ const chromeStartMock = chromeServiceMock.createStartContract();
+ setupMock.getStartServices.mockImplementation(() => {
+ return Promise.resolve([
+ {
+ application: applicationStartMock,
+ chrome: chromeStartMock,
+ },
+ {},
+ {},
+ ]) as any;
+ });
+
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ expect(setupMock.application.register).toBeCalledTimes(1);
+ expect(setupMock.workspaces.workspaceEnabled$.getValue()).toEqual(true);
+ expect(WorkspaceClientMock).toBeCalledTimes(1);
+ expect(workspaceClientMock.enterWorkspace).toBeCalledWith('workspaceId');
+ expect(setupMock.getStartServices).toBeCalledTimes(1);
+ await new Promise((resolve: any) => setTimeout(resolve, 1000));
+ expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_FATAL_ERROR_APP_ID, {
+ replace: true,
+ state: {
+ error: 'error',
+ },
+ });
+ windowSpy.mockRestore();
+ });
+
+ it('#setup when workspace id is in url and enterWorkspace return success', async () => {
+ const windowSpy = jest.spyOn(window, 'window', 'get');
+ windowSpy.mockImplementation(
+ () =>
+ ({
+ location: {
+ href: 'http://localhost/w/workspaceId/app',
+ },
+ } as any)
+ );
+ workspaceClientMock.enterWorkspace.mockResolvedValue({
+ success: true,
+ error: 'error',
+ });
+ const setupMock = coreMock.createSetup();
+ const applicationStartMock = applicationServiceMock.createStartContract();
+ let currentAppIdSubscriber: Subscriber | undefined;
+ setupMock.getStartServices.mockImplementation(() => {
+ return Promise.resolve([
+ {
+ application: {
+ ...applicationStartMock,
+ currentAppId$: new Observable((subscriber) => {
+ currentAppIdSubscriber = subscriber;
+ }),
+ },
+ },
+ {},
+ {},
+ ]) as any;
+ });
+
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ await new Promise((resolve: any) => setTimeout(resolve, 0));
+ currentAppIdSubscriber?.next(WORKSPACE_FATAL_ERROR_APP_ID);
+ await new Promise((resolve: any) => setTimeout(resolve, 0));
+ expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_OVERVIEW_APP_ID);
+ windowSpy.mockRestore();
+ });
+});
diff --git a/src/plugins/workspace/public/workspace_client.mock.ts b/src/plugins/workspace/public/workspace_client.mock.ts
new file mode 100644
index 000000000000..2ceeae5627d1
--- /dev/null
+++ b/src/plugins/workspace/public/workspace_client.mock.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const workspaceClientMock = {
+ init: jest.fn(),
+ enterWorkspace: jest.fn(),
+ getCurrentWorkspaceId: jest.fn(),
+ getCurrentWorkspace: jest.fn(),
+ create: jest.fn(),
+ delete: jest.fn(),
+ list: jest.fn(),
+ get: jest.fn(),
+ update: jest.fn(),
+ stop: jest.fn(),
+};
+
+export const WorkspaceClientMock = jest.fn(function () {
+ return workspaceClientMock;
+});
+
+jest.doMock('./workspace_client', () => ({
+ WorkspaceClient: WorkspaceClientMock,
+}));
From c5a1a6466d8451ccb019351aeee43ef34785e46e Mon Sep 17 00:00:00 2001
From: tygao
Date: Tue, 10 Oct 2023 15:13:58 +0800
Subject: [PATCH 03/22] Register Advance Settings, Data Source management,Index
Pattern management and SavedObject management as standalone app, retire
dashboard management (#208)
* feat: init retire dashboard management
Signed-off-by: tygao
* move index pattern to Library (#91)
* move index pattern to libaray
Signed-off-by: Hailong Cui
* Remove it from Dashboards management when workspace is on
Signed-off-by: Hailong Cui
---------
Signed-off-by: Hailong Cui
index pattern always show under library
Signed-off-by: Hailong Cui
* functional test
Signed-off-by: Hailong Cui
* feat: move data source / advanced settings / saved objects management out of Dashboard management
Signed-off-by: SuZhou-Joe
* feat: update test
Signed-off-by: SuZhou-Joe
* feat: update snapshot
Signed-off-by: SuZhou-Joe
* feat: update snapshot
Signed-off-by: SuZhou-Joe
* fix: fix failed overview header ut
Signed-off-by: tygao
* fix: deeplink inside saved objects management page
Signed-off-by: SuZhou-Joe
* fix: unit test fail
Signed-off-by: SuZhou-Joe
* feat: add unit test for each page wrapper
Signed-off-by: SuZhou-Joe
* feat: some optimization
Signed-off-by: SuZhou-Joe
* remove management dependency
Signed-off-by: Hailong Cui
* test: update cypress config to use workspace branch
Signed-off-by: tygao
* Replace ManagementAppMountParams with AppMountParameters
Signed-off-by: Hailong Cui
---------
Signed-off-by: tygao
Signed-off-by: Hailong Cui
Signed-off-by: SuZhou-Joe
Co-authored-by: Hailong Cui
Co-authored-by: SuZhou-Joe
---
.github/workflows/cypress_workflow.yml | 2 +-
.../__snapshots__/page_wrapper.test.tsx.snap | 13 +++
.../page_wrapper/page_wrapper.test.tsx | 16 ++++
.../components/page_wrapper/page_wrapper.tsx | 4 +-
.../mount_management_section.tsx | 22 ++---
.../__snapshots__/page_wrapper.test.tsx.snap | 13 +++
.../page_wrapper/page_wrapper.test.tsx | 16 ++++
.../components/page_wrapper/page_wrapper.tsx | 4 +-
.../components/new_theme_modal.tsx | 4 +-
.../opensearch_dashboards.json | 2 +-
.../mount_management_section.tsx | 80 +++++++++++--------
.../index_pattern_management/public/plugin.ts | 11 +--
.../management_section/mount_section.tsx | 60 +++++++-------
.../__snapshots__/header.test.tsx.snap | 4 +-
.../objects_table/saved_objects_table.tsx | 6 +-
.../__snapshots__/page_wrapper.test.tsx.snap | 13 +++
.../management_section/page_wrapper/index.ts | 6 ++
.../page_wrapper/page_wrapper.test.tsx | 16 ++++
.../page_wrapper/page_wrapper.tsx | 21 +++++
.../saved_objects_table_page.tsx | 6 --
.../saved_objects_management/public/plugin.ts | 7 +-
21 files changed, 207 insertions(+), 119 deletions(-)
create mode 100644 src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
create mode 100644 src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx
create mode 100644 src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
create mode 100644 src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx
create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts
create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx
create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx
diff --git a/.github/workflows/cypress_workflow.yml b/.github/workflows/cypress_workflow.yml
index 42894281fe4f..b8527eef1ed8 100644
--- a/.github/workflows/cypress_workflow.yml
+++ b/.github/workflows/cypress_workflow.yml
@@ -3,7 +3,7 @@ name: Run cypress tests
# trigger on every PR for all branches
on:
pull_request:
- branches: [ '**' ]
+ branches: ['**']
paths-ignore:
- '**/*.md'
diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
new file mode 100644
index 000000000000..3c5257e2e8d1
--- /dev/null
+++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PageWrapper should render normally 1`] = `
+
+`;
diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx
new file mode 100644
index 000000000000..550eb3ee1cae
--- /dev/null
+++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx
@@ -0,0 +1,16 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { PageWrapper } from './page_wrapper';
+
+describe('PageWrapper', () => {
+ it('should render normally', async () => {
+ const { findByText, container } = render(Foo);
+ await findByText('Foo');
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx
index e0b725edc42d..1b1949c334e4 100644
--- a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx
+++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx
@@ -6,10 +6,10 @@
import { EuiPageContent } from '@elastic/eui';
import React from 'react';
-export const PageWrapper = (props: { fullWidth?: boolean; children?: React.ReactChild }) => {
+export const PageWrapper = (props: { children?: React.ReactChild }) => {
return (
{
- const wrapBreadcrumb = (item: ChromeBreadcrumb, scopedHistory: ScopedHistory) => ({
+ chrome.setBreadcrumbs([
+ ...crumb.map((item) => ({
...item,
- ...(item.href ? reactRouterNavigate(scopedHistory, item.href) : {}),
- });
-
- chrome.setBreadcrumbs([...crumbs.map((item) => wrapBreadcrumb(item, params.history))]);
- };
- setBreadcrumbsScoped(crumb);
+ ...(item.href ? reactRouterNavigate(params.history, item.href) : {}),
+ })),
+ ]);
const canSave = application.capabilities.advancedSettings.save as boolean;
diff --git a/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
new file mode 100644
index 000000000000..3c5257e2e8d1
--- /dev/null
+++ b/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PageWrapper should render normally 1`] = `
+
+`;
diff --git a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx
new file mode 100644
index 000000000000..550eb3ee1cae
--- /dev/null
+++ b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx
@@ -0,0 +1,16 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { PageWrapper } from './page_wrapper';
+
+describe('PageWrapper', () => {
+ it('should render normally', async () => {
+ const { findByText, container } = render(Foo);
+ await findByText('Foo');
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx
index e0b725edc42d..1b1949c334e4 100644
--- a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx
+++ b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx
@@ -6,10 +6,10 @@
import { EuiPageContent } from '@elastic/eui';
import React from 'react';
-export const PageWrapper = (props: { fullWidth?: boolean; children?: React.ReactChild }) => {
+export const PageWrapper = (props: { children?: React.ReactChild }) => {
return (
= ({ addBasePath, onClose }) => {
modes. You or your administrator can change to the previous theme by visiting {advancedSettingsLink}."
values={{
advancedSettingsLink: (
-
+
,
- params: ManagementAppMountParams,
+ params: AppMountParameters,
getMlCardState: () => MlCardState
) {
const [
@@ -75,6 +82,17 @@ export async function mountManagementSection(
chrome.setBadge(readOnlyBadge);
}
+ const setBreadcrumbsScope = (crumbs: ChromeBreadcrumb[] = [], appHistory?: ScopedHistory) => {
+ const wrapBreadcrumb = (item: ChromeBreadcrumb, scopedHistory: ScopedHistory) => ({
+ ...item,
+ ...(item.href ? reactRouterNavigate(scopedHistory, item.href) : {}),
+ });
+
+ chrome.setBreadcrumbs([
+ ...crumbs.map((item) => wrapBreadcrumb(item, appHistory || params.history)),
+ ]);
+ };
+
const deps: IndexPatternManagmentContext = {
chrome,
application,
@@ -86,40 +104,36 @@ export async function mountManagementSection(
docLinks,
data,
indexPatternManagementStart: indexPatternManagementStart as IndexPatternManagementStart,
- setBreadcrumbs: params.setBreadcrumbs,
+ setBreadcrumbs: setBreadcrumbsScope,
getMlCardState,
dataSourceEnabled,
};
- const router = (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-
- const content = (
-
- {router}
-
- );
-
ReactDOM.render(
-
- {content}
- ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
params.element
);
diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts
index cdac2c9d982d..758c81ee538f 100644
--- a/src/plugins/index_pattern_management/public/plugin.ts
+++ b/src/plugins/index_pattern_management/public/plugin.ts
@@ -47,12 +47,11 @@ import {
IndexPatternManagementServiceStart,
} from './service';
-import { ManagementAppMountParams, ManagementSetup } from '../../management/public';
+import { ManagementAppMountParams } from '../../management/public';
import { DEFAULT_APP_CATEGORIES } from '../../../core/public';
import { reactRouterNavigate } from '../../opensearch_dashboards_react/public';
export interface IndexPatternManagementSetupDependencies {
- management: ManagementSetup;
urlForwarding: UrlForwardingSetup;
}
@@ -85,14 +84,8 @@ export class IndexPatternManagementPlugin
public setup(
core: CoreSetup,
- { management, urlForwarding }: IndexPatternManagementSetupDependencies
+ { urlForwarding }: IndexPatternManagementSetupDependencies
) {
- const opensearchDashboardsSection = management.sections.section.opensearchDashboards;
-
- if (!opensearchDashboardsSection) {
- throw new Error('`opensearchDashboards` management section not found.');
- }
-
const newAppPath = IPM_APP_ID;
const legacyPatternsPath = 'management/opensearch-dashboards/index_patterns';
diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx
index c19f8ccdd96a..7cb48e090c27 100644
--- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx
+++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx
@@ -35,6 +35,7 @@ import { I18nProvider } from '@osd/i18n/react';
import { EuiLoadingSpinner } from '@elastic/eui';
import { AppMountParameters, CoreSetup } from 'src/core/public';
import { ManagementAppMountParams } from 'src/plugins/management/public';
+import { PageWrapper } from './page_wrapper';
import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin';
import { ISavedObjectsManagementServiceRegistry } from '../services';
import { getAllowedTypes } from './../lib';
@@ -43,37 +44,27 @@ import { WORKSPACE_TYPE } from '../../../../core/public';
interface MountParams {
core: CoreSetup;
serviceRegistry: ISavedObjectsManagementServiceRegistry;
- mountParams?: ManagementAppMountParams;
appMountParams?: AppMountParameters;
title: string;
allowedObjectTypes?: string[];
- fullWidth?: boolean;
}
const SavedObjectsEditionPage = lazy(() => import('./saved_objects_edition_page'));
const SavedObjectsTablePage = lazy(() => import('./saved_objects_table_page'));
export const mountManagementSection = async ({
core,
- mountParams,
appMountParams,
serviceRegistry,
title,
allowedObjectTypes,
- fullWidth = true,
}: MountParams) => {
const [coreStart, { data, uiActions }, pluginStart] = await core.getStartServices();
- const usedMountParams = mountParams || appMountParams || ({} as ManagementAppMountParams);
+ const usedMountParams = appMountParams || ({} as ManagementAppMountParams);
const { element, history } = usedMountParams;
const { chrome } = coreStart;
- const setBreadcrumbs = mountParams?.setBreadcrumbs || chrome.setBreadcrumbs;
- let finalAllowedObjectTypes = allowedObjectTypes;
- if (finalAllowedObjectTypes === undefined) {
- /**
- * Workspace needs to be filtered out since it is a concept with higher level than normal saved objects.
- */
- finalAllowedObjectTypes = (await getAllowedTypes(coreStart.http)).filter(
- (item) => item !== WORKSPACE_TYPE
- );
+ const setBreadcrumbs = chrome.setBreadcrumbs;
+ if (allowedObjectTypes === undefined) {
+ allowedObjectTypes = await getAllowedTypes(coreStart.http);
}
coreStart.chrome.docTitle.change(title);
@@ -97,31 +88,34 @@ export const mountManagementSection = async ({
}>
-
+
+
+
}>
-
+
+
+
diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap
index 6b9d1038f445..dace178024f2 100644
--- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap
+++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap
@@ -10,9 +10,7 @@ exports[`Header should render normally 1`] = `
grow={false}
>
-
- Saved Objects
-
+
boolean;
dateFormat: string;
title: string;
- fullWidth: boolean;
}
export interface SavedObjectsTableState {
@@ -1080,10 +1079,7 @@ export class SavedObjectsTable extends Component
+
{this.renderFlyout()}
{this.renderRelationships()}
{this.renderDeleteConfirmModal()}
diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
new file mode 100644
index 000000000000..3c5257e2e8d1
--- /dev/null
+++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PageWrapper should render normally 1`] = `
+
+`;
diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts b/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts
new file mode 100644
index 000000000000..3cf0cdd26c99
--- /dev/null
+++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts
@@ -0,0 +1,6 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export { PageWrapper } from './page_wrapper';
diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx
new file mode 100644
index 000000000000..550eb3ee1cae
--- /dev/null
+++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx
@@ -0,0 +1,16 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { PageWrapper } from './page_wrapper';
+
+describe('PageWrapper', () => {
+ it('should render normally', async () => {
+ const { findByText, container } = render(Foo);
+ await findByText('Foo');
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx
new file mode 100644
index 000000000000..1b1949c334e4
--- /dev/null
+++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx
@@ -0,0 +1,21 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { EuiPageContent } from '@elastic/eui';
+import React from 'react';
+
+export const PageWrapper = (props: { children?: React.ReactChild }) => {
+ return (
+
+ );
+};
diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx
index d37ba4c7ee95..3e8121c7c2f5 100644
--- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx
+++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx
@@ -50,7 +50,6 @@ const SavedObjectsTablePage = ({
namespaceRegistry,
setBreadcrumbs,
title,
- fullWidth,
}: {
coreStart: CoreStart;
dataStart: DataPublicPluginStart;
@@ -61,7 +60,6 @@ const SavedObjectsTablePage = ({
namespaceRegistry: SavedObjectsManagementNamespaceServiceStart;
setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void;
title: string;
- fullWidth: boolean;
}) => {
const capabilities = coreStart.application.capabilities;
const itemsPerPage = coreStart.uiSettings.get('savedObjects:perPage', 50);
@@ -71,9 +69,6 @@ const SavedObjectsTablePage = ({
setBreadcrumbs([
{
text: title,
- /**
- * There is no need to set a link for current bread crumb
- */
href: undefined,
},
]);
@@ -109,7 +104,6 @@ const SavedObjectsTablePage = ({
return inAppUrl ? Boolean(get(capabilities, inAppUrl.uiCapabilitiesPath)) : false;
}}
title={title}
- fullWidth={fullWidth}
/>
);
};
diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts
index a7e1c0d1a1cb..dba28e05e98e 100644
--- a/src/plugins/saved_objects_management/public/plugin.ts
+++ b/src/plugins/saved_objects_management/public/plugin.ts
@@ -122,7 +122,6 @@ export class SavedObjectsManagementPlugin
appMountParams,
title,
allowedObjectTypes,
- fullWidth: false,
});
};
@@ -130,9 +129,7 @@ export class SavedObjectsManagementPlugin
* Register saved objects overview & saved search & saved query here
*/
core.application.register({
- id: 'objects_all',
- appRoute: '/app/objects',
- exactRoute: true,
+ id: 'objects',
title: MANAGE_LIBRARY_TITLE_WORDINGS,
order: 10000,
category: DEFAULT_APP_CATEGORIES.opensearchDashboards,
@@ -143,7 +140,6 @@ export class SavedObjectsManagementPlugin
core.application.register({
id: 'objects_searches',
- appRoute: '/app/objects/search',
title: SAVED_SEARCHES_WORDINGS,
order: 8000,
category: DEFAULT_APP_CATEGORIES.opensearchDashboards,
@@ -155,7 +151,6 @@ export class SavedObjectsManagementPlugin
core.application.register({
id: 'objects_query',
- appRoute: '/app/objects/query',
title: SAVED_QUERIES_WORDINGS,
order: 8001,
category: DEFAULT_APP_CATEGORIES.opensearchDashboards,
From 8e1310b1004ec8dbdf70ac5f57eed9aacd8027a8 Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Tue, 10 Oct 2023 15:23:53 +0800
Subject: [PATCH 04/22] feat: remove useless test object id
Signed-off-by: SuZhou-Joe
---
.../__snapshots__/workspace_fatal_error.test.tsx.snap | 2 --
.../components/workspace_fatal_error/workspace_fatal_error.tsx | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap b/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
index df744cde09c8..594066e959f7 100644
--- a/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/__snapshots__/workspace_fatal_error.test.tsx.snap
@@ -57,7 +57,6 @@ exports[` render error with callout 1`] = `
>
}
actions={[
-
+
{
+ beforeEach(() => {
+ WorkspaceClientMock.mockClear();
+ Object.values(workspaceClientMock).forEach((item) => item.mockClear());
+ });
+ it('#setup', async () => {
+ const setupMock = coreMock.createSetup();
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ expect(setupMock.application.register).toBeCalledTimes(1);
+ expect(WorkspaceClientMock).toBeCalledTimes(1);
+ expect(workspaceClientMock.enterWorkspace).toBeCalledTimes(0);
+ });
+
+ it('#setup when workspace id is in url and enterWorkspace return error', async () => {
+ const windowSpy = jest.spyOn(window, 'window', 'get');
+ windowSpy.mockImplementation(
+ () =>
+ ({
+ location: {
+ href: 'http://localhost/w/workspaceId/app',
+ },
+ } as any)
+ );
+ workspaceClientMock.enterWorkspace.mockResolvedValue({
+ success: false,
+ error: 'error',
+ });
+ const setupMock = coreMock.createSetup();
+ const applicationStartMock = applicationServiceMock.createStartContract();
+ const chromeStartMock = chromeServiceMock.createStartContract();
+ setupMock.getStartServices.mockImplementation(() => {
+ return Promise.resolve([
+ {
+ application: applicationStartMock,
+ chrome: chromeStartMock,
+ },
+ {},
+ {},
+ ]) as any;
+ });
+
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ expect(setupMock.application.register).toBeCalledTimes(1);
+ expect(WorkspaceClientMock).toBeCalledTimes(1);
+ expect(workspaceClientMock.enterWorkspace).toBeCalledWith('workspaceId');
+ expect(setupMock.getStartServices).toBeCalledTimes(1);
+ await waitFor(
+ () => {
+ expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_FATAL_ERROR_APP_ID, {
+ replace: true,
+ state: {
+ error: 'error',
+ },
+ });
+ },
+ {
+ container: document.body,
+ }
+ );
+ windowSpy.mockRestore();
+ });
+
+ it('#setup when workspace id is in url and enterWorkspace return success', async () => {
+ const windowSpy = jest.spyOn(window, 'window', 'get');
+ windowSpy.mockImplementation(
+ () =>
+ ({
+ location: {
+ href: 'http://localhost/w/workspaceId/app',
+ },
+ } as any)
+ );
+ workspaceClientMock.enterWorkspace.mockResolvedValue({
+ success: true,
+ error: 'error',
+ });
+ const setupMock = coreMock.createSetup();
+ const applicationStartMock = applicationServiceMock.createStartContract();
+ let currentAppIdSubscriber: Subscriber | undefined;
+ setupMock.getStartServices.mockImplementation(() => {
+ return Promise.resolve([
+ {
+ application: {
+ ...applicationStartMock,
+ currentAppId$: new Observable((subscriber) => {
+ currentAppIdSubscriber = subscriber;
+ }),
+ },
+ },
+ {},
+ {},
+ ]) as any;
+ });
+
+ const workspacePlugin = new WorkspacePlugin();
+ await workspacePlugin.setup(setupMock);
+ currentAppIdSubscriber?.next(WORKSPACE_FATAL_ERROR_APP_ID);
+ expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_OVERVIEW_APP_ID);
+ windowSpy.mockRestore();
+ });
+});
diff --git a/src/plugins/workspace/public/workspace_client.mock.ts b/src/plugins/workspace/public/workspace_client.mock.ts
new file mode 100644
index 000000000000..2ceeae5627d1
--- /dev/null
+++ b/src/plugins/workspace/public/workspace_client.mock.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const workspaceClientMock = {
+ init: jest.fn(),
+ enterWorkspace: jest.fn(),
+ getCurrentWorkspaceId: jest.fn(),
+ getCurrentWorkspace: jest.fn(),
+ create: jest.fn(),
+ delete: jest.fn(),
+ list: jest.fn(),
+ get: jest.fn(),
+ update: jest.fn(),
+ stop: jest.fn(),
+};
+
+export const WorkspaceClientMock = jest.fn(function () {
+ return workspaceClientMock;
+});
+
+jest.doMock('./workspace_client', () => ({
+ WorkspaceClient: WorkspaceClientMock,
+}));
diff --git a/src/plugins/workspace/public/workspace_client.test.ts b/src/plugins/workspace/public/workspace_client.test.ts
new file mode 100644
index 000000000000..7d05c3f22458
--- /dev/null
+++ b/src/plugins/workspace/public/workspace_client.test.ts
@@ -0,0 +1,181 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { httpServiceMock, workspacesServiceMock } from '../../../core/public/mocks';
+import { WorkspaceClient } from './workspace_client';
+
+const getWorkspaceClient = () => {
+ const httpSetupMock = httpServiceMock.createSetupContract();
+ const workspaceMock = workspacesServiceMock.createSetupContract();
+ return {
+ httpSetupMock,
+ workspaceMock,
+ workspaceClient: new WorkspaceClient(httpSetupMock, workspaceMock),
+ };
+};
+
+describe('#WorkspaceClient', () => {
+ it('#init', async () => {
+ const { workspaceClient, httpSetupMock, workspaceMock } = getWorkspaceClient();
+ await workspaceClient.init();
+ expect(workspaceMock.initialized$.getValue()).toEqual(true);
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/_list', {
+ method: 'POST',
+ body: JSON.stringify({
+ perPage: 999,
+ }),
+ });
+ });
+
+ it('#enterWorkspace', async () => {
+ const { workspaceClient, httpSetupMock, workspaceMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: false,
+ });
+ const result = await workspaceClient.enterWorkspace('foo');
+ expect(result.success).toEqual(false);
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ });
+ const successResult = await workspaceClient.enterWorkspace('foo');
+ expect(workspaceMock.currentWorkspaceId$.getValue()).toEqual('foo');
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/foo', {
+ method: 'GET',
+ });
+ expect(successResult.success).toEqual(true);
+ });
+
+ it('#getCurrentWorkspaceId', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ });
+ await workspaceClient.enterWorkspace('foo');
+ expect(await workspaceClient.getCurrentWorkspaceId()).toEqual({
+ success: true,
+ result: 'foo',
+ });
+ });
+
+ it('#getCurrentWorkspace', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ result: {
+ name: 'foo',
+ },
+ });
+ await workspaceClient.enterWorkspace('foo');
+ expect(await workspaceClient.getCurrentWorkspace()).toEqual({
+ success: true,
+ result: {
+ name: 'foo',
+ },
+ });
+ });
+
+ it('#create', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ result: {
+ name: 'foo',
+ workspaces: [],
+ },
+ });
+ await workspaceClient.create({
+ name: 'foo',
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces', {
+ method: 'POST',
+ body: JSON.stringify({
+ attributes: {
+ name: 'foo',
+ },
+ }),
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/_list', {
+ method: 'POST',
+ body: JSON.stringify({
+ perPage: 999,
+ }),
+ });
+ });
+
+ it('#delete', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ result: {
+ name: 'foo',
+ workspaces: [],
+ },
+ });
+ await workspaceClient.delete('foo');
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/foo', {
+ method: 'DELETE',
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/_list', {
+ method: 'POST',
+ body: JSON.stringify({
+ perPage: 999,
+ }),
+ });
+ });
+
+ it('#list', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ result: {
+ workspaces: [],
+ },
+ });
+ await workspaceClient.list({
+ perPage: 999,
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/_list', {
+ method: 'POST',
+ body: JSON.stringify({
+ perPage: 999,
+ }),
+ });
+ });
+
+ it('#get', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ await workspaceClient.get('foo');
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/foo', {
+ method: 'GET',
+ });
+ });
+
+ it('#update', async () => {
+ const { workspaceClient, httpSetupMock } = getWorkspaceClient();
+ httpSetupMock.fetch.mockResolvedValue({
+ success: true,
+ result: {
+ workspaces: [],
+ },
+ });
+ await workspaceClient.update('foo', {
+ name: 'foo',
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/foo', {
+ method: 'PUT',
+ body: JSON.stringify({
+ attributes: {
+ name: 'foo',
+ },
+ }),
+ });
+ expect(httpSetupMock.fetch).toBeCalledWith('/api/workspaces/_list', {
+ method: 'POST',
+ body: JSON.stringify({
+ perPage: 999,
+ }),
+ });
+ });
+});
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index 4dc023462fe1..9f1a106a0a50 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
HttpFetchError,
HttpFetchOptions,
@@ -102,7 +103,7 @@ export class WorkspaceClient {
}
};
- private getPath(path: Array): string {
+ private getPath(...path: Array): string {
return [WORKSPACES_API_BASE_URL, join(...path)].filter((item) => item).join('/');
}
@@ -179,7 +180,7 @@ export class WorkspaceClient {
permissions: WorkspaceRoutePermissionItem[];
}
): Promise> {
- const path = this.getPath([]);
+ const path = this.getPath();
const result = await this.safeFetch(path, {
method: 'POST',
@@ -202,7 +203,7 @@ export class WorkspaceClient {
* @returns
*/
public async delete(id: string): Promise> {
- const result = await this.safeFetch(this.getPath([id]), { method: 'DELETE' });
+ const result = await this.safeFetch(this.getPath(id), { method: 'DELETE' });
if (result.success) {
await this.updateWorkspaceList();
@@ -216,15 +217,15 @@ export class WorkspaceClient {
*
* @param {object} [options={}]
* @property {string} options.search
- * @property {string} options.search_fields - see OpenSearch Simple Query String
+ * @property {string} options.searchFields - see OpenSearch Simple Query String
* Query field argument for more information
* @property {integer} [options.page=1]
- * @property {integer} [options.per_page=20]
+ * @property {integer} [options.perPage=20]
* @property {array} options.fields
* @property {string array} permissionModes
* @returns A find result with workspaces matching the specified search.
*/
- public list = (
+ public list(
options?: WorkspaceFindOptions
): Promise<
IResponse<{
@@ -233,13 +234,13 @@ export class WorkspaceClient {
per_page: number;
page: number;
}>
- > => {
- const path = this.getPath(['_list']);
+ > {
+ const path = this.getPath('_list');
return this.safeFetch(path, {
method: 'POST',
body: JSON.stringify(options || {}),
});
- };
+ }
/**
* Fetches a single workspace
@@ -247,8 +248,8 @@ export class WorkspaceClient {
* @param {string} id
* @returns The workspace for the given id.
*/
- public async get(id: string): Promise> {
- const path = this.getPath([id]);
+ public get(id: string): Promise> {
+ const path = this.getPath(id);
return this.safeFetch(path, {
method: 'GET',
});
@@ -269,7 +270,7 @@ export class WorkspaceClient {
}
>
): Promise> {
- const path = this.getPath([id]);
+ const path = this.getPath(id);
const body = {
attributes,
};
diff --git a/src/plugins/workspace/server/index.ts b/src/plugins/workspace/server/index.ts
index 9447b7c6dc8c..fe44b4d71757 100644
--- a/src/plugins/workspace/server/index.ts
+++ b/src/plugins/workspace/server/index.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { PluginConfigDescriptor, PluginInitializerContext } from '../../../core/server';
import { WorkspacePlugin } from './plugin';
import { configSchema } from '../config';
diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts
index 798ea103101f..411b8c586d4c 100644
--- a/src/plugins/workspace/server/plugin.ts
+++ b/src/plugins/workspace/server/plugin.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
PluginInitializerContext,
CoreSetup,
@@ -20,6 +21,7 @@ import {
SavedObjectsPermissionControlContract,
} from './permission_control/client';
import { registerPermissionCheckRoutes } from './permission_control/routes';
+import { cleanWorkspaceId, getWorkspaceIdFromUrl } from '../../../core/server/utils';
export class WorkspacePlugin implements Plugin<{}, {}> {
private readonly logger: Logger;
@@ -31,12 +33,11 @@ export class WorkspacePlugin implements Plugin<{}, {}> {
* Proxy all {basePath}/w/{workspaceId}{osdPath*} paths to {basePath}{osdPath*}
*/
setupDeps.http.registerOnPreRouting(async (request, response, toolkit) => {
- const regexp = /\/w\/([^\/]*)/;
- const matchedResult = request.url.pathname.match(regexp);
+ const workspaceId = getWorkspaceIdFromUrl(request.url.toString());
- if (matchedResult) {
+ if (workspaceId) {
const requestUrl = new URL(request.url.toString());
- requestUrl.pathname = requestUrl.pathname.replace(regexp, '');
+ requestUrl.pathname = cleanWorkspaceId(requestUrl.pathname);
return toolkit.rewriteUrl(requestUrl.toString());
}
return toolkit.next();
diff --git a/src/plugins/workspace/server/routes/index.ts b/src/plugins/workspace/server/routes/index.ts
index 00ad05f3c961..2701c2a767ab 100644
--- a/src/plugins/workspace/server/routes/index.ts
+++ b/src/plugins/workspace/server/routes/index.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { schema } from '@osd/config-schema';
import { ensureRawRequest } from '../../../../core/server';
diff --git a/src/plugins/workspace/server/types.ts b/src/plugins/workspace/server/types.ts
index 2f46f5c7eb16..bf3337c4ae46 100644
--- a/src/plugins/workspace/server/types.ts
+++ b/src/plugins/workspace/server/types.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
Logger,
OpenSearchDashboardsRequest,
diff --git a/src/plugins/workspace/server/workspace_client.ts b/src/plugins/workspace/server/workspace_client.ts
index 56e40dfb3ebb..8fbb9ac7035e 100644
--- a/src/plugins/workspace/server/workspace_client.ts
+++ b/src/plugins/workspace/server/workspace_client.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { i18n } from '@osd/i18n';
import { omit } from 'lodash';
import type {
From 2653ab4c049b62e52755611bf94fb75cecde54c4 Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Wed, 11 Oct 2023 17:46:35 +0800
Subject: [PATCH 13/22] feat: optimization
Signed-off-by: SuZhou-Joe
---
src/core/public/utils/workspace.ts | 5 ++++-
src/plugins/workspace/public/plugin.test.ts | 21 ++++++++++++-------
.../workspace/public/workspace_client.ts | 4 ++--
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/src/core/public/utils/workspace.ts b/src/core/public/utils/workspace.ts
index 9f6d7cdf1e24..f9c90994c8be 100644
--- a/src/core/public/utils/workspace.ts
+++ b/src/core/public/utils/workspace.ts
@@ -26,7 +26,10 @@ export const formatUrlWithWorkspaceId = (
/**
* Patch workspace id into path
*/
- newUrl.pathname = basePath?.remove(newUrl.pathname) || '';
+ if (basePath) {
+ newUrl.pathname = basePath.remove(newUrl.pathname);
+ }
+
if (workspaceId) {
newUrl.pathname = `${WORKSPACE_PATH_PREFIX}/${workspaceId}${newUrl.pathname}`;
} else {
diff --git a/src/plugins/workspace/public/plugin.test.ts b/src/plugins/workspace/public/plugin.test.ts
index e15b07ae9552..370f60caab52 100644
--- a/src/plugins/workspace/public/plugin.test.ts
+++ b/src/plugins/workspace/public/plugin.test.ts
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
+import { waitFor } from '@testing-library/dom';
import { workspaceClientMock, WorkspaceClientMock } from './workspace_client.mock';
import { applicationServiceMock, chromeServiceMock, coreMock } from '../../../core/public/mocks';
import { WorkspacePlugin } from './plugin';
@@ -57,13 +58,19 @@ describe('Workspace plugin', () => {
expect(WorkspaceClientMock).toBeCalledTimes(1);
expect(workspaceClientMock.enterWorkspace).toBeCalledWith('workspaceId');
expect(setupMock.getStartServices).toBeCalledTimes(1);
- await new Promise((resolve: any) => setTimeout(resolve, 1000));
- expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_FATAL_ERROR_APP_ID, {
- replace: true,
- state: {
- error: 'error',
+ await waitFor(
+ () => {
+ expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_FATAL_ERROR_APP_ID, {
+ replace: true,
+ state: {
+ error: 'error',
+ },
+ });
},
- });
+ {
+ container: document.body,
+ }
+ );
windowSpy.mockRestore();
});
@@ -101,9 +108,7 @@ describe('Workspace plugin', () => {
const workspacePlugin = new WorkspacePlugin();
await workspacePlugin.setup(setupMock);
- await new Promise((resolve: any) => setTimeout(resolve, 0));
currentAppIdSubscriber?.next(WORKSPACE_FATAL_ERROR_APP_ID);
- await new Promise((resolve: any) => setTimeout(resolve, 0));
expect(applicationStartMock.navigateToApp).toBeCalledWith(WORKSPACE_OVERVIEW_APP_ID);
windowSpy.mockRestore();
});
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index 4dc023462fe1..f05a019733b6 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -216,10 +216,10 @@ export class WorkspaceClient {
*
* @param {object} [options={}]
* @property {string} options.search
- * @property {string} options.search_fields - see OpenSearch Simple Query String
+ * @property {string} options.searchFields - see OpenSearch Simple Query String
* Query field argument for more information
* @property {integer} [options.page=1]
- * @property {integer} [options.per_page=20]
+ * @property {integer} [options.perPage=20]
* @property {array} options.fields
* @property {string array} permissionModes
* @returns A find result with workspaces matching the specified search.
From 1eb48dd366c4d01fff08fa264b2f28ac98260d13 Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Wed, 11 Oct 2023 17:52:31 +0800
Subject: [PATCH 14/22] feat: optimization
Signed-off-by: SuZhou-Joe
---
src/plugins/workspace/public/workspace_client.ts | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index f05a019733b6..693f40d0ab55 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -102,7 +102,7 @@ export class WorkspaceClient {
}
};
- private getPath(path: Array): string {
+ private getPath(...path: Array): string {
return [WORKSPACES_API_BASE_URL, join(...path)].filter((item) => item).join('/');
}
@@ -179,7 +179,7 @@ export class WorkspaceClient {
permissions: WorkspaceRoutePermissionItem[];
}
): Promise> {
- const path = this.getPath([]);
+ const path = this.getPath();
const result = await this.safeFetch(path, {
method: 'POST',
@@ -202,7 +202,7 @@ export class WorkspaceClient {
* @returns
*/
public async delete(id: string): Promise> {
- const result = await this.safeFetch(this.getPath([id]), { method: 'DELETE' });
+ const result = await this.safeFetch(this.getPath(id), { method: 'DELETE' });
if (result.success) {
await this.updateWorkspaceList();
@@ -234,7 +234,7 @@ export class WorkspaceClient {
page: number;
}>
> => {
- const path = this.getPath(['_list']);
+ const path = this.getPath('_list');
return this.safeFetch(path, {
method: 'POST',
body: JSON.stringify(options || {}),
@@ -248,7 +248,7 @@ export class WorkspaceClient {
* @returns The workspace for the given id.
*/
public async get(id: string): Promise> {
- const path = this.getPath([id]);
+ const path = this.getPath(id);
return this.safeFetch(path, {
method: 'GET',
});
@@ -269,7 +269,7 @@ export class WorkspaceClient {
}
>
): Promise> {
- const path = this.getPath([id]);
+ const path = this.getPath(id);
const body = {
attributes,
};
From a1d00ea73b384f1b9087a1fc2d2e59ccce8de35a Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Wed, 11 Oct 2023 18:32:25 +0800
Subject: [PATCH 15/22] feat: move workspace/utils to core
Signed-off-by: SuZhou-Joe
---
src/core/public/utils/index.ts | 3 ++-
src/core/server/utils/index.ts | 1 +
src/core/utils/index.ts | 1 +
src/core/{public => }/utils/workspace.test.ts | 2 +-
src/core/{public => }/utils/workspace.ts | 20 +++++++++----------
.../workspace_fatal_error.tsx | 3 ++-
src/plugins/workspace/server/plugin.ts | 8 ++++----
7 files changed, 20 insertions(+), 18 deletions(-)
rename src/core/{public => }/utils/workspace.test.ts (95%)
rename src/core/{public => }/utils/workspace.ts (63%)
diff --git a/src/core/public/utils/index.ts b/src/core/public/utils/index.ts
index b62b6ded5c83..871b71888294 100644
--- a/src/core/public/utils/index.ts
+++ b/src/core/public/utils/index.ts
@@ -31,10 +31,11 @@
export { shareWeakReplay } from './share_weak_replay';
export { Sha256 } from './crypto';
export { MountWrapper, mountReactNode } from './mount';
-export { getWorkspaceIdFromUrl, formatUrlWithWorkspaceId } from './workspace';
export {
WORKSPACE_PATH_PREFIX,
PUBLIC_WORKSPACE_ID,
MANAGEMENT_WORKSPACE_ID,
WORKSPACE_TYPE,
+ formatUrlWithWorkspaceId,
+ getWorkspaceIdFromUrl,
} from '../../utils';
diff --git a/src/core/server/utils/index.ts b/src/core/server/utils/index.ts
index d2c9e0086ad7..42b01e72b0d1 100644
--- a/src/core/server/utils/index.ts
+++ b/src/core/server/utils/index.ts
@@ -32,3 +32,4 @@ export * from './crypto';
export * from './from_root';
export * from './package_json';
export * from './streams';
+export { getWorkspaceIdFromUrl, cleanWorkspaceId } from '../../utils';
diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts
index 1b7d29406443..f2884c60581c 100644
--- a/src/core/utils/index.ts
+++ b/src/core/utils/index.ts
@@ -45,3 +45,4 @@ export {
WORKSPACE_TYPE,
PERSONAL_WORKSPACE_ID_PREFIX,
} from './constants';
+export { getWorkspaceIdFromUrl, formatUrlWithWorkspaceId, cleanWorkspaceId } from './workspace';
diff --git a/src/core/public/utils/workspace.test.ts b/src/core/utils/workspace.test.ts
similarity index 95%
rename from src/core/public/utils/workspace.test.ts
rename to src/core/utils/workspace.test.ts
index a1cd4bf9a42e..7d2a1f700c5f 100644
--- a/src/core/public/utils/workspace.test.ts
+++ b/src/core/utils/workspace.test.ts
@@ -4,7 +4,7 @@
*/
import { getWorkspaceIdFromUrl, formatUrlWithWorkspaceId } from './workspace';
-import { httpServiceMock } from '../mocks';
+import { httpServiceMock } from '../public/mocks';
describe('#getWorkspaceIdFromUrl', () => {
it('return workspace when there is a match', () => {
diff --git a/src/core/public/utils/workspace.ts b/src/core/utils/workspace.ts
similarity index 63%
rename from src/core/public/utils/workspace.ts
rename to src/core/utils/workspace.ts
index f9c90994c8be..46393f0bbb56 100644
--- a/src/core/public/utils/workspace.ts
+++ b/src/core/utils/workspace.ts
@@ -3,8 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { WORKSPACE_PATH_PREFIX } from './index';
-import { IBasePath } from '../index';
+import { WORKSPACE_PATH_PREFIX } from './constants';
+import { IBasePath } from '../public';
export const getWorkspaceIdFromUrl = (url: string): string => {
const regexp = /\/w\/([^\/]*)/;
@@ -17,23 +17,21 @@ export const getWorkspaceIdFromUrl = (url: string): string => {
return '';
};
-export const formatUrlWithWorkspaceId = (
- url: string,
- workspaceId: string,
- basePath?: IBasePath
-) => {
+export const cleanWorkspaceId = (path: string) => {
+ return path.replace(/^\/w\/([^\/]*)/, '');
+};
+
+export const formatUrlWithWorkspaceId = (url: string, workspaceId: string, basePath: IBasePath) => {
const newUrl = new URL(url, window.location.href);
/**
* Patch workspace id into path
*/
- if (basePath) {
- newUrl.pathname = basePath.remove(newUrl.pathname);
- }
+ newUrl.pathname = basePath.remove(newUrl.pathname);
if (workspaceId) {
newUrl.pathname = `${WORKSPACE_PATH_PREFIX}/${workspaceId}${newUrl.pathname}`;
} else {
- newUrl.pathname = newUrl.pathname.replace(/^\/w\/([^\/]*)/, '');
+ newUrl.pathname = cleanWorkspaceId(newUrl.pathname);
}
newUrl.pathname =
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.tsx b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.tsx
index d4f187b78e56..b1081e92237f 100644
--- a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.tsx
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.tsx
@@ -13,6 +13,7 @@ import {
} from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@osd/i18n/react';
+import { IBasePath } from 'opensearch-dashboards/public';
import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
import { formatUrlWithWorkspaceId } from '../../../../../core/public/utils';
@@ -24,7 +25,7 @@ export function WorkspaceFatalError(props: { error?: string }) {
window.location.href = formatUrlWithWorkspaceId(
application?.getUrlForApp('home') || '',
'',
- http?.basePath
+ http?.basePath as IBasePath
);
};
return (
diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts
index 798ea103101f..7c2f8f806c2a 100644
--- a/src/plugins/workspace/server/plugin.ts
+++ b/src/plugins/workspace/server/plugin.ts
@@ -20,6 +20,7 @@ import {
SavedObjectsPermissionControlContract,
} from './permission_control/client';
import { registerPermissionCheckRoutes } from './permission_control/routes';
+import { cleanWorkspaceId, getWorkspaceIdFromUrl } from '../../../core/server/utils';
export class WorkspacePlugin implements Plugin<{}, {}> {
private readonly logger: Logger;
@@ -31,12 +32,11 @@ export class WorkspacePlugin implements Plugin<{}, {}> {
* Proxy all {basePath}/w/{workspaceId}{osdPath*} paths to {basePath}{osdPath*}
*/
setupDeps.http.registerOnPreRouting(async (request, response, toolkit) => {
- const regexp = /\/w\/([^\/]*)/;
- const matchedResult = request.url.pathname.match(regexp);
+ const workspaceId = getWorkspaceIdFromUrl(request.url.toString());
- if (matchedResult) {
+ if (workspaceId) {
const requestUrl = new URL(request.url.toString());
- requestUrl.pathname = requestUrl.pathname.replace(regexp, '');
+ requestUrl.pathname = cleanWorkspaceId(requestUrl.pathname);
return toolkit.rewriteUrl(requestUrl.toString());
}
return toolkit.next();
From 2da52460e24d384fd540b8d8e5ae015c9d9cb65f Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 09:44:58 +0800
Subject: [PATCH 16/22] feat: update comment
Signed-off-by: SuZhou-Joe
---
src/plugins/workspace/public/workspace_client.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index 693f40d0ab55..de399950b97a 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -221,7 +221,6 @@ export class WorkspaceClient {
* @property {integer} [options.page=1]
* @property {integer} [options.perPage=20]
* @property {array} options.fields
- * @property {string array} permissionModes
* @returns A find result with workspaces matching the specified search.
*/
public list = (
From 2b6764afea8c4e17c4c79f00ca0db5b249249359 Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 10:47:29 +0800
Subject: [PATCH 17/22] feat: optimize code
Signed-off-by: SuZhou-Joe
---
src/plugins/workspace/public/workspace_client.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index de399950b97a..2a49c6687e3f 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -223,7 +223,7 @@ export class WorkspaceClient {
* @property {array} options.fields
* @returns A find result with workspaces matching the specified search.
*/
- public list = (
+ public list(
options?: WorkspaceFindOptions
): Promise<
IResponse<{
@@ -232,13 +232,13 @@ export class WorkspaceClient {
per_page: number;
page: number;
}>
- > => {
+ > {
const path = this.getPath('_list');
return this.safeFetch(path, {
method: 'POST',
body: JSON.stringify(options || {}),
});
- };
+ }
/**
* Fetches a single workspace
@@ -246,7 +246,7 @@ export class WorkspaceClient {
* @param {string} id
* @returns The workspace for the given id.
*/
- public async get(id: string): Promise> {
+ public get(id: string): Promise> {
const path = this.getPath(id);
return this.safeFetch(path, {
method: 'GET',
From bf64805ea1ddc1530ec56942cc21bae1989da52d Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 10:49:31 +0800
Subject: [PATCH 18/22] feat: update unit test
Signed-off-by: SuZhou-Joe
---
.../workspace_fatal_error.test.tsx | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
index 4b6f13e3a228..f681c1c9f4fd 100644
--- a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
@@ -5,7 +5,7 @@
import React from 'react';
import { IntlProvider } from 'react-intl';
-import { fireEvent, render } from '@testing-library/react';
+import { fireEvent, render, waitFor } from '@testing-library/react';
import { WorkspaceFatalError } from './workspace_fatal_error';
describe('', () => {
@@ -47,7 +47,14 @@ describe('', () => {
);
fireEvent.click(getByText('Go back to home'));
- expect(setHrefSpy).toBeCalledTimes(1);
+ await waitFor(
+ () => {
+ expect(setHrefSpy).toBeCalledTimes(1);
+ },
+ {
+ container: document.body,
+ }
+ );
window.location = location;
});
});
From 6ea389117f49a3efc9d0ce2ceeb5041b687f5bee Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 14:06:39 +0800
Subject: [PATCH 19/22] feat: optimization
Signed-off-by: SuZhou-Joe
---
src/core/utils/workspace.ts | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/core/utils/workspace.ts b/src/core/utils/workspace.ts
index 46393f0bbb56..c369f95d5817 100644
--- a/src/core/utils/workspace.ts
+++ b/src/core/utils/workspace.ts
@@ -34,10 +34,9 @@ export const formatUrlWithWorkspaceId = (url: string, workspaceId: string, baseP
newUrl.pathname = cleanWorkspaceId(newUrl.pathname);
}
- newUrl.pathname =
- basePath?.prepend(newUrl.pathname, {
- withoutWorkspace: true,
- }) || '';
+ newUrl.pathname = basePath.prepend(newUrl.pathname, {
+ withoutWorkspace: true,
+ });
return newUrl.toString();
};
From d0ac2ec9328fd7601c688d30de0054322480de90 Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 14:23:14 +0800
Subject: [PATCH 20/22] feat: add space under license
Signed-off-by: SuZhou-Joe
---
src/plugins/workspace/public/workspace_client.ts | 1 +
src/plugins/workspace/server/index.ts | 1 +
src/plugins/workspace/server/plugin.ts | 1 +
src/plugins/workspace/server/routes/index.ts | 1 +
src/plugins/workspace/server/types.ts | 1 +
src/plugins/workspace/server/workspace_client.ts | 1 +
6 files changed, 6 insertions(+)
diff --git a/src/plugins/workspace/public/workspace_client.ts b/src/plugins/workspace/public/workspace_client.ts
index 2a49c6687e3f..6262225902e0 100644
--- a/src/plugins/workspace/public/workspace_client.ts
+++ b/src/plugins/workspace/public/workspace_client.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
HttpFetchError,
HttpFetchOptions,
diff --git a/src/plugins/workspace/server/index.ts b/src/plugins/workspace/server/index.ts
index 9447b7c6dc8c..fe44b4d71757 100644
--- a/src/plugins/workspace/server/index.ts
+++ b/src/plugins/workspace/server/index.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { PluginConfigDescriptor, PluginInitializerContext } from '../../../core/server';
import { WorkspacePlugin } from './plugin';
import { configSchema } from '../config';
diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts
index 7c2f8f806c2a..411b8c586d4c 100644
--- a/src/plugins/workspace/server/plugin.ts
+++ b/src/plugins/workspace/server/plugin.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
PluginInitializerContext,
CoreSetup,
diff --git a/src/plugins/workspace/server/routes/index.ts b/src/plugins/workspace/server/routes/index.ts
index 00ad05f3c961..2701c2a767ab 100644
--- a/src/plugins/workspace/server/routes/index.ts
+++ b/src/plugins/workspace/server/routes/index.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { schema } from '@osd/config-schema';
import { ensureRawRequest } from '../../../../core/server';
diff --git a/src/plugins/workspace/server/types.ts b/src/plugins/workspace/server/types.ts
index 2f46f5c7eb16..bf3337c4ae46 100644
--- a/src/plugins/workspace/server/types.ts
+++ b/src/plugins/workspace/server/types.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import {
Logger,
OpenSearchDashboardsRequest,
diff --git a/src/plugins/workspace/server/workspace_client.ts b/src/plugins/workspace/server/workspace_client.ts
index 56e40dfb3ebb..8fbb9ac7035e 100644
--- a/src/plugins/workspace/server/workspace_client.ts
+++ b/src/plugins/workspace/server/workspace_client.ts
@@ -2,6 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
import { i18n } from '@osd/i18n';
import { omit } from 'lodash';
import type {
From 640c45678ec154e3fc97607ec78a6f813d07d71a Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Thu, 12 Oct 2023 15:29:08 +0800
Subject: [PATCH 21/22] fix: unit test
Signed-off-by: SuZhou-Joe
---
.../workspace_fatal_error.test.tsx | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
index f681c1c9f4fd..d98e0063dcfa 100644
--- a/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
+++ b/src/plugins/workspace/public/components/workspace_fatal_error/workspace_fatal_error.test.tsx
@@ -7,6 +7,8 @@ import React from 'react';
import { IntlProvider } from 'react-intl';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { WorkspaceFatalError } from './workspace_fatal_error';
+import { context } from '../../../../opensearch_dashboards_react/public';
+import { coreMock } from '../../../../../core/public/mocks';
describe('', () => {
it('render normally', async () => {
@@ -41,9 +43,18 @@ describe('', () => {
get: () => 'http://localhost/',
set: setHrefSpy,
});
+ const coreStartMock = coreMock.createStart();
const { getByText } = render(
-
+
+
+
);
fireEvent.click(getByText('Go back to home'));
From adc60295d24eb9cde0b59ffa3c79115f577fd38d Mon Sep 17 00:00:00 2001
From: SuZhou-Joe
Date: Fri, 13 Oct 2023 11:37:17 +0800
Subject: [PATCH 22/22] feat: some sync
Signed-off-by: SuZhou-Joe
---
src/core/public/index.ts | 2 --
src/core/public/utils/workspace.ts | 15 ---------------
src/core/public/workspace/index.ts | 1 +
src/plugins/workspace/public/utils.ts | 27 +--------------------------
4 files changed, 2 insertions(+), 43 deletions(-)
delete mode 100644 src/core/public/utils/workspace.ts
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 3a8358d0f2a0..1f26a26de8ef 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -358,5 +358,3 @@ export {
MANAGEMENT_WORKSPACE_ID,
WORKSPACE_TYPE,
} from '../utils';
-
-export { getWorkspaceIdFromUrl } from './utils';
diff --git a/src/core/public/utils/workspace.ts b/src/core/public/utils/workspace.ts
deleted file mode 100644
index e93355aa00e3..000000000000
--- a/src/core/public/utils/workspace.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-export const getWorkspaceIdFromUrl = (url: string): string => {
- const regexp = /\/w\/([^\/]*)/;
- const urlObject = new URL(url);
- const matchedResult = urlObject.pathname.match(regexp);
- if (matchedResult) {
- return matchedResult[1];
- }
-
- return '';
-};
diff --git a/src/core/public/workspace/index.ts b/src/core/public/workspace/index.ts
index e46cac0b4b51..4b9b2c86f649 100644
--- a/src/core/public/workspace/index.ts
+++ b/src/core/public/workspace/index.ts
@@ -2,4 +2,5 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
+
export { WorkspacesStart, WorkspacesService, WorkspacesSetup } from './workspaces_service';
diff --git a/src/plugins/workspace/public/utils.ts b/src/plugins/workspace/public/utils.ts
index 09528c2b080f..f7c59dbfc53c 100644
--- a/src/plugins/workspace/public/utils.ts
+++ b/src/plugins/workspace/public/utils.ts
@@ -3,32 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { WORKSPACE_PATH_PREFIX } from '../../../core/public/utils';
-import { AppCategory, IBasePath } from '../../../core/public';
-
-export const formatUrlWithWorkspaceId = (
- url: string,
- workspaceId: string,
- basePath?: IBasePath
-) => {
- const newUrl = new URL(url, window.location.href);
- /**
- * Patch workspace id into path
- */
- newUrl.pathname = basePath?.remove(newUrl.pathname) || '';
- if (workspaceId) {
- newUrl.pathname = `${WORKSPACE_PATH_PREFIX}/${workspaceId}${newUrl.pathname}`;
- } else {
- newUrl.pathname = newUrl.pathname.replace(/^\/w\/([^\/]*)/, '');
- }
-
- newUrl.pathname =
- basePath?.prepend(newUrl.pathname, {
- withoutWorkspace: true,
- }) || '';
-
- return newUrl.toString();
-};
+import { AppCategory } from '../../../core/public';
/**
* Given a list of feature config, check if a feature matches config