mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Core] Deprecate nav link status (#176383)
This commit is contained in:
parent
1f93119b86
commit
9db8d2558c
116 changed files with 640 additions and 988 deletions
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { BfetchPublicSetup, BfetchPublicStart } from '@kbn/bfetch-plugin/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { mount } from './mount';
|
||||
|
@ -40,7 +40,7 @@ export class BfetchExplorerPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: 'bfetch-explorer',
|
||||
title: 'bfetch explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core, explorer),
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { AppNavLinkStatus } from '@kbn/core-application-browser';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { StartDeps, SetupDeps } from './types';
|
||||
|
||||
|
@ -23,7 +22,7 @@ export class ContentManagementExamplesPlugin
|
|||
core.application.register({
|
||||
id: `contentManagementExamples`,
|
||||
title: `Content Management Examples`,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp } = await import('./examples');
|
||||
const [coreStart, deps] = await core.getStartServices();
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
"@kbn/core",
|
||||
"@kbn/developer-examples-plugin",
|
||||
"@kbn/content-management-plugin",
|
||||
"@kbn/core-application-browser",
|
||||
"@kbn/shared-ux-link-redirect-app",
|
||||
"@kbn/content-management-table-list-view",
|
||||
"@kbn/content-management-table-list-view-table",
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public';
|
||||
|
@ -35,7 +29,7 @@ export class ControlsExamplePlugin
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: 'Controls examples',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
|
@ -25,7 +25,7 @@ export class DataViewFieldEditorPlugin implements Plugin<void, void, SetupDeps,
|
|||
core.application.register({
|
||||
id: 'dataViewFieldEditorExample',
|
||||
title: 'Data view field editor example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -14,13 +14,7 @@ import {
|
|||
EuiWrappingPopover,
|
||||
IconType,
|
||||
} from '@elastic/eui';
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
SimpleSavedObject,
|
||||
} from '@kbn/core/public';
|
||||
import { CoreSetup, CoreStart, Plugin, SimpleSavedObject } from '@kbn/core/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import type { DiscoverSetup, DiscoverStart } from '@kbn/discover-plugin/public';
|
||||
import { noop } from 'lodash';
|
||||
|
@ -50,7 +44,7 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount() {
|
||||
plugins.discover?.locator?.navigate(
|
||||
{ profile: 'customization-examples' },
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { EmbeddableExamplesStart } from '@kbn/embeddable-examples-plugin/public/plugin';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { UiActionsService } from '@kbn/ui-actions-plugin/public';
|
||||
import { EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
||||
import { Start as InspectorStart } from '@kbn/inspector-plugin/public';
|
||||
|
@ -30,7 +30,7 @@ export class EmbeddableExplorerPlugin implements Plugin<void, void, {}, StartDep
|
|||
core.application.register({
|
||||
id: 'embeddableExplorer',
|
||||
title: 'Embeddable explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public';
|
||||
import { Setup as InspectorSetup, Start as InspectorStart } from '@kbn/inspector-plugin/public';
|
||||
|
@ -47,7 +47,7 @@ export class ExpressionsExplorerPlugin implements Plugin<void, void, SetupDeps,
|
|||
core.application.register({
|
||||
id: 'expressionsExplorer',
|
||||
title: 'Expressions Explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -8,13 +8,7 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { FieldFormatsSetup, FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import {
|
||||
|
@ -77,7 +71,7 @@ export class FieldFormatsExamplePlugin implements Plugin<void, void, SetupDeps,
|
|||
core.application.register({
|
||||
id: 'fieldFormatsExample',
|
||||
title: 'Field formats example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount({ element }: AppMountParameters) {
|
||||
const [, plugins] = await core.getStartServices();
|
||||
ReactDOM.render(
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { AppNavLinkStatus } from '@kbn/core-application-browser';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { PLUGIN_ID, PLUGIN_NAME, exampleFileKind, MyImageMetadata } from '../common';
|
||||
import { FilesExamplePluginsStart, FilesExamplePluginsSetup } from './types';
|
||||
|
@ -32,7 +31,7 @@ export class FilesExamplePlugin
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
"@kbn/core",
|
||||
"@kbn/files-plugin",
|
||||
"@kbn/shared-ux-file-types",
|
||||
"@kbn/core-application-browser",
|
||||
"@kbn/shared-ux-file-context",
|
||||
"@kbn/shared-ux-file-image",
|
||||
"@kbn/shared-ux-file-upload",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { HelloLocator, HelloLocatorDefinition } from './locator';
|
||||
|
||||
interface SetupDeps {
|
||||
|
@ -31,7 +31,7 @@ export class LocatorExamplesPlugin
|
|||
core.application.register({
|
||||
id: 'locatorExamples',
|
||||
title: 'Access links examples',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp } = await import('./app');
|
||||
return renderApp(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
|
||||
interface SetupDeps {
|
||||
|
@ -24,7 +24,7 @@ export class LocatorExplorerPlugin implements Plugin<void, void, SetupDeps, Star
|
|||
core.application.register({
|
||||
id: 'locatorExplorer',
|
||||
title: 'Locator explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp } = await import('./app');
|
||||
return renderApp(
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import type { ExpressionsServiceSetup } from '@kbn/expressions-plugin/common';
|
||||
import { ExpressionsServiceFork } from '@kbn/expressions-plugin/common/service/expressions_fork';
|
||||
import { AppMountParameters, AppNavLinkStatus, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { App, ExpressionsContext } from './app';
|
||||
import { countEvent, getEvents, pluck } from './functions';
|
||||
|
@ -33,7 +33,7 @@ export class PartialResultsExamplePlugin implements Plugin<void, void, SetupDeps
|
|||
application.register({
|
||||
id: 'partialResultsExample',
|
||||
title: 'Partial Results Example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async ({ element }: AppMountParameters) => {
|
||||
ReactDOM.render(
|
||||
<ExpressionsContext.Provider value={expressionsStart}>
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
|
@ -41,7 +35,7 @@ export class PortableDashboardsExamplePlugin
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: 'Portable dashboard examples',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { AppMountParameters, AppNavLinkStatus, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import image from './resizable_layout_examples.png';
|
||||
|
||||
|
@ -22,7 +22,7 @@ export class ResizableLayoutExamplesPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { PLUGIN_ID, PLUGIN_NAME } from '../common/constants';
|
||||
import { mount } from './mount';
|
||||
|
@ -26,7 +26,7 @@ export class ResponseStreamPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
});
|
||||
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
CoreStart,
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
} from '@kbn/core/public';
|
||||
import { CoreStart, Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { getServices } from './services';
|
||||
|
||||
|
@ -25,7 +19,7 @@ export class RoutingExamplePlugin implements Plugin<{}, {}, SetupDeps, {}> {
|
|||
core.application.register({
|
||||
id: 'routingExample',
|
||||
title: 'Routing',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
const startServices = getServices(coreStart);
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
AppNavLinkStatus,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { AppPluginSetupDependencies, AppPluginStartDependencies } from './types';
|
||||
import { MetricsTracking } from './services';
|
||||
import { PLUGIN_NAME } from '../common';
|
||||
|
@ -33,7 +27,7 @@ export class ScreenshotModeExamplePlugin implements Plugin<void, void> {
|
|||
core.application.register({
|
||||
id: 'screenshotModeExample',
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import {
|
||||
AppPluginSetupDependencies,
|
||||
AppPluginStartDependencies,
|
||||
|
@ -40,7 +34,7 @@ export class SearchExamplesPlugin
|
|||
core.application.register({
|
||||
id: 'searchExamples',
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { AppMountParameters, CoreSetup, Plugin, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { AppPluginDependencies } from './with_data_services/types';
|
||||
import image from './state_sync.png';
|
||||
|
@ -37,7 +37,7 @@ export class StateContainersExamplesPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: 'stateContainersExampleBrowserHistory',
|
||||
title: examples.stateContainersExampleBrowserHistory.title,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp, History } = await import('./todo/app');
|
||||
const [coreStart] = await core.getStartServices();
|
||||
|
@ -54,7 +54,7 @@ export class StateContainersExamplesPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: 'stateContainersExampleHashHistory',
|
||||
title: examples.stateContainersExampleHashHistory.title,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp, History } = await import('./todo/app');
|
||||
const [coreStart] = await core.getStartServices();
|
||||
|
@ -72,7 +72,7 @@ export class StateContainersExamplesPlugin implements Plugin {
|
|||
core.application.register({
|
||||
id: 'stateContainersExampleWithDataServices',
|
||||
title: examples.stateContainersExampleWithDataServices.title,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const { renderApp } = await import('./with_data_services/application');
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import {
|
||||
PHONE_TRIGGER,
|
||||
|
@ -64,7 +64,7 @@ export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps
|
|||
core.application.register({
|
||||
id: 'uiActionsExplorer',
|
||||
title: 'Ui Actions Explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import {
|
||||
AppPluginSetupDependencies,
|
||||
AppPluginStartDependencies,
|
||||
|
@ -39,7 +33,7 @@ export class UnifiedFieldListExamplesPlugin
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -20,4 +20,6 @@ export {
|
|||
parseAppUrl,
|
||||
relativeToAbsolute,
|
||||
removeSlashes,
|
||||
DEFAULT_APP_VISIBILITY,
|
||||
DEFAULT_LINK_VISIBILITY,
|
||||
} from './src/utils';
|
||||
|
|
|
@ -30,12 +30,12 @@ import { ApplicationService } from './application_service';
|
|||
import {
|
||||
App,
|
||||
AppDeepLink,
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
AppUpdater,
|
||||
PublicAppInfo,
|
||||
} from '@kbn/core-application-browser';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { DEFAULT_APP_VISIBILITY } from './utils';
|
||||
|
||||
const createApp = (props: Partial<App>): App => {
|
||||
return {
|
||||
|
@ -109,7 +109,17 @@ describe('#setup()', () => {
|
|||
setup.register(pluginId, createApp({ id: 'app1', updater$ }));
|
||||
setup.register(
|
||||
pluginId,
|
||||
createApp({ id: 'app2', deepLinks: [{ id: 'subapp1', title: 'Subapp', path: '/subapp' }] })
|
||||
createApp({
|
||||
id: 'app2',
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'subapp1',
|
||||
title: 'Subapp',
|
||||
path: '/subapp',
|
||||
visibleIn: undefined, // not specified
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
const { applications$ } = await service.start(startDeps);
|
||||
|
||||
|
@ -118,18 +128,18 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app1')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
})
|
||||
);
|
||||
expect(applications.get('app2')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app2',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: ['globalSearch'], // if not specified, deep links are visible in globalSearch
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
@ -147,20 +157,23 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app1')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
status: AppStatus.inaccessible,
|
||||
defaultPath: 'foo/bar',
|
||||
tooltip: 'App inaccessible due to reason',
|
||||
deepLinks: [
|
||||
expect.objectContaining({ id: 'subapp2', title: 'Subapp 2', path: '/subapp2' }),
|
||||
],
|
||||
deepLinks: [], // deep links are removed when the app is inaccessible
|
||||
})
|
||||
);
|
||||
expect(applications.get('app2')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app2',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
visibleIn: ['globalSearch'],
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -212,7 +225,7 @@ describe('#setup()', () => {
|
|||
if (app.id === 'app1') {
|
||||
return {
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
tooltip: 'App inaccessible due to reason',
|
||||
};
|
||||
}
|
||||
|
@ -228,7 +241,7 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app1')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
status: AppStatus.inaccessible,
|
||||
tooltip: 'App inaccessible due to reason',
|
||||
})
|
||||
|
@ -236,7 +249,7 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app2')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app2',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
tooltip: 'App accessible',
|
||||
})
|
||||
|
@ -248,7 +261,7 @@ describe('#setup()', () => {
|
|||
const pluginId = Symbol('plugin');
|
||||
const appStatusUpdater$ = new BehaviorSubject<AppUpdater>((app) => ({
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
}));
|
||||
setup.register(pluginId, createApp({ id: 'app1', updater$: appStatusUpdater$ }));
|
||||
setup.register(pluginId, createApp({ id: 'app2' }));
|
||||
|
@ -263,7 +276,7 @@ describe('#setup()', () => {
|
|||
}
|
||||
return {
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
})
|
||||
);
|
||||
|
@ -275,7 +288,7 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app1')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
status: AppStatus.inaccessible,
|
||||
tooltip: 'App inaccessible due to reason',
|
||||
})
|
||||
|
@ -284,7 +297,7 @@ describe('#setup()', () => {
|
|||
expect.objectContaining({
|
||||
id: 'app2',
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -298,7 +311,7 @@ describe('#setup()', () => {
|
|||
new BehaviorSubject<AppUpdater>((app) => {
|
||||
return {
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: ['globalSearch'], // passing "globalSearch" but as the app is inaccessible it will be removed
|
||||
};
|
||||
})
|
||||
);
|
||||
|
@ -306,7 +319,7 @@ describe('#setup()', () => {
|
|||
new BehaviorSubject<AppUpdater>((app) => {
|
||||
return {
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
@ -318,7 +331,7 @@ describe('#setup()', () => {
|
|||
expect(applications.get('app1')).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
status: AppStatus.inaccessible,
|
||||
})
|
||||
);
|
||||
|
@ -333,7 +346,7 @@ describe('#setup()', () => {
|
|||
const statusUpdater = new BehaviorSubject<AppUpdater>((app) => {
|
||||
return {
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
};
|
||||
});
|
||||
setup.registerAppUpdater(statusUpdater);
|
||||
|
@ -348,14 +361,14 @@ describe('#setup()', () => {
|
|||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
})
|
||||
);
|
||||
|
||||
statusUpdater.next((app) => {
|
||||
return {
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -363,7 +376,7 @@ describe('#setup()', () => {
|
|||
expect.objectContaining({
|
||||
id: 'app1',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -408,15 +421,13 @@ describe('#setup()', () => {
|
|||
{
|
||||
id: 'foo',
|
||||
title: 'Foo',
|
||||
searchable: true,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['globalSearch'],
|
||||
path: '/foo',
|
||||
},
|
||||
{
|
||||
id: 'bar',
|
||||
title: 'Bar',
|
||||
searchable: false,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
path: '/bar',
|
||||
},
|
||||
];
|
||||
|
@ -434,18 +445,16 @@ describe('#setup()', () => {
|
|||
deepLinks: [],
|
||||
id: 'foo',
|
||||
keywords: [],
|
||||
navLinkStatus: 1,
|
||||
visibleIn: ['globalSearch'],
|
||||
path: '/foo',
|
||||
searchable: true,
|
||||
title: 'Foo',
|
||||
},
|
||||
{
|
||||
deepLinks: [],
|
||||
id: 'bar',
|
||||
keywords: [],
|
||||
navLinkStatus: 3,
|
||||
visibleIn: [],
|
||||
path: '/bar',
|
||||
searchable: false,
|
||||
title: 'Bar',
|
||||
},
|
||||
]);
|
||||
|
@ -455,8 +464,7 @@ describe('#setup()', () => {
|
|||
{
|
||||
id: 'bar',
|
||||
title: 'Bar',
|
||||
searchable: false,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
path: '/bar',
|
||||
},
|
||||
],
|
||||
|
@ -469,9 +477,8 @@ describe('#setup()', () => {
|
|||
deepLinks: [],
|
||||
id: 'bar',
|
||||
keywords: [],
|
||||
navLinkStatus: 3,
|
||||
visibleIn: [],
|
||||
path: '/bar',
|
||||
searchable: false,
|
||||
title: 'Bar',
|
||||
},
|
||||
]);
|
||||
|
@ -548,7 +555,7 @@ describe('#start()', () => {
|
|||
expect.objectContaining({
|
||||
appRoute: '/app/app1',
|
||||
id: 'app1',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
})
|
||||
);
|
||||
|
@ -556,7 +563,7 @@ describe('#start()', () => {
|
|||
expect.objectContaining({
|
||||
appRoute: '/app/app2',
|
||||
id: 'app2',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
status: AppStatus.accessible,
|
||||
})
|
||||
);
|
||||
|
|
|
@ -29,7 +29,7 @@ import type {
|
|||
NavigateToUrlOptions,
|
||||
} from '@kbn/core-application-browser';
|
||||
import { CapabilitiesService } from '@kbn/core-capabilities-browser-internal';
|
||||
import { AppStatus, AppNavLinkStatus } from '@kbn/core-application-browser';
|
||||
import { AppStatus } from '@kbn/core-application-browser';
|
||||
import type { CustomBrandingStart } from '@kbn/core-custom-branding-browser';
|
||||
import { AppRouter } from './ui';
|
||||
import type { InternalApplicationSetup, InternalApplicationStart, Mounter } from './types';
|
||||
|
@ -206,7 +206,6 @@ export class ApplicationService {
|
|||
this.apps.set(app.id, {
|
||||
...appProps,
|
||||
status: app.status ?? AppStatus.accessible,
|
||||
navLinkStatus: app.navLinkStatus ?? AppNavLinkStatus.default,
|
||||
deepLinks: populateDeepLinkDefaults(appProps.deepLinks),
|
||||
});
|
||||
if (updater$) {
|
||||
|
@ -468,10 +467,6 @@ const updateStatus = (app: App, statusUpdaters: AppUpdaterWrapper[]): App => {
|
|||
changes.status ?? AppStatus.accessible,
|
||||
fields.status ?? AppStatus.accessible
|
||||
),
|
||||
navLinkStatus: Math.max(
|
||||
changes.navLinkStatus ?? AppNavLinkStatus.default,
|
||||
fields.navLinkStatus ?? AppNavLinkStatus.default
|
||||
),
|
||||
...(fields.deepLinks ? { deepLinks: populateDeepLinkDefaults(fields.deepLinks) } : {}),
|
||||
};
|
||||
}
|
||||
|
@ -489,7 +484,7 @@ const populateDeepLinkDefaults = (deepLinks?: AppDeepLink[]): AppDeepLink[] => {
|
|||
}
|
||||
return deepLinks.map((deepLink) => ({
|
||||
...deepLink,
|
||||
navLinkStatus: deepLink.navLinkStatus ?? AppNavLinkStatus.default,
|
||||
visibleIn: deepLink.visibleIn ?? ['globalSearch'], // by default, deepLinks are only visible in global search.
|
||||
deepLinks: populateDeepLinkDefaults(deepLink.deepLinks),
|
||||
}));
|
||||
};
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { AppDeepLinkLocations } from '@kbn/core-application-browser/src/application';
|
||||
|
||||
export const DEFAULT_APP_VISIBILITY: AppDeepLinkLocations[] = ['globalSearch', 'sideNav'];
|
||||
|
||||
export const DEFAULT_LINK_VISIBILITY: AppDeepLinkLocations[] = ['globalSearch'];
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { of } from 'rxjs';
|
||||
import { App, AppDeepLink, AppNavLinkStatus, AppStatus } from '@kbn/core-application-browser';
|
||||
import { App, AppDeepLink, AppStatus } from '@kbn/core-application-browser';
|
||||
import { getAppInfo } from './get_app_info';
|
||||
|
||||
describe('getAppInfo', () => {
|
||||
|
@ -17,8 +17,6 @@ describe('getAppInfo', () => {
|
|||
id: 'some-id',
|
||||
title: 'some-title',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
appRoute: `/app/some-id`,
|
||||
...props,
|
||||
});
|
||||
|
@ -27,8 +25,7 @@ describe('getAppInfo', () => {
|
|||
id: 'some-deep-link-id',
|
||||
title: 'my deep link',
|
||||
path: '/my-deep-link',
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
...props,
|
||||
|
@ -42,14 +39,19 @@ describe('getAppInfo', () => {
|
|||
id: 'some-id',
|
||||
title: 'some-title',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
appRoute: `/app/some-id`,
|
||||
keywords: [],
|
||||
deepLinks: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('does not return any deepLinks if the app is inaccessible', () => {
|
||||
const app = createApp({ status: AppStatus.inaccessible, deepLinks: [createDeepLink()] });
|
||||
const info = getAppInfo(app);
|
||||
expect(info.deepLinks).toEqual([]);
|
||||
});
|
||||
|
||||
it('populates default values for nested deepLinks', () => {
|
||||
const app = createApp({
|
||||
deepLinks: [
|
||||
|
@ -66,16 +68,14 @@ describe('getAppInfo', () => {
|
|||
id: 'some-id',
|
||||
title: 'some-title',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
appRoute: `/app/some-id`,
|
||||
keywords: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'sub-id',
|
||||
title: 'sub-title',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'], // default visibleIn added
|
||||
keywords: [],
|
||||
deepLinks: [
|
||||
{
|
||||
|
@ -83,8 +83,7 @@ describe('getAppInfo', () => {
|
|||
title: 'sub-sub-title',
|
||||
path: '/sub-sub',
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
deepLinks: [], // default empty array added
|
||||
},
|
||||
],
|
||||
|
@ -93,92 +92,41 @@ describe('getAppInfo', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('computes the navLinkStatus depending on the app status', () => {
|
||||
it('computes the visibleIn depending on the app status', () => {
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
status: AppStatus.inaccessible,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
status: AppStatus.accessible,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('computes the searchable flag depending on the navLinkStatus when needed', () => {
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: undefined,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: undefined,
|
||||
// status is not set, default to accessible
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
searchable: true,
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
searchable: undefined,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
searchable: false,
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: undefined,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
searchable: false,
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -209,8 +157,7 @@ describe('getAppInfo', () => {
|
|||
id: 'some-id',
|
||||
title: 'some-title',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
appRoute: `/app/some-id`,
|
||||
keywords: [],
|
||||
order: 3,
|
||||
|
@ -218,16 +165,14 @@ describe('getAppInfo', () => {
|
|||
{
|
||||
id: 'sub-id',
|
||||
title: 'sub-title',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
order: 2,
|
||||
keywords: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'sub-sub-id',
|
||||
title: 'sub-sub-title',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
order: 1,
|
||||
path: '/sub-sub',
|
||||
keywords: ['sub sub'],
|
||||
|
@ -239,13 +184,13 @@ describe('getAppInfo', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('computes the deepLinks navLinkStatus when needed', () => {
|
||||
it('computes the deepLinks visibleIn when needed', () => {
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
@ -254,7 +199,7 @@ describe('getAppInfo', () => {
|
|||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['globalSearch', 'sideNav'],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
@ -262,100 +207,14 @@ describe('getAppInfo', () => {
|
|||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
}),
|
||||
],
|
||||
deepLinks: [createDeepLink({ visibleIn: undefined })],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: undefined,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('computes the deepLinks searchable depending on the navLinkStatus when needed', () => {
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: undefined,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
searchable: true,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: undefined,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
searchable: false,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
expect(
|
||||
getAppInfo(
|
||||
createApp({
|
||||
deepLinks: [
|
||||
createDeepLink({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
deepLinks: [
|
||||
expect.objectContaining({
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
|
|
@ -7,31 +7,23 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
type App,
|
||||
AppStatus,
|
||||
type AppDeepLink,
|
||||
type PublicAppInfo,
|
||||
type PublicAppDeepLinkInfo,
|
||||
} from '@kbn/core-application-browser';
|
||||
import { DEFAULT_APP_VISIBILITY, DEFAULT_LINK_VISIBILITY } from './constants';
|
||||
|
||||
export function getAppInfo(app: App): PublicAppInfo {
|
||||
const { updater$, mount, navLinkStatus = AppNavLinkStatus.default, ...infos } = app;
|
||||
const { updater$, mount, visibleIn = DEFAULT_APP_VISIBILITY, ...infos } = app;
|
||||
return {
|
||||
...infos,
|
||||
status: app.status!,
|
||||
navLinkStatus:
|
||||
navLinkStatus === AppNavLinkStatus.default
|
||||
? app.status === AppStatus.inaccessible
|
||||
? AppNavLinkStatus.hidden
|
||||
: AppNavLinkStatus.visible
|
||||
: navLinkStatus,
|
||||
searchable:
|
||||
app.searchable ??
|
||||
(navLinkStatus === AppNavLinkStatus.default || navLinkStatus === AppNavLinkStatus.visible),
|
||||
status: app.status ?? AppStatus.accessible,
|
||||
visibleIn: app.status === AppStatus.inaccessible ? [] : visibleIn,
|
||||
appRoute: app.appRoute!,
|
||||
keywords: app.keywords ?? [],
|
||||
deepLinks: getDeepLinkInfos(app.deepLinks),
|
||||
deepLinks: app.status === AppStatus.inaccessible ? [] : getDeepLinkInfos(app.deepLinks),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,16 +31,11 @@ function getDeepLinkInfos(deepLinks?: AppDeepLink[]): PublicAppDeepLinkInfo[] {
|
|||
if (!deepLinks) return [];
|
||||
|
||||
return deepLinks.map(
|
||||
({ navLinkStatus = AppNavLinkStatus.default, ...rawDeepLink }): PublicAppDeepLinkInfo => {
|
||||
({ visibleIn = DEFAULT_LINK_VISIBILITY, ...rawDeepLink }): PublicAppDeepLinkInfo => {
|
||||
return {
|
||||
...rawDeepLink,
|
||||
keywords: rawDeepLink.keywords ?? [],
|
||||
navLinkStatus:
|
||||
navLinkStatus === AppNavLinkStatus.default ? AppNavLinkStatus.hidden : navLinkStatus,
|
||||
searchable:
|
||||
rawDeepLink.searchable ??
|
||||
(navLinkStatus === AppNavLinkStatus.default ||
|
||||
navLinkStatus === AppNavLinkStatus.visible),
|
||||
visibleIn,
|
||||
deepLinks: getDeepLinkInfos(rawDeepLink.deepLinks),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,3 +12,4 @@ export { parseAppUrl } from './parse_app_url';
|
|||
export { relativeToAbsolute } from './relative_to_absolute';
|
||||
export { removeSlashes } from './remove_slashes';
|
||||
export { getLocationObservable } from './get_location_observable';
|
||||
export { DEFAULT_APP_VISIBILITY, DEFAULT_LINK_VISIBILITY } from './constants';
|
||||
|
|
|
@ -18,13 +18,14 @@ export type { AppMount, AppMountParameters, AppUnmount } from './src/app_mount';
|
|||
export type {
|
||||
App,
|
||||
AppDeepLink,
|
||||
AppDeepLinkLocations,
|
||||
PublicAppInfo,
|
||||
AppNavOptions,
|
||||
PublicAppDeepLinkInfo,
|
||||
AppUpdater,
|
||||
AppUpdatableFields,
|
||||
} from './src/application';
|
||||
export { AppNavLinkStatus, AppStatus } from './src/application';
|
||||
export { AppStatus } from './src/application';
|
||||
export type {
|
||||
ApplicationSetup,
|
||||
ApplicationStart,
|
||||
|
|
|
@ -27,31 +27,6 @@ export enum AppStatus {
|
|||
inaccessible = 1,
|
||||
}
|
||||
|
||||
/**
|
||||
* Status of the application's navLink.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export enum AppNavLinkStatus {
|
||||
/**
|
||||
* The application navLink will be `visible` if the application's {@link AppStatus} is set to `accessible`
|
||||
* and `hidden` if the application status is set to `inaccessible`.
|
||||
*/
|
||||
default = 0,
|
||||
/**
|
||||
* The application navLink is visible and clickable in the navigation bar.
|
||||
*/
|
||||
visible = 1,
|
||||
/**
|
||||
* The application navLink is visible but inactive and not clickable in the navigation bar.
|
||||
*/
|
||||
disabled = 2,
|
||||
/**
|
||||
* The application navLink does not appear in the navigation bar.
|
||||
*/
|
||||
hidden = 3,
|
||||
}
|
||||
|
||||
/**
|
||||
* App navigation menu options
|
||||
* @public
|
||||
|
@ -93,7 +68,7 @@ export type AppUpdater = (app: App) => Partial<AppUpdatableFields> | undefined;
|
|||
*/
|
||||
export type AppUpdatableFields = Pick<
|
||||
App,
|
||||
'status' | 'navLinkStatus' | 'searchable' | 'tooltip' | 'defaultPath' | 'deepLinks'
|
||||
'status' | 'visibleIn' | 'tooltip' | 'defaultPath' | 'deepLinks'
|
||||
>;
|
||||
|
||||
/**
|
||||
|
@ -126,17 +101,20 @@ export interface App<HistoryLocationState = unknown> extends AppNavOptions {
|
|||
status?: AppStatus;
|
||||
|
||||
/**
|
||||
* The initial status of the application's navLink.
|
||||
* Defaulting to `visible` if `status` is `accessible` and `hidden` if status is `inaccessible`
|
||||
* See {@link AppNavLinkStatus}
|
||||
* Optional list of locations where the app is visible.
|
||||
*
|
||||
* Accepts the following values:
|
||||
* - "globalSearch": the link will appear in the global search bar
|
||||
* - "home": the link will appear on the Kibana home page
|
||||
* - "kibanaOverview": the link will appear in the Kibana overview page
|
||||
* - "sideNav": the link will appear in the side navigation.
|
||||
* Note: "sideNav" will be deprecated when we change the navigation to "solutions" style.
|
||||
*
|
||||
* @default ['globalSearch', 'sideNav']
|
||||
* unless the status is marked as `inaccessible`.
|
||||
* @note Set to `[]` (empty array) to hide this link
|
||||
*/
|
||||
navLinkStatus?: AppNavLinkStatus;
|
||||
|
||||
/**
|
||||
* The initial flag to determine if the application is searchable in the global search.
|
||||
* Defaulting to `true` if `navLinkStatus` is `visible` or omitted.
|
||||
*/
|
||||
searchable?: boolean;
|
||||
visibleIn?: AppDeepLinkLocations[];
|
||||
|
||||
/**
|
||||
* Allow to define the default path a user should be directed to when navigating to the app.
|
||||
|
@ -172,7 +150,7 @@ export interface App<HistoryLocationState = unknown> extends AppNavOptions {
|
|||
* start() {
|
||||
* // later, when the navlink needs to be updated
|
||||
* appUpdater.next(() => {
|
||||
* navLinkStatus: AppNavLinkStatus.disabled,
|
||||
* visibleIn: ['globalSearch'],
|
||||
* })
|
||||
* }
|
||||
* ```
|
||||
|
@ -268,16 +246,15 @@ export interface App<HistoryLocationState = unknown> extends AppNavOptions {
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
export type PublicAppDeepLinkInfo = Omit<
|
||||
AppDeepLink,
|
||||
'deepLinks' | 'keywords' | 'navLinkStatus' | 'searchable'
|
||||
> & {
|
||||
export type PublicAppDeepLinkInfo = Omit<AppDeepLink, 'deepLinks' | 'keywords' | 'visibleIn'> & {
|
||||
deepLinks: PublicAppDeepLinkInfo[];
|
||||
keywords: string[];
|
||||
navLinkStatus: AppNavLinkStatus;
|
||||
searchable: boolean;
|
||||
visibleIn: AppDeepLinkLocations[];
|
||||
};
|
||||
|
||||
/** The places in the UI where a deepLink can be shown */
|
||||
export type AppDeepLinkLocations = 'globalSearch' | 'sideNav' | 'home' | 'kibanaOverview';
|
||||
|
||||
/**
|
||||
* Input type for registering secondary in-app locations for an application.
|
||||
*
|
||||
|
@ -293,10 +270,10 @@ export type AppDeepLink<Id extends string = string> = {
|
|||
title: string;
|
||||
/** Optional keywords to match with in deep links search. Omit if this part of the hierarchy does not have a page URL. */
|
||||
keywords?: string[];
|
||||
/** Optional status of the chrome navigation, defaults to `hidden` */
|
||||
navLinkStatus?: AppNavLinkStatus;
|
||||
/** Optional flag to determine if the link is searchable in the global search. Defaulting to `true` if `navLinkStatus` is `visible` or omitted */
|
||||
searchable?: boolean;
|
||||
/**
|
||||
* Optional list of locations where the deepLink is visible. By default the deepLink is visible in "globalSearch".
|
||||
*/
|
||||
visibleIn?: AppDeepLinkLocations[];
|
||||
/**
|
||||
* Optional category to use instead of the parent app category.
|
||||
* This property is added to customize the way a deep link is rendered in the global search.
|
||||
|
@ -326,13 +303,12 @@ export type AppDeepLink<Id extends string = string> = {
|
|||
*/
|
||||
export type PublicAppInfo = Omit<
|
||||
App,
|
||||
'mount' | 'updater$' | 'keywords' | 'deepLinks' | 'searchable'
|
||||
'mount' | 'updater$' | 'keywords' | 'deepLinks' | 'visibleIn'
|
||||
> & {
|
||||
// remove optional on fields populated with default values
|
||||
status: AppStatus;
|
||||
navLinkStatus: AppNavLinkStatus;
|
||||
appRoute: string;
|
||||
keywords: string[];
|
||||
deepLinks: PublicAppDeepLinkInfo[];
|
||||
searchable: boolean;
|
||||
visibleIn: AppDeepLinkLocations[];
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ import type { DocLinksStart } from '@kbn/core-doc-links-browser';
|
|||
import type { InternalHttpSetup, InternalHttpStart } from '@kbn/core-http-browser-internal';
|
||||
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
|
||||
import type { NotificationsSetup, NotificationsStart } from '@kbn/core-notifications-browser';
|
||||
import { AppNavLinkStatus, type AppMountParameters } from '@kbn/core-application-browser';
|
||||
import { type AppMountParameters } from '@kbn/core-application-browser';
|
||||
import type {
|
||||
InternalApplicationSetup,
|
||||
InternalApplicationStart,
|
||||
|
@ -49,7 +49,7 @@ export class CoreAppsService {
|
|||
application.register(this.coreContext.coreId, {
|
||||
id: 'error',
|
||||
title: 'App Error',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount(params: AppMountParameters) {
|
||||
// Do not use an async import here in order to ensure that network failures
|
||||
// cannot prevent the error UI from displaying. This UI is tiny so an async
|
||||
|
@ -66,7 +66,7 @@ export class CoreAppsService {
|
|||
title: 'Server Status',
|
||||
appRoute: '/status',
|
||||
chromeless: true,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount(params: AppMountParameters) {
|
||||
return renderStatusApp(params, { http, notifications });
|
||||
},
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, lastValueFrom } from 'rxjs';
|
||||
import { take, map, takeLast } from 'rxjs/operators';
|
||||
import type { App } from '@kbn/core-application-browser';
|
||||
import { type App, AppStatus } from '@kbn/core-application-browser';
|
||||
import { NavLinksService } from './nav_links_service';
|
||||
|
||||
const availableApps = new Map([
|
||||
['app1', { id: 'app1', order: 0, title: 'App 1', icon: 'app1' }],
|
||||
const availableApps: ReadonlyMap<string, App> = new Map([
|
||||
['app1', { id: 'app1', order: 0, title: 'App 1', icon: 'app1', mount: () => () => undefined }],
|
||||
[
|
||||
'app2',
|
||||
{
|
||||
|
@ -20,12 +20,14 @@ const availableApps = new Map([
|
|||
order: -10,
|
||||
title: 'App 2',
|
||||
euiIconType: 'canvasApp',
|
||||
mount: () => () => undefined,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'deepApp1',
|
||||
order: 50,
|
||||
title: 'Deep App 1',
|
||||
path: '/deepapp1',
|
||||
visibleIn: ['sideNav'],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'deepApp2',
|
||||
|
@ -38,7 +40,42 @@ const availableApps = new Map([
|
|||
],
|
||||
},
|
||||
],
|
||||
['chromelessApp', { id: 'chromelessApp', order: 20, title: 'Chromless App', chromeless: true }],
|
||||
[
|
||||
'chromelessApp',
|
||||
{
|
||||
id: 'chromelessApp',
|
||||
order: 20,
|
||||
title: 'Chromless App',
|
||||
chromeless: true,
|
||||
mount: () => () => undefined,
|
||||
},
|
||||
],
|
||||
[
|
||||
'inaccessibleApp', // inaccessible app
|
||||
{
|
||||
id: 'inaccessibleApp',
|
||||
order: 30,
|
||||
title: 'App inaccessible',
|
||||
mount: () => () => undefined,
|
||||
status: AppStatus.inaccessible,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'deepInaccessibleApp1',
|
||||
order: 50,
|
||||
title: 'Deep App 3',
|
||||
path: '/deepapp3',
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'deepInaccessibleApp2',
|
||||
order: 40,
|
||||
title: 'Deep App 3',
|
||||
path: '/deepapp3',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const mockHttp = {
|
||||
|
@ -55,7 +92,7 @@ describe('NavLinksService', () => {
|
|||
beforeEach(() => {
|
||||
service = new NavLinksService();
|
||||
mockAppService = {
|
||||
applications$: new BehaviorSubject<ReadonlyMap<string, App>>(availableApps as any),
|
||||
applications$: new BehaviorSubject<ReadonlyMap<string, App>>(availableApps),
|
||||
};
|
||||
start = service.start({ application: mockAppService, http: mockHttp });
|
||||
});
|
||||
|
@ -63,25 +100,34 @@ describe('NavLinksService', () => {
|
|||
describe('#getNavLinks$()', () => {
|
||||
it('does not include `chromeless` applications', async () => {
|
||||
expect(
|
||||
await start
|
||||
.getNavLinks$()
|
||||
.pipe(
|
||||
await lastValueFrom(
|
||||
start.getNavLinks$().pipe(
|
||||
take(1),
|
||||
map((links) => links.map((l) => l.id))
|
||||
)
|
||||
.toPromise()
|
||||
)
|
||||
).not.toContain('chromelessApp');
|
||||
});
|
||||
|
||||
it('does not include `inaccesible` applications', async () => {
|
||||
expect(
|
||||
await lastValueFrom(
|
||||
start.getNavLinks$().pipe(
|
||||
take(1),
|
||||
map((links) => links.map((l) => l.id))
|
||||
)
|
||||
)
|
||||
).not.toContain('inaccessibleApp');
|
||||
});
|
||||
|
||||
it('sorts navlinks by `order` property', async () => {
|
||||
expect(
|
||||
await start
|
||||
.getNavLinks$()
|
||||
.pipe(
|
||||
await lastValueFrom(
|
||||
start.getNavLinks$().pipe(
|
||||
take(1),
|
||||
map((links) => links.map((l) => l.id))
|
||||
)
|
||||
.toPromise()
|
||||
)
|
||||
).toEqual(['app2', 'app1', 'app2:deepApp2', 'app2:deepApp1']);
|
||||
});
|
||||
|
||||
|
@ -94,7 +140,7 @@ describe('NavLinksService', () => {
|
|||
});
|
||||
|
||||
it('completes when service is stopped', async () => {
|
||||
const last$ = start.getNavLinks$().pipe(takeLast(1)).toPromise();
|
||||
const last$ = lastValueFrom(start.getNavLinks$().pipe(takeLast(1)));
|
||||
service.stop();
|
||||
await expect(last$).resolves.toBeInstanceOf(Array);
|
||||
});
|
||||
|
@ -108,6 +154,10 @@ describe('NavLinksService', () => {
|
|||
it('returns undefined if it does not exist', () => {
|
||||
expect(start.get('phony')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined if app is inaccessible', () => {
|
||||
expect(start.get('inaccessibleApp')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAll()', () => {
|
||||
|
@ -133,15 +183,15 @@ describe('NavLinksService', () => {
|
|||
|
||||
describe('#enableForcedAppSwitcherNavigation()', () => {
|
||||
it('flips #getForceAppSwitcherNavigation$()', async () => {
|
||||
await expect(start.getForceAppSwitcherNavigation$().pipe(take(1)).toPromise()).resolves.toBe(
|
||||
false
|
||||
);
|
||||
await expect(
|
||||
lastValueFrom(start.getForceAppSwitcherNavigation$().pipe(take(1)))
|
||||
).resolves.toBe(false);
|
||||
|
||||
start.enableForcedAppSwitcherNavigation();
|
||||
|
||||
await expect(start.getForceAppSwitcherNavigation$().pipe(take(1)).toPromise()).resolves.toBe(
|
||||
true
|
||||
);
|
||||
await expect(
|
||||
lastValueFrom(start.getForceAppSwitcherNavigation$().pipe(take(1)))
|
||||
).resolves.toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -34,10 +34,11 @@ export class NavLinksService {
|
|||
[...apps]
|
||||
.filter(([, app]) => !app.chromeless)
|
||||
.reduce((navLinks: Array<[string, NavLinkWrapper]>, [appId, app]) => {
|
||||
navLinks.push(
|
||||
[appId, toNavLink(app, http.basePath)],
|
||||
...toNavDeepLinks(app, app.deepLinks, http.basePath)
|
||||
);
|
||||
const navLink = toNavLink(app, http.basePath);
|
||||
if (navLink) {
|
||||
navLinks.push([appId, navLink]);
|
||||
}
|
||||
navLinks.push(...toNavDeepLinks(app, app.deepLinks, http.basePath));
|
||||
return navLinks;
|
||||
}, [])
|
||||
);
|
||||
|
@ -100,7 +101,10 @@ function toNavDeepLinks(
|
|||
return deepLinks.reduce((navDeepLinks: Array<[string, NavLinkWrapper]>, deepLink) => {
|
||||
const id = `${app.id}:${deepLink.id}`;
|
||||
if (deepLink.path) {
|
||||
navDeepLinks.push([id, toNavLink(app, basePath, { ...deepLink, id })]);
|
||||
const navDeepLink = toNavLink(app, basePath, { ...deepLink, id });
|
||||
if (navDeepLink) {
|
||||
navDeepLinks.push([id, navDeepLink]);
|
||||
}
|
||||
}
|
||||
navDeepLinks.push(...toNavDeepLinks(app, deepLink.deepLinks, basePath));
|
||||
return navDeepLinks;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
type PublicAppInfo,
|
||||
type PublicAppDeepLinkInfo,
|
||||
|
@ -19,8 +18,7 @@ const app = (props: Partial<PublicAppInfo> = {}): PublicAppInfo => ({
|
|||
id: 'some-id',
|
||||
title: 'some-title',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
appRoute: `/app/some-id`,
|
||||
keywords: [],
|
||||
deepLinks: [],
|
||||
|
@ -31,8 +29,7 @@ const deepLink = (props: Partial<PublicAppDeepLinkInfo> = {}): PublicAppDeepLink
|
|||
id: 'some-deep-link-id',
|
||||
title: 'my deep link',
|
||||
path: '/my-deep-link',
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
...props,
|
||||
|
@ -49,16 +46,18 @@ describe('toNavLink', () => {
|
|||
order: 12,
|
||||
tooltip: 'tooltip',
|
||||
euiIconType: 'my-icon',
|
||||
visibleIn: ['sideNav'],
|
||||
}),
|
||||
basePath
|
||||
);
|
||||
expect(link.properties).toEqual(
|
||||
expect(link?.properties).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
order: 12,
|
||||
tooltip: 'tooltip',
|
||||
euiIconType: 'my-icon',
|
||||
visibleIn: ['sideNav'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -70,7 +69,7 @@ describe('toNavLink', () => {
|
|||
}),
|
||||
basePath
|
||||
);
|
||||
expect(link.properties.baseUrl).toEqual('http://localhost/base-path/my-route/my-path');
|
||||
expect(link?.properties.baseUrl).toEqual('http://localhost/base-path/my-route/my-path');
|
||||
});
|
||||
|
||||
it('generates the `url` property', () => {
|
||||
|
@ -80,7 +79,7 @@ describe('toNavLink', () => {
|
|||
}),
|
||||
basePath
|
||||
);
|
||||
expect(link.properties.url).toEqual('/base-path/my-route/my-path');
|
||||
expect(link?.properties.url).toEqual('/base-path/my-route/my-path');
|
||||
|
||||
link = toNavLink(
|
||||
app({
|
||||
|
@ -89,136 +88,28 @@ describe('toNavLink', () => {
|
|||
}),
|
||||
basePath
|
||||
);
|
||||
expect(link.properties.url).toEqual('/base-path/my-route/my-path/some/default/path');
|
||||
expect(link?.properties.url).toEqual('/base-path/my-route/my-path/some/default/path');
|
||||
});
|
||||
|
||||
it('uses the application status when the navLinkStatus is set to default', () => {
|
||||
it('does not return navLink if the app status is inaccessible', () => {
|
||||
expect(
|
||||
toNavLink(
|
||||
app({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
status: AppStatus.accessible,
|
||||
}),
|
||||
basePath
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: false,
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
toNavLink(
|
||||
app({
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
status: AppStatus.inaccessible,
|
||||
}),
|
||||
basePath
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('uses the navLinkStatus of the application to set the hidden and disabled properties', () => {
|
||||
expect(
|
||||
toNavLink(
|
||||
app({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
}),
|
||||
basePath
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: false,
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
toNavLink(
|
||||
app({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
}),
|
||||
basePath
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: true,
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
toNavLink(
|
||||
app({
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
}),
|
||||
basePath
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: true,
|
||||
hidden: false,
|
||||
})
|
||||
);
|
||||
)
|
||||
).toBe(null);
|
||||
});
|
||||
|
||||
describe('deepLink parameter', () => {
|
||||
it('should be hidden and not disabled by default', () => {
|
||||
expect(toNavLink(app(), basePath, deepLink()).properties).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should not be hidden when navLinkStatus is visible', () => {
|
||||
expect(
|
||||
toNavLink(
|
||||
app(),
|
||||
basePath,
|
||||
deepLink({
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
})
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: false,
|
||||
hidden: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should be disabled when navLinkStatus is disabled', () => {
|
||||
expect(
|
||||
toNavLink(
|
||||
app(),
|
||||
basePath,
|
||||
deepLink({
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
})
|
||||
).properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
disabled: true,
|
||||
hidden: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should have href, baseUrl and url containing the path', () => {
|
||||
const testApp = app({
|
||||
appRoute: '/app/app-id',
|
||||
defaultPath: '/default-path',
|
||||
});
|
||||
|
||||
expect(toNavLink(testApp, basePath).properties).toEqual(
|
||||
expect(toNavLink(testApp, basePath)?.properties).toEqual(
|
||||
expect.objectContaining({
|
||||
baseUrl: 'http://localhost/base-path/app/app-id',
|
||||
url: '/base-path/app/app-id/default-path',
|
||||
|
@ -234,7 +125,7 @@ describe('toNavLink', () => {
|
|||
id: 'deep-link-id',
|
||||
path: '/my-deep-link',
|
||||
})
|
||||
).properties
|
||||
)?.properties
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
baseUrl: 'http://localhost/base-path/app/app-id',
|
||||
|
@ -245,10 +136,10 @@ describe('toNavLink', () => {
|
|||
});
|
||||
|
||||
it('should use the main app category', () => {
|
||||
expect(toNavLink(app(), basePath, deepLink()).properties.category).toBeUndefined();
|
||||
expect(toNavLink(app(), basePath, deepLink())?.properties.category).toBeUndefined();
|
||||
|
||||
const category = { id: 'some-category', label: 'some category' };
|
||||
expect(toNavLink(app({ category }), basePath, deepLink()).properties.category).toEqual(
|
||||
expect(toNavLink(app({ category }), basePath, deepLink())?.properties.category).toEqual(
|
||||
category
|
||||
);
|
||||
});
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
|
||||
import type { IBasePath } from '@kbn/core-http-browser';
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
type PublicAppInfo,
|
||||
type PublicAppDeepLinkInfo,
|
||||
AppStatus,
|
||||
} from '@kbn/core-application-browser';
|
||||
import { appendAppPath } from '@kbn/core-application-browser-internal';
|
||||
import { NavLinkWrapper } from './nav_link';
|
||||
|
@ -20,36 +19,23 @@ export function toNavLink(
|
|||
app: PublicAppInfo,
|
||||
basePath: IBasePath,
|
||||
deepLink?: PublicAppDeepLinkInfo
|
||||
): NavLinkWrapper {
|
||||
): NavLinkWrapper | null {
|
||||
const relativeBaseUrl = basePath.prepend(app.appRoute!);
|
||||
const url = appendAppPath(relativeBaseUrl, deepLink?.path || app.defaultPath);
|
||||
const href = relativeToAbsolute(url);
|
||||
const baseUrl = relativeToAbsolute(relativeBaseUrl);
|
||||
|
||||
if (app.status === AppStatus.inaccessible) return null;
|
||||
|
||||
return new NavLinkWrapper({
|
||||
...(deepLink || app),
|
||||
...(app.category ? { category: app.category } : {}), // deepLinks use the main app category
|
||||
hidden: deepLink ? isDeepNavLinkHidden(deepLink) : isAppNavLinkHidden(app),
|
||||
disabled: (deepLink?.navLinkStatus ?? app.navLinkStatus) === AppNavLinkStatus.disabled,
|
||||
baseUrl,
|
||||
href,
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
function isAppNavLinkHidden(app: PublicAppInfo) {
|
||||
return app.navLinkStatus === AppNavLinkStatus.default
|
||||
? app.status === AppStatus.inaccessible
|
||||
: app.navLinkStatus === AppNavLinkStatus.hidden;
|
||||
}
|
||||
|
||||
function isDeepNavLinkHidden(deepLink: PublicAppDeepLinkInfo) {
|
||||
return (
|
||||
deepLink.navLinkStatus === AppNavLinkStatus.default ||
|
||||
deepLink.navLinkStatus === AppNavLinkStatus.hidden
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url - a relative or root relative url. If a relative path is given then the
|
||||
* absolute url returned will depend on the current page where this function is called from. For example
|
||||
|
|
|
@ -28,6 +28,7 @@ const getNavLink = (partial: Partial<ChromeNavLink> = {}): ChromeNavLink => ({
|
|||
baseUrl: '/app',
|
||||
url: `/app/${partial.id ?? 'kibana'}`,
|
||||
href: `/app/${partial.id ?? 'kibana'}`,
|
||||
visibleIn: ['globalSearch'],
|
||||
...partial,
|
||||
});
|
||||
|
||||
|
@ -236,6 +237,7 @@ describe('initNavigation()', () => {
|
|||
id: 'foo',
|
||||
title: 'FOO',
|
||||
url: '/app/foo',
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
href: '/app/foo',
|
||||
id: 'foo',
|
||||
|
@ -302,6 +304,9 @@ describe('initNavigation()', () => {
|
|||
"id": "discover",
|
||||
"title": "DISCOVER",
|
||||
"url": "/app/discover",
|
||||
"visibleIn": Array [
|
||||
"globalSearch",
|
||||
],
|
||||
},
|
||||
"href": "/app/discover",
|
||||
"id": "discover",
|
||||
|
@ -317,6 +322,9 @@ describe('initNavigation()', () => {
|
|||
"id": "dashboards",
|
||||
"title": "DASHBOARDS",
|
||||
"url": "/app/dashboards",
|
||||
"visibleIn": Array [
|
||||
"globalSearch",
|
||||
],
|
||||
},
|
||||
"href": "/app/dashboards",
|
||||
"id": "dashboards",
|
||||
|
@ -332,6 +340,9 @@ describe('initNavigation()', () => {
|
|||
"id": "visualize",
|
||||
"title": "VISUALIZE",
|
||||
"url": "/app/visualize",
|
||||
"visibleIn": Array [
|
||||
"globalSearch",
|
||||
],
|
||||
},
|
||||
"href": "/app/visualize",
|
||||
"id": "visualize",
|
||||
|
@ -792,6 +803,7 @@ describe('getActiveNodes$()', () => {
|
|||
baseUrl: '/app',
|
||||
url: '/app/item1',
|
||||
href: '/app/item1',
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -848,6 +860,7 @@ describe('getActiveNodes$()', () => {
|
|||
baseUrl: '/app',
|
||||
url: '/app/item1',
|
||||
href: '/app/item1',
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
getIsActive: expect.any(Function),
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ const getDeepLink = (id: string, path: string, title = ''): ChromeNavLink => ({
|
|||
href: `http://mocked/kibana/foo/${path}`,
|
||||
title,
|
||||
baseUrl: '',
|
||||
visibleIn: ['globalSearch'],
|
||||
});
|
||||
|
||||
describe('flattenNav', () => {
|
||||
|
|
|
@ -233,8 +233,6 @@ function getNodeStatus(
|
|||
if (!hasUserAccessToCloudLink()) return 'remove';
|
||||
}
|
||||
|
||||
if (deepLink && deepLink.hidden) return 'hidden';
|
||||
|
||||
return sideNavStatus ?? 'visible';
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ import { CollapsibleNav } from './collapsible_nav';
|
|||
|
||||
const { kibana, observability, security, management } = DEFAULT_APP_CATEGORIES;
|
||||
|
||||
const visibleIn = ['globalSearch' as const, 'sideNav' as const];
|
||||
|
||||
function mockLink({ title = 'discover', category }: Partial<ChromeNavLink>) {
|
||||
return {
|
||||
title,
|
||||
|
@ -28,6 +30,7 @@ function mockLink({ title = 'discover', category }: Partial<ChromeNavLink>) {
|
|||
url: '/',
|
||||
isActive: true,
|
||||
'data-test-subj': title,
|
||||
visibleIn,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ export function CollapsibleNav({
|
|||
allLinks.filter(
|
||||
(link) =>
|
||||
// Filterting out hidden links,
|
||||
!link.hidden &&
|
||||
link.visibleIn.includes('sideNav') &&
|
||||
// and non-data overview pages
|
||||
!overviewIDsToHide.includes(link.id)
|
||||
),
|
||||
|
|
|
@ -60,7 +60,14 @@ describe('Header', () => {
|
|||
const breadcrumbs$ = new BehaviorSubject([{ text: 'test' }]);
|
||||
const isLocked$ = new BehaviorSubject(false);
|
||||
const navLinks$ = new BehaviorSubject([
|
||||
{ id: 'kibana', title: 'kibana', baseUrl: '', href: '', url: '' },
|
||||
{
|
||||
id: 'kibana',
|
||||
title: 'kibana',
|
||||
baseUrl: '',
|
||||
href: '',
|
||||
url: '',
|
||||
visibleIn: ['globalSearch' as const],
|
||||
},
|
||||
]);
|
||||
const headerBanner$ = new BehaviorSubject(undefined);
|
||||
const customNavLink$ = new BehaviorSubject({
|
||||
|
@ -69,6 +76,7 @@ describe('Header', () => {
|
|||
baseUrl: '',
|
||||
url: '',
|
||||
href: '',
|
||||
visibleIn: ['globalSearch' as const],
|
||||
});
|
||||
const recentlyAccessed$ = new BehaviorSubject([
|
||||
{ link: '', label: 'dashboard', id: 'dashboard' },
|
||||
|
|
|
@ -44,12 +44,6 @@ function onClick(
|
|||
return;
|
||||
}
|
||||
|
||||
const navLink = navLinks.find((item) => item.href === anchor.href);
|
||||
if (navLink && navLink.disabled) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isDefaultPrevented() || event.altKey || event.metaKey || event.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ export function createEuiListItem({
|
|||
externalLink = false,
|
||||
iconProps,
|
||||
}: Props): EuiListGroupItemProps {
|
||||
const { href, id, title, disabled, euiIconType, icon, tooltip, url } = link;
|
||||
const { href, id, title, euiIconType, icon, tooltip, url } = link;
|
||||
|
||||
return {
|
||||
label: tooltip ?? title,
|
||||
|
@ -64,7 +64,6 @@ export function createEuiListItem({
|
|||
}
|
||||
},
|
||||
isActive: !externalLink && appId === id,
|
||||
isDisabled: disabled,
|
||||
'data-test-subj': dataTestSubj,
|
||||
...(basePath && {
|
||||
iconType: euiIconType,
|
||||
|
@ -81,7 +80,7 @@ export function createEuiButtonItem({
|
|||
navigateToUrl,
|
||||
dataTestSubj,
|
||||
}: Omit<Props, 'appId' | 'basePath'>) {
|
||||
const { href, disabled, url, id } = link;
|
||||
const { href, url, id } = link;
|
||||
|
||||
return {
|
||||
href,
|
||||
|
@ -93,7 +92,6 @@ export function createEuiButtonItem({
|
|||
event.preventDefault();
|
||||
navigateToUrl(url);
|
||||
},
|
||||
isDisabled: disabled,
|
||||
'data-test-subj': dataTestSubj || `collapsibleNavAppButton-${id}`,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { AppCategory } from '@kbn/core-application-common';
|
||||
import type { AppDeepLinkLocations } from '@kbn/core-application-browser';
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -66,18 +67,18 @@ export interface ChromeNavLink {
|
|||
readonly href: string;
|
||||
|
||||
/**
|
||||
* Disables a link from being clickable.
|
||||
* List of locations where the nav link should be visible.
|
||||
*
|
||||
* @internalRemarks
|
||||
* This is only used by the ML and Graph plugins currently. They use this field
|
||||
* to disable the nav link when the license is expired.
|
||||
* Accepts the following values:
|
||||
* - "globalSearch": the link will appear in the global search bar
|
||||
* - "home": the link will appear on the Kibana home page
|
||||
* - "kibanaOverview": the link will appear in the Kibana overview page
|
||||
* - "sideNav": the link will appear in the side navigation.
|
||||
* Note: "sideNav" will be deprecated when we change the navigation to "solutions" style.
|
||||
*
|
||||
* @default ['globalSearch']
|
||||
*/
|
||||
readonly disabled?: boolean;
|
||||
|
||||
/**
|
||||
* Hides a link from the navigation.
|
||||
*/
|
||||
readonly hidden?: boolean;
|
||||
readonly visibleIn: AppDeepLinkLocations[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
"@kbn/deeplinks-ml",
|
||||
"@kbn/deeplinks-management",
|
||||
"@kbn/deeplinks-search",
|
||||
"@kbn/deeplinks-observability"
|
||||
"@kbn/deeplinks-observability",
|
||||
"@kbn/core-application-browser"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import type { PluginInitializer } from '@kbn/core-plugins-browser';
|
||||
import { AppNavLinkStatus } from '@kbn/core-application-browser';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
|
||||
|
@ -39,7 +38,7 @@ export const plugin: PluginInitializer<
|
|||
title: 'Mock IDP',
|
||||
chromeless: true,
|
||||
appRoute: MOCK_IDP_LOGIN_PATH,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params) => {
|
||||
const [[coreStart], { LoginPage }] = await Promise.all([
|
||||
coreSetup.getStartServices(),
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
],
|
||||
"kbn_references": [
|
||||
"@kbn/config-schema",
|
||||
"@kbn/core-application-browser",
|
||||
"@kbn/core-i18n-browser",
|
||||
"@kbn/core-lifecycle-browser",
|
||||
"@kbn/core-notifications-browser",
|
||||
|
|
|
@ -35,6 +35,8 @@ describe('Active node', () => {
|
|||
return activeNodes$;
|
||||
};
|
||||
|
||||
const visibleIn = ['globalSearch' as const];
|
||||
|
||||
const navigationBody: ChromeProjectNavigationNode[] = [
|
||||
{
|
||||
id: 'group1',
|
||||
|
@ -51,6 +53,7 @@ describe('Active node', () => {
|
|||
baseUrl: '',
|
||||
url: '',
|
||||
href: '',
|
||||
visibleIn,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -63,6 +66,7 @@ describe('Active node', () => {
|
|||
baseUrl: '',
|
||||
url: '',
|
||||
href: '',
|
||||
visibleIn,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -195,7 +195,7 @@ const nodeToEuiCollapsibleNavProps = (
|
|||
const dataTestSubj = getTestSubj(navNode, isSelected);
|
||||
|
||||
let spaceBefore = navNode.spaceBefore;
|
||||
if (spaceBefore === undefined && treeDepth === 1 && hasChildren) {
|
||||
if (spaceBefore === undefined && treeDepth === 1 && hasChildren && !isItem) {
|
||||
// For groups at level 1 that don't have a space specified we default to add a "m"
|
||||
// space. For all other groups, unless specified, there is no vertical space.
|
||||
spaceBefore = DEFAULT_SPACE_BETWEEN_LEVEL_1_GROUPS;
|
||||
|
@ -309,7 +309,7 @@ const nodeToEuiCollapsibleNavProps = (
|
|||
const hasVisibleChildren = (items?.length ?? 0) > 0;
|
||||
const isVisible = isItem || hasVisibleChildren;
|
||||
|
||||
if (isVisible && spaceBefore) {
|
||||
if (isVisible && Boolean(spaceBefore)) {
|
||||
items.unshift({
|
||||
renderItem: () => <EuiSpacer size={spaceBefore!} />,
|
||||
});
|
||||
|
|
|
@ -109,11 +109,12 @@ export type {
|
|||
TelemetryCounterType,
|
||||
} from '@kbn/analytics-client';
|
||||
|
||||
export { AppNavLinkStatus, AppStatus } from '@kbn/core-application-browser';
|
||||
export { AppStatus } from '@kbn/core-application-browser';
|
||||
export type {
|
||||
ApplicationSetup,
|
||||
ApplicationStart,
|
||||
App,
|
||||
AppDeepLinkLocations,
|
||||
AppMount,
|
||||
AppUnmount,
|
||||
AppMountParameters,
|
||||
|
|
|
@ -9,11 +9,10 @@
|
|||
// TODO: https://github.com/elastic/kibana/issues/110892
|
||||
/* eslint-disable @kbn/eslint/no_export_all */
|
||||
|
||||
import { PluginInitializerContext } from '@kbn/core/public';
|
||||
import { DevToolsPlugin } from './plugin';
|
||||
export * from './plugin';
|
||||
export * from '../common/constants';
|
||||
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new DevToolsPlugin(initializerContext);
|
||||
export function plugin() {
|
||||
return new DevToolsPlugin();
|
||||
}
|
||||
|
|
|
@ -7,19 +7,14 @@
|
|||
*/
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppDeepLink } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppDeepLink, AppStatus } from '@kbn/core/public';
|
||||
import { AppUpdater } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { sortBy } from 'lodash';
|
||||
|
||||
import {
|
||||
PluginInitializerContext,
|
||||
AppNavLinkStatus,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
} from '@kbn/core/public';
|
||||
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
|
||||
import { UrlForwardingSetup } from '@kbn/url-forwarding-plugin/public';
|
||||
import { deepLinkIds as devtoolsDeeplinkIds } from '@kbn/deeplinks-devtools';
|
||||
import { ConfigSchema } from './types';
|
||||
import { CreateDevToolArgs, DevToolApp, createDevToolApp } from './dev_tool';
|
||||
import { DocTitleService, BreadcrumbService } from './services';
|
||||
|
||||
|
@ -50,7 +45,7 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
|
|||
return sortBy([...this.devTools.values()], 'order');
|
||||
}
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext<ConfigSchema>) {}
|
||||
constructor() {}
|
||||
|
||||
public setup(coreSetup: CoreSetup, { urlForwarding }: { urlForwarding: UrlForwardingSetup }) {
|
||||
const { application: applicationSetup, getStartServices } = coreSetup;
|
||||
|
@ -112,12 +107,8 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
|
|||
|
||||
public start() {
|
||||
if (this.getSortedDevTools().length === 0) {
|
||||
this.appStateUpdater.next(() => ({ navLinkStatus: AppNavLinkStatus.hidden }));
|
||||
this.appStateUpdater.next(() => ({ status: AppStatus.inaccessible }));
|
||||
} else {
|
||||
const config = this.initializerContext.config.get();
|
||||
const navLinkStatus =
|
||||
AppNavLinkStatus[config.deeplinks.navLinkStatus as keyof typeof AppNavLinkStatus];
|
||||
|
||||
this.appStateUpdater.next(() => {
|
||||
const deepLinks: AppDeepLink[] = [...this.devTools.values()]
|
||||
.filter(
|
||||
|
@ -125,11 +116,10 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
|
|||
(tool) => !tool.enableRouting && !tool.isDisabled() && typeof tool.title === 'string'
|
||||
)
|
||||
.map((tool) => {
|
||||
const deepLink = {
|
||||
const deepLink: AppDeepLink = {
|
||||
id: tool.id,
|
||||
title: tool.title as string,
|
||||
path: `#/${tool.id}`,
|
||||
navLinkStatus,
|
||||
};
|
||||
if (!devtoolsDeeplinkIds.some((id) => id === deepLink.id)) {
|
||||
throw new Error('Deeplink must be registered in package.');
|
||||
|
@ -139,7 +129,6 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
|
|||
|
||||
return {
|
||||
deepLinks,
|
||||
navLinkStatus,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
|
||||
export interface ConfigSchema {
|
||||
deeplinks: {
|
||||
navLinkStatus: keyof typeof AppNavLinkStatus;
|
||||
navLinkStatus: 'default' | 'visible';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -296,6 +296,7 @@ export class DiscoverPlugin
|
|||
euiIconType: 'logoKibana',
|
||||
defaultPath: '#/',
|
||||
category: DEFAULT_APP_CATEGORIES.kibana,
|
||||
visibleIn: ['globalSearch', 'sideNav', 'kibanaOverview'],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const [coreStart, discoverStartPlugins] = await core.getStartServices();
|
||||
setScopedHistory(params.history);
|
||||
|
|
|
@ -37,7 +37,11 @@ export const renderApp = async (
|
|||
const navLinksSubscription = chrome.navLinks.getNavLinks$().subscribe((navLinks) => {
|
||||
const solutions = featureCatalogue
|
||||
.getSolutions()
|
||||
.filter(({ id }) => navLinks.find(({ category, hidden }) => !hidden && category?.id === id));
|
||||
.filter(({ id }) =>
|
||||
navLinks.find(
|
||||
({ visibleIn, category }) => visibleIn.includes('home') && category?.id === id
|
||||
)
|
||||
);
|
||||
|
||||
render(
|
||||
<RedirectAppLinks
|
||||
|
|
|
@ -19,7 +19,6 @@ import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
|||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public';
|
||||
import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public';
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public';
|
||||
import { PLUGIN_ID, HOME_APP_BASE_PATH } from '../common/constants';
|
||||
|
@ -77,7 +76,7 @@ export class HomePublicPlugin
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: 'Home',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const trackUiMetric = usageCollection
|
||||
? usageCollection.reportUiCounter.bind(usageCollection, 'Kibana_home')
|
||||
|
|
|
@ -34,7 +34,11 @@ export const renderApp = (
|
|||
const solutions = home.featureCatalogue
|
||||
.getSolutions()
|
||||
.filter(({ id }) => id !== 'kibana')
|
||||
.filter(({ id }) => navLinks.find(({ category, hidden }) => !hidden && category?.id === id));
|
||||
.filter(({ id }) =>
|
||||
navLinks.find(
|
||||
({ category, visibleIn }) => visibleIn.includes('kibanaOverview') && category?.id === id
|
||||
)
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<I18nProvider>
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
Plugin,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
AppStatus,
|
||||
AppNavLinkStatus,
|
||||
} from '@kbn/core/public';
|
||||
import {
|
||||
KibanaOverviewPluginSetup,
|
||||
|
@ -49,7 +48,8 @@ export class KibanaOverviewPlugin
|
|||
map((navLinks) => {
|
||||
const hasKibanaApp = Boolean(
|
||||
navLinks.find(
|
||||
({ id, category, hidden }) => !hidden && category?.id === 'kibana' && id !== PLUGIN_ID
|
||||
({ id, category, visibleIn }) =>
|
||||
visibleIn.length > 0 && category?.id === 'kibana' && id !== PLUGIN_ID
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -58,11 +58,7 @@ export class KibanaOverviewPlugin
|
|||
distinct(),
|
||||
map((hasKibanaApp) => {
|
||||
return () => {
|
||||
if (!hasKibanaApp) {
|
||||
return { status: AppStatus.inaccessible, navLinkStatus: AppNavLinkStatus.hidden };
|
||||
} else {
|
||||
return { status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.default };
|
||||
}
|
||||
return { status: hasKibanaApp ? AppStatus.accessible : AppStatus.inaccessible };
|
||||
};
|
||||
})
|
||||
);
|
||||
|
@ -76,6 +72,7 @@ export class KibanaOverviewPlugin
|
|||
order: 1,
|
||||
updater$: appUpdater$,
|
||||
appRoute: PLUGIN_PATH,
|
||||
visibleIn: ['globalSearch', 'home', 'sideNav'],
|
||||
async mount(params: AppMountParameters) {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
AppMountParameters,
|
||||
AppUpdater,
|
||||
AppStatus,
|
||||
AppNavLinkStatus,
|
||||
AppDeepLink,
|
||||
} from '@kbn/core/public';
|
||||
import { ConfigSchema, ManagementSetup, ManagementStart, NavigationCardsSubject } from './types';
|
||||
|
@ -55,21 +54,15 @@ export class ManagementPlugin
|
|||
private readonly managementSections = new ManagementSectionsService();
|
||||
|
||||
private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => {
|
||||
const config = this.initializerContext.config.get();
|
||||
const navLinkStatus =
|
||||
AppNavLinkStatus[config.deeplinks.navLinkStatus as keyof typeof AppNavLinkStatus];
|
||||
|
||||
const deepLinks: AppDeepLink[] = Object.values(this.managementSections.definedSections).map(
|
||||
(section: ManagementSection) => ({
|
||||
id: section.id,
|
||||
title: section.title,
|
||||
navLinkStatus,
|
||||
deepLinks: section.getAppsEnabled().map((mgmtApp) => ({
|
||||
id: mgmtApp.id,
|
||||
title: mgmtApp.title,
|
||||
path: mgmtApp.basePath,
|
||||
keywords: mgmtApp.keywords,
|
||||
navLinkStatus,
|
||||
})),
|
||||
})
|
||||
);
|
||||
|
@ -161,7 +154,7 @@ export class ManagementPlugin
|
|||
this.appUpdater.next(() => {
|
||||
return {
|
||||
status: AppStatus.inaccessible,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import { ScopedHistory, Capabilities } from '@kbn/core/public';
|
|||
import type { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { ChromeBreadcrumb, CoreTheme } from '@kbn/core/public';
|
||||
import type { CardsNavigationComponentProps } from '@kbn/management-cards-navigation';
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { ManagementSection, RegisterManagementSectionArgs } from './utils';
|
||||
import type { ManagementAppLocatorParams } from '../common/locator';
|
||||
|
||||
|
@ -101,6 +100,6 @@ export interface AppDependencies {
|
|||
|
||||
export interface ConfigSchema {
|
||||
deeplinks: {
|
||||
navLinkStatus: keyof typeof AppNavLinkStatus;
|
||||
navLinkStatus: 'default' | 'visible';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import { App, AppMountParameters, CoreSetup } from '@kbn/core/public';
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { navigateToLegacyKibanaUrl } from './navigate_to_legacy_kibana_url';
|
||||
import { ForwardDefinition, UrlForwardingStart } from '../plugin';
|
||||
|
||||
|
@ -19,7 +18,7 @@ export const createLegacyUrlForwardApp = (
|
|||
chromeless: true,
|
||||
title: 'Legacy URL migration',
|
||||
appRoute: '/app/kibana#/',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const hash = params.history.location.hash.substr(1);
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DEFAULT_APP_VISIBILITY } from '@kbn/core-application-browser-internal';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
|
||||
|
||||
export class CorePluginDeepLinksPlugin
|
||||
implements Plugin<CorePluginDeepLinksPluginSetup, CorePluginDeepLinksPluginStart>
|
||||
|
@ -19,19 +20,19 @@ export class CorePluginDeepLinksPlugin
|
|||
appRoute: '/app/dl',
|
||||
defaultPath: '/home',
|
||||
category: DEFAULT_APP_CATEGORIES.security,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'home',
|
||||
title: 'DL Home',
|
||||
path: '/home',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
},
|
||||
{
|
||||
id: 'pageA',
|
||||
title: 'DL page A',
|
||||
path: '/page-a',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
},
|
||||
{
|
||||
id: 'sectionOne',
|
||||
|
@ -41,7 +42,7 @@ export class CorePluginDeepLinksPlugin
|
|||
id: 'pageB',
|
||||
title: 'DL page B',
|
||||
path: '/page-b',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: DEFAULT_APP_VISIBILITY,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
],
|
||||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
"@kbn/shared-ux-router"
|
||||
"@kbn/shared-ux-router",
|
||||
"@kbn/core-application-browser-internal"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import Url from 'url';
|
||||
import expect from '@kbn/expect';
|
||||
import { AppNavLinkStatus, AppStatus, AppUpdatableFields } from '@kbn/core-application-browser';
|
||||
import { AppStatus, AppUpdatableFields } from '@kbn/core-application-browser';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
import '@kbn/core-app-status-plugin/public/types';
|
||||
|
||||
|
@ -47,16 +47,15 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
|||
await PageObjects.common.navigateToApp('app_status_start');
|
||||
});
|
||||
|
||||
it('can change the navLink status at runtime', async () => {
|
||||
it('can change the visibleIn array at runtime', async () => {
|
||||
await setAppStatus({
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: ['sideNav'],
|
||||
});
|
||||
let link = await appsMenu.getLink('App Status');
|
||||
expect(link).not.to.eql(undefined);
|
||||
expect(link!.disabled).to.eql(true);
|
||||
|
||||
await setAppStatus({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
});
|
||||
link = await appsMenu.getLink('App Status');
|
||||
expect(link).to.eql(undefined);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import {
|
||||
|
@ -42,7 +42,7 @@ export class AlertingExamplePlugin implements Plugin<Setup, Start, AlertingExamp
|
|||
core.application.register({
|
||||
id: 'AlertingExample',
|
||||
title: 'Alerting Example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
|
@ -27,7 +27,7 @@ export class EmbeddedLensExamplePlugin
|
|||
core.application.register({
|
||||
id: 'embedded_lens_example',
|
||||
title: 'Embedded Lens example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
});
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { ObservabilityPublicStart } from '@kbn/observability-plugin/public';
|
||||
import type { ExploratoryViewPublicStart } from '@kbn/exploratory-view-plugin/public';
|
||||
|
@ -29,7 +29,7 @@ export class ExploratoryViewExamplePlugin
|
|||
core.application.register({
|
||||
id: 'exploratory_view_example',
|
||||
title: 'Observability Exploratory View example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
order: 1000,
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from '@kbn/core/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import {
|
||||
|
@ -38,7 +38,7 @@ export class GenAiStreamingResponseExamplePlugin
|
|||
core.application.register({
|
||||
id: 'GenAiStreamingResponseExample',
|
||||
title: 'OpenAI Streaming Response Example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import type { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
|
@ -30,7 +30,7 @@ export class LensInlineEditingPlugin
|
|||
core.application.register({
|
||||
id: 'lens_embeddable_inline_editing_example',
|
||||
title: 'Lens inline editing embeddable',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
});
|
||||
|
||||
|
|
|
@ -5,13 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
} from '@kbn/core/public';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { PLUGIN_ID, PLUGIN_NAME, ReportingExampleLocatorDefinition } from '../common';
|
||||
import { SetupDeps, StartDeps, MyForwardableState } from './types';
|
||||
|
||||
|
@ -20,7 +14,7 @@ export class ReportingExamplePlugin implements Plugin<void, void, {}, {}> {
|
|||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
title: PLUGIN_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
async mount(params: AppMountParameters) {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
|
|
@ -9,7 +9,6 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import type { AppMountParameters, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
|
||||
import { App, HttpContext } from './app';
|
||||
|
||||
|
@ -25,7 +24,7 @@ export class ScreenshottingExamplePlugin implements Plugin<void, void> {
|
|||
application.register({
|
||||
id: APPLICATION_ID,
|
||||
title: APPLICATION_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async ({ element }: AppMountParameters) => {
|
||||
const [{ http }] = await getStartServices();
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
|
@ -30,7 +30,7 @@ export class TestingEmbeddedLensPlugin
|
|||
core.application.register({
|
||||
id: 'testing_embedded_lens',
|
||||
title: 'Embedded Lens testing playground',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DataViewsPublicPluginStart, DataView } from '@kbn/data-views-plugin/public';
|
||||
import {
|
||||
DateHistogramIndexPatternColumn,
|
||||
|
@ -95,7 +95,7 @@ export class EmbeddedLensExamplePlugin
|
|||
core.application.register({
|
||||
id: 'third_party_lens_navigation_prompt',
|
||||
title: 'Third party Lens navigation prompt',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: (params) => {
|
||||
(async () => {
|
||||
const [, { lens: lensStart, dataViews }] = await core.getStartServices();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { ExpressionsSetup } from '@kbn/expressions-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/public';
|
||||
import { DataViewsPublicPluginStart, DataView } from '@kbn/data-views-plugin/public';
|
||||
import { LensPublicSetup, LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
|
@ -90,7 +90,7 @@ export class EmbeddedLensExamplePlugin
|
|||
core.application.register({
|
||||
id: 'third_party_lens_vis_example',
|
||||
title: 'Third party Lens vis example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: ({ history }) => {
|
||||
(async () => {
|
||||
const [coreStart, { lens: lensStart, dataViews }] = await core.getStartServices();
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreStart,
|
||||
} from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||
|
@ -54,7 +48,7 @@ export class TriggersActionsUiExamplePlugin
|
|||
core.application.register({
|
||||
id: 'triggersActionsUiExample',
|
||||
title: 'Triggers Actions UI Example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
// category set as cases expects the label to exist
|
||||
category: {
|
||||
id: 'fakeId',
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { createElement as h } from 'react';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { Plugin, CoreSetup, CoreStart, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import {
|
||||
AdvancedUiActionsSetup,
|
||||
|
@ -130,7 +130,7 @@ export class UiActionsEnhancedExamplesPlugin
|
|||
core.application.register({
|
||||
id: 'ui_actions_enhanced-explorer',
|
||||
title: 'UI Actions Enhanced Explorer',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: mount(core),
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import type {
|
|||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
|
@ -361,7 +360,6 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
appRoute: '/app/apm',
|
||||
icon: 'plugins/apm/public/icon.svg',
|
||||
category: DEFAULT_APP_CATEGORIES.observability,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'service-groups-list',
|
||||
|
@ -372,33 +370,26 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
id: 'services',
|
||||
title: servicesTitle,
|
||||
path: '/services',
|
||||
navLinkStatus: config.serverless.enabled
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.default,
|
||||
},
|
||||
{
|
||||
id: 'traces',
|
||||
title: tracesTitle,
|
||||
path: '/traces',
|
||||
navLinkStatus: config.serverless.enabled
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.default,
|
||||
},
|
||||
{ id: 'service-map', title: serviceMapTitle, path: '/service-map' },
|
||||
{
|
||||
id: 'dependencies',
|
||||
title: dependenciesTitle,
|
||||
path: '/dependencies/inventory',
|
||||
navLinkStatus: config.serverless.enabled
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.default,
|
||||
},
|
||||
{ id: 'settings', title: apmSettingsTitle, path: '/settings' },
|
||||
{
|
||||
id: 'storage-explorer',
|
||||
title: apmStorageExplorerTitle,
|
||||
path: '/storage-explorer',
|
||||
searchable: featureFlags.storageExplorerAvailable,
|
||||
visibleIn: featureFlags.storageExplorerAvailable
|
||||
? ['globalSearch']
|
||||
: [],
|
||||
},
|
||||
{ id: 'tutorial', title: apmTutorialTitle, path: '/tutorial' },
|
||||
],
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { getCasesDeepLinks } from './deep_links';
|
||||
|
||||
describe('getCasesDeepLinks', () => {
|
||||
|
@ -55,10 +54,10 @@ describe('getCasesDeepLinks', () => {
|
|||
const deepLinks = getCasesDeepLinks({
|
||||
extend: {
|
||||
cases: {
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
},
|
||||
cases_create: {
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
},
|
||||
cases_configure: {
|
||||
order: 8002,
|
||||
|
@ -70,13 +69,13 @@ describe('getCasesDeepLinks', () => {
|
|||
id: 'cases',
|
||||
path: '/cases',
|
||||
title: 'Cases',
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'cases_create',
|
||||
path: '/cases/create',
|
||||
title: 'Create',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
},
|
||||
{
|
||||
id: 'cases_configure',
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
Plugin,
|
||||
PluginInitializerContext,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
AppNavLinkStatus,
|
||||
} from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public';
|
||||
|
@ -67,9 +66,9 @@ export interface PluginsStart {
|
|||
guidedOnboarding: GuidedOnboardingPluginStart;
|
||||
lens: LensPublicStart;
|
||||
licensing: LicensingPluginStart;
|
||||
ml: MlPluginStart;
|
||||
security: SecurityPluginStart;
|
||||
share: SharePluginStart;
|
||||
ml: MlPluginStart;
|
||||
}
|
||||
|
||||
export interface ESConfig {
|
||||
|
@ -78,7 +77,6 @@ export interface ESConfig {
|
|||
|
||||
export class EnterpriseSearchPlugin implements Plugin {
|
||||
private config: ClientConfigType;
|
||||
private esConfig: ESConfig;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.config = initializerContext.config.get<ClientConfigType>();
|
||||
|
@ -86,6 +84,7 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
}
|
||||
|
||||
private data: ClientData = {} as ClientData;
|
||||
private esConfig: ESConfig;
|
||||
|
||||
private async getInitialData(http: HttpSetup) {
|
||||
try {
|
||||
|
@ -167,6 +166,7 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData);
|
||||
},
|
||||
title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE,
|
||||
visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'],
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
|
@ -252,8 +252,8 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(EnterpriseSearchAISearch, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
title: AI_SEARCH_PLUGIN.NAV_TITLE,
|
||||
visibleIn: [],
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
|
@ -274,8 +274,6 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(Applications, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
title: APPLICATIONS_PLUGIN.NAV_TITLE,
|
||||
});
|
||||
|
||||
|
@ -297,8 +295,6 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(Analytics, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.default,
|
||||
searchable: true,
|
||||
title: ANALYTICS_PLUGIN.NAME,
|
||||
});
|
||||
|
||||
|
@ -320,8 +316,8 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(SearchExperiences, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
title: SEARCH_EXPERIENCES_PLUGIN.NAME,
|
||||
visibleIn: [],
|
||||
});
|
||||
|
||||
if (config.canDeployEntSearch) {
|
||||
|
@ -343,8 +339,8 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(AppSearch, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
title: APP_SEARCH_PLUGIN.NAME,
|
||||
visibleIn: [],
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
|
@ -368,8 +364,8 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
return renderApp(WorkplaceSearch, kibanaDeps, pluginData);
|
||||
},
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
title: WORKPLACE_SEARCH_PLUGIN.NAME,
|
||||
visibleIn: [],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AppNavLinkStatus } from '@kbn/core-application-browser';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import {
|
||||
|
@ -114,7 +113,7 @@ export class Plugin
|
|||
title: i18n.translate('xpack.exploratoryView.appTitle', {
|
||||
defaultMessage: 'Exploratory View',
|
||||
}),
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
updater$: appUpdater$,
|
||||
keywords: [
|
||||
'observability',
|
||||
|
@ -136,10 +135,6 @@ export class Plugin
|
|||
}
|
||||
|
||||
public start(coreStart: CoreStart, pluginsStart: ExploratoryViewPublicPluginsStart) {
|
||||
this.appUpdater$.next(() => ({
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
}));
|
||||
|
||||
return {
|
||||
createExploratoryViewUrl,
|
||||
getAppDataView: getAppDataView(pluginsStart.dataViews),
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
"@kbn/share-plugin",
|
||||
"@kbn/charts-plugin",
|
||||
"@kbn/shared-ux-router",
|
||||
"@kbn/core-application-browser",
|
||||
"@kbn/observability-shared-plugin",
|
||||
"@kbn/core-ui-settings-browser-mocks",
|
||||
"@kbn/observability-ai-assistant-plugin",
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
Plugin,
|
||||
PluginInitializerContext,
|
||||
} from '@kbn/core/public';
|
||||
import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
|
||||
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public';
|
||||
|
@ -248,7 +248,7 @@ export class FleetPlugin implements Plugin<FleetSetup, FleetStart, FleetSetupDep
|
|||
core.application.register({
|
||||
id: 'ingestManager',
|
||||
category: DEFAULT_APP_CATEGORIES.management,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
title: i18n.translate('xpack.fleet.oldAppTitle', { defaultMessage: 'Ingest Manager' }),
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
|
|
|
@ -9,7 +9,7 @@ import { getAppResultsMock } from './application.test.mocks';
|
|||
|
||||
import { EMPTY, of } from 'rxjs';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
import { ApplicationStart, AppNavLinkStatus, AppStatus, PublicAppInfo } from '@kbn/core/public';
|
||||
import { ApplicationStart, AppStatus, PublicAppInfo } from '@kbn/core/public';
|
||||
import {
|
||||
GlobalSearchProviderFindOptions,
|
||||
GlobalSearchProviderResult,
|
||||
|
@ -27,8 +27,7 @@ const createApp = (props: Partial<PublicAppInfo> = {}): PublicAppInfo => ({
|
|||
title: 'App 1',
|
||||
appRoute: '/app/app1',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
chromeless: false,
|
||||
keywords: props.keywords || [],
|
||||
deepLinks: [],
|
||||
|
@ -167,13 +166,13 @@ describe('applicationResultProvider', () => {
|
|||
it('does not ignore apps with non-visible navlink', async () => {
|
||||
application.applications$ = of(
|
||||
createAppMap([
|
||||
createApp({ id: 'app1', title: 'App 1', navLinkStatus: AppNavLinkStatus.visible }),
|
||||
createApp({ id: 'app1', title: 'App 1', visibleIn: ['globalSearch'] }),
|
||||
createApp({
|
||||
id: 'disabled',
|
||||
title: 'disabled',
|
||||
navLinkStatus: AppNavLinkStatus.disabled,
|
||||
visibleIn: [],
|
||||
}),
|
||||
createApp({ id: 'hidden', title: 'hidden', navLinkStatus: AppNavLinkStatus.hidden }),
|
||||
createApp({ id: 'hidden', title: 'hidden', visibleIn: [] }),
|
||||
])
|
||||
);
|
||||
const provider = createApplicationResultProvider(Promise.resolve(application));
|
||||
|
|
|
@ -5,12 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
PublicAppInfo,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
} from '@kbn/core/public';
|
||||
import { AppStatus, PublicAppInfo, DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
|
||||
import {
|
||||
AppLink,
|
||||
appToResult,
|
||||
|
@ -24,8 +19,7 @@ const createApp = (props: Partial<PublicAppInfo> = {}): PublicAppInfo => ({
|
|||
title: 'App 1',
|
||||
appRoute: '/app/app1',
|
||||
status: AppStatus.accessible,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
chromeless: false,
|
||||
keywords: [],
|
||||
deepLinks: [],
|
||||
|
@ -48,7 +42,7 @@ describe('getAppResults', () => {
|
|||
createApp({
|
||||
id: 'dashboard_not_searchable',
|
||||
title: 'dashboard not searchable',
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -68,8 +62,7 @@ describe('getAppResults', () => {
|
|||
path: '/sub1',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
{
|
||||
id: 'sub2',
|
||||
|
@ -82,13 +75,11 @@ describe('getAppResults', () => {
|
|||
path: '/sub2/sub1',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
},
|
||||
],
|
||||
keywords: [],
|
||||
|
@ -116,8 +107,7 @@ describe('getAppResults', () => {
|
|||
path: '/sub-observability',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
{
|
||||
id: 'sub-security',
|
||||
|
@ -125,8 +115,7 @@ describe('getAppResults', () => {
|
|||
path: '/sub-security',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
euiIconType: 'logoSecurity',
|
||||
category: DEFAULT_APP_CATEGORIES.security,
|
||||
},
|
||||
|
@ -164,8 +153,7 @@ describe('getAppResults', () => {
|
|||
path: '/sub1',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
],
|
||||
keywords: [],
|
||||
|
@ -173,7 +161,7 @@ describe('getAppResults', () => {
|
|||
createApp({
|
||||
id: 'AppNotSearchable',
|
||||
title: 'App 1 not searchable',
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -197,8 +185,7 @@ describe('getAppResults', () => {
|
|||
path: '/sub1',
|
||||
deepLinks: [],
|
||||
keywords: [],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
{
|
||||
id: 'sub2',
|
||||
|
@ -211,13 +198,11 @@ describe('getAppResults', () => {
|
|||
path: '/sub2/sub1',
|
||||
deepLinks: [],
|
||||
keywords: ['TwoOne'],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
],
|
||||
keywords: ['two'],
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: true,
|
||||
visibleIn: ['globalSearch'],
|
||||
},
|
||||
],
|
||||
keywords: [],
|
||||
|
|
|
@ -33,7 +33,7 @@ export const getAppResults = (
|
|||
.flatMap((app) =>
|
||||
term.length > 0
|
||||
? flattenDeepLinks(app)
|
||||
: app.searchable
|
||||
: app.visibleIn.includes('globalSearch')
|
||||
? [
|
||||
{
|
||||
id: app.id,
|
||||
|
@ -122,7 +122,7 @@ export const appToResult = (appLink: AppLink, score: number): GlobalSearchProvid
|
|||
const flattenDeepLinks = (app: PublicAppInfo, deepLink?: PublicAppDeepLinkInfo): AppLink[] => {
|
||||
if (!deepLink) {
|
||||
return [
|
||||
...(app.searchable
|
||||
...(app.visibleIn.includes('globalSearch')
|
||||
? [
|
||||
{
|
||||
id: app.id,
|
||||
|
@ -137,7 +137,7 @@ const flattenDeepLinks = (app: PublicAppInfo, deepLink?: PublicAppDeepLinkInfo):
|
|||
];
|
||||
}
|
||||
return [
|
||||
...(deepLink.path && deepLink.searchable
|
||||
...(deepLink.path && deepLink.visibleIn.includes('globalSearch')
|
||||
? [
|
||||
{
|
||||
...deepLink,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { BehaviorSubject } from 'rxjs';
|
||||
import { SpacesApi } from '@kbn/spaces-plugin/public';
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
AppStatus,
|
||||
AppUpdater,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
|
@ -143,11 +143,11 @@ export class GraphPlugin
|
|||
const licenseInformation = checkLicense(license);
|
||||
|
||||
this.appUpdater$.next(() => ({
|
||||
navLinkStatus: licenseInformation.showAppLink
|
||||
status: licenseInformation.showAppLink
|
||||
? licenseInformation.enableAppLink
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.disabled
|
||||
: AppNavLinkStatus.hidden,
|
||||
? AppStatus.accessible
|
||||
: AppStatus.inaccessible
|
||||
: AppStatus.inaccessible,
|
||||
tooltip: licenseInformation.showAppLink ? licenseInformation.message : undefined,
|
||||
}));
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ import {
|
|||
type AppUpdater,
|
||||
type CoreStart,
|
||||
type AppDeepLink,
|
||||
AppNavLinkStatus,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
PluginInitializerContext,
|
||||
AppDeepLinkLocations,
|
||||
} from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { enableInfrastructureHostsView } from '@kbn/observability-plugin/public';
|
||||
|
@ -249,9 +249,7 @@ export class Plugin implements InfraClientPluginClass {
|
|||
hostsEnabled: boolean;
|
||||
metricsExplorerEnabled: boolean;
|
||||
}): AppDeepLink[] => {
|
||||
const serverlessNavLinkStatus = this.isServerlessEnv
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.hidden;
|
||||
const visibleIn: AppDeepLinkLocations[] = this.isServerlessEnv ? ['globalSearch'] : [];
|
||||
|
||||
return [
|
||||
{
|
||||
|
@ -260,7 +258,7 @@ export class Plugin implements InfraClientPluginClass {
|
|||
defaultMessage: 'Inventory',
|
||||
}),
|
||||
path: '/inventory',
|
||||
navLinkStatus: serverlessNavLinkStatus,
|
||||
visibleIn,
|
||||
},
|
||||
...(hostsEnabled
|
||||
? [
|
||||
|
@ -270,7 +268,7 @@ export class Plugin implements InfraClientPluginClass {
|
|||
defaultMessage: 'Hosts',
|
||||
}),
|
||||
path: '/hosts',
|
||||
navLinkStatus: serverlessNavLinkStatus,
|
||||
visibleIn,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
@ -330,7 +328,7 @@ export class Plugin implements InfraClientPluginClass {
|
|||
id: 'infra',
|
||||
appRoute: '/app/infra',
|
||||
title: 'infra',
|
||||
navLinkStatus: 3,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const { renderApp } = await import('./apps/legacy_app');
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ import { EmbeddableStateTransfer } from '@kbn/embeddable-plugin/public';
|
|||
import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
|
||||
import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public';
|
||||
import { AppNavLinkStatus } from '@kbn/core/public';
|
||||
import {
|
||||
UiActionsStart,
|
||||
ACTION_VISUALIZE_FIELD,
|
||||
|
@ -451,7 +450,7 @@ export class LensPlugin {
|
|||
core.application.register({
|
||||
id: APP_ID,
|
||||
title: NOT_INTERNATIONALIZED_PRODUCT_NAME,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const { core: coreStart, plugins: deps } = startServices();
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ class MyPlugin {
|
|||
const showLinks = hasRequiredLicense && license.getFeature('name').isAvailable;
|
||||
|
||||
appUpdater$.next(() => {
|
||||
navLinkStatus: showLinks ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden
|
||||
status: showLinks ? AppStatus.accessible : AppStatus.inaccessible,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
registerMapExtension,
|
||||
registerCasesAttachments,
|
||||
} = await import('./register_helper');
|
||||
registerSearchLinks(this.appUpdater$, fullLicense, mlCapabilities, !this.isServerless);
|
||||
registerSearchLinks(this.appUpdater$, fullLicense, mlCapabilities, this.isServerless);
|
||||
|
||||
if (
|
||||
pluginsSetup.triggersActionsUi &&
|
||||
|
|
|
@ -16,7 +16,7 @@ export function registerSearchLinks(
|
|||
appUpdater: BehaviorSubject<AppUpdater>,
|
||||
isFullLicense: boolean,
|
||||
mlCapabilities: MlCapabilities,
|
||||
showMLNavMenu: boolean
|
||||
isServerless: boolean
|
||||
) {
|
||||
appUpdater.next(() => ({
|
||||
keywords: [
|
||||
|
@ -24,6 +24,6 @@ export function registerSearchLinks(
|
|||
defaultMessage: 'ML',
|
||||
}),
|
||||
],
|
||||
deepLinks: getDeepLinks(isFullLicense, mlCapabilities, showMLNavMenu),
|
||||
deepLinks: getDeepLinks(isFullLicense, mlCapabilities, isServerless),
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -8,50 +8,37 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { LinkId } from '@kbn/deeplinks-ml';
|
||||
|
||||
import { type AppDeepLink, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { type AppDeepLink } from '@kbn/core/public';
|
||||
import { ML_PAGES } from '../../../common/constants/locator';
|
||||
import type { MlCapabilities } from '../../shared';
|
||||
|
||||
function createDeepLinks(
|
||||
mlCapabilities: MlCapabilities,
|
||||
isFullLicense: boolean,
|
||||
showMLNavMenu: boolean
|
||||
isServerless: boolean
|
||||
) {
|
||||
function getNavStatus(
|
||||
visible: boolean,
|
||||
showInServerless: boolean = true
|
||||
): AppNavLinkStatus | undefined {
|
||||
if (showMLNavMenu === false) {
|
||||
// in serverless the status needs to be "visible" rather than "default"
|
||||
// for the links to appear in the nav menu.
|
||||
return showInServerless && visible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden;
|
||||
}
|
||||
|
||||
return visible ? AppNavLinkStatus.default : AppNavLinkStatus.hidden;
|
||||
}
|
||||
|
||||
return {
|
||||
getOverviewLinkDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(mlCapabilities.isADEnabled || mlCapabilities.isDFAEnabled);
|
||||
getOverviewLinkDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.isADEnabled && !mlCapabilities.isDFAEnabled) return null;
|
||||
|
||||
return {
|
||||
id: 'overview',
|
||||
title: i18n.translate('xpack.ml.deepLink.overview', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
path: `/${ML_PAGES.OVERVIEW}`,
|
||||
navLinkStatus,
|
||||
};
|
||||
},
|
||||
|
||||
getAnomalyDetectionDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(mlCapabilities.isADEnabled);
|
||||
getAnomalyDetectionDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.isADEnabled) return null;
|
||||
|
||||
return {
|
||||
id: 'anomalyDetection',
|
||||
title: i18n.translate('xpack.ml.deepLink.anomalyDetection', {
|
||||
defaultMessage: 'Anomaly Detection',
|
||||
}),
|
||||
path: `/${ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE}`,
|
||||
navLinkStatus,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'anomalyExplorer',
|
||||
|
@ -59,7 +46,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Anomaly explorer',
|
||||
}),
|
||||
path: `/${ML_PAGES.ANOMALY_EXPLORER}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'singleMetricViewer',
|
||||
|
@ -67,21 +53,20 @@ function createDeepLinks(
|
|||
defaultMessage: 'Single metric viewer',
|
||||
}),
|
||||
path: `/${ML_PAGES.SINGLE_METRIC_VIEWER}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
getDataFrameAnalyticsDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(mlCapabilities.isDFAEnabled);
|
||||
getDataFrameAnalyticsDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.isDFAEnabled) return null;
|
||||
|
||||
return {
|
||||
id: 'dataFrameAnalytics',
|
||||
title: i18n.translate('xpack.ml.deepLink.dataFrameAnalytics', {
|
||||
defaultMessage: 'Data Frame Analytics',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE}`,
|
||||
navLinkStatus,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'resultExplorer',
|
||||
|
@ -89,7 +74,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Results explorer',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'analyticsMap',
|
||||
|
@ -97,67 +81,65 @@ function createDeepLinks(
|
|||
defaultMessage: 'Analytics map',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_MAP}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
getModelManagementDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(
|
||||
mlCapabilities.isDFAEnabled || mlCapabilities.isNLPEnabled
|
||||
);
|
||||
getModelManagementDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.isDFAEnabled && !mlCapabilities.isNLPEnabled) return null;
|
||||
|
||||
const deepLinks: Array<AppDeepLink<LinkId>> = [
|
||||
{
|
||||
id: 'nodesOverview',
|
||||
title: i18n.translate('xpack.ml.deepLink.trainedModels', {
|
||||
defaultMessage: 'Trained Models',
|
||||
}),
|
||||
path: `/${ML_PAGES.TRAINED_MODELS_MANAGE}`,
|
||||
},
|
||||
];
|
||||
|
||||
if (!isServerless) {
|
||||
deepLinks.push({
|
||||
id: 'nodes',
|
||||
title: i18n.translate('xpack.ml.deepLink.nodes', {
|
||||
defaultMessage: 'Nodes',
|
||||
}),
|
||||
path: `/${ML_PAGES.NODES}`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'modelManagement',
|
||||
title: i18n.translate('xpack.ml.deepLink.modelManagement', {
|
||||
defaultMessage: 'Model Management',
|
||||
}),
|
||||
path: `/${ML_PAGES.TRAINED_MODELS_MANAGE}`,
|
||||
navLinkStatus,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'nodesOverview',
|
||||
title: i18n.translate('xpack.ml.deepLink.trainedModels', {
|
||||
defaultMessage: 'Trained Models',
|
||||
}),
|
||||
path: `/${ML_PAGES.TRAINED_MODELS_MANAGE}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'nodes',
|
||||
title: i18n.translate('xpack.ml.deepLink.nodes', {
|
||||
defaultMessage: 'Nodes',
|
||||
}),
|
||||
path: `/${ML_PAGES.NODES}`,
|
||||
navLinkStatus: getNavStatus(
|
||||
mlCapabilities.isDFAEnabled || mlCapabilities.isNLPEnabled,
|
||||
false
|
||||
),
|
||||
},
|
||||
],
|
||||
deepLinks,
|
||||
};
|
||||
},
|
||||
|
||||
getMemoryUsageDeepLink: (): AppDeepLink<LinkId> => {
|
||||
getMemoryUsageDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!isFullLicense) return null;
|
||||
|
||||
return {
|
||||
id: 'memoryUsage',
|
||||
title: i18n.translate('xpack.ml.deepLink.memoryUsage', {
|
||||
defaultMessage: 'Memory Usage',
|
||||
}),
|
||||
path: `/${ML_PAGES.MEMORY_USAGE}`,
|
||||
navLinkStatus: getNavStatus(isFullLicense, true),
|
||||
};
|
||||
},
|
||||
|
||||
getSettingsDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(mlCapabilities.isADEnabled);
|
||||
getSettingsDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.isADEnabled) return null;
|
||||
|
||||
return {
|
||||
id: 'settings',
|
||||
title: i18n.translate('xpack.ml.deepLink.settings', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
path: `/${ML_PAGES.SETTINGS}`,
|
||||
navLinkStatus,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'calendarSettings',
|
||||
|
@ -165,7 +147,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Calendars',
|
||||
}),
|
||||
path: `/${ML_PAGES.CALENDARS_MANAGE}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'filterListsSettings',
|
||||
|
@ -173,14 +154,14 @@ function createDeepLinks(
|
|||
defaultMessage: 'Filter Lists',
|
||||
}),
|
||||
path: `/${ML_PAGES.SETTINGS}`, // Link to settings page as read only users cannot view filter lists.
|
||||
navLinkStatus,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
getAiopsDeepLink: (): AppDeepLink<LinkId> => {
|
||||
const navLinkStatus = getNavStatus(mlCapabilities.canUseAiops);
|
||||
getAiopsDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!mlCapabilities.canUseAiops) return null;
|
||||
|
||||
return {
|
||||
id: 'aiOps',
|
||||
title: i18n.translate('xpack.ml.deepLink.aiOps', {
|
||||
|
@ -188,7 +169,6 @@ function createDeepLinks(
|
|||
}),
|
||||
// Default to the index select page for log rate analysis since we don't have an AIops overview page
|
||||
path: `/${ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT}`,
|
||||
navLinkStatus,
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'logRateAnalysis',
|
||||
|
@ -196,7 +176,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Log Rate Analysis',
|
||||
}),
|
||||
path: `/${ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'logPatternAnalysis',
|
||||
|
@ -204,7 +183,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Log Pattern Analysis',
|
||||
}),
|
||||
path: `/${ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
{
|
||||
id: 'changePointDetections',
|
||||
|
@ -212,20 +190,20 @@ function createDeepLinks(
|
|||
defaultMessage: 'Change Point Detection',
|
||||
}),
|
||||
path: `/${ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT}`,
|
||||
navLinkStatus,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
getNotificationsDeepLink: (): AppDeepLink<LinkId> => {
|
||||
getNotificationsDeepLink: (): AppDeepLink<LinkId> | null => {
|
||||
if (!isFullLicense) return null;
|
||||
|
||||
return {
|
||||
id: 'notifications',
|
||||
title: i18n.translate('xpack.ml.deepLink.notifications', {
|
||||
defaultMessage: 'Notifications',
|
||||
}),
|
||||
path: `/${ML_PAGES.NOTIFICATIONS}`,
|
||||
navLinkStatus: getNavStatus(isFullLicense),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -236,7 +214,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Data Visualizer',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_VISUALIZER}`,
|
||||
navLinkStatus: getNavStatus(true),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -248,7 +225,6 @@ function createDeepLinks(
|
|||
}),
|
||||
keywords: ['CSV', 'JSON'],
|
||||
path: `/${ML_PAGES.DATA_VISUALIZER_FILE}`,
|
||||
navLinkStatus: getNavStatus(true),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -259,7 +235,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Index Data Visualizer',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_VISUALIZER_INDEX_SELECT}`,
|
||||
navLinkStatus: getNavStatus(true),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -270,7 +245,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'ES|QL Data Visualizer',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_VISUALIZER_ESQL}`,
|
||||
navLinkStatus: getNavStatus(true),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -281,7 +255,6 @@ function createDeepLinks(
|
|||
defaultMessage: 'Data Drift',
|
||||
}),
|
||||
path: `/${ML_PAGES.DATA_DRIFT_INDEX_SELECT}`,
|
||||
navLinkStatus: getNavStatus(true),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
@ -290,8 +263,10 @@ function createDeepLinks(
|
|||
export function getDeepLinks(
|
||||
isFullLicense: boolean,
|
||||
mlCapabilities: MlCapabilities,
|
||||
showMLNavMenu: boolean
|
||||
) {
|
||||
const links = createDeepLinks(mlCapabilities, isFullLicense, showMLNavMenu);
|
||||
return Object.values(links).map((link) => link());
|
||||
isServerless: boolean
|
||||
): Array<AppDeepLink<LinkId>> {
|
||||
const links = createDeepLinks(mlCapabilities, isFullLicense, isServerless);
|
||||
return Object.values(links)
|
||||
.map((link) => link())
|
||||
.filter((link): link is AppDeepLink<LinkId> => link !== null);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
App,
|
||||
AppDeepLink,
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
AppUpdater,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
|
@ -197,7 +196,7 @@ export class Plugin
|
|||
}),
|
||||
order: 8001,
|
||||
path: ALERTS_PATH,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'rules',
|
||||
|
@ -205,7 +204,7 @@ export class Plugin
|
|||
defaultMessage: 'Rules',
|
||||
}),
|
||||
path: RULES_PATH,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -214,7 +213,7 @@ export class Plugin
|
|||
title: i18n.translate('xpack.observability.slosLinkTitle', {
|
||||
defaultMessage: 'SLOs',
|
||||
}),
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
order: 8002,
|
||||
path: SLOS_PATH,
|
||||
},
|
||||
|
@ -223,15 +222,13 @@ export class Plugin
|
|||
extend: {
|
||||
[CasesDeepLinkId.cases]: {
|
||||
order: 8003,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
},
|
||||
[CasesDeepLinkId.casesCreate]: {
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
},
|
||||
[CasesDeepLinkId.casesConfigure]: {
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
searchable: false,
|
||||
visibleIn: [],
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
@ -316,7 +313,9 @@ export class Plugin
|
|||
'user',
|
||||
'experience',
|
||||
],
|
||||
searchable: !Boolean(pluginsSetup.serverless),
|
||||
visibleIn: Boolean(pluginsSetup.serverless)
|
||||
? ['home', 'kibanaOverview']
|
||||
: ['globalSearch', 'home', 'kibanaOverview', 'sideNav'],
|
||||
};
|
||||
|
||||
coreSetup.application.register(app);
|
||||
|
@ -437,7 +436,7 @@ export class Plugin
|
|||
//
|
||||
// See https://github.com/elastic/kibana/issues/103325.
|
||||
const otherLinks: NavigationEntry[] = deepLinks
|
||||
.filter((link) => link.navLinkStatus === AppNavLinkStatus.visible)
|
||||
.filter((link) => (link.visibleIn ?? []).length > 0)
|
||||
.map((link) => ({
|
||||
app: observabilityAppId,
|
||||
label: link.title,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import React, { ComponentType, lazy, Ref } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {
|
||||
AppNavLinkStatus,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
type AppMountParameters,
|
||||
type CoreSetup,
|
||||
|
@ -59,7 +58,7 @@ export class ObservabilityAIAssistantPlugin
|
|||
euiIconType: 'logoObservability',
|
||||
appRoute: '/app/observabilityAIAssistant',
|
||||
category: DEFAULT_APP_CATEGORIES.observability,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
deepLinks: [
|
||||
{
|
||||
id: 'conversations',
|
||||
|
|
|
@ -682,7 +682,9 @@ describe('[Logs onboarding] System logs', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when integration installation succeed', () => {
|
||||
// Skpping this test because it's failing in the CI
|
||||
// https://github.com/elastic/kibana/issues/176995
|
||||
xdescribe('when integration installation succeed', () => {
|
||||
beforeEach(() => {
|
||||
cy.deleteIntegration('system');
|
||||
cy.intercept('GET', '/api/fleet/epm/packages/system').as(
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
DEFAULT_APP_CATEGORIES,
|
||||
Plugin,
|
||||
PluginInitializerContext,
|
||||
AppNavLinkStatus,
|
||||
} from '@kbn/core/public';
|
||||
import {
|
||||
DataPublicPluginSetup,
|
||||
|
@ -71,7 +70,6 @@ export class ObservabilityOnboardingPlugin
|
|||
const config = this.ctx.config.get<ObservabilityOnboardingConfig>();
|
||||
const {
|
||||
ui: { enabled: isObservabilityOnboardingUiEnabled },
|
||||
serverless: { enabled: isServerlessEnabled },
|
||||
} = config;
|
||||
|
||||
const pluginSetupDeps = plugins;
|
||||
|
@ -80,9 +78,6 @@ export class ObservabilityOnboardingPlugin
|
|||
// and go to /app/observabilityOnboarding
|
||||
if (isObservabilityOnboardingUiEnabled) {
|
||||
core.application.register({
|
||||
navLinkStatus: isServerlessEnabled
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.hidden,
|
||||
id: PLUGIN_ID,
|
||||
title: 'Observability Onboarding',
|
||||
order: 8500,
|
||||
|
@ -110,6 +105,7 @@ export class ObservabilityOnboardingPlugin
|
|||
config,
|
||||
});
|
||||
},
|
||||
visibleIn: [],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
import { App, AppDeepLink, ApplicationStart, AppNavLinkStatus, AppUpdater } from '@kbn/core/public';
|
||||
import { App, AppDeepLink, ApplicationStart, AppUpdater } from '@kbn/core/public';
|
||||
import { casesFeatureId, sloFeatureId } from '../../common';
|
||||
import { updateGlobalNavigation } from './update_global_navigation';
|
||||
|
||||
|
@ -29,7 +29,7 @@ describe('updateGlobalNavigation', () => {
|
|||
|
||||
expect(callback).toHaveBeenCalledWith({
|
||||
deepLinks,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ describe('updateGlobalNavigation', () => {
|
|||
|
||||
expect(callback).toHaveBeenCalledWith({
|
||||
deepLinks,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -65,7 +65,7 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'Cases',
|
||||
order: 8003,
|
||||
path: '/cases',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [], // no visibility set
|
||||
};
|
||||
|
||||
const deepLinks = [caseRoute];
|
||||
|
@ -81,10 +81,10 @@ describe('updateGlobalNavigation', () => {
|
|||
deepLinks: [
|
||||
{
|
||||
...caseRoute,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch'], // visibility set
|
||||
},
|
||||
],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -101,7 +101,7 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'Cases',
|
||||
order: 8003,
|
||||
path: '/cases',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
|
||||
const deepLinks = [caseRoute];
|
||||
|
@ -114,13 +114,8 @@ describe('updateGlobalNavigation', () => {
|
|||
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
|
||||
|
||||
expect(callback).toHaveBeenCalledWith({
|
||||
deepLinks: [
|
||||
{
|
||||
...caseRoute,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
},
|
||||
],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
deepLinks: [], // Deeplink has been filtered out
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -138,7 +133,7 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'Alerts',
|
||||
order: 8001,
|
||||
path: '/alerts',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
},
|
||||
];
|
||||
const callback = jest.fn();
|
||||
|
@ -155,10 +150,10 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'Alerts',
|
||||
order: 8001,
|
||||
path: '/alerts',
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
},
|
||||
],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -173,7 +168,7 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'SLOs',
|
||||
order: 8002,
|
||||
path: '/slos',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
|
||||
const deepLinks = [sloRoute];
|
||||
|
@ -186,13 +181,8 @@ describe('updateGlobalNavigation', () => {
|
|||
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
|
||||
|
||||
expect(callback).toHaveBeenCalledWith({
|
||||
deepLinks: [
|
||||
{
|
||||
...sloRoute,
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
},
|
||||
],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
deepLinks: [], // Deeplink has been filtered out
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -209,7 +199,7 @@ describe('updateGlobalNavigation', () => {
|
|||
title: 'SLOs',
|
||||
order: 8002,
|
||||
path: '/slos',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
visibleIn: [],
|
||||
};
|
||||
|
||||
const deepLinks = [sloRoute];
|
||||
|
@ -225,10 +215,10 @@ describe('updateGlobalNavigation', () => {
|
|||
deepLinks: [
|
||||
{
|
||||
...sloRoute,
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
},
|
||||
],
|
||||
navLinkStatus: AppNavLinkStatus.visible,
|
||||
visibleIn: ['sideNav', 'globalSearch', 'home', 'kibanaOverview'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
import { AppNavLinkStatus, AppUpdater, ApplicationStart, AppDeepLink } from '@kbn/core/public';
|
||||
import { AppUpdater, ApplicationStart, AppDeepLink } from '@kbn/core/public';
|
||||
import { CasesDeepLinkId } from '@kbn/cases-plugin/public';
|
||||
import { casesFeatureId, sloFeatureId } from '../../common';
|
||||
|
||||
|
@ -27,43 +27,52 @@ export function updateGlobalNavigation({
|
|||
uptime,
|
||||
}).some((visible) => visible);
|
||||
|
||||
const updatedDeepLinks = deepLinks.map((link) => {
|
||||
switch (link.id) {
|
||||
case CasesDeepLinkId.cases:
|
||||
return {
|
||||
...link,
|
||||
navLinkStatus:
|
||||
capabilities[casesFeatureId].read_cases && someVisible
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.hidden,
|
||||
};
|
||||
case 'alerts':
|
||||
return {
|
||||
...link,
|
||||
navLinkStatus: someVisible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden,
|
||||
};
|
||||
case 'rules':
|
||||
return {
|
||||
...link,
|
||||
navLinkStatus: someVisible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden,
|
||||
};
|
||||
case 'slos':
|
||||
return {
|
||||
...link,
|
||||
navLinkStatus: !!capabilities[sloFeatureId]?.read
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.hidden,
|
||||
};
|
||||
default:
|
||||
return link;
|
||||
}
|
||||
});
|
||||
const updatedDeepLinks = deepLinks
|
||||
.map((link) => {
|
||||
switch (link.id) {
|
||||
case CasesDeepLinkId.cases:
|
||||
if (capabilities[casesFeatureId].read_cases && someVisible) {
|
||||
return {
|
||||
...link,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
case 'alerts':
|
||||
if (someVisible) {
|
||||
return {
|
||||
...link,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
case 'rules':
|
||||
if (someVisible) {
|
||||
return {
|
||||
...link,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
case 'slos':
|
||||
if (!!capabilities[sloFeatureId]?.read) {
|
||||
return {
|
||||
...link,
|
||||
visibleIn: ['sideNav', 'globalSearch'],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
return link;
|
||||
}
|
||||
})
|
||||
.filter((link): link is AppDeepLink => link !== null);
|
||||
|
||||
updater$.next(() => ({
|
||||
deepLinks: updatedDeepLinks,
|
||||
navLinkStatus:
|
||||
visibleIn:
|
||||
someVisible || !!capabilities[sloFeatureId]?.read
|
||||
? AppNavLinkStatus.visible
|
||||
: AppNavLinkStatus.hidden,
|
||||
? ['sideNav', 'globalSearch', 'home', 'kibanaOverview']
|
||||
: [],
|
||||
}));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue