Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface App<HistoryLocationState = unknown>
| [navLinkStatus](./kibana-plugin-core-public.app.navlinkstatus.md) | <code>AppNavLinkStatus</code> | The initial status of the application's navLink. Defaulting to <code>visible</code> if <code>status</code> is <code>accessible</code> and <code>hidden</code> if status is <code>inaccessible</code> See [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) |
| [order](./kibana-plugin-core-public.app.order.md) | <code>number</code> | An ordinal used to sort nav links relative to one another for display. |
| [status](./kibana-plugin-core-public.app.status.md) | <code>AppStatus</code> | The initial status of the application. Defaulting to <code>accessible</code> |
| [subLinks](./kibana-plugin-core-public.app.sublinks.md) | <code>AppSubLink[]</code> | Array of links that represent secondary in-app locations for the given app.<!-- -->Can be updated using the [App.updater$](./kibana-plugin-core-public.app.updater_.md) observable. See [AppSubLink](./kibana-plugin-core-public.appsublink.md) for more details. |
| [title](./kibana-plugin-core-public.app.title.md) | <code>string</code> | The title of the application. |
| [tooltip](./kibana-plugin-core-public.app.tooltip.md) | <code>string</code> | A tooltip shown when hovering over app link. |
| [updater$](./kibana-plugin-core-public.app.updater_.md) | <code>Observable&lt;AppUpdater&gt;</code> | An [AppUpdater](./kibana-plugin-core-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-core-public.appupdatablefields.md) at runtime. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [App](./kibana-plugin-core-public.app.md) &gt; [subLinks](./kibana-plugin-core-public.app.sublinks.md)

## App.subLinks property

Array of links that represent secondary in-app locations for the given app.

Can be updated using the [App.updater$](./kibana-plugin-core-public.app.updater_.md) observable. See [AppSubLink](./kibana-plugin-core-public.appsublink.md) for more details.

<b>Signature:</b>

