diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 7398aad65009..4744ab34cfd3 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -47,6 +47,7 @@ import { IUiSettingsClient } from '../ui_settings'; import { SavedObjectsStart } from '../saved_objects'; import { AppCategory } from '../../types'; import { ScopedHistory } from './scoped_history'; +import { WorkspacesStart } from '../workspace'; /** * Accessibility status of an application. @@ -334,6 +335,8 @@ export interface AppMountContext { injectedMetadata: { getInjectedVar: (name: string, defaultValue?: any) => unknown; }; + /** {@link WorkspacesService} */ + workspaces: WorkspacesStart; }; } diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 8fe5a36ebb55..d7de8b4595d5 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -54,6 +54,7 @@ import { ContextService } from './context'; import { IntegrationsService } from './integrations'; import { CoreApp } from './core_app'; import type { InternalApplicationSetup, InternalApplicationStart } from './application/types'; +import { WorkspacesService } from './workspace'; interface Params { rootDomElement: HTMLElement; @@ -110,6 +111,7 @@ export class CoreSystem { private readonly rootDomElement: HTMLElement; private readonly coreContext: CoreContext; + private readonly workspaces: WorkspacesService; private fatalErrorsSetup: FatalErrorsSetup | null = null; constructor(params: Params) { @@ -138,6 +140,7 @@ export class CoreSystem { this.rendering = new RenderingService(); this.application = new ApplicationService(); this.integrations = new IntegrationsService(); + this.workspaces = new WorkspacesService(); this.coreContext = { coreId: Symbol('core'), env: injectedMetadata.env }; @@ -160,6 +163,7 @@ export class CoreSystem { const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); + const workspaces = this.workspaces.setup(); const pluginDependencies = this.plugins.getOpaqueIds(); const context = this.context.setup({ @@ -176,6 +180,7 @@ export class CoreSystem { injectedMetadata, notifications, uiSettings, + workspaces, }; // Services that do not expose contracts at setup @@ -220,6 +225,7 @@ export class CoreSystem { targetDomElement: notificationsTargetDomElement, }); const application = await this.application.start({ http, overlays }); + const workspaces = this.workspaces.start({ application, http }); const chrome = await this.chrome.start({ application, docLinks, @@ -242,6 +248,7 @@ export class CoreSystem { overlays, savedObjects, uiSettings, + workspaces, })); const core: InternalCoreStart = { @@ -256,6 +263,7 @@ export class CoreSystem { overlays, uiSettings, fatalErrors, + workspaces, }; await this.plugins.start(core); diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 03ef6b6392f9..14ab91e1cb13 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -87,6 +87,7 @@ import { HandlerParameters, } from './context'; import { Branding } from '../types'; +import { WorkspacesStart, WorkspacesSetup } from './workspace'; export type { Logos } from '../common'; export { PackageInfo, EnvironmentMode } from '../server/types'; @@ -102,6 +103,7 @@ export { StringValidation, StringValidationRegex, StringValidationRegexString, + WorkspaceAttribute, } from '../types'; export { @@ -239,6 +241,8 @@ export interface CoreSetup; + /** {@link WorkspacesSetup} */ + workspaces: WorkspacesSetup; } /** @@ -293,6 +297,8 @@ export interface CoreStart { getInjectedVar: (name: string, defaultValue?: any) => unknown; getBranding: () => Branding; }; + /** {@link WorkspacesStart} */ + workspaces: WorkspacesStart; } export { @@ -341,3 +347,10 @@ export { }; export { __osdBootstrap__ } from './osd_bootstrap'; + +export { + WorkspacesStart, + WorkspacesSetup, + WorkspacesService, + WorkspaceObservables, +} from './workspace'; diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index e863d627c801..722070d5a9ea 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -47,6 +47,7 @@ import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; import { contextServiceMock } from './context/context_service.mock'; import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; +import { workspacesServiceMock } from './workspace/workspaces_service.mock'; export { chromeServiceMock } from './chrome/chrome_service.mock'; export { docLinksServiceMock } from './doc_links/doc_links_service.mock'; @@ -60,6 +61,7 @@ export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; export { scopedHistoryMock } from './application/scoped_history.mock'; export { applicationServiceMock } from './application/application_service.mock'; +export { workspacesServiceMock } from './workspace/workspaces_service.mock'; function createCoreSetupMock({ basePath = '', @@ -85,6 +87,7 @@ function createCoreSetupMock({ getInjectedVar: injectedMetadataServiceMock.createSetupContract().getInjectedVar, getBranding: injectedMetadataServiceMock.createSetupContract().getBranding, }, + workspaces: workspacesServiceMock.createSetupContractMock(), }; return mock; @@ -106,6 +109,7 @@ function createCoreStartMock({ basePath = '' } = {}) { getBranding: injectedMetadataServiceMock.createStartContract().getBranding, }, fatalErrors: fatalErrorsServiceMock.createStartContract(), + workspaces: workspacesServiceMock.createStartContract(), }; return mock; diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index 42c40e91183f..87738fc7e57a 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -121,6 +121,7 @@ export function createPluginSetupContext< getBranding: deps.injectedMetadata.getBranding, }, getStartServices: () => plugin.startDependencies, + workspaces: deps.workspaces, }; } @@ -168,5 +169,6 @@ export function createPluginStartContext< getBranding: deps.injectedMetadata.getBranding, }, fatalErrors: deps.fatalErrors, + workspaces: deps.workspaces, }; } diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index b2cf4e8880cf..7e8c96c1f9d0 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -58,6 +58,7 @@ import { CoreSetup, CoreStart, PluginInitializerContext } from '..'; import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; import { contextServiceMock } from '../context/context_service.mock'; +import { workspacesServiceMock } from '../workspace/workspaces_service.mock'; export let mockPluginInitializers: Map; @@ -108,6 +109,7 @@ describe('PluginsService', () => { injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createSetupContract(), uiSettings: uiSettingsServiceMock.createSetupContract(), + workspaces: workspacesServiceMock.createSetupContractMock(), }; mockSetupContext = { ...mockSetupDeps, @@ -127,6 +129,7 @@ describe('PluginsService', () => { uiSettings: uiSettingsServiceMock.createStartContract(), savedObjects: savedObjectsServiceMock.createStartContract(), fatalErrors: fatalErrorsServiceMock.createStartContract(), + workspaces: workspacesServiceMock.createStartContract(), }; mockStartContext = { ...mockStartDeps, diff --git a/src/core/public/workspace/index.ts b/src/core/public/workspace/index.ts new file mode 100644 index 000000000000..4ef6aaae7fd4 --- /dev/null +++ b/src/core/public/workspace/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +export { + WorkspacesStart, + WorkspacesService, + WorkspacesSetup, + WorkspaceObservables, +} from './workspaces_service'; diff --git a/src/core/public/workspace/workspaces_service.mock.ts b/src/core/public/workspace/workspaces_service.mock.ts new file mode 100644 index 000000000000..3c35315aa850 --- /dev/null +++ b/src/core/public/workspace/workspaces_service.mock.ts @@ -0,0 +1,36 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { BehaviorSubject } from 'rxjs'; +import { WorkspaceAttribute } from '..'; + +const currentWorkspaceId$ = new BehaviorSubject(''); +const workspaceList$ = new BehaviorSubject([]); +const currentWorkspace$ = new BehaviorSubject(null); +const initialized$ = new BehaviorSubject(false); +const workspaceEnabled$ = new BehaviorSubject(false); + +const createWorkspacesSetupContractMock = () => ({ + currentWorkspaceId$, + workspaceList$, + currentWorkspace$, + initialized$, + workspaceEnabled$, + registerWorkspaceMenuRender: jest.fn(), +}); + +const createWorkspacesStartContractMock = () => ({ + currentWorkspaceId$, + workspaceList$, + currentWorkspace$, + initialized$, + workspaceEnabled$, + renderWorkspaceMenu: jest.fn(), +}); + +export const workspacesServiceMock = { + createSetupContractMock: createWorkspacesSetupContractMock, + createStartContract: createWorkspacesStartContractMock, +}; diff --git a/src/core/public/workspace/workspaces_service.ts b/src/core/public/workspace/workspaces_service.ts new file mode 100644 index 000000000000..39519ccdddbe --- /dev/null +++ b/src/core/public/workspace/workspaces_service.ts @@ -0,0 +1,134 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { BehaviorSubject, combineLatest } from 'rxjs'; +import { isEqual } from 'lodash'; + +import { CoreService, WorkspaceAttribute } from '../../types'; +import { InternalApplicationStart } from '../application'; +import { HttpSetup } from '../http'; + +type WorkspaceMenuRenderFn = ({ + basePath, + getUrlForApp, + observables, +}: { + getUrlForApp: InternalApplicationStart['getUrlForApp']; + basePath: HttpSetup['basePath']; + observables: WorkspaceObservables; +}) => JSX.Element | null; + +type WorkspaceObject = WorkspaceAttribute & { readonly?: boolean }; + +export interface WorkspaceObservables { + currentWorkspaceId$: BehaviorSubject; + currentWorkspace$: BehaviorSubject; + workspaceList$: BehaviorSubject; + workspaceEnabled$: BehaviorSubject; + initialized$: BehaviorSubject; +} + +enum WORKSPACE_ERROR { + WORKSPACE_STALED = 'WORKSPACE_STALED', +} + +/** + * @public + */ +export interface WorkspacesSetup extends WorkspaceObservables { + registerWorkspaceMenuRender: (render: WorkspaceMenuRenderFn) => void; +} + +export interface WorkspacesStart extends WorkspaceObservables { + renderWorkspaceMenu: () => JSX.Element | null; +} + +export class WorkspacesService implements CoreService { + private currentWorkspaceId$ = new BehaviorSubject(''); + private workspaceList$ = new BehaviorSubject([]); + private currentWorkspace$ = new BehaviorSubject(null); + private initialized$ = new BehaviorSubject(false); + private workspaceEnabled$ = new BehaviorSubject(false); + private _renderWorkspaceMenu: WorkspaceMenuRenderFn | null = null; + + constructor() { + combineLatest([this.initialized$, this.workspaceList$, this.currentWorkspaceId$]).subscribe( + ([workspaceInitialized, workspaceList, currentWorkspaceId]) => { + if (workspaceInitialized) { + const currentWorkspace = workspaceList.find((w) => w && w.id === currentWorkspaceId); + + /** + * Do a simple idempotent verification here + */ + if (!isEqual(currentWorkspace, this.currentWorkspace$.getValue())) { + this.currentWorkspace$.next(currentWorkspace ?? null); + } + + if (currentWorkspaceId && !currentWorkspace?.id) { + /** + * Current workspace is staled + */ + this.currentWorkspaceId$.error({ + reason: WORKSPACE_ERROR.WORKSPACE_STALED, + }); + this.currentWorkspace$.error({ + reason: WORKSPACE_ERROR.WORKSPACE_STALED, + }); + } + } + } + ); + } + + public setup(): WorkspacesSetup { + return { + currentWorkspaceId$: this.currentWorkspaceId$, + currentWorkspace$: this.currentWorkspace$, + workspaceList$: this.workspaceList$, + initialized$: this.initialized$, + workspaceEnabled$: this.workspaceEnabled$, + registerWorkspaceMenuRender: (render: WorkspaceMenuRenderFn) => + (this._renderWorkspaceMenu = render), + }; + } + + public start({ + http, + application, + }: { + application: InternalApplicationStart; + http: HttpSetup; + }): WorkspacesStart { + const observables = { + currentWorkspaceId$: this.currentWorkspaceId$, + currentWorkspace$: this.currentWorkspace$, + workspaceList$: this.workspaceList$, + initialized$: this.initialized$, + workspaceEnabled$: this.workspaceEnabled$, + }; + return { + ...observables, + renderWorkspaceMenu: () => { + if (this._renderWorkspaceMenu) { + return this._renderWorkspaceMenu({ + basePath: http.basePath, + getUrlForApp: application.getUrlForApp, + observables, + }); + } + return null; + }, + }; + } + + public async stop() { + this.currentWorkspace$.unsubscribe(); + this.currentWorkspaceId$.unsubscribe(); + this.workspaceList$.unsubscribe(); + this.workspaceEnabled$.unsubscribe(); + this.initialized$.unsubscribe(); + this._renderWorkspaceMenu = null; + } +} diff --git a/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap b/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap index 1b3c486615c8..d3d0fe94fb68 100644 --- a/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap +++ b/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap @@ -993,6 +993,54 @@ exports[`dashboard listing hideWriteControls 1`] = ` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -2085,6 +2133,54 @@ exports[`dashboard listing render table listing with initial filters from URL 1` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -3238,6 +3334,54 @@ exports[`dashboard listing renders call to action when no dashboards exist 1`] = "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -4391,6 +4535,54 @@ exports[`dashboard listing renders table rows 1`] = ` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -5544,6 +5736,54 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > diff --git a/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap b/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap index 101e0e520304..0c48ffdc474a 100644 --- a/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap +++ b/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap @@ -859,6 +859,54 @@ exports[`Dashboard top nav render in embed mode 1`] = ` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -1776,6 +1824,54 @@ exports[`Dashboard top nav render in embed mode, and force hide filter bar 1`] = "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -2693,6 +2789,54 @@ exports[`Dashboard top nav render in embed mode, components can be forced show b "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -3610,6 +3754,54 @@ exports[`Dashboard top nav render in full screen mode with appended URL param bu "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -4527,6 +4719,54 @@ exports[`Dashboard top nav render in full screen mode, no componenets should be "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } > @@ -5444,6 +5684,54 @@ exports[`Dashboard top nav render with all components 1`] = ` "allowTrackUserAgent": [MockFunction], "reportUiStats": [MockFunction], }, + "workspaces": Object { + "currentWorkspace$": BehaviorSubject { + "_isScalar": false, + "_value": null, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "currentWorkspaceId$": BehaviorSubject { + "_isScalar": false, + "_value": "", + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "initialized$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "renderWorkspaceMenu": [MockFunction], + "workspaceEnabled$": BehaviorSubject { + "_isScalar": false, + "_value": false, + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + "workspaceList$": BehaviorSubject { + "_isScalar": false, + "_value": Array [], + "closed": false, + "hasError": false, + "isStopped": false, + "observers": Array [], + "thrownError": null, + }, + }, } } >