diff --git a/x-pack/plugins/observability/public/components/shared/page_template/README.md b/x-pack/plugins/observability/public/components/shared/page_template/README.md index fb2a603cc7a7..104b365e94fe 100644 --- a/x-pack/plugins/observability/public/components/shared/page_template/README.md +++ b/x-pack/plugins/observability/public/components/shared/page_template/README.md @@ -12,7 +12,42 @@ To register a solution's navigation structure you'll first need to ensure your s ], ``` -Now within your solution's **public** plugin `setup` lifecycle method you can call the `registerSections` method, this will register your solution's specific navigation structure with the overall Observability navigation registry. E.g. +Now within your solution's **public** plugin `setup` lifecycle method you can +call the `registerSections` method, this will register your solution's specific +navigation structure with the overall Observability navigation registry. + +The `registerSections` function takes an `Observable` of an array of +`NavigationSection`s. Each section can be defined as + +```typescript +export interface NavigationSection { + // the label of the section, should be translated + label: string | undefined; + // the key to sort by in ascending order relative to other entries + sortKey: number; + // the entries to render inside the section + entries: NavigationEntry[]; +} +``` + +Each entry inside of a navigation section is defined as + +```typescript +export interface NavigationEntry { + // the label of the menu entry, should be translated + label: string; + // the kibana app id + app: string; + // the path after the application prefix corresponding to this entry + path: string; + // whether to only match when the full path matches, defaults to `false` + matchFullPath?: boolean; + // whether to ignore trailing slashes, defaults to `true` + ignoreTrailingSlash?: boolean; +} +``` + +A registration might therefore look like the following: ```typescript // x-pack/plugins/example_plugin/public/plugin.ts @@ -29,6 +64,7 @@ export class Plugin implements PluginClass { label: 'A solution section', sortKey: 200, entries: [ + { label: 'Home Page', app: 'exampleA', path: '/', matchFullPath: true }, { label: 'Example Page', app: 'exampleA', path: '/example' }, { label: 'Another Example Page', app: 'exampleA', path: '/another-example' }, ], diff --git a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx index 8025c6d65869..bebcd53f8ae6 100644 --- a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx +++ b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx @@ -71,6 +71,8 @@ export function ObservabilityPageTemplate({ entry.app === currentAppId && matchPath(currentPath, { path: entry.path, + exact: !!entry.matchFullPath, + strict: !entry.ignoreTrailingSlash, }) != null; return { diff --git a/x-pack/plugins/observability/public/services/navigation_registry.ts b/x-pack/plugins/observability/public/services/navigation_registry.ts index f42f34fcfe9b..79a36731f7ed 100644 --- a/x-pack/plugins/observability/public/services/navigation_registry.ts +++ b/x-pack/plugins/observability/public/services/navigation_registry.ts @@ -9,15 +9,25 @@ import { combineLatest, Observable, ReplaySubject } from 'rxjs'; import { map, scan, shareReplay, switchMap } from 'rxjs/operators'; export interface NavigationSection { + // the label of the section, should be translated label: string | undefined; + // the key to sort by in ascending order relative to other entries sortKey: number; + // the entries to render inside the section entries: NavigationEntry[]; } export interface NavigationEntry { + // the label of the menu entry, should be translated label: string; + // the kibana app id app: string; + // the path after the application prefix corresponding to this entry path: string; + // whether to only match when the full path matches, defaults to `false` + matchFullPath?: boolean; + // whether to ignore trailing slashes, defaults to `true` + ignoreTrailingSlash?: boolean; } export interface NavigationRegistry {