diff --git a/src/plugins/workspace/public/application.tsx b/src/plugins/workspace/public/application.tsx
index f85a0ec672c9..83c287357bbe 100644
--- a/src/plugins/workspace/public/application.tsx
+++ b/src/plugins/workspace/public/application.tsx
@@ -13,11 +13,16 @@ import { WorkspaceUpdaterApp } from './components/workspace_updater_app';
import { WorkspaceListApp } from './components/workspace_list_app';
import { WorkspaceUpdaterProps } from './components/workspace_updater';
import { Services } from './types';
+import { WorkspaceCreatorProps } from './components/workspace_creator/workspace_creator';
-export const renderCreatorApp = ({ element }: AppMountParameters, services: Services) => {
+export const renderCreatorApp = (
+ { element }: AppMountParameters,
+ services: Services,
+ props: WorkspaceCreatorProps
+) => {
ReactDOM.render(
-
+
,
element
);
diff --git a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx
index 9cc4f9b53f69..d6c972f8d9de 100644
--- a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx
+++ b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.test.tsx
@@ -88,13 +88,21 @@ describe('WorkspaceCreator', () => {
});
it('should not create workspace when name is empty', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).not.toHaveBeenCalled();
});
it('should not create workspace with invalid name', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: '~' },
@@ -103,7 +111,11 @@ describe('WorkspaceCreator', () => {
});
it('should not create workspace with invalid description', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -116,7 +128,11 @@ describe('WorkspaceCreator', () => {
});
it('cancel create workspace', async () => {
- const { findByText, getByTestId } = render();
+ const { findByText, getByTestId } = render(
+
+ );
fireEvent.click(getByTestId('workspaceForm-bottomBar-cancelButton'));
await findByText('Discard changes?');
fireEvent.click(getByTestId('confirmModalConfirmButton'));
@@ -124,7 +140,11 @@ describe('WorkspaceCreator', () => {
});
it('create workspace with detailed information', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -155,7 +175,11 @@ describe('WorkspaceCreator', () => {
it('create workspace with customized features', async () => {
setHrefSpy.mockReset();
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -181,7 +205,11 @@ describe('WorkspaceCreator', () => {
it('should show danger toasts after create workspace failed', async () => {
workspaceClientCreate.mockReturnValue({ result: { id: 'failResult' }, success: false });
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -198,7 +226,11 @@ describe('WorkspaceCreator', () => {
workspaceClientCreate.mockImplementation(async () => {
throw new Error();
});
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
diff --git a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx
index 0ba7ca9947df..176971172590 100644
--- a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx
+++ b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx
@@ -6,16 +6,27 @@
import React, { useCallback } from 'react';
import { EuiPage, EuiPageBody, EuiPageHeader, EuiPageContent, EuiSpacer } from '@elastic/eui';
import { i18n } from '@osd/i18n';
+import { useObservable } from 'react-use';
+
+import { PublicAppInfo } from 'opensearch-dashboards/public';
import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
import { WorkspaceForm, WorkspaceFormSubmitData, WorkspaceOperationType } from '../workspace_form';
import { WORKSPACE_OVERVIEW_APP_ID } from '../../../common/constants';
import { formatUrlWithWorkspaceId } from '../../../../../core/public/utils';
import { WorkspaceClient } from '../../workspace_client';
+import { BehaviorSubject, of } from 'rxjs';
+
+export interface WorkspaceCreatorProps {
+ workspaceConfigurableApps$?: BehaviorSubject;
+}
-export const WorkspaceCreator = () => {
+export const WorkspaceCreator = (props: WorkspaceCreatorProps) => {
const {
services: { application, notifications, http, workspaceClient },
} = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>();
+ const workspaceConfigurableApps = useObservable(
+ props.workspaceConfigurableApps$ ?? of(undefined)
+ );
const handleWorkspaceFormSubmit = useCallback(
async (data: WorkspaceFormSubmitData) => {
@@ -80,6 +91,7 @@ export const WorkspaceCreator = () => {
application={application}
onSubmit={handleWorkspaceFormSubmit}
operationType={WorkspaceOperationType.Create}
+ workspaceConfigurableApps={workspaceConfigurableApps}
/>
)}
diff --git a/src/plugins/workspace/public/components/workspace_creator_app.tsx b/src/plugins/workspace/public/components/workspace_creator_app.tsx
index b74359929352..e384f5d5bfed 100644
--- a/src/plugins/workspace/public/components/workspace_creator_app.tsx
+++ b/src/plugins/workspace/public/components/workspace_creator_app.tsx
@@ -8,8 +8,9 @@ import { I18nProvider } from '@osd/i18n/react';
import { i18n } from '@osd/i18n';
import { useOpenSearchDashboards } from '../../../opensearch_dashboards_react/public';
import { WorkspaceCreator } from './workspace_creator';
+import { WorkspaceCreatorProps } from './workspace_creator/workspace_creator';
-export const WorkspaceCreatorApp = () => {
+export const WorkspaceCreatorApp = (props: WorkspaceCreatorProps) => {
const {
services: { chrome },
} = useOpenSearchDashboards();
@@ -29,7 +30,7 @@ export const WorkspaceCreatorApp = () => {
return (
-
+
);
};
diff --git a/src/plugins/workspace/public/components/workspace_form/types.ts b/src/plugins/workspace/public/components/workspace_form/types.ts
index 592102eecada..d29048d9364f 100644
--- a/src/plugins/workspace/public/components/workspace_form/types.ts
+++ b/src/plugins/workspace/public/components/workspace_form/types.ts
@@ -4,7 +4,7 @@
*/
import type { WorkspaceOperationType } from './constants';
-import type { ApplicationStart } from '../../../../../core/public';
+import type { ApplicationStart, PublicAppInfo } from '../../../../../core/public';
export interface WorkspaceFormSubmitData {
name: string;
@@ -35,5 +35,5 @@ export interface WorkspaceFormProps {
onSubmit?: (formData: WorkspaceFormSubmitData) => void;
defaultValues?: WorkspaceFormData;
operationType?: WorkspaceOperationType;
- restrictedApps?: Set;
+ workspaceConfigurableApps?: PublicAppInfo[];
}
diff --git a/src/plugins/workspace/public/components/workspace_form/utils.test.ts b/src/plugins/workspace/public/components/workspace_form/utils.test.ts
index babaea2208e6..adc5a11bbc40 100644
--- a/src/plugins/workspace/public/components/workspace_form/utils.test.ts
+++ b/src/plugins/workspace/public/components/workspace_form/utils.test.ts
@@ -7,72 +7,6 @@ import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../../../core/pu
import { convertApplicationsToFeaturesOrGroups } from './utils';
describe('convertApplicationsToFeaturesOrGroups', () => {
- it('should not filter out restrict Apps', () => {
- expect(
- convertApplicationsToFeaturesOrGroups(
- [
- { id: 'foo1', title: 'Foo 1', navLinkStatus: AppNavLinkStatus.hidden },
- { id: 'foo2', title: 'Foo 2', navLinkStatus: AppNavLinkStatus.visible, chromeless: true },
- {
- id: 'foo3',
- title: 'Foo 3',
- navLinkStatus: AppNavLinkStatus.visible,
- category: DEFAULT_APP_CATEGORIES.management,
- },
- {
- id: 'workspace_overview',
- title: 'Workspace Overview',
- navLinkStatus: AppNavLinkStatus.visible,
- },
- {
- id: 'bar',
- title: 'Bar',
- navLinkStatus: AppNavLinkStatus.visible,
- },
- ],
- new Set(['foo1'])
- )
- ).toEqual([
- {
- id: 'foo1',
- name: 'Foo 1',
- },
- {
- id: 'bar',
- name: 'Bar',
- },
- ]);
- });
-
- it('should filter out invisible features', () => {
- expect(
- convertApplicationsToFeaturesOrGroups([
- { id: 'foo1', title: 'Foo 1', navLinkStatus: AppNavLinkStatus.hidden },
- { id: 'foo2', title: 'Foo 2', navLinkStatus: AppNavLinkStatus.visible, chromeless: true },
- {
- id: 'foo3',
- title: 'Foo 3',
- navLinkStatus: AppNavLinkStatus.visible,
- category: DEFAULT_APP_CATEGORIES.management,
- },
- {
- id: 'workspace_overview',
- title: 'Workspace Overview',
- navLinkStatus: AppNavLinkStatus.visible,
- },
- {
- id: 'bar',
- title: 'Bar',
- navLinkStatus: AppNavLinkStatus.visible,
- },
- ])
- ).toEqual([
- {
- id: 'bar',
- name: 'Bar',
- },
- ]);
- });
it('should group same category applications in same feature group', () => {
expect(
convertApplicationsToFeaturesOrGroups([
diff --git a/src/plugins/workspace/public/components/workspace_form/utils.ts b/src/plugins/workspace/public/components/workspace_form/utils.ts
index 1f9d202769fd..7750686a1994 100644
--- a/src/plugins/workspace/public/components/workspace_form/utils.ts
+++ b/src/plugins/workspace/public/components/workspace_form/utils.ts
@@ -3,11 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import {
- AppNavLinkStatus,
- DEFAULT_APP_CATEGORIES,
- PublicAppInfo,
-} from '../../../../../core/public';
+import { PublicAppInfo } from '../../../../../core/public';
import { DEFAULT_SELECTED_FEATURES_IDS } from '../../../common/constants';
import { WorkspaceFeature, WorkspaceFeatureGroup, WorkspaceFormErrors } from './types';
@@ -44,29 +40,10 @@ export const getNumberOfErrors = (formErrors: WorkspaceFormErrors) => {
export const convertApplicationsToFeaturesOrGroups = (
applications: Array<
Pick
- >,
- restrictedApps?: Set
+ >
) => {
const UNDEFINED = 'undefined';
- // Filter out all hidden applications and management applications and default selected features
- const visibleApplications = applications.filter(({ navLinkStatus, chromeless, category, id }) => {
- /**
- * Restrict apps are apps that can be configured into a workspace, but restrict to access
- * because the current workspace didn't have the apps configured, such apps should NOT filter out
- */
- if (restrictedApps && restrictedApps.has(id)) {
- return true;
- }
-
- return (
- navLinkStatus !== AppNavLinkStatus.hidden &&
- !chromeless &&
- !DEFAULT_SELECTED_FEATURES_IDS.includes(id) &&
- category?.id !== DEFAULT_APP_CATEGORIES.management.id
- );
- });
-
/**
*
* Convert applications to features map, the map use category label as
@@ -74,7 +51,7 @@ export const convertApplicationsToFeaturesOrGroups = (
* transfer application to feature.
*
**/
- const categoryLabel2Features = visibleApplications.reduce<{
+ const categoryLabel2Features = applications.reduce<{
[key: string]: WorkspaceFeature[];
}>((previousValue, application) => {
const label = application.category?.label || UNDEFINED;
diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_feature_selector.test.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_feature_selector.test.tsx
index 0875b0d1ff10..313d459b6018 100644
--- a/src/plugins/workspace/public/components/workspace_form/workspace_feature_selector.test.tsx
+++ b/src/plugins/workspace/public/components/workspace_form/workspace_feature_selector.test.tsx
@@ -9,7 +9,7 @@ import {
WorkspaceFeatureSelector,
WorkspaceFeatureSelectorProps,
} from './workspace_feature_selector';
-import { AppNavLinkStatus } from '../../../../../core/public';
+import { AppNavLinkStatus, AppStatus } from '../../../../../core/public';
const setup = (options?: Partial) => {
const onChangeMock = jest.fn();
@@ -19,28 +19,36 @@ const setup = (options?: Partial) => {
title: 'App 1',
category: { id: 'category-1', label: 'Category 1' },
navLinkStatus: AppNavLinkStatus.visible,
+ status: AppStatus.accessible,
+ appRoute: '/app-1',
},
{
id: 'app-2',
title: 'App 2',
category: { id: 'category-1', label: 'Category 1' },
navLinkStatus: AppNavLinkStatus.visible,
+ status: AppStatus.accessible,
+ appRoute: '/app-2',
},
{
id: 'app-3',
title: 'App 3',
category: { id: 'category-2', label: 'Category 2' },
navLinkStatus: AppNavLinkStatus.visible,
+ status: AppStatus.accessible,
+ appRoute: '/app-3',
},
{
id: 'app-4',
title: 'App 4',
navLinkStatus: AppNavLinkStatus.visible,
+ status: AppStatus.accessible,
+ appRoute: '/app-4',
},
];
const renderResult = render(
- >;
selectedFeatures: string[];
onChange: (newFeatures: string[]) => void;
- restrictedApps?: Set;
+ workspaceConfigurableApps?: PublicAppInfo[];
}
export const WorkspaceFeatureSelector = ({
- applications,
selectedFeatures,
onChange,
- restrictedApps,
+ workspaceConfigurableApps,
}: WorkspaceFeatureSelectorProps) => {
const featuresOrGroups = useMemo(
- () => convertApplicationsToFeaturesOrGroups(applications, restrictedApps),
- [applications, restrictedApps]
+ () => convertApplicationsToFeaturesOrGroups(workspaceConfigurableApps ?? []),
+ [workspaceConfigurableApps]
);
const handleFeatureChange = useCallback(
diff --git a/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx b/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx
index be50228512f2..b6f93bf3acff 100644
--- a/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx
+++ b/src/plugins/workspace/public/components/workspace_form/workspace_form.tsx
@@ -32,7 +32,6 @@ export const WorkspaceForm = (props: WorkspaceFormProps) => {
formData,
formErrors,
selectedTab,
- applications,
numberOfErrors,
handleFormSubmit,
handleColorChange,
@@ -133,10 +132,9 @@ export const WorkspaceForm = (props: WorkspaceFormProps) => {
)}
diff --git a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.test.tsx b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.test.tsx
index d829154426dd..0f86a800a309 100644
--- a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.test.tsx
+++ b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.test.tsx
@@ -113,12 +113,21 @@ describe('WorkspaceUpdater', () => {
it('cannot render when the name of the current workspace is empty', async () => {
const mockedWorkspacesService = workspacesServiceMock.createSetupContract();
- const { container } = render();
+ const { container } = render(
+
+ );
expect(container).toMatchInlineSnapshot(``);
});
it('cannot update workspace with invalid name', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: '~' },
@@ -127,7 +136,11 @@ describe('WorkspaceUpdater', () => {
});
it('cannot update workspace with invalid description', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -140,7 +153,11 @@ describe('WorkspaceUpdater', () => {
});
it('cancel update workspace', async () => {
- const { findByText, getByTestId } = render();
+ const { findByText, getByTestId } = render(
+
+ );
fireEvent.click(getByTestId('workspaceForm-bottomBar-cancelButton'));
await findByText('Discard changes?');
fireEvent.click(getByTestId('confirmModalConfirmButton'));
@@ -148,7 +165,11 @@ describe('WorkspaceUpdater', () => {
});
it('update workspace successfully', async () => {
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -190,7 +211,11 @@ describe('WorkspaceUpdater', () => {
it('should show danger toasts after update workspace failed', async () => {
workspaceClientUpdate.mockReturnValue({ result: false, success: false });
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -207,7 +232,11 @@ describe('WorkspaceUpdater', () => {
workspaceClientUpdate.mockImplementation(() => {
throw new Error('update workspace failed');
});
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
@@ -222,7 +251,12 @@ describe('WorkspaceUpdater', () => {
it('should show danger toasts when currentWorkspace is missing after click update button', async () => {
const mockedWorkspacesService = workspacesServiceMock.createSetupContract();
- const { getByTestId } = render();
+ const { getByTestId } = render(
+
+ );
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
diff --git a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx
index b877ccc8191b..c79a66e7b40a 100644
--- a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx
+++ b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx
@@ -6,7 +6,7 @@
import React, { useCallback, useEffect, useState } from 'react';
import { EuiPage, EuiPageBody, EuiPageHeader, EuiPageContent } from '@elastic/eui';
import { i18n } from '@osd/i18n';
-import { WorkspaceAttribute } from 'opensearch-dashboards/public';
+import { PublicAppInfo, WorkspaceAttribute } from 'opensearch-dashboards/public';
import { useObservable } from 'react-use';
import { BehaviorSubject, of } from 'rxjs';
import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
@@ -17,7 +17,7 @@ import { WorkspaceClient } from '../../workspace_client';
import { WorkspaceFormData } from '../workspace_form/types';
export interface WorkspaceUpdaterProps {
- restrictedApps$?: BehaviorSubject>;
+ workspaceConfigurableApps$?: BehaviorSubject;
}
function getFormDataFromWorkspace(
@@ -32,7 +32,9 @@ export const WorkspaceUpdater = (props: WorkspaceUpdaterProps) => {
} = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>();
const currentWorkspace = useObservable(workspaces ? workspaces.currentWorkspace$ : of(null));
- const restrictedApps = useObservable(props.restrictedApps$ ?? of(undefined));
+ const workspaceConfigurableApps = useObservable(
+ props.workspaceConfigurableApps$ ?? of(undefined)
+ );
const [currentWorkspaceFormData, setCurrentWorkspaceFormData] = useState(
getFormDataFromWorkspace(currentWorkspace)
);
@@ -113,7 +115,7 @@ export const WorkspaceUpdater = (props: WorkspaceUpdaterProps) => {
defaultValues={currentWorkspaceFormData}
onSubmit={handleWorkspaceFormSubmit}
operationType={WorkspaceOperationType.Update}
- restrictedApps={restrictedApps}
+ workspaceConfigurableApps={workspaceConfigurableApps}
/>
)}
diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts
index 52ba42feb31e..a615b71cf4e5 100644
--- a/src/plugins/workspace/public/plugin.ts
+++ b/src/plugins/workspace/public/plugin.ts
@@ -14,7 +14,7 @@ import {
AppNavLinkStatus,
AppUpdater,
AppStatus,
- DEFAULT_APP_CATEGORIES,
+ PublicAppInfo,
} from '../../../core/public';
import {
WORKSPACE_FATAL_ERROR_APP_ID,
@@ -29,7 +29,8 @@ import { WorkspaceClient } from './workspace_client';
import { SavedObjectsManagementPluginSetup } from '../../../plugins/saved_objects_management/public';
import { WorkspaceMenu } from './components/workspace_menu/workspace_menu';
import { getWorkspaceColumn } from './components/workspace_column';
-import { isAppAccessibleInWorkspace } from './utils';
+import { filterWorkspaceConfigurableApps, isAppAccessibleInWorkspace } from './utils';
+import { first } from 'rxjs/operators';
type WorkspaceAppType = (
params: AppMountParameters,
@@ -46,7 +47,7 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
private currentWorkspaceSubscription?: Subscription;
private currentWorkspaceIdSubscription?: Subscription;
private appUpdater$ = new BehaviorSubject(() => undefined);
- private restrictedApps$ = new BehaviorSubject(new Set());
+ private workspaceConfigurableApps$ = new BehaviorSubject([]);
private _changeSavedObjectCurrentWorkspace() {
if (this.coreStart) {
return this.coreStart.workspaces.currentWorkspaceId$.subscribe((currentWorkspaceId) => {
@@ -61,7 +62,7 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
* Filter nav links by the current workspace, once the current workspace change, the nav links(left nav bar)
* should also be updated according to the configured features of the current workspace
*/
- private filterNavLinks(core: CoreStart) {
+ private filterNavLinks = (core: CoreStart) => {
const currentWorkspace$ = core.workspaces.currentWorkspace$;
this.currentWorkspaceSubscription?.unsubscribe();
@@ -76,15 +77,6 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
return;
}
- /**
- * Restricted apps can be configured into a workspace, but they are not configured by the
- * current workspace. Apps of management category can NOT configured into a workspace, so
- * needs to be excluded.
- */
- if (app.category?.id !== DEFAULT_APP_CATEGORIES.management.id) {
- this.restrictedApps$.next(this.restrictedApps$.value.add(app.id));
- }
-
/**
* Change the app to `inaccessible` if it is not configured in the workspace
* If trying to access such app, an "Application Not Found" page will be displayed
@@ -93,7 +85,20 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
});
}
});
- }
+ };
+
+ /**
+ * Initiate an observable with the value of all applications which can be configured by workspace
+ */
+ private setWorkspaceConfigurableApps = async (core: CoreStart) => {
+ const allApps = await new Promise((resolve) => {
+ core.application.applications$.pipe(first()).subscribe((apps) => {
+ resolve([...apps.values()]);
+ });
+ });
+ const availableApps = filterWorkspaceConfigurableApps(allApps);
+ this.workspaceConfigurableApps$.next(availableApps);
+ };
public async setup(core: CoreSetup, { savedObjectsManagement }: WorkspacePluginSetupDeps) {
const workspaceClient = new WorkspaceClient(core.http, core.workspaces);
@@ -149,7 +154,9 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
workspaceClient,
};
- return renderApp(params, services, { restrictedApps$: this.restrictedApps$ });
+ return renderApp(params, services, {
+ workspaceConfigurableApps$: this.workspaceConfigurableApps$,
+ });
};
// create
@@ -223,8 +230,10 @@ export class WorkspacePlugin implements Plugin<{}, {}, WorkspacePluginSetupDeps>
this.currentWorkspaceIdSubscription = this._changeSavedObjectCurrentWorkspace();
- // When starts, filter the nav links based on the current workspace
- this.filterNavLinks(core);
+ this.setWorkspaceConfigurableApps(core).then(() => {
+ // filter the nav links based on the current workspace
+ this.filterNavLinks(core);
+ });
return {};
}
diff --git a/src/plugins/workspace/public/utils.ts b/src/plugins/workspace/public/utils.ts
index e70a26028525..dd0cb8275469 100644
--- a/src/plugins/workspace/public/utils.ts
+++ b/src/plugins/workspace/public/utils.ts
@@ -3,7 +3,15 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { App, AppCategory, AppNavLinkStatus, WorkspaceObject } from '../../../core/public';
+import {
+ App,
+ AppCategory,
+ AppNavLinkStatus,
+ DEFAULT_APP_CATEGORIES,
+ PublicAppInfo,
+ WorkspaceObject,
+} from '../../../core/public';
+import { DEFAULT_SELECTED_FEATURES_IDS } from '../common/constants';
/**
* Checks if a given feature matches the provided feature configuration.
@@ -99,3 +107,16 @@ export function isAppAccessibleInWorkspace(app: App, workspace: WorkspaceObject)
}
return false;
}
+
+export const filterWorkspaceConfigurableApps = (applications: PublicAppInfo[]) => {
+ const visibleApplications = applications.filter(({ navLinkStatus, chromeless, category, id }) => {
+ return (
+ navLinkStatus !== AppNavLinkStatus.hidden &&
+ !chromeless &&
+ !DEFAULT_SELECTED_FEATURES_IDS.includes(id) &&
+ category?.id !== DEFAULT_APP_CATEGORIES.management.id
+ );
+ });
+
+ return visibleApplications;
+};