```typescript
subLinks?: AppSubLink[];
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [AppSubLink](./kibana-plugin-core-public.appsublink.md)

## AppSubLink type

Input type for registering secondary in-app locations for an application.

Sublinks must include at least one of `path` or `subLinks`<!-- -->. A sublink that does not have a `path` represents a topological level in the application's hierarchy, but does not have a destination URL that is user-accessible.

Used to populate navigational search results (where available).

<b>Signature:</b>

```typescript
export declare type AppSubLink = {
id: string;
title: string;
} & ({
path: string;
subLinks?: AppSubLink[];
} | {
path?: string;
subLinks: AppSubLink[];
});
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Defines the list of fields that can be updated via an [AppUpdater](./kibana-plug
<b>Signature:</b>

```typescript
export declare type AppUpdatableFields = Pick<App, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath'>;
export declare type AppUpdatableFields = Pick<App, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath' | 'subLinks'>;
```
2 changes: 2 additions & 0 deletions docs/development/core/public/kibana-plugin-core-public.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md) | A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return <code>confirm</code> to to prompt a message to the user before leaving the page, or <code>default</code> to keep the default behavior (doing nothing).<!-- -->See [AppMountParameters](./kibana-plugin-core-public.appmountparameters.md) for detailed usage examples. |
| [AppMount](./kibana-plugin-core-public.appmount.md) | A mount function called when the user navigates to this app's route. |
| [AppMountDeprecated](./kibana-plugin-core-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. |
| [AppSubLink](./kibana-plugin-core-public.appsublink.md) | Input type for registering secondary in-app locations for an application.<!-- -->Sublinks must include at least one of <code>path</code> or <code>subLinks</code>. A sublink that does not have a <code>path</code> represents a topological level in the application's hierarchy, but does not have a destination URL that is user-accessible.<!-- -->Used to populate navigational search results (where available). |
| [AppUnmount](./kibana-plugin-core-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. |
| [AppUpdatableFields](./kibana-plugin-core-public.appupdatablefields.md) | Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-core-public.appupdater.md)<!-- -->. |
| [AppUpdater](./kibana-plugin-core-public.appupdater.md) | Updater for applications. see [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) |
Expand All @@ -160,6 +161,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [PluginInitializer](./kibana-plugin-core-public.plugininitializer.md) | The <code>plugin</code> export at the root of a plugin's <code>public</code> directory should conform to this interface. |
| [PluginOpaqueId](./kibana-plugin-core-public.pluginopaqueid.md) | |
| [PublicAppInfo](./kibana-plugin-core-public.publicappinfo.md) | Public information about a registered [application](./kibana-plugin-core-public.app.md) |
| [PublicAppSubLinkInfo](./kibana-plugin-core-public.publicappsublinkinfo.md) | Public information about a registered app's [subLinks](./kibana-plugin-core-public.appsublink.md) |
| [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. |
| [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value |
| [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ Public information about a registered [application](./kibana-plugin-core-public.
<b>Signature:</b>

```typescript
export declare type PublicAppInfo = Omit<App, 'mount' | 'updater$'> & {
export declare type PublicAppInfo = Omit<App, 'mount' | 'updater$' | 'subLinks'> & {
status: AppStatus;
navLinkStatus: AppNavLinkStatus;
appRoute: string;
subLinks: PublicAppSubLinkInfo[];
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [PublicAppSubLinkInfo](./kibana-plugin-core-public.publicappsublinkinfo.md)

## PublicAppSubLinkInfo type

Public information about a registered app's [subLinks](./kibana-plugin-core-public.appsublink.md)

<b>Signature:</b>

```typescript
export declare type PublicAppSubLinkInfo = Omit<AppSubLink, 'subLinks'> & {
subLinks: PublicAppSubLinkInfo[];
};
```
2 changes: 2 additions & 0 deletions src/core/public/application/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export {
AppNavLinkStatus,
AppUpdatableFields,
AppUpdater,
AppSubLink,
ApplicationSetup,
ApplicationStart,
AppLeaveHandler,
Expand All @@ -40,6 +41,7 @@ export {
AppLeaveConfirmAction,
NavigateToAppOptions,
PublicAppInfo,
PublicAppSubLinkInfo,
// Internal types
InternalApplicationSetup,
InternalApplicationStart,
Expand Down
53 changes: 51 additions & 2 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export enum AppNavLinkStatus {
* Defines the list of fields that can be updated via an {@link AppUpdater}.
* @public
*/
export type AppUpdatableFields = Pick<App, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath'>;
export type AppUpdatableFields = Pick<
App,
'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath' | 'subLinks'
>;

/**
* Updater for applications.
Expand Down Expand Up @@ -232,18 +235,64 @@ export interface App<HistoryLocationState = unknown> {
* ```
*/
exactRoute?: boolean;

/**
* Array of links that represent secondary in-app locations for the given app.
*
* Can be updated using the {@link App.updater$} observable. See {@link AppSubLink} for more details.
*/
subLinks?: AppSubLink[];
}

/**
* Input type for registering secondary in-app locations for an application.
*
* Sublinks must include at least one of `path` or `subLinks`. A sublink that does not have a `path` represents a
* topological level in the application's hierarchy, but does not have a destination URL that is user-accessible.
*
* Used to populate navigational search results (where available).
* @public
*/
export type AppSubLink = {
/** Identifier to represent this sublink, should be unique for this application */
id: string;
/** Title to label represent this sublink */
title: string;
} & (
| {
/** URL path to access this link, relative to the application's appRoute. */
path: string;
/** Optional array of links that are 'underneath' this section in the hierarchy */
subLinks?: AppSubLink[];
}
| {
/** Optional path to access this section. Omit if this part of the hierarchy does not have a page URL. */
path?: string;
/** Array links that are 'underneath' this section in this hierarchy. */
subLinks: AppSubLink[];
}
);

/**
* Public information about a registered app's {@link AppSubLink | subLinks}
*
* @public
*/
export type PublicAppSubLinkInfo = Omit<AppSubLink, 'subLinks'> & {
subLinks: PublicAppSubLinkInfo[];
};

/**
* Public information about a registered {@link App | application}
*
* @public
*/
export type PublicAppInfo = Omit<App, 'mount' | 'updater$'> & {
export type PublicAppInfo = Omit<App, 'mount' | 'updater$' | 'subLinks'> & {
// remove optional on fields populated with default values
status: AppStatus;
navLinkStatus: AppNavLinkStatus;
appRoute: string;
subLinks: PublicAppSubLinkInfo[];
};

/**
Expand Down
36 changes: 36 additions & 0 deletions src/core/public/application/utils/get_app_info.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,42 @@ describe('getAppInfo', () => {
status: AppStatus.accessible,
navLinkStatus: AppNavLinkStatus.visible,
appRoute: `/app/some-id`,
subLinks: [],
});
});

it('populates default values for nested subLinks', () => {
const app = createApp({
subLinks: [
{
id: 'sub-id',
title: 'sub-title',
subLinks: [{ id: 'sub-sub-id', title: 'sub-sub-title', path: '/sub-sub' }],
},
],
});
const info = getAppInfo(app);

expect(info).toEqual({
id: 'some-id',
title: 'some-title',
status: AppStatus.accessible,
navLinkStatus: AppNavLinkStatus.visible,
appRoute: `/app/some-id`,
subLinks: [
{
id: 'sub-id',
title: 'sub-title',
subLinks: [
{
id: 'sub-sub-id',
title: 'sub-sub-title',
path: '/sub-sub',
subLinks: [], // default empty array added
},
],
},
],
});
});

Expand Down
27 changes: 25 additions & 2 deletions src/core/public/application/utils/get_app_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@
* under the License.
*/

import { App, AppNavLinkStatus, AppStatus, PublicAppInfo } from '../types';
import {
App,
AppNavLinkStatus,
AppStatus,
AppSubLink,
PublicAppInfo,
PublicAppSubLinkInfo,
} from '../types';

export function getAppInfo(app: App<unknown>): PublicAppInfo {
export function getAppInfo(app: App): PublicAppInfo {
const navLinkStatus =
app.navLinkStatus === AppNavLinkStatus.default
? app.status === AppStatus.inaccessible
Expand All @@ -32,5 +39,21 @@ export function getAppInfo(app: App<unknown>): PublicAppInfo {
status: app.status!,
navLinkStatus,
appRoute: app.appRoute!,
subLinks: getSubLinkInfos(app, app.subLinks),
};
}

function getSubLinkInfos(app: App, subLinks?: AppSubLink[]): PublicAppSubLinkInfo[] {
if (!subLinks) {
return [];
}

return subLinks.map((rawSubLink) => {
return {
id: rawSubLink.id,
title: rawSubLink.title,
path: rawSubLink.path,
subLinks: getSubLinkInfos(app, rawSubLink.subLinks),
};
});
}
1 change: 1 addition & 0 deletions src/core/public/chrome/nav_links/to_nav_link.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const app = (props: Partial<PublicAppInfo> = {}): PublicAppInfo => ({
status: AppStatus.accessible,
navLinkStatus: AppNavLinkStatus.default,
appRoute: `/app/some-id`,
subLinks: [],
...props,
});

Expand Down
4 changes: 3 additions & 1 deletion src/core/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export {
ApplicationSetup,
ApplicationStart,
App,
PublicAppInfo,
AppMount,
AppMountDeprecated,
AppUnmount,
Expand All @@ -110,6 +109,9 @@ export {
AppNavLinkStatus,
AppUpdatableFields,
AppUpdater,
AppSubLink,
PublicAppInfo,
PublicAppSubLinkInfo,
ScopedHistory,
NavigateToAppOptions,
} from './application';
Expand Down
23 changes: 21 additions & 2 deletions src/core/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export interface App<HistoryLocationState = unknown> {
navLinkStatus?: AppNavLinkStatus;
order?: number;
status?: AppStatus;
subLinks?: AppSubLink[];
title: string;
tooltip?: string;
updater$?: Observable<AppUpdater>;
Expand Down Expand Up @@ -181,11 +182,23 @@ export enum AppStatus {
inaccessible = 1
}

// @public
export type AppSubLink = {
id: string;
title: string;
} & ({
path: string;
subLinks?: AppSubLink[];
} | {
path?: string;
subLinks: AppSubLink[];
});

// @public
export type AppUnmount = () => void;

// @public
export type AppUpdatableFields = Pick<App, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath'>;
export type AppUpdatableFields = Pick<App, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath' | 'subLinks'>;

// @public
export type AppUpdater = (app: App) => Partial<AppUpdatableFields> | undefined;
Expand Down Expand Up @@ -967,10 +980,16 @@ export interface PluginInitializerContext<ConfigSchema extends object = object>
export type PluginOpaqueId = symbol;

// @public
export type PublicAppInfo = Omit<App, 'mount' | 'updater$'> & {
export type PublicAppInfo = Omit<App, 'mount' | 'updater$' | 'subLinks'> & {
status: AppStatus;
navLinkStatus: AppNavLinkStatus;
appRoute: string;
subLinks: PublicAppSubLinkInfo[];
};

// @public
export type PublicAppSubLinkInfo = Omit<AppSubLink, 'subLinks'> & {
subLinks: PublicAppSubLinkInfo[];
};

// @public
Expand Down
20 changes: 19 additions & 1 deletion src/plugins/management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import {
AppUpdater,
AppStatus,
AppNavLinkStatus,
AppSubLink,
} from '../../../core/public';

import { MANAGEMENT_APP_ID } from '../common/contants';
import {
ManagementSectionsService,
getSectionsServiceStartPrivate,
} from './management_sections_service';
import { ManagementSection } from './utils';

interface ManagementSetupDependencies {
home?: HomePublicPluginSetup;
Expand All @@ -46,7 +48,23 @@ interface ManagementSetupDependencies {
export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart> {
private readonly managementSections = new ManagementSectionsService();

private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => {
const subLinks: AppSubLink[] = Object.values(this.managementSections.definedSections).map(
(section: ManagementSection) => ({
id: section.id,
title: section.title,
subLinks: section.getAppsEnabled().map((mgmtApp) => ({
id: mgmtApp.id,
title: mgmtApp.title,
path: mgmtApp.basePath,
})),
})
);

return {
subLinks,
};
});

private hasAnyEnabledApps = true;

Expand Down
Loading