From 657372fa052effe25703b2d3c3aefb1ede5a51da Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 29 Feb 2024 13:43:13 +0800 Subject: [PATCH] Make url stateful in hash Make url stateful in hash --- CHANGELOG.md | 2 +- src/plugins/workspace/common/constants.ts | 1 + .../workspace/opensearch_dashboards.json | 5 +- src/plugins/workspace/public/plugin.ts | 91 ++++++++++++++++++- src/plugins/workspace/public/utils.ts | 11 +++ 5 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/plugins/workspace/public/utils.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 246d200143af..8f790e0d1c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1028,4 +1028,4 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### 🔩 Tests -- Update caniuse to fix failed integration tests ([#2322](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2322)) +- Update caniuse to fix failed integration tests ([#2322](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2322)) \ No newline at end of file diff --git a/src/plugins/workspace/common/constants.ts b/src/plugins/workspace/common/constants.ts index b6bd7b00f676..e5cace442a83 100644 --- a/src/plugins/workspace/common/constants.ts +++ b/src/plugins/workspace/common/constants.ts @@ -3,4 +3,5 @@ * SPDX-License-Identifier: Apache-2.0 */ +export const WORKSPACE_ID_STATE_KEY = '_w'; export const WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID = 'workspace'; diff --git a/src/plugins/workspace/opensearch_dashboards.json b/src/plugins/workspace/opensearch_dashboards.json index 40a7eb5c3f9f..176bf5c2d132 100644 --- a/src/plugins/workspace/opensearch_dashboards.json +++ b/src/plugins/workspace/opensearch_dashboards.json @@ -2,9 +2,10 @@ "id": "workspace", "version": "opensearchDashboards", "server": true, - "ui": false, + "ui": true, "requiredPlugins": [ - "savedObjects" + "savedObjects", + "opensearchDashboardsUtils" ], "optionalPlugins": [], "requiredBundles": [] diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts index 18e84e3a6f35..1fb4cd0f4046 100644 --- a/src/plugins/workspace/public/plugin.ts +++ b/src/plugins/workspace/public/plugin.ts @@ -3,10 +3,97 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Plugin } from '../../../core/public'; +import { BehaviorSubject, combineLatest } from 'rxjs'; +import { debounce } from 'lodash'; +import { CoreSetup, Plugin } from '../../../core/public'; +import { getStateFromOsdUrl } from '../../opensearch_dashboards_utils/public'; +import { formatUrlWithWorkspaceId } from './utils'; +import { WORKSPACE_ID_STATE_KEY } from '../common/constants'; export class WorkspacePlugin implements Plugin<{}, {}, {}> { - public async setup() { + private core?: CoreSetup; + private URLChange$ = new BehaviorSubject(''); + private getWorkpsaceIdFromURL(): string | null { + return getStateFromOsdUrl(WORKSPACE_ID_STATE_KEY); + } + private async getWorkpsaceId(): Promise { + if (this.getWorkpsaceIdFromURL()) { + return this.getWorkpsaceIdFromURL() || ''; + } + + return (await this.core?.workspaces.currentWorkspaceId$.getValue()) || ''; + } + private getPatchedUrl = (url: string, workspaceId: string) => { + return formatUrlWithWorkspaceId(url, workspaceId); + }; + private async listenToHashChange(): Promise { + window.addEventListener('hashchange', async () => { + if (this.shouldPatchUrl()) { + const workspaceId = await this.getWorkpsaceId(); + this.URLChange$.next(this.getPatchedUrl(window.location.href, workspaceId)); + } + }); + } + private shouldPatchUrl(): boolean { + const currentWorkspaceId = this.core?.workspaces.currentWorkspaceId$.getValue(); + const workspaceIdFromURL = this.getWorkpsaceIdFromURL(); + if (!currentWorkspaceId && !workspaceIdFromURL) { + return false; + } + + if (currentWorkspaceId === workspaceIdFromURL) { + return false; + } + + return true; + } + private async listenToApplicationChange(): Promise { + const startService = await this.core?.getStartServices(); + if (startService) { + combineLatest([ + this.core?.workspaces.currentWorkspaceId$, + startService[0].application.currentAppId$, + ]).subscribe(async ([]) => { + if (this.shouldPatchUrl()) { + const currentWorkspaceId = await this.getWorkpsaceId(); + this.URLChange$.next(this.getPatchedUrl(window.location.href, currentWorkspaceId)); + } + }); + } + } + public async setup(core: CoreSetup) { + this.core = core; + /** + * Retrive workspace id from url + */ + const workspaceId = this.getWorkpsaceIdFromURL(); + + if (workspaceId) { + /** + * Enter a workspace + */ + this.core.workspaces.currentWorkspaceId$.next(workspaceId); + } + + /** + * listen to application change and patch workspace id in hash + */ + this.listenToApplicationChange(); + + /** + * listen to application internal hash change and patch workspace id in hash + */ + this.listenToHashChange(); + + /** + * All the URLChange will flush in this subscriber + */ + this.URLChange$.subscribe( + debounce(async (url) => { + history.replaceState(history.state, '', url); + }, 500) + ); + return {}; } diff --git a/src/plugins/workspace/public/utils.ts b/src/plugins/workspace/public/utils.ts new file mode 100644 index 000000000000..4443e450a3cd --- /dev/null +++ b/src/plugins/workspace/public/utils.ts @@ -0,0 +1,11 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { setStateToOsdUrl } from '../../opensearch_dashboards_utils/public'; +import { WORKSPACE_ID_STATE_KEY } from '../common/constants'; + +export const formatUrlWithWorkspaceId = (url: string, workspaceId: string) => { + return setStateToOsdUrl(WORKSPACE_ID_STATE_KEY, workspaceId, undefined, url); +};