diff --git a/src/core/public/http/base_path.ts b/src/core/public/http/base_path.ts index 44d2560bb4c..254e4e2e6ad 100644 --- a/src/core/public/http/base_path.ts +++ b/src/core/public/http/base_path.ts @@ -29,6 +29,7 @@ */ import { modifyUrl } from '@osd/std'; +import type { PrependOptions } from './types'; export class BasePath { constructor( @@ -45,7 +46,8 @@ export class BasePath { return this.basePath; }; - public prepend = (path: string, withoutWorkspace: boolean = false): string => { + public prepend = (path: string, prependOptions?: PrependOptions): string => { + const { withoutWorkspace } = prependOptions || {}; const basePath = withoutWorkspace ? this.basePath : this.get(); if (!basePath) return path; return modifyUrl(path, (parts) => { @@ -55,17 +57,19 @@ export class BasePath { }); }; - public remove = (path: string): string => { - if (!this.get()) { + public remove = (path: string, prependOptions?: PrependOptions): string => { + const { withoutWorkspace } = prependOptions || {}; + const basePath = withoutWorkspace ? this.basePath : this.get(); + if (!basePath) { return path; } - if (path === this.get()) { + if (path === basePath) { return '/'; } - if (path.startsWith(`${this.get()}/`)) { - return path.slice(this.get().length); + if (path.startsWith(`${basePath}/`)) { + return path.slice(basePath.length); } return path; diff --git a/src/core/public/http/http_service.ts b/src/core/public/http/http_service.ts index 45f69f1a692..c2caf18be88 100644 --- a/src/core/public/http/http_service.ts +++ b/src/core/public/http/http_service.ts @@ -37,6 +37,7 @@ import { LoadingCountService } from './loading_count_service'; import { Fetch } from './fetch'; import { CoreService } from '../../types'; import { getWorkspaceIdFromUrl } from '../utils'; +import { WORKSPACE_PATH_PREFIX } from '../../utils/constants'; interface HttpDeps { injectedMetadata: InjectedMetadataSetup; @@ -54,7 +55,7 @@ export class HttpService implements CoreService { let workspaceBasePath = ''; const workspaceId = getWorkspaceIdFromUrl(window.location.href); if (workspaceId) { - workspaceBasePath = `/w/${workspaceId}`; + workspaceBasePath = `${WORKSPACE_PATH_PREFIX}/${workspaceId}`; } const basePath = new BasePath( injectedMetadata.getBasePath(), diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index 4c81dbdd7a5..a50b9cb0c95 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -87,6 +87,16 @@ export interface HttpSetup { */ export type HttpStart = HttpSetup; +/** + * prepend options + * + * withoutWorkspace option will prepend a relative url with only basePath + * workspaceId will rewrite the /w/{workspaceId} part, if workspace id is an empty string, prepend will remove the workspaceId part + */ +export interface PrependOptions { + withoutWorkspace?: boolean; +} + /** * APIs for manipulating the basePath on URL segments. * @public @@ -105,12 +115,12 @@ export interface IBasePath { /** * Prepends `path` with the basePath + workspace. */ - prepend: (url: string) => string; + prepend: (url: string, prependOptions?: PrependOptions) => string; /** * Removes the prepended basePath + workspace from the `path`. */ - remove: (url: string) => string; + remove: (url: string, prependOptions?: PrependOptions) => string; /** * Returns the server's root basePath as configured, without any namespace prefix. diff --git a/src/core/public/index.ts b/src/core/public/index.ts index ae35430d580..c1a8d34aa67 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -357,3 +357,5 @@ export { WorkspaceAttribute, WorkspaceFindOptions, } from './workspace'; + +export { getWorkspaceIdFromUrl, WORKSPACE_TYPE } from './utils'; diff --git a/src/core/public/utils/index.ts b/src/core/public/utils/index.ts index 0719f5e83c5..ad363c53bd4 100644 --- a/src/core/public/utils/index.ts +++ b/src/core/public/utils/index.ts @@ -31,4 +31,5 @@ export { shareWeakReplay } from './share_weak_replay'; export { Sha256 } from './crypto'; export { MountWrapper, mountReactNode } from './mount'; -export { getWorkspaceIdFromUrl } from './workspace'; +export { getWorkspaceIdFromUrl, WORKSPACE_TYPE } from './workspace'; +export { WORKSPACE_PATH_PREFIX } from '../../utils'; diff --git a/src/core/public/utils/workspace.ts b/src/core/public/utils/workspace.ts index e93355aa00e..9a0f55b3fa8 100644 --- a/src/core/public/utils/workspace.ts +++ b/src/core/public/utils/workspace.ts @@ -13,3 +13,5 @@ export const getWorkspaceIdFromUrl = (url: string): string => { return ''; }; + +export const WORKSPACE_TYPE = 'workspace'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 6a234a405e5..e369b98d810 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -509,4 +509,4 @@ export const config = { }, }; -export { formatWorkspaces, workspacesValidator } from './workspaces'; +export { formatWorkspaces, workspacesValidator, WORKSPACE_TYPE } from './workspaces'; diff --git a/src/core/server/workspaces/constants.ts b/src/core/server/workspaces/constants.ts new file mode 100644 index 00000000000..73c2d601084 --- /dev/null +++ b/src/core/server/workspaces/constants.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const WORKSPACE_TYPE = 'workspace'; diff --git a/src/core/server/workspaces/index.ts b/src/core/server/workspaces/index.ts index 28079e7a36b..c1f88784aa0 100644 --- a/src/core/server/workspaces/index.ts +++ b/src/core/server/workspaces/index.ts @@ -14,3 +14,4 @@ export { WorkspaceAttribute, WorkspaceFindOptions } from './types'; export { WorkspacePermissionControl } from './workspace_permission_control'; export { workspacesValidator, formatWorkspaces } from './utils'; +export { WORKSPACE_TYPE } from './constants'; diff --git a/src/core/server/workspaces/saved_objects/workspace.ts b/src/core/server/workspaces/saved_objects/workspace.ts index d73a9e3b760..284ed013b7e 100644 --- a/src/core/server/workspaces/saved_objects/workspace.ts +++ b/src/core/server/workspaces/saved_objects/workspace.ts @@ -4,28 +4,15 @@ */ import { SavedObjectsType } from 'opensearch-dashboards/server'; +import { WORKSPACE_TYPE } from '../constants'; export const workspace: SavedObjectsType = { - name: 'workspace', + name: WORKSPACE_TYPE, namespaceType: 'agnostic', hidden: false, - management: { - icon: 'apps', // todo: pending ux #2034 - defaultSearchField: 'title', - importableAndExportable: true, - getTitle(obj) { - return obj.attributes.title; - }, - getEditUrl(obj) { - return `/management/opensearch-dashboards/dataSources/${encodeURIComponent(obj.id)}`; - }, - getInAppUrl(obj) { - return { - path: `/app/management/opensearch-dashboards/dataSources/${encodeURIComponent(obj.id)}`, - uiCapabilitiesPath: 'management.opensearchDashboards.dataSources', - }; - }, - }, + /** + * workspace won't appear in management page. + */ mappings: { dynamic: false, properties: { diff --git a/src/core/server/workspaces/workspaces_client.ts b/src/core/server/workspaces/workspaces_client.ts index 058d7477efd..7d4fdc85814 100644 --- a/src/core/server/workspaces/workspaces_client.ts +++ b/src/core/server/workspaces/workspaces_client.ts @@ -12,8 +12,7 @@ import { } from './types'; import { WorkspacesSetupDeps } from './workspaces_service'; import { workspace } from './saved_objects'; - -export const WORKSPACES_TYPE_FOR_SAVED_OBJECT = 'workspace'; +import { WORKSPACE_TYPE } from './constants'; export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { private setupDep: WorkspacesSetupDeps; @@ -50,7 +49,7 @@ export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { try { const result = await this.getSavedObjectClientsFromRequestDetail(requestDetail).create< Omit - >(WORKSPACES_TYPE_FOR_SAVED_OBJECT, payload); + >(WORKSPACE_TYPE, payload); return { success: true, result: { @@ -75,7 +74,7 @@ export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { } = await this.getSavedObjectClientsFromRequestDetail(requestDetail).find( { ...options, - type: WORKSPACES_TYPE_FOR_SAVED_OBJECT, + type: WORKSPACE_TYPE, } ); return { @@ -99,7 +98,7 @@ export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { try { const result = await this.getSavedObjectClientsFromRequestDetail(requestDetail).get< WorkspaceAttribute - >(WORKSPACES_TYPE_FOR_SAVED_OBJECT, id); + >(WORKSPACE_TYPE, id); return { success: true, result: this.getFlatternedResultWithSavedObject(result), @@ -119,7 +118,7 @@ export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { try { await this.getSavedObjectClientsFromRequestDetail(requestDetail).update< Omit - >(WORKSPACES_TYPE_FOR_SAVED_OBJECT, id, payload); + >(WORKSPACE_TYPE, id, payload); return { success: true, result: true, @@ -133,10 +132,7 @@ export class WorkspacesClientWithSavedObject implements IWorkspaceDBImpl { } public async delete(requestDetail: IRequestDetail, id: string): Promise> { try { - await this.getSavedObjectClientsFromRequestDetail(requestDetail).delete( - WORKSPACES_TYPE_FOR_SAVED_OBJECT, - id - ); + await this.getSavedObjectClientsFromRequestDetail(requestDetail).delete(WORKSPACE_TYPE, id); return { success: true, result: true, diff --git a/src/core/utils/constants.ts b/src/core/utils/constants.ts new file mode 100644 index 00000000000..e35ff014b38 --- /dev/null +++ b/src/core/utils/constants.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const WORKSPACE_PATH_PREFIX = '/w'; diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index 797d90c1813..5c3130c500d 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -38,3 +38,4 @@ export { } from './context'; export { DEFAULT_APP_CATEGORIES } from './default_app_categories'; export { DEFAULT_WORKSPACE_TEMPLATES } from './default_workspace_templates'; +export { WORKSPACE_PATH_PREFIX } from './constants'; 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 bcd947c4566..c19f8ccdd96 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 @@ -38,6 +38,7 @@ import { ManagementAppMountParams } from 'src/plugins/management/public'; import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; import { ISavedObjectsManagementServiceRegistry } from '../services'; import { getAllowedTypes } from './../lib'; +import { WORKSPACE_TYPE } from '../../../../core/public'; interface MountParams { core: CoreSetup; @@ -67,7 +68,12 @@ export const mountManagementSection = async ({ const setBreadcrumbs = mountParams?.setBreadcrumbs || chrome.setBreadcrumbs; let finalAllowedObjectTypes = allowedObjectTypes; if (finalAllowedObjectTypes === undefined) { - finalAllowedObjectTypes = await getAllowedTypes(coreStart.http); + /** + * 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 + ); } coreStart.chrome.docTitle.change(title); diff --git a/src/plugins/workspace/public/components/utils/workspace_column.tsx b/src/plugins/workspace/public/components/utils/workspace_column.tsx index b51a4d3178f..77ada67c7cd 100644 --- a/src/plugins/workspace/public/components/utils/workspace_column.tsx +++ b/src/plugins/workspace/public/components/utils/workspace_column.tsx @@ -31,10 +31,6 @@ function WorkspaceColumn({ coreSetup, workspaces, record }: WorkspaceColumnProps }); wsLookUp?.set('public', publicWsName); - if (record.type === 'workspace') { - return null; - } - if (!workspaces) { return {publicWsName}; } diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts index 45e8d6deb03..f79eb6d9bf5 100644 --- a/src/plugins/workspace/public/plugin.ts +++ b/src/plugins/workspace/public/plugin.ts @@ -14,9 +14,9 @@ import { } from '../../../core/public'; import { WORKSPACE_APP_ID } from '../common/constants'; import { mountDropdownList } from './mount'; -import { getWorkspaceIdFromUrl } from '../../../core/public/utils'; import { SavedObjectsManagementPluginSetup } from '../../saved_objects_management/public'; import { getWorkspaceColumn } from './components/utils/workspace_column'; +import { getWorkspaceIdFromUrl, WORKSPACE_PATH_PREFIX } from '../../../core/public/utils'; interface WorkspacesPluginSetupDeps { savedObjectsManagement?: SavedObjectsManagementPluginSetup; @@ -36,13 +36,16 @@ export class WorkspacesPlugin implements Plugin<{}, {}, WorkspacesPluginSetupDep */ newUrl.pathname = this.coreSetup?.http.basePath.remove(newUrl.pathname) || ''; if (workspaceId) { - newUrl.pathname = `${this.coreSetup?.http.basePath.serverBasePath || ''}/w/${workspaceId}${ - newUrl.pathname - }`; + newUrl.pathname = `${WORKSPACE_PATH_PREFIX}/${workspaceId}${newUrl.pathname}`; } else { - newUrl.pathname = `${this.coreSetup?.http.basePath.serverBasePath || ''}${newUrl.pathname}`; + newUrl.pathname = newUrl.pathname.replace(/^\/w\/([^\/]*)/, ''); } + newUrl.pathname = + this.coreSetup?.http.basePath.prepend(newUrl.pathname, { + withoutWorkspace: true, + }) || ''; + return newUrl.toString(); }; public async setup(core: CoreSetup, { savedObjectsManagement }: WorkspacesPluginSetupDeps) {