diff --git a/docs/development/core/public/kibana-plugin-public.appbase.category.md b/docs/development/core/public/kibana-plugin-public.appbase.category.md
new file mode 100644
index 0000000000000..215ebbbd0e186
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appbase.category.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [category](./kibana-plugin-public.appbase.category.md)
+
+## AppBase.category property
+
+The category definition of the product See [AppCategory](./kibana-plugin-public.appcategory.md) See DEFAULT\_APP\_CATEGORIES for more reference
+
+Signature:
+
+```typescript
+category?: AppCategory;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.md b/docs/development/core/public/kibana-plugin-public.appbase.md
index eb6d91cb92488..6f547450b6a12 100644
--- a/docs/development/core/public/kibana-plugin-public.appbase.md
+++ b/docs/development/core/public/kibana-plugin-public.appbase.md
@@ -16,6 +16,7 @@ export interface AppBase
| Property | Type | Description |
| --- | --- | --- |
| [capabilities](./kibana-plugin-public.appbase.capabilities.md) | Partial<Capabilities>
| Custom capabilities defined by the app. |
+| [category](./kibana-plugin-public.appbase.category.md) | AppCategory
| The category definition of the product See [AppCategory](./kibana-plugin-public.appcategory.md) See DEFAULT\_APP\_CATEGORIES for more reference |
| [chromeless](./kibana-plugin-public.appbase.chromeless.md) | boolean
| Hide the UI chrome when the application is mounted. Defaults to false
. Takes precedence over chrome service visibility settings. |
| [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) | string
| A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon
property. |
| [icon](./kibana-plugin-public.appbase.icon.md) | string
| A URL to an image file used as an icon. Used as a fallback if euiIconType
is not provided. |
diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md b/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md
new file mode 100644
index 0000000000000..0245b548ae74f
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [ariaLabel](./kibana-plugin-public.appcategory.arialabel.md)
+
+## AppCategory.ariaLabel property
+
+If the visual label isn't appropriate for screen readers, can override it here
+
+Signature:
+
+```typescript
+ariaLabel?: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md b/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md
new file mode 100644
index 0000000000000..90133735a0082
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [euiIconType](./kibana-plugin-public.appcategory.euiicontype.md)
+
+## AppCategory.euiIconType property
+
+Define an icon to be used for the category If the category is only 1 item, and no icon is defined, will default to the product icon Defaults to initials if no icon is defined
+
+Signature:
+
+```typescript
+euiIconType?: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.label.md b/docs/development/core/public/kibana-plugin-public.appcategory.label.md
new file mode 100644
index 0000000000000..171b1627f9ef8
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appcategory.label.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [label](./kibana-plugin-public.appcategory.label.md)
+
+## AppCategory.label property
+
+Label used for cateogry name. Also used as aria-label if one isn't set.
+
+Signature:
+
+```typescript
+label: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.md b/docs/development/core/public/kibana-plugin-public.appcategory.md
new file mode 100644
index 0000000000000..f1085e7325272
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appcategory.md
@@ -0,0 +1,23 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md)
+
+## AppCategory interface
+
+A category definition for nav links to know where to sort them in the left hand nav
+
+Signature:
+
+```typescript
+export interface AppCategory
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [ariaLabel](./kibana-plugin-public.appcategory.arialabel.md) | string
| If the visual label isn't appropriate for screen readers, can override it here |
+| [euiIconType](./kibana-plugin-public.appcategory.euiicontype.md) | string
| Define an icon to be used for the category If the category is only 1 item, and no icon is defined, will default to the product icon Defaults to initials if no icon is defined |
+| [label](./kibana-plugin-public.appcategory.label.md) | string
| Label used for cateogry name. Also used as aria-label if one isn't set. |
+| [order](./kibana-plugin-public.appcategory.order.md) | number
| The order that categories will be sorted in Prefer large steps between categories to allow for further editing (Default categories are in steps of 1000) |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.order.md b/docs/development/core/public/kibana-plugin-public.appcategory.order.md
new file mode 100644
index 0000000000000..ef17ac04b78d6
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appcategory.order.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [order](./kibana-plugin-public.appcategory.order.md)
+
+## AppCategory.order property
+
+The order that categories will be sorted in Prefer large steps between categories to allow for further editing (Default categories are in steps of 1000)
+
+Signature:
+
+```typescript
+order?: number;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md
new file mode 100644
index 0000000000000..19d5a43a29307
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [category](./kibana-plugin-public.chromenavlink.category.md)
+
+## ChromeNavLink.category property
+
+The category the app lives in
+
+Signature:
+
+```typescript
+readonly category?: AppCategory;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.md
index 4cb9080222ac5..2afd6ce2d58c4 100644
--- a/docs/development/core/public/kibana-plugin-public.chromenavlink.md
+++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.md
@@ -17,6 +17,7 @@ export interface ChromeNavLink
| --- | --- | --- |
| [active](./kibana-plugin-public.chromenavlink.active.md) | boolean
| Indicates whether or not this app is currently on the screen. |
| [baseUrl](./kibana-plugin-public.chromenavlink.baseurl.md) | string
| The base route used to open the root of an application. |
+| [category](./kibana-plugin-public.chromenavlink.category.md) | AppCategory
| The category the app lives in |
| [disabled](./kibana-plugin-public.chromenavlink.disabled.md) | boolean
| Disables a link from being clickable. |
| [euiIconType](./kibana-plugin-public.chromenavlink.euiicontype.md) | string
| A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon
property. |
| [hidden](./kibana-plugin-public.chromenavlink.hidden.md) | boolean
| Hides a link from the navigation. |
diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md
new file mode 100644
index 0000000000000..7026e9b519cc0
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [category](./kibana-plugin-public.legacynavlink.category.md)
+
+## LegacyNavLink.category property
+
+Signature:
+
+```typescript
+category?: AppCategory;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.md
index fc0c445f517b3..e112110dd10f8 100644
--- a/docs/development/core/public/kibana-plugin-public.legacynavlink.md
+++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.md
@@ -15,6 +15,7 @@ export interface LegacyNavLink
| Property | Type | Description |
| --- | --- | --- |
+| [category](./kibana-plugin-public.legacynavlink.category.md) | AppCategory
| |
| [euiIconType](./kibana-plugin-public.legacynavlink.euiicontype.md) | string
| |
| [icon](./kibana-plugin-public.legacynavlink.icon.md) | string
| |
| [id](./kibana-plugin-public.legacynavlink.id.md) | string
| |
diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md
index 27037d46926c1..52aca7501e64d 100644
--- a/docs/development/core/public/kibana-plugin-public.md
+++ b/docs/development/core/public/kibana-plugin-public.md
@@ -32,6 +32,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| --- | --- |
| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. |
| [AppBase](./kibana-plugin-public.appbase.md) | |
+| [AppCategory](./kibana-plugin-public.appcategory.md) | A category definition for nav links to know where to sort them in the left hand nav |
| [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application.See |
| [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application.See |
| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | |
diff --git a/packages/kbn-i18n/src/loader.ts b/packages/kbn-i18n/src/loader.ts
index 2d68079735c03..21f540f588f46 100644
--- a/packages/kbn-i18n/src/loader.ts
+++ b/packages/kbn-i18n/src/loader.ts
@@ -17,15 +17,13 @@
* under the License.
*/
-import { readFile } from 'fs';
+import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';
import { unique } from './core/helper';
import { Translation } from './translation';
-const asyncReadFile = promisify(readFile);
-
const TRANSLATION_FILE_EXTENSION = '.json';
/**
@@ -69,7 +67,8 @@ function getLocaleFromFileName(fullFileName: string) {
* @returns
*/
async function loadFile(pathToFile: string): Promise {
- return JSON.parse(await asyncReadFile(pathToFile, 'utf8'));
+ // doing this at the moment because fs is mocked in a lot of places where this would otherwise fail
+ return JSON.parse(await promisify(fs.readFile)(pathToFile, 'utf8'));
}
/**
diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts
index 0d955482d2226..63e542b0127ed 100644
--- a/src/core/public/application/types.ts
+++ b/src/core/public/application/types.ts
@@ -31,6 +31,7 @@ import { PluginOpaqueId } from '../plugins';
import { IUiSettingsClient } from '../ui_settings';
import { RecursiveReadonly } from '../../utils';
import { SavedObjectsStart } from '../saved_objects';
+import { AppCategory } from '../../types';
/** @public */
export interface AppBase {
@@ -44,6 +45,13 @@ export interface AppBase {
*/
title: string;
+ /**
+ * The category definition of the product
+ * See {@link AppCategory}
+ * See DEFAULT_APP_CATEGORIES for more reference
+ */
+ category?: AppCategory;
+
/**
* The initial status of the application.
* Defaulting to `accessible`
diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts
index abd04722a49f2..9018b21973634 100644
--- a/src/core/public/chrome/chrome_service.test.ts
+++ b/src/core/public/chrome/chrome_service.test.ts
@@ -29,6 +29,7 @@ import { notificationServiceMock } from '../notifications/notifications_service.
import { docLinksServiceMock } from '../doc_links/doc_links_service.mock';
import { ChromeService } from './chrome_service';
import { App } from '../application';
+import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock';
class FakeApp implements App {
public title = `${this.id} App`;
@@ -51,6 +52,7 @@ function defaultStartDeps(availableApps?: App[]) {
http: httpServiceMock.createStartContract(),
injectedMetadata: injectedMetadataServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
+ uiSettings: uiSettingsServiceMock.createStartContract(),
};
if (availableApps) {
diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx
index 09ea1afe35766..6ab9fe158742a 100644
--- a/src/core/public/chrome/chrome_service.tsx
+++ b/src/core/public/chrome/chrome_service.tsx
@@ -38,7 +38,7 @@ import { LoadingIndicator, HeaderWrapper as Header } from './ui';
import { DocLinksStart } from '../doc_links';
import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu';
import { KIBANA_ASK_ELASTIC_LINK } from './constants';
-
+import { IUiSettingsClient } from '../ui_settings';
export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle };
const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed';
@@ -85,6 +85,7 @@ interface StartDeps {
http: HttpStart;
injectedMetadata: InjectedMetadataStart;
notifications: NotificationsStart;
+ uiSettings: IUiSettingsClient;
}
/** @internal */
@@ -139,6 +140,7 @@ export class ChromeService {
http,
injectedMetadata,
notifications,
+ uiSettings,
}: StartDeps): Promise {
this.initVisibility(application);
@@ -173,7 +175,6 @@ export class ChromeService {
getHeaderComponent: () => (
-
),
diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts
index 3b16c030ddcc9..4d3a1e9ecd199 100644
--- a/src/core/public/chrome/nav_links/nav_link.ts
+++ b/src/core/public/chrome/nav_links/nav_link.ts
@@ -18,6 +18,7 @@
*/
import { pick } from '../../../utils';
+import { AppCategory } from '../../';
/**
* @public
@@ -33,6 +34,11 @@ export interface ChromeNavLink {
*/
readonly title: string;
+ /**
+ * The category the app lives in
+ */
+ readonly category?: AppCategory;
+
/**
* The base route used to open the root of an application.
*/
diff --git a/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap
new file mode 100644
index 0000000000000..0ebc44ba67862
--- /dev/null
+++ b/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap
@@ -0,0 +1,5224 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NavDrawer Advanced setting set to grouped renders grouped items 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`NavDrawer Advanced setting set to grouped renders individual items if there are less than 7 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`NavDrawer Advanced setting set to grouped renders individual items if there is only 1 category 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`NavDrawer Advanced setting set to individual renders individual items 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index d05a6bb53405c..c3cefd180b16f 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -17,141 +17,40 @@
* under the License.
*/
-import Url from 'url';
-
-import React, { Component, createRef } from 'react';
-import * as Rx from 'rxjs';
-
import {
- // TODO: add type annotations
EuiHeader,
- EuiHeaderLogo,
EuiHeaderSection,
EuiHeaderSectionItem,
EuiHeaderSectionItemButton,
- EuiHorizontalRule,
EuiIcon,
- EuiImage,
// @ts-ignore
EuiNavDrawer,
// @ts-ignore
- EuiNavDrawerGroup,
- // @ts-ignore
EuiShowFor,
} from '@elastic/eui';
-
import { i18n } from '@kbn/i18n';
-import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
-
-import { HeaderBadge } from './header_badge';
-import { HeaderBreadcrumbs } from './header_breadcrumbs';
-import { HeaderHelpMenu } from './header_help_menu';
-import { HeaderNavControls } from './header_nav_controls';
-
+import React, { Component, createRef } from 'react';
+import * as Rx from 'rxjs';
import {
ChromeBadge,
ChromeBreadcrumb,
+ ChromeNavControl,
ChromeNavLink,
ChromeRecentlyAccessedHistoryItem,
- ChromeNavControl,
} from '../..';
+import { InternalApplicationStart } from '../../../application/types';
import { HttpStart } from '../../../http';
import { ChromeHelpExtension } from '../../chrome_service';
-import { InternalApplicationStart } from '../../../application/types';
-
-// Providing a buffer between the limit and the cut off index
-// protects from truncating just the last couple (6) characters
-const TRUNCATE_LIMIT: number = 64;
-const TRUNCATE_AT: number = 58;
-
-/**
- *
- * @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
- * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get
- * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that
- * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart".
- * @return {string} the relative url transformed into an absolute url
- */
-function relativeToAbsolute(url: string) {
- // convert all link urls to absolute urls
- const a = document.createElement('a');
- a.setAttribute('href', url);
- return a.href;
-}
-
-function extendRecentlyAccessedHistoryItem(
- navLinks: ChromeNavLink[],
- recentlyAccessed: ChromeRecentlyAccessedHistoryItem,
- basePath: HttpStart['basePath']
-) {
- const href = relativeToAbsolute(basePath.prepend(recentlyAccessed.link));
- const navLink = navLinks.find(nl => href.startsWith(nl.subUrlBase || nl.baseUrl));
-
- let titleAndAriaLabel = recentlyAccessed.label;
- if (navLink) {
- const objectTypeForAriaAppendix = navLink.title;
- titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', {
- defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}',
- values: {
- recentlyAccessedItemLinklabel: recentlyAccessed.label,
- pageType: objectTypeForAriaAppendix,
- },
- });
- }
-
- return {
- ...recentlyAccessed,
- href,
- euiIconType: navLink ? navLink.euiIconType : undefined,
- title: titleAndAriaLabel,
- };
-}
-
-function extendNavLink(navLink: ChromeNavLink) {
- if (navLink.legacy) {
- return {
- ...navLink,
- href: navLink.url && !navLink.active ? navLink.url : navLink.baseUrl,
- };
- }
-
- return {
- ...navLink,
- href: navLink.baseUrl,
- };
-}
-
-function isModifiedEvent(event: MouseEvent) {
- return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
-}
-
-function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void {
- let current = element;
- while (current) {
- if (current.tagName === 'A') {
- return current as HTMLAnchorElement;
- }
-
- if (!current.parentElement || current.parentElement === document.body) {
- return undefined;
- }
-
- current = current.parentElement;
- }
-}
-
-function truncateRecentItemLabel(label: string): string {
- if (label.length > TRUNCATE_LIMIT) {
- label = `${label.substring(0, TRUNCATE_AT)}…`;
- }
-
- return label;
-}
-
-export type HeaderProps = Pick>;
+import { HeaderBadge } from './header_badge';
+import { NavSetting, OnIsLockedUpdate } from './';
+import { HeaderBreadcrumbs } from './header_breadcrumbs';
+import { HeaderHelpMenu } from './header_help_menu';
+import { HeaderNavControls } from './header_nav_controls';
+import { euiNavLink } from './nav_link';
+import { HeaderLogo } from './header_logo';
+import { NavDrawer } from './nav_drawer';
-interface Props {
+export interface HeaderProps {
kibanaVersion: string;
application: InternalApplicationStart;
appTitle$: Rx.Observable;
@@ -168,28 +67,29 @@ interface Props {
legacyMode: boolean;
navControlsLeft$: Rx.Observable;
navControlsRight$: Rx.Observable;
- intl: InjectedIntl;
basePath: HttpStart['basePath'];
isLocked?: boolean;
- onIsLockedUpdate?: (isLocked: boolean) => void;
+ navSetting$: Rx.Observable;
+ onIsLockedUpdate?: OnIsLockedUpdate;
}
interface State {
appTitle: string;
- currentAppId?: string;
isVisible: boolean;
- navLinks: ReadonlyArray>;
- recentlyAccessed: ReadonlyArray>;
+ navLinks: ChromeNavLink[];
+ recentlyAccessed: ChromeRecentlyAccessedHistoryItem[];
forceNavigation: boolean;
navControlsLeft: readonly ChromeNavControl[];
navControlsRight: readonly ChromeNavControl[];
+ navSetting: NavSetting;
+ currentAppId: string | undefined;
}
-class HeaderUI extends Component {
+export class Header extends Component {
private subscription?: Rx.Subscription;
private navDrawerRef = createRef();
- constructor(props: Props) {
+ constructor(props: HeaderProps) {
super(props);
this.state = {
@@ -200,6 +100,8 @@ class HeaderUI extends Component {
forceNavigation: false,
navControlsLeft: [],
navControlsRight: [],
+ navSetting: 'grouped',
+ currentAppId: '',
};
}
@@ -214,7 +116,8 @@ class HeaderUI extends Component {
Rx.combineLatest(
this.props.navControlsLeft$,
this.props.navControlsRight$,
- this.props.application.currentAppId$
+ this.props.application.currentAppId$,
+ this.props.navSetting$
)
).subscribe({
next: ([
@@ -223,18 +126,17 @@ class HeaderUI extends Component {
forceNavigation,
navLinks,
recentlyAccessed,
- [navControlsLeft, navControlsRight, currentAppId],
+ [navControlsLeft, navControlsRight, currentAppId, navSetting],
]) => {
this.setState({
appTitle,
isVisible,
forceNavigation,
- navLinks: navLinks.map(extendNavLink),
- recentlyAccessed: recentlyAccessed.map(ra =>
- extendRecentlyAccessedHistoryItem(navLinks, ra, this.props.basePath)
- ),
+ navLinks: navLinks.filter(navLink => !navLink.hidden),
+ recentlyAccessed,
navControlsLeft,
navControlsRight,
+ navSetting,
currentAppId,
});
},
@@ -247,26 +149,12 @@ class HeaderUI extends Component {
}
}
- public renderLogo() {
- const { homeHref, intl } = this.props;
- return (
-
- );
- }
-
public renderMenuTrigger() {
return (
this.navDrawerRef.current.toggleOpen()}
>
@@ -275,98 +163,29 @@ class HeaderUI extends Component {
}
public render() {
+ const { appTitle, isVisible, navControlsLeft, navControlsRight } = this.state;
const {
- application,
badge$,
- basePath,
breadcrumbs$,
helpExtension$,
helpSupportUrl$,
- intl,
- isLocked,
kibanaDocLink,
kibanaVersion,
- onIsLockedUpdate,
- legacyMode,
} = this.props;
- const {
- appTitle,
- currentAppId,
- isVisible,
- navControlsLeft,
- navControlsRight,
- navLinks,
- recentlyAccessed,
- } = this.state;
+ const navLinks = this.state.navLinks.map(link =>
+ euiNavLink(
+ link,
+ this.props.legacyMode,
+ this.state.currentAppId,
+ this.props.basePath,
+ this.props.application.navigateToApp
+ )
+ );
if (!isVisible) {
return null;
}
- const navLinksArray = navLinks
- .filter(navLink => !navLink.hidden)
- .map(navLink => ({
- key: navLink.id,
- label: navLink.tooltip ?? navLink.title,
-
- // Use href and onClick to support "open in new tab" and SPA navigation in the same link
- href: navLink.href,
- onClick: (event: MouseEvent) => {
- if (
- !legacyMode && // ignore when in legacy mode
- !navLink.legacy && // ignore links to legacy apps
- !event.defaultPrevented && // onClick prevented default
- event.button === 0 && // ignore everything but left clicks
- !isModifiedEvent(event) // ignore clicks with modifier keys
- ) {
- event.preventDefault();
- application.navigateToApp(navLink.id);
- }
- },
-
- // Legacy apps use `active` property, NP apps should match the current app
- isActive: navLink.active || currentAppId === navLink.id,
- isDisabled: navLink.disabled,
-
- iconType: navLink.euiIconType,
- icon:
- !navLink.euiIconType && navLink.icon ? (
-
- ) : (
- undefined
- ),
- 'data-test-subj': 'navDrawerAppsMenuLink',
- }));
-
- const recentLinksArray = [
- {
- label: intl.formatMessage({
- id: 'core.ui.chrome.sideGlobalNav.viewRecentItemsLabel',
- defaultMessage: 'Recently viewed',
- }),
- iconType: 'clock',
- isDisabled: recentlyAccessed.length > 0 ? false : true,
- flyoutMenu: {
- title: intl.formatMessage({
- id: 'core.ui.chrome.sideGlobalNav.viewRecentItemsFlyoutTitle',
- defaultMessage: 'Recent items',
- }),
- listItems: recentlyAccessed.map(item => ({
- label: truncateRecentItemLabel(item.label),
- title: item.title,
- 'aria-label': item.title,
- href: item.href,
- iconType: item.euiIconType,
- })),
- },
- },
- ];
-
return (
@@ -375,7 +194,13 @@ class HeaderUI extends Component {
{this.renderMenuTrigger()}
- {this.renderLogo()}
+
+
+
@@ -399,75 +224,17 @@ class HeaderUI extends Component {
-
-
-
-
-
-
+ />
);
}
-
- private onNavClick = (event: React.MouseEvent) => {
- const anchor = findClosestAnchor((event as any).nativeEvent.target);
- if (!anchor) {
- return;
- }
-
- const navLink = this.state.navLinks.find(item => item.href === anchor.href);
- if (navLink && navLink.disabled) {
- event.preventDefault();
- return;
- }
-
- if (
- !this.state.forceNavigation ||
- event.isDefaultPrevented() ||
- event.altKey ||
- event.metaKey ||
- event.ctrlKey
- ) {
- return;
- }
-
- const toParsed = Url.parse(anchor.href);
- const fromParsed = Url.parse(document.location.href);
- const sameProto = toParsed.protocol === fromParsed.protocol;
- const sameHost = toParsed.host === fromParsed.host;
- const samePath = toParsed.path === fromParsed.path;
-
- if (sameProto && sameHost && samePath) {
- if (toParsed.hash) {
- document.location.reload();
- }
-
- // event.preventDefault() keeps the browser from seeing the new url as an update
- // and even setting window.location does not mimic that behavior, so instead
- // we use stopPropagation() to prevent angular from seeing the click and
- // starting a digest cycle/attempting to handle it in the router.
- event.stopPropagation();
- }
- };
}
-
-export const Header = injectI18n(HeaderUI);
diff --git a/src/core/public/chrome/ui/header/header_logo.tsx b/src/core/public/chrome/ui/header/header_logo.tsx
new file mode 100644
index 0000000000000..793b8646dabf7
--- /dev/null
+++ b/src/core/public/chrome/ui/header/header_logo.tsx
@@ -0,0 +1,104 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Url from 'url';
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiHeaderLogo } from '@elastic/eui';
+import { NavLink } from './nav_link';
+
+function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void {
+ let current = element;
+ while (current) {
+ if (current.tagName === 'A') {
+ return current as HTMLAnchorElement;
+ }
+
+ if (!current.parentElement || current.parentElement === document.body) {
+ return undefined;
+ }
+
+ current = current.parentElement;
+ }
+}
+
+function onClick(
+ event: React.MouseEvent,
+ forceNavigation: boolean,
+ navLinks: NavLink[]
+) {
+ const anchor = findClosestAnchor((event as any).nativeEvent.target);
+ if (!anchor) {
+ return;
+ }
+
+ const navLink = navLinks.find(item => item.href === anchor.href);
+ if (navLink && navLink.isDisabled) {
+ event.preventDefault();
+ return;
+ }
+
+ if (
+ !forceNavigation ||
+ event.isDefaultPrevented() ||
+ event.altKey ||
+ event.metaKey ||
+ event.ctrlKey
+ ) {
+ return;
+ }
+
+ const toParsed = Url.parse(anchor.href);
+ const fromParsed = Url.parse(document.location.href);
+ const sameProto = toParsed.protocol === fromParsed.protocol;
+ const sameHost = toParsed.host === fromParsed.host;
+ const samePath = toParsed.path === fromParsed.path;
+
+ if (sameProto && sameHost && samePath) {
+ if (toParsed.hash) {
+ document.location.reload();
+ }
+
+ // event.preventDefault() keeps the browser from seeing the new url as an update
+ // and even setting window.location does not mimic that behavior, so instead
+ // we use stopPropagation() to prevent angular from seeing the click and
+ // starting a digest cycle/attempting to handle it in the router.
+ event.stopPropagation();
+ }
+}
+
+interface Props {
+ href: string;
+ navLinks: NavLink[];
+ forceNavigation: boolean;
+}
+
+export function HeaderLogo({ href, forceNavigation, navLinks }: Props) {
+ return (
+ onClick(e, forceNavigation, navLinks)}
+ href={href}
+ aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel', {
+ defaultMessage: 'Go to home page',
+ })}
+ />
+ );
+}
diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts
index 6d59fc6d9433b..b396c94b3f2a3 100644
--- a/src/core/public/chrome/ui/header/index.ts
+++ b/src/core/public/chrome/ui/header/index.ts
@@ -26,3 +26,5 @@ export {
ChromeHelpExtensionMenuDocumentationLink,
ChromeHelpExtensionMenuGitHubLink,
} from './header_help_menu';
+export type NavSetting = 'grouped' | 'individual';
+export type OnIsLockedUpdate = (isLocked: boolean) => void;
diff --git a/src/core/public/chrome/ui/header/nav_drawer.test.tsx b/src/core/public/chrome/ui/header/nav_drawer.test.tsx
new file mode 100644
index 0000000000000..7272935b93a52
--- /dev/null
+++ b/src/core/public/chrome/ui/header/nav_drawer.test.tsx
@@ -0,0 +1,103 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { cloneDeep } from 'lodash';
+import { mount } from 'enzyme';
+import React from 'react';
+import { NavSetting } from './';
+import { ChromeNavLink } from '../../../';
+import { AppCategory } from 'src/core/types';
+import { DEFAULT_APP_CATEGORIES } from '../../../../utils';
+import { NavDrawer } from './nav_drawer';
+import { euiNavLink } from './nav_link';
+
+const { analyze, management, observability, security } = DEFAULT_APP_CATEGORIES;
+const mockIBasePath = {
+ get: () => '/app',
+ prepend: () => '/app',
+ remove: () => '/app',
+};
+
+const getMockProps = (chromeNavLinks: ChromeNavLink[], navSetting: NavSetting = 'grouped') => ({
+ navSetting,
+ navLinks: chromeNavLinks.map(link =>
+ euiNavLink(link, true, undefined, mockIBasePath, () => Promise.resolve())
+ ),
+ chromeNavLinks,
+ recentlyAccessedItems: [],
+ basePath: mockIBasePath,
+});
+
+const makeLink = (id: string, order: number, category?: AppCategory) => ({
+ id,
+ category,
+ order,
+ title: id,
+ baseUrl: `http://localhost:5601/app/${id}`,
+ legacy: true,
+});
+
+const getMockChromeNavLink = () =>
+ cloneDeep([
+ makeLink('discover', 100, analyze),
+ makeLink('siem', 500, security),
+ makeLink('metrics', 600, observability),
+ makeLink('monitoring', 800, management),
+ makeLink('visualize', 200, analyze),
+ makeLink('dashboard', 300, analyze),
+ makeLink('canvas', 400, { label: 'customCategory' }),
+ makeLink('logs', 700, observability),
+ ]);
+
+describe('NavDrawer', () => {
+ describe('Advanced setting set to individual', () => {
+ it('renders individual items', () => {
+ const component = mount(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+ });
+ describe('Advanced setting set to grouped', () => {
+ it('renders individual items if there are less than 7', () => {
+ const links = getMockChromeNavLink().slice(0, 5);
+ const component = mount();
+ expect(component).toMatchSnapshot();
+ });
+ it('renders individual items if there is only 1 category', () => {
+ // management doesn't count as a category
+ const navLinks = [
+ makeLink('discover', 100, analyze),
+ makeLink('siem', 500, analyze),
+ makeLink('metrics', 600, analyze),
+ makeLink('monitoring', 800, analyze),
+ makeLink('visualize', 200, analyze),
+ makeLink('dashboard', 300, management),
+ makeLink('canvas', 400, management),
+ makeLink('logs', 700, management),
+ ];
+ const component = mount();
+ expect(component).toMatchSnapshot();
+ });
+ it('renders grouped items', () => {
+ const component = mount();
+ expect(component).toMatchSnapshot();
+ });
+ });
+});
diff --git a/src/core/public/chrome/ui/header/nav_drawer.tsx b/src/core/public/chrome/ui/header/nav_drawer.tsx
new file mode 100644
index 0000000000000..dbb68d5dd3901
--- /dev/null
+++ b/src/core/public/chrome/ui/header/nav_drawer.tsx
@@ -0,0 +1,170 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { groupBy, sortBy } from 'lodash';
+import { i18n } from '@kbn/i18n';
+// @ts-ignore
+import { EuiNavDrawer, EuiHorizontalRule, EuiNavDrawerGroup } from '@elastic/eui';
+import { NavSetting, OnIsLockedUpdate } from './';
+import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..';
+import { AppCategory } from '../../../../types';
+import { HttpStart } from '../../../http';
+import { NavLink } from './nav_link';
+import { RecentLinks } from './recent_links';
+
+function getAllCategories(allCategorizedLinks: Record) {
+ const allCategories = {} as Record;
+
+ for (const [key, value] of Object.entries(allCategorizedLinks)) {
+ allCategories[key] = value[0].category;
+ }
+
+ return allCategories;
+}
+
+function getOrderedCategories(
+ mainCategories: Record,
+ categoryDictionary: ReturnType
+) {
+ return sortBy(
+ Object.keys(mainCategories),
+ categoryName => categoryDictionary[categoryName]?.order
+ );
+}
+
+export interface Props {
+ navSetting: NavSetting;
+ isLocked?: boolean;
+ onIsLockedUpdate?: OnIsLockedUpdate;
+ navLinks: NavLink[];
+ chromeNavLinks: ChromeNavLink[];
+ recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[];
+ basePath: HttpStart['basePath'];
+}
+
+function navDrawerRenderer(
+ {
+ navSetting,
+ isLocked,
+ onIsLockedUpdate,
+ navLinks,
+ chromeNavLinks,
+ recentlyAccessedItems,
+ basePath,
+ }: Props,
+ ref: React.Ref
+) {
+ const disableGroupedNavSetting = navSetting === 'individual';
+ const groupedNavLinks = groupBy(navLinks, link => link?.category?.label);
+ const { undefined: unknowns, ...allCategorizedLinks } = groupedNavLinks;
+ const { Management: management, ...mainCategories } = allCategorizedLinks;
+ const categoryDictionary = getAllCategories(allCategorizedLinks);
+ const orderedCategories = getOrderedCategories(mainCategories, categoryDictionary);
+ const showUngroupedNav =
+ disableGroupedNavSetting || navLinks.length < 7 || Object.keys(mainCategories).length === 1;
+
+ return (
+
+ {RecentLinks({
+ recentlyAccessedItems,
+ navLinks: chromeNavLinks,
+ basePath,
+ })}
+
+ {showUngroupedNav ? (
+
+ ) : (
+ <>
+ {
+ const category = categoryDictionary[categoryName]!;
+ const links = mainCategories[categoryName];
+
+ if (links.length === 1) {
+ return {
+ ...links[0],
+ label: category.label,
+ iconType: category.euiIconType || links[0].iconType,
+ };
+ }
+
+ return {
+ 'data-test-subj': 'navDrawerCategory',
+ iconType: category.euiIconType,
+ label: category.label,
+ flyoutMenu: {
+ title: category.label,
+ listItems: sortBy(links, 'order').map(link => {
+ link['data-test-subj'] = 'navDrawerFlyoutLink';
+ return link;
+ }),
+ },
+ };
+ }),
+ ...sortBy(unknowns, 'order'),
+ ]}
+ />
+
+ {
+ link['data-test-subj'] = 'navDrawerFlyoutLink';
+ return link;
+ }),
+ },
+ },
+ ]}
+ />
+ >
+ )}
+
+ );
+}
+
+export const NavDrawer = React.forwardRef(navDrawerRenderer);
diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx
new file mode 100644
index 0000000000000..52b59c53b658c
--- /dev/null
+++ b/src/core/public/chrome/ui/header/nav_link.tsx
@@ -0,0 +1,87 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { EuiImage } from '@elastic/eui';
+import { ChromeNavLink, CoreStart } from '../../../';
+import { HttpStart } from '../../../http';
+
+function isModifiedEvent(event: MouseEvent) {
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
+}
+
+function LinkIcon({ url }: { url: string }) {
+ return ;
+}
+
+export type NavLink = ReturnType;
+
+export function euiNavLink(
+ navLink: ChromeNavLink,
+ legacyMode: boolean,
+ currentAppId: string | undefined,
+ basePath: HttpStart['basePath'],
+ navigateToApp: CoreStart['application']['navigateToApp']
+) {
+ const {
+ legacy,
+ url,
+ active,
+ baseUrl,
+ id,
+ title,
+ disabled,
+ euiIconType,
+ icon,
+ category,
+ order,
+ tooltip,
+ } = navLink;
+ let href = navLink.baseUrl;
+
+ if (legacy) {
+ href = url && !active ? url : baseUrl;
+ }
+
+ return {
+ category,
+ key: id,
+ label: tooltip ?? title,
+ href, // Use href and onClick to support "open in new tab" and SPA navigation in the same link
+ onClick(event: MouseEvent) {
+ if (
+ !legacyMode && // ignore when in legacy mode
+ !legacy && // ignore links to legacy apps
+ !event.defaultPrevented && // onClick prevented default
+ event.button === 0 && // ignore everything but left clicks
+ !isModifiedEvent(event) // ignore clicks with modifier keys
+ ) {
+ event.preventDefault();
+ navigateToApp(navLink.id);
+ }
+ },
+ // Legacy apps use `active` property, NP apps should match the current app
+ isActive: active || currentAppId === id,
+ isDisabled: disabled,
+ iconType: euiIconType,
+ icon: !euiIconType && icon ? : undefined,
+ order,
+ 'data-test-subj': 'navDrawerAppsMenuLink',
+ };
+}
diff --git a/src/core/public/chrome/ui/header/recent_links.tsx b/src/core/public/chrome/ui/header/recent_links.tsx
new file mode 100644
index 0000000000000..a947ab1c45056
--- /dev/null
+++ b/src/core/public/chrome/ui/header/recent_links.tsx
@@ -0,0 +1,113 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+// @ts-ignore
+import { EuiNavDrawerGroup } from '@elastic/eui';
+import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..';
+import { HttpStart } from '../../../http';
+
+// Providing a buffer between the limit and the cut off index
+// protects from truncating just the last couple (6) characters
+const TRUNCATE_LIMIT: number = 64;
+const TRUNCATE_AT: number = 58;
+
+export function truncateRecentItemLabel(label: string): string {
+ if (label.length > TRUNCATE_LIMIT) {
+ label = `${label.substring(0, TRUNCATE_AT)}…`;
+ }
+
+ return label;
+}
+
+/**
+ * @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
+ * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get
+ * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that
+ * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart".
+ * @return {string} the relative url transformed into an absolute url
+ */
+function relativeToAbsolute(url: string) {
+ const a = document.createElement('a');
+ a.setAttribute('href', url);
+ return a.href;
+}
+
+function prepareForEUI(
+ recentlyAccessed: ChromeRecentlyAccessedHistoryItem[],
+ navLinks: ChromeNavLink[],
+ basePath: HttpStart['basePath']
+) {
+ return recentlyAccessed.map(({ link, label }) => {
+ const href = relativeToAbsolute(basePath.prepend(link));
+ const navLink = navLinks.find(nl => href.startsWith(nl.baseUrl ?? nl.subUrlBase));
+ let titleAndAriaLabel = label;
+
+ if (navLink) {
+ titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', {
+ defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}',
+ values: {
+ recentlyAccessedItemLinklabel: label,
+ pageType: navLink.title,
+ },
+ });
+ }
+
+ return {
+ href,
+ label: truncateRecentItemLabel(label),
+ title: titleAndAriaLabel,
+ 'aria-label': titleAndAriaLabel,
+ iconType: navLink?.euiIconType,
+ };
+ });
+}
+
+interface Props {
+ recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[];
+ navLinks: ChromeNavLink[];
+ basePath: HttpStart['basePath'];
+}
+
+export function RecentLinks({ recentlyAccessedItems, navLinks, basePath }: Props) {
+ return (
+
+ );
+}
diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts
index 97bd49416f705..b9439a0f96e7e 100644
--- a/src/core/public/core_system.ts
+++ b/src/core/public/core_system.ts
@@ -246,6 +246,7 @@ export class CoreSystem {
http,
injectedMetadata,
notifications,
+ uiSettings,
});
application.registerMountContext(this.coreContext.coreId, 'core', () => ({
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index a3faddecec47a..67b31c28d2478 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -78,7 +78,8 @@ import {
/** @interal */
export { CoreContext, CoreSystem } from './core_system';
-export { RecursiveReadonly } from '../utils';
+export { RecursiveReadonly, DEFAULT_APP_CATEGORIES } from '../utils';
+export { AppCategory } from '../types';
export {
ApplicationSetup,
diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts
index 0bde1b68e1876..1075a7741ee32 100644
--- a/src/core/public/injected_metadata/injected_metadata_service.ts
+++ b/src/core/public/injected_metadata/injected_metadata_service.ts
@@ -26,10 +26,12 @@ import {
UserProvidedValues,
} from '../../server/types';
import { deepFreeze } from '../../utils/';
+import { AppCategory } from '../';
/** @public */
export interface LegacyNavLink {
id: string;
+ category?: AppCategory;
title: string;
order: number;
url: string;
@@ -52,6 +54,7 @@ export interface InjectedMetadataParams {
buildNumber: number;
branch: string;
basePath: string;
+ category?: AppCategory;
csp: {
warnLegacyBrowsers: boolean;
};
@@ -75,6 +78,7 @@ export interface InjectedMetadataParams {
basePath: string;
serverName: string;
devMode: boolean;
+ category?: AppCategory;
uiSettings: {
defaults: Record;
user?: Record;
diff --git a/src/core/public/legacy/legacy_service.ts b/src/core/public/legacy/legacy_service.ts
index f906aff1759e2..cc3210771eecc 100644
--- a/src/core/public/legacy/legacy_service.ts
+++ b/src/core/public/legacy/legacy_service.ts
@@ -74,6 +74,7 @@ export class LegacyPlatformService {
appUrl: navLink.url,
subUrlBase: navLink.subUrlBase,
linkToLastSubUrl: navLink.linkToLastSubUrl,
+ category: navLink.category,
})
);
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index f7b260c68ee96..0da6e0d422f2d 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -26,6 +26,7 @@ export interface App extends AppBase {
// @public (undocumented)
export interface AppBase {
capabilities?: Partial;
+ category?: AppCategory;
chromeless?: boolean;
euiIconType?: string;
icon?: string;
@@ -40,6 +41,14 @@ export interface AppBase {
updater$?: Observable;
}
+// @public
+export interface AppCategory {
+ ariaLabel?: string;
+ euiIconType?: string;
+ label: string;
+ order?: number;
+}
+
// @public
export type AppLeaveAction = AppLeaveDefaultAction | AppLeaveConfirmAction;
@@ -251,6 +260,7 @@ export interface ChromeNavLink {
// @deprecated
readonly active?: boolean;
readonly baseUrl: string;
+ readonly category?: AppCategory;
// @deprecated
readonly disabled?: boolean;
readonly euiIconType?: string;
@@ -410,6 +420,26 @@ export class CoreSystem {
stop(): void;
}
+// @internal (undocumented)
+export const DEFAULT_APP_CATEGORIES: Readonly<{
+ analyze: {
+ label: string;
+ order: number;
+ };
+ observability: {
+ label: string;
+ order: number;
+ };
+ security: {
+ label: string;
+ order: number;
+ };
+ management: {
+ label: string;
+ euiIconType: string;
+ };
+}>;
+
// @public (undocumented)
export interface DocLinksStart {
// (undocumented)
@@ -746,6 +776,8 @@ export interface LegacyCoreStart extends CoreStart {
// @public (undocumented)
export interface LegacyNavLink {
+ // (undocumented)
+ category?: AppCategory;
// (undocumented)
euiIconType?: string;
// (undocumented)
diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
index 9867274d224bd..a19133c30659b 100644
--- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
+++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
@@ -65,6 +65,7 @@ function getUiAppsNavLinks({ uiAppSpecs = [] }: LegacyUiExports, pluginSpecs: Le
return {
id,
+ category: spec.category,
title: spec.title,
order: typeof spec.order === 'number' ? spec.order : 0,
icon: spec.icon,
@@ -79,6 +80,7 @@ function getNavLinks(uiExports: LegacyUiExports, pluginSpecs: LegacyPluginSpec[]
return (uiExports.navLinkSpecs || [])
.map(spec => ({
id: spec.id,
+ category: spec.category,
title: spec.title,
order: typeof spec.order === 'number' ? spec.order : 0,
url: spec.url,
diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts
index 40b8244a31890..d51058ca561c6 100644
--- a/src/core/server/legacy/types.ts
+++ b/src/core/server/legacy/types.ts
@@ -139,7 +139,7 @@ export type LegacyNavLinkSpec = Record & ChromeNavLink;
*/
export type LegacyAppSpec = Pick<
ChromeNavLink,
- 'title' | 'order' | 'icon' | 'euiIconType' | 'url' | 'linkToLastSubUrl' | 'hidden'
+ 'title' | 'order' | 'icon' | 'euiIconType' | 'url' | 'linkToLastSubUrl' | 'hidden' | 'category'
> & { pluginId?: string; id?: string; listed?: boolean };
/**
diff --git a/src/core/types/app_category.ts b/src/core/types/app_category.ts
new file mode 100644
index 0000000000000..83a3693f009b6
--- /dev/null
+++ b/src/core/types/app_category.ts
@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/** @public */
+
+/**
+ * A category definition for nav links to know where to sort them in the left hand nav
+ * @public
+ */
+export interface AppCategory {
+ /**
+ * Label used for cateogry name.
+ * Also used as aria-label if one isn't set.
+ */
+ label: string;
+
+ /**
+ * If the visual label isn't appropriate for screen readers,
+ * can override it here
+ */
+ ariaLabel?: string;
+
+ /**
+ * The order that categories will be sorted in
+ * Prefer large steps between categories to allow for further editing
+ * (Default categories are in steps of 1000)
+ */
+ order?: number;
+
+ /**
+ * Define an icon to be used for the category
+ * If the category is only 1 item, and no icon is defined, will default to the product icon
+ * Defaults to initials if no icon is defined
+ */
+ euiIconType?: string;
+}
diff --git a/src/core/types/index.ts b/src/core/types/index.ts
index d01b514c770a7..7ddb6b0d8dfbb 100644
--- a/src/core/types/index.ts
+++ b/src/core/types/index.ts
@@ -23,3 +23,4 @@
*/
export * from './core_service';
export * from './capabilities';
+export * from './app_category';
diff --git a/src/core/utils/default_app_categories.ts b/src/core/utils/default_app_categories.ts
new file mode 100644
index 0000000000000..3e3cc2fef2a22
--- /dev/null
+++ b/src/core/utils/default_app_categories.ts
@@ -0,0 +1,48 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+/** @internal */
+export const DEFAULT_APP_CATEGORIES = Object.freeze({
+ analyze: {
+ label: i18n.translate('core.ui.analyzeNavList.label', {
+ defaultMessage: 'Analyze',
+ }),
+ order: 1000,
+ },
+ observability: {
+ label: i18n.translate('core.ui.observabilityNavList.label', {
+ defaultMessage: 'Observability',
+ }),
+ order: 2000,
+ },
+ security: {
+ label: i18n.translate('core.ui.securityNavList.label', {
+ defaultMessage: 'Security',
+ }),
+ order: 3000,
+ },
+ management: {
+ label: i18n.translate('core.ui.managementNavList.label', {
+ defaultMessage: 'Management',
+ }),
+ euiIconType: 'managementApp',
+ },
+});
diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts
index 7c8ed481c0a7d..7317c222d3bc3 100644
--- a/src/core/utils/index.ts
+++ b/src/core/utils/index.ts
@@ -28,3 +28,4 @@ export * from './pick';
export * from './promise';
export * from './url';
export * from './unset';
+export * from './default_app_categories';
diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js
index 0366d8b27f211..55bd852050218 100644
--- a/src/legacy/core_plugins/kibana/index.js
+++ b/src/legacy/core_plugins/kibana/index.js
@@ -34,6 +34,7 @@ import { getUiSettingDefaults } from './ui_setting_defaults';
import { registerCspCollector } from './server/lib/csp_usage_collector';
import { injectVars } from './inject_vars';
import { i18n } from '@kbn/i18n';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
const mkdirAsync = promisify(Fs.mkdir);
@@ -83,6 +84,7 @@ export default function(kibana) {
order: -1003,
url: `${kbnBaseUrl}#/discover`,
euiIconType: 'discoverApp',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
{
id: 'kibana:visualize',
@@ -92,6 +94,7 @@ export default function(kibana) {
order: -1002,
url: `${kbnBaseUrl}#/visualize`,
euiIconType: 'visualizeApp',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
{
id: 'kibana:dashboard',
@@ -107,6 +110,7 @@ export default function(kibana) {
// to determine what url to use for the app link.
subUrlBase: `${kbnBaseUrl}#/dashboard`,
euiIconType: 'dashboardApp',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
{
id: 'kibana:dev_tools',
@@ -116,16 +120,18 @@ export default function(kibana) {
order: 9001,
url: '/app/kibana#/dev_tools',
euiIconType: 'devToolsApp',
+ category: DEFAULT_APP_CATEGORIES.management,
},
{
- id: 'kibana:management',
+ id: 'kibana:stack_management',
title: i18n.translate('kbn.managementTitle', {
- defaultMessage: 'Management',
+ defaultMessage: 'Stack Management',
}),
order: 9003,
url: `${kbnBaseUrl}#/management`,
euiIconType: 'managementApp',
linkToLastSubUrl: false,
+ category: DEFAULT_APP_CATEGORIES.management,
},
],
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx
index d2dda32f318fe..1aad7e953b8de 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx
@@ -39,7 +39,7 @@ const DiscoverFetchError = ({ fetchError }: Props) => {
if (fetchError.lang === 'painless') {
const { chrome } = getServices();
- const mangagementUrlObj = chrome.navLinks.get('kibana:management');
+ const mangagementUrlObj = chrome.navLinks.get('kibana:stack_management');
const managementUrl = mangagementUrlObj ? mangagementUrlObj.url : '';
const url = `${managementUrl}/kibana/index_patterns`;
diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js b/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js
index be2ceb66f69d0..27d4f1a8b1c1f 100644
--- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js
+++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js
@@ -129,8 +129,8 @@ describe('home', () => {
test('should not render directory entry when showOnHomePage is false', async () => {
const directoryEntry = {
- id: 'management',
- title: 'Management',
+ id: 'stack-management',
+ title: 'Stack Management',
description: 'Your center console for managing the Elastic Stack.',
icon: 'managementApp',
path: 'management_landing_page',
diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js
index d62770956b88e..1305310b6f615 100644
--- a/src/legacy/core_plugins/kibana/public/management/index.js
+++ b/src/legacy/core_plugins/kibana/public/management/index.js
@@ -74,7 +74,7 @@ export function updateLandingPage(version) {
@@ -93,7 +93,7 @@ export function updateLandingPage(version) {
@@ -173,11 +173,11 @@ uiModules.get('apps/management').directive('kbnManagementLanding', function(kbnV
FeatureCatalogueRegistryProvider.register(() => {
return {
- id: 'management',
- title: i18n.translate('kbn.management.managementLabel', {
- defaultMessage: 'Management',
+ id: 'stack-management',
+ title: i18n.translate('kbn.stackManagement.managementLabel', {
+ defaultMessage: 'Stack Management',
}),
- description: i18n.translate('kbn.management.managementDescription', {
+ description: i18n.translate('kbn.stackManagement.managementDescription', {
defaultMessage: 'Your center console for managing the Elastic Stack.',
}),
icon: 'managementApp',
diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js
index 2c2861b8e0a8e..1a9d8f2b40e98 100644
--- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js
+++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js
@@ -1170,5 +1170,24 @@ export function getUiSettingDefaults() {
category: ['accessibility'],
requiresPageReload: true,
},
+ pageNavigation: {
+ name: i18n.translate('kbn.advancedSettings.pageNavigationName', {
+ defaultMessage: 'Side nav style',
+ }),
+ value: 'grouped',
+ description: i18n.translate('kbn.advancedSettings.pageNavigationDesc', {
+ defaultMessage: 'Change the style of navigation',
+ }),
+ type: 'select',
+ options: ['grouped', 'individual'],
+ optionLabels: {
+ grouped: i18n.translate('kbn.advancedSettings.pageNavigationGrouped', {
+ defaultMessage: 'Grouped',
+ }),
+ individual: i18n.translate('kbn.advancedSettings.pageNavigationIndividual', {
+ defaultMessage: 'Individual',
+ }),
+ },
+ },
};
}
diff --git a/src/legacy/core_plugins/management/index.ts b/src/legacy/core_plugins/management/index.ts
index 65601b5371815..4962c948f842f 100644
--- a/src/legacy/core_plugins/management/index.ts
+++ b/src/legacy/core_plugins/management/index.ts
@@ -23,7 +23,7 @@ import { Legacy } from '../../../../kibana';
// eslint-disable-next-line import/no-default-export
export default function ManagementPlugin(kibana: any) {
const config: Legacy.PluginSpecOptions = {
- id: 'management',
+ id: 'stack-management',
publicDir: resolve(__dirname, 'public'),
config: (Joi: any) => {
return Joi.object({
diff --git a/src/legacy/core_plugins/telemetry/common/constants.ts b/src/legacy/core_plugins/telemetry/common/constants.ts
index cb4ff79969a32..cf2c9c883871b 100644
--- a/src/legacy/core_plugins/telemetry/common/constants.ts
+++ b/src/legacy/core_plugins/telemetry/common/constants.ts
@@ -80,4 +80,4 @@ export const PATH_TO_ADVANCED_SETTINGS = 'kibana#/management/kibana/settings';
* The type name used within the Monitoring index to publish management stats.
* @type {string}
*/
-export const KIBANA_MANAGEMENT_STATS_TYPE = 'management';
+export const KIBANA_STACK_MANAGEMENT_STATS_TYPE = 'stack_management';
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts
index f45cf7fc6bb33..44926b644ced5 100644
--- a/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts
+++ b/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts
@@ -19,7 +19,7 @@
import { Server } from 'hapi';
import { size } from 'lodash';
-import { KIBANA_MANAGEMENT_STATS_TYPE } from '../../../common/constants';
+import { KIBANA_STACK_MANAGEMENT_STATS_TYPE } from '../../../common/constants';
import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/server';
import { SavedObjectsClient } from '../../../../../../core/server';
@@ -54,7 +54,7 @@ export function registerManagementUsageCollector(
server: any
) {
const collector = usageCollection.makeUsageCollector({
- type: KIBANA_MANAGEMENT_STATS_TYPE,
+ type: KIBANA_STACK_MANAGEMENT_STATS_TYPE,
isReady: () => true,
fetch: createCollectorFetch(server),
});
diff --git a/src/legacy/core_plugins/timelion/index.ts b/src/legacy/core_plugins/timelion/index.ts
index ec121647f4e47..d725327e2365b 100644
--- a/src/legacy/core_plugins/timelion/index.ts
+++ b/src/legacy/core_plugins/timelion/index.ts
@@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n';
import { Legacy } from 'kibana';
import { LegacyPluginApi, LegacyPluginInitializer } from 'src/legacy/plugin_discovery/types';
import { CoreSetup, PluginInitializerContext } from 'src/core/server';
+import { DEFAULT_APP_CATEGORIES } from '../../../core/utils';
import { plugin } from './server';
import { CustomCoreSetup } from './server/plugin';
@@ -60,6 +61,7 @@ const timelionPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPl
icon: 'plugins/timelion/icon.svg',
euiIconType: 'timelionApp',
main: 'plugins/timelion/app',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
hacks: [resolve(__dirname, 'public/legacy')],
diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts
index fe886b9d17811..9425003eae874 100644
--- a/src/legacy/plugin_discovery/types.ts
+++ b/src/legacy/plugin_discovery/types.ts
@@ -24,6 +24,7 @@ import { Capabilities } from '../../core/server';
import { SavedObjectsSchemaDefinition } from '../../core/server/saved_objects/schema';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { SavedObjectsManagementDefinition } from '../../core/server/saved_objects/management';
+import { AppCategory } from '../../core/types';
/**
* Usage
@@ -53,6 +54,7 @@ export interface LegacyPluginOptions {
uiExports: Partial<{
app: Partial<{
title: string;
+ category?: AppCategory;
description: string;
main: string;
icon: string;
diff --git a/src/legacy/ui/public/management/breadcrumbs.ts b/src/legacy/ui/public/management/breadcrumbs.ts
index fe53bcfde9e1f..936e99caff565 100644
--- a/src/legacy/ui/public/management/breadcrumbs.ts
+++ b/src/legacy/ui/public/management/breadcrumbs.ts
@@ -20,8 +20,8 @@
import { i18n } from '@kbn/i18n';
export const MANAGEMENT_BREADCRUMB = Object.freeze({
- text: i18n.translate('common.ui.management.breadcrumb', {
- defaultMessage: 'Management',
+ text: i18n.translate('common.ui.stackManagement.breadcrumb', {
+ defaultMessage: 'Stack Management',
}),
href: '#/management',
});
diff --git a/src/legacy/ui/ui_apps/ui_app.js b/src/legacy/ui/ui_apps/ui_app.js
index 9c82ff2abedb5..1cfd54588b516 100644
--- a/src/legacy/ui/ui_apps/ui_app.js
+++ b/src/legacy/ui/ui_apps/ui_app.js
@@ -32,6 +32,7 @@ export class UiApp {
hidden,
linkToLastSubUrl,
listed,
+ category,
url = `/app/${id}`,
} = spec;
@@ -46,6 +47,7 @@ export class UiApp {
this._icon = icon;
this._euiIconType = euiIconType;
this._linkToLastSubUrl = linkToLastSubUrl;
+ this._category = category;
this._hidden = hidden;
this._listed = listed;
this._url = url;
@@ -68,6 +70,7 @@ export class UiApp {
euiIconType: this._euiIconType,
url: this._url,
linkToLastSubUrl: this._linkToLastSubUrl,
+ category: this._category,
});
}
}
@@ -115,6 +118,7 @@ export class UiApp {
main: this._main,
navLink: this._navLink,
linkToLastSubUrl: this._linkToLastSubUrl,
+ category: this._category,
};
}
}
diff --git a/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js b/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js
index d7ac49d9d49a3..639a5a7c58e18 100644
--- a/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js
+++ b/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js
@@ -34,6 +34,7 @@ function applySpecDefaults(spec, type, pluginSpec) {
linkToLastSubUrl = true,
listed = !hidden,
url = `/app/${id}`,
+ category,
} = spec;
if (spec.injectVars) {
@@ -61,6 +62,7 @@ function applySpecDefaults(spec, type, pluginSpec) {
linkToLastSubUrl,
listed,
url,
+ category,
};
}
diff --git a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js
index 37e023127ed41..543fe05b13e43 100644
--- a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js
+++ b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js
@@ -45,6 +45,7 @@ describe('UiNavLink', () => {
euiIconType: spec.euiIconType,
hidden: spec.hidden,
disabled: spec.disabled,
+ category: undefined,
// defaults
linkToLastSubUrl: true,
diff --git a/src/legacy/ui/ui_nav_links/ui_nav_link.js b/src/legacy/ui/ui_nav_links/ui_nav_link.js
index 7537a60adbcf2..5888c21a53c95 100644
--- a/src/legacy/ui/ui_nav_links/ui_nav_link.js
+++ b/src/legacy/ui/ui_nav_links/ui_nav_link.js
@@ -31,6 +31,7 @@ export class UiNavLink {
hidden = false,
disabled = false,
tooltip = '',
+ category,
} = spec;
this._id = id;
@@ -44,6 +45,7 @@ export class UiNavLink {
this._hidden = hidden;
this._disabled = disabled;
this._tooltip = tooltip;
+ this._category = category;
}
getOrder() {
@@ -63,6 +65,7 @@ export class UiNavLink {
hidden: this._hidden,
disabled: this._disabled,
tooltip: this._tooltip,
+ category: this._category,
};
}
}
diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx
index cb0b82d0f0bde..69ba813d2347e 100644
--- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx
+++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx
@@ -161,14 +161,15 @@ export class ManagementSidebarNav extends React.Component<
}
public render() {
- const HEADER_ID = 'management-nav-header';
+ const HEADER_ID = 'stack-management-nav-header';
return (
<>
diff --git a/src/plugins/management/public/legacy/sections_register.js b/src/plugins/management/public/legacy/sections_register.js
index 63d919377f89e..ca35db56c340b 100644
--- a/src/plugins/management/public/legacy/sections_register.js
+++ b/src/plugins/management/public/legacy/sections_register.js
@@ -27,7 +27,8 @@ export class LegacyManagementAdapter {
'management',
{
display: i18n.translate('management.displayName', {
- defaultMessage: 'Management',
+ // todo
+ defaultMessage: 'Stack Management',
}),
},
capabilities
@@ -35,6 +36,7 @@ export class LegacyManagementAdapter {
this.main.register('data', {
display: i18n.translate('management.connectDataDisplayName', {
+ // todo
defaultMessage: 'Connect Data',
}),
order: 0,
diff --git a/src/plugins/management/public/management_app.tsx b/src/plugins/management/public/management_app.tsx
index 705d98eaaf2ff..02b3ea306c23d 100644
--- a/src/plugins/management/public/management_app.tsx
+++ b/src/plugins/management/public/management_app.tsx
@@ -64,7 +64,8 @@ export class ManagementApp {
coreStart.chrome.setBreadcrumbs([
{
text: i18n.translate('management.breadcrumb', {
- defaultMessage: 'Management',
+ // todo
+ defaultMessage: 'Stack Management',
}),
href: '#/management',
},
diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.js b/test/functional/apps/dashboard/create_and_add_embeddables.js
index 90f02c36b3b7f..0b628100a98bd 100644
--- a/test/functional/apps/dashboard/create_and_add_embeddables.js
+++ b/test/functional/apps/dashboard/create_and_add_embeddables.js
@@ -34,6 +34,7 @@ export default function({ getService, getPageObjects }) {
await esArchiver.load('dashboard/current/kibana');
await kibanaServer.uiSettings.replace({
defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c',
+ pageNavigation: 'individual',
});
await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.preserveCrossAppState();
@@ -83,7 +84,7 @@ export default function({ getService, getPageObjects }) {
describe('is false', () => {
before(async () => {
- await PageObjects.header.clickManagement();
+ await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
await PageObjects.settings.toggleAdvancedSettingCheckbox('visualize:enableLabs');
});
@@ -98,7 +99,7 @@ export default function({ getService, getPageObjects }) {
});
after(async () => {
- await PageObjects.header.clickManagement();
+ await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
await PageObjects.settings.clearAdvancedSettings('visualize:enableLabs');
await PageObjects.header.clickDashboard();
diff --git a/test/functional/apps/management/_index_pattern_filter.js b/test/functional/apps/management/_index_pattern_filter.js
index a32024adb5ec7..e685c43e9ce98 100644
--- a/test/functional/apps/management/_index_pattern_filter.js
+++ b/test/functional/apps/management/_index_pattern_filter.js
@@ -27,7 +27,7 @@ export default function({ getService, getPageObjects }) {
describe('index pattern filter', function describeIndexTests() {
before(async function() {
// delete .kibana index and then wait for Kibana to re-create it
- await kibanaServer.uiSettings.replace({});
+ await kibanaServer.uiSettings.replace({ pageNavigation: 'individual' });
await PageObjects.settings.navigateTo();
await PageObjects.settings.clickKibanaIndexPatterns();
});
diff --git a/test/functional/apps/visualize/_lab_mode.js b/test/functional/apps/visualize/_lab_mode.js
index 3ee806af8165d..b082480d95a2e 100644
--- a/test/functional/apps/visualize/_lab_mode.js
+++ b/test/functional/apps/visualize/_lab_mode.js
@@ -23,7 +23,6 @@ export default function({ getService, getPageObjects }) {
const log = getService('log');
const PageObjects = getPageObjects(['common', 'header', 'discover', 'settings']);
- // Flaky: https://github.com/elastic/kibana/issues/19743
describe('visualize lab mode', () => {
it('disabling does not break loading saved searches', async () => {
await PageObjects.common.navigateToUrl('discover', '');
@@ -36,7 +35,7 @@ export default function({ getService, getPageObjects }) {
log.info('found saved search before toggling enableLabs mode');
// Navigate to advanced setting and disable lab mode
- await PageObjects.header.clickManagement();
+ await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
await PageObjects.settings.toggleAdvancedSettingCheckbox('visualize:enableLabs');
@@ -50,7 +49,7 @@ export default function({ getService, getPageObjects }) {
after(async () => {
await PageObjects.discover.closeLoadSaveSearchPanel();
- await PageObjects.header.clickManagement();
+ await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
await PageObjects.settings.clearAdvancedSettings('visualize:enableLabs');
});
diff --git a/test/functional/page_objects/header_page.js b/test/functional/page_objects/header_page.js
index f82e4e4387e27..05edd64545a56 100644
--- a/test/functional/page_objects/header_page.js
+++ b/test/functional/page_objects/header_page.js
@@ -59,8 +59,8 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
await this.awaitGlobalLoadingIndicatorHidden();
}
- async clickManagement() {
- await appsMenu.clickLink('Management');
+ async clickStackManagement() {
+ await appsMenu.clickLink('Stack Management');
await this.awaitGlobalLoadingIndicatorHidden();
}
diff --git a/test/functional/page_objects/settings_page.js b/test/functional/page_objects/settings_page.ts
similarity index 90%
rename from test/functional/page_objects/settings_page.js
rename to test/functional/page_objects/settings_page.ts
index a4ae361b12ed8..e92780143f09a 100644
--- a/test/functional/page_objects/settings_page.js
+++ b/test/functional/page_objects/settings_page.ts
@@ -19,8 +19,10 @@
import { map as mapAsync } from 'bluebird';
import expect from '@kbn/expect';
+import { NavSetting } from '../../../src/core/public/chrome/ui/header/';
+import { FtrProviderContext } from '../ftr_provider_context';
-export function SettingsPageProvider({ getService, getPageObjects }) {
+export function SettingsPageProvider({ getService, getPageObjects }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const browser = getService('browser');
@@ -34,7 +36,8 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
async clickNavigation() {
find.clickDisplayedByCssSelector('.app-link:nth-child(5) a');
}
- async clickLinkText(text) {
+
+ async clickLinkText(text: string) {
await find.clickByDisplayedLinkText(text);
}
async clickKibanaSettings() {
@@ -55,6 +58,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
// check for the index pattern info flyout that covers the
// create index pattern button on smaller screens
+ // @ts-ignore
await retry.waitFor('index pattern info flyout', async () => {
if (await testSubjects.exists('CreateIndexPatternPrompt')) {
await testSubjects.click('CreateIndexPatternPrompt > euiFlyoutCloseButton');
@@ -62,18 +66,18 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
});
}
- async getAdvancedSettings(propertyName) {
+ async getAdvancedSettings(propertyName: string) {
log.debug('in getAdvancedSettings');
const setting = await testSubjects.find(`advancedSetting-editField-${propertyName}`);
return await setting.getAttribute('value');
}
- async expectDisabledAdvancedSetting(propertyName) {
+ async expectDisabledAdvancedSetting(propertyName: string) {
const setting = await testSubjects.find(`advancedSetting-editField-${propertyName}`);
expect(setting.getAttribute('disabled')).to.eql('');
}
- async getAdvancedSettingCheckbox(propertyName) {
+ async getAdvancedSettingCheckbox(propertyName: string) {
log.debug('in getAdvancedSettingCheckbox');
return await testSubjects.getAttribute(
`advancedSetting-editField-${propertyName}`,
@@ -81,12 +85,12 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
);
}
- async clearAdvancedSettings(propertyName) {
+ async clearAdvancedSettings(propertyName: string) {
await testSubjects.click(`advancedSetting-resetField-${propertyName}`);
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async setAdvancedSettingsSelect(propertyName, propertyValue) {
+ async setAdvancedSettingsSelect(propertyName: string, propertyValue: string) {
await find.clickByCssSelector(
`[data-test-subj="advancedSetting-editField-${propertyName}"] option[value="${propertyValue}"]`
);
@@ -95,7 +99,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async setAdvancedSettingsInput(propertyName, propertyValue) {
+ async setAdvancedSettingsInput(propertyName: string, propertyValue: string) {
const input = await testSubjects.find(`advancedSetting-editField-${propertyName}`);
await input.clearValue();
await input.type(propertyValue);
@@ -103,7 +107,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async toggleAdvancedSettingCheckbox(propertyName) {
+ async toggleAdvancedSettingCheckbox(propertyName: string) {
testSubjects.click(`advancedSetting-editField-${propertyName}`);
await PageObjects.header.waitUntilLoadingHasFinished();
await testSubjects.click(`advancedSetting-saveEditField-${propertyName}`);
@@ -126,7 +130,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
return await testSubjects.find('createIndexPatternTimeFieldSelect');
}
- async selectTimeFieldOption(selection) {
+ async selectTimeFieldOption(selection: string) {
// open dropdown
await this.clickTimeFieldNameField();
// close dropdown, keep focus
@@ -141,7 +145,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
});
}
- async getTimeFieldOption(selection) {
+ async getTimeFieldOption(selection: string) {
return await find.displayedByCssSelector('option[value="' + selection + '"]');
}
@@ -174,9 +178,9 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
return await find.allByCssSelector('table.euiTable thead tr th');
}
- async sortBy(columnName) {
+ async sortBy(columnName: string) {
const chartTypes = await find.allByCssSelector('table.euiTable thead tr th button');
- async function getChartType(chart) {
+ async function getChartType(chart: Record) {
const chartString = await chart.getVisibleText();
if (chartString === columnName) {
await chart.click();
@@ -187,7 +191,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
return Promise.all(getChartTypesPromises);
}
- async getTableRow(rowNumber, colNumber) {
+ async getTableRow(rowNumber: number, colNumber: number) {
// passing in zero-based index, but adding 1 for css 1-based indexes
return await find.byCssSelector(
'table.euiTable tbody tr:nth-child(' +
@@ -234,13 +238,13 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
});
}
- async setFieldTypeFilter(type) {
+ async setFieldTypeFilter(type: string) {
await find.clickByCssSelector(
'select[data-test-subj="indexedFieldTypeFilterDropdown"] > option[label="' + type + '"]'
);
}
- async setScriptedFieldLanguageFilter(language) {
+ async setScriptedFieldLanguageFilter(language: string) {
await find.clickByCssSelector(
'select[data-test-subj="scriptedFieldLanguageFilterDropdown"] > option[label="' +
language +
@@ -248,13 +252,13 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
);
}
- async filterField(name) {
+ async filterField(name: string) {
const input = await testSubjects.find('indexPatternFieldFilter');
await input.clearValue();
await input.type(name);
}
- async openControlsByName(name) {
+ async openControlsByName(name: string) {
await this.filterField(name);
const tableFields = await (
await find.byCssSelector(
@@ -312,7 +316,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
}
async createIndexPattern(
- indexPatternName,
+ indexPatternName: string,
timefield = '@timestamp',
isStandardIndexPattern = true
) {
@@ -364,7 +368,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
async getIndexPatternIdFromUrl() {
const currentUrl = await browser.getCurrentUrl();
- const indexPatternId = currentUrl.match(/.*\/(.*)/)[1];
+ const indexPatternId = currentUrl.match(/.*\/(.*)/)![1];
log.debug('index pattern ID: ', indexPatternId);
@@ -423,12 +427,19 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await testSubjects.click('tab-sourceFilters');
}
- async editScriptedField(name) {
+ async editScriptedField(name: string) {
await this.filterField(name);
await find.clickByCssSelector('.euiTableRowCell--hasActions button:first-child');
}
- async addScriptedField(name, language, type, format, popularity, script) {
+ async addScriptedField(
+ name: string,
+ language: string,
+ type: string,
+ format: Record,
+ popularity: string,
+ script: string
+ ) {
await this.clickAddScriptedField();
await this.setScriptedFieldName(name);
if (language) await this.setScriptedFieldLanguage(language);
@@ -469,42 +480,42 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async setScriptedFieldName(name) {
+ async setScriptedFieldName(name: string) {
log.debug('set scripted field name = ' + name);
const field = await testSubjects.find('editorFieldName');
await field.clearValue();
await field.type(name);
}
- async setScriptedFieldLanguage(language) {
+ async setScriptedFieldLanguage(language: string) {
log.debug('set scripted field language = ' + language);
await find.clickByCssSelector(
'select[data-test-subj="editorFieldLang"] > option[value="' + language + '"]'
);
}
- async setScriptedFieldType(type) {
+ async setScriptedFieldType(type: string) {
log.debug('set scripted field type = ' + type);
await find.clickByCssSelector(
'select[data-test-subj="editorFieldType"] > option[value="' + type + '"]'
);
}
- async setFieldFormat(format) {
+ async setFieldFormat(format: string) {
log.debug('set scripted field format = ' + format);
await find.clickByCssSelector(
'select[data-test-subj="editorSelectedFormatId"] > option[value="' + format + '"]'
);
}
- async setScriptedFieldUrlType(type) {
+ async setScriptedFieldUrlType(type: string) {
log.debug('set scripted field Url type = ' + type);
await find.clickByCssSelector(
'select[data-test-subj="urlEditorType"] > option[value="' + type + '"]'
);
}
- async setScriptedFieldUrlTemplate(template) {
+ async setScriptedFieldUrlTemplate(template: string) {
log.debug('set scripted field Url Template = ' + template);
const urlTemplateField = await find.byCssSelector(
'input[data-test-subj="urlEditorUrlTemplate"]'
@@ -512,7 +523,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await urlTemplateField.type(template);
}
- async setScriptedFieldUrlLabelTemplate(labelTemplate) {
+ async setScriptedFieldUrlLabelTemplate(labelTemplate: string) {
log.debug('set scripted field Url Label Template = ' + labelTemplate);
const urlEditorLabelTemplate = await find.byCssSelector(
'input[data-test-subj="urlEditorLabelTemplate"]'
@@ -520,7 +531,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await urlEditorLabelTemplate.type(labelTemplate);
}
- async setScriptedFieldDatePattern(datePattern) {
+ async setScriptedFieldDatePattern(datePattern: string) {
log.debug('set scripted field Date Pattern = ' + datePattern);
const datePatternField = await find.byCssSelector(
'input[data-test-subj="dateEditorPattern"]'
@@ -531,21 +542,21 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await datePatternField.type(datePattern);
}
- async setScriptedFieldStringTransform(stringTransform) {
+ async setScriptedFieldStringTransform(stringTransform: string) {
log.debug('set scripted field string Transform = ' + stringTransform);
await find.clickByCssSelector(
'select[data-test-subj="stringEditorTransform"] > option[value="' + stringTransform + '"]'
);
}
- async setScriptedFieldPopularity(popularity) {
+ async setScriptedFieldPopularity(popularity: string) {
log.debug('set scripted field popularity = ' + popularity);
const field = await testSubjects.find('editorFieldCount');
await field.clearValue();
await field.type(popularity);
}
- async setScriptedFieldScript(script) {
+ async setScriptedFieldScript(script: string) {
log.debug('set scripted field script = ' + script);
const aceEditorCssSelector = '[data-test-subj="editorFieldScript"] .ace_editor';
await find.clickByCssSelector(aceEditorCssSelector);
@@ -555,7 +566,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await browser.pressKeys(...script.split(''));
}
- async openScriptedFieldHelp(activeTab) {
+ async openScriptedFieldHelp(activeTab: string) {
log.debug('open Scripted Fields help');
let isOpen = await testSubjects.exists('scriptedFieldsHelpFlyout');
if (!isOpen) {
@@ -577,7 +588,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await flyout.ensureClosed('scriptedFieldsHelpFlyout');
}
- async executeScriptedField(script, additionalField) {
+ async executeScriptedField(script: string, additionalField: string) {
log.debug('execute Scripted Fields help');
await this.closeScriptedFieldHelp(); // ensure script help is closed so script input is not blocked
await this.setScriptedFieldScript(script);
@@ -595,7 +606,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
return scriptResults;
}
- async importFile(path, overwriteAll = true) {
+ async importFile(path: string, overwriteAll = true) {
log.debug(`importFile(${path})`);
log.debug(`Clicking importObjects`);
@@ -645,7 +656,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await testSubjects.click('importSavedObjectsConfirmBtn');
}
- async associateIndexPattern(oldIndexPatternId, newIndexPatternTitle) {
+ async associateIndexPattern(oldIndexPatternId: string, newIndexPatternTitle: string) {
await find.clickByCssSelector(
`select[data-test-subj="managementChangeIndexSelection-${oldIndexPatternId}"] >
[data-test-subj="indexPatternOption-${newIndexPatternTitle}"]`
@@ -710,7 +721,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
return await deleteButton.isEnabled();
}
- async canSavedObjectBeDeleted(id) {
+ async canSavedObjectBeDeleted(id: string) {
const allCheckBoxes = await testSubjects.findAll('checkboxSelectRow*');
for (const checkBox of allCheckBoxes) {
if (await checkBox.isSelected()) {
@@ -722,6 +733,12 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
await checkBox.click();
return await this.canSavedObjectsBeDeleted();
}
+
+ async setNavType(navType: NavSetting) {
+ await PageObjects.common.navigateToApp('settings');
+ await this.clickKibanaSettings();
+ await this.setAdvancedSettingsSelect('pageNavigation', navType);
+ }
}
return new SettingsPage();
diff --git a/test/plugin_functional/test_suites/core_plugins/application_status.ts b/test/plugin_functional/test_suites/core_plugins/application_status.ts
index b6d13a5604011..0cc64277efe11 100644
--- a/test/plugin_functional/test_suites/core_plugins/application_status.ts
+++ b/test/plugin_functional/test_suites/core_plugins/application_status.ts
@@ -28,7 +28,7 @@ import '../../plugins/core_app_status/public/types';
// eslint-disable-next-line import/no-default-export
export default function({ getService, getPageObjects }: PluginFunctionalProviderContext) {
- const PageObjects = getPageObjects(['common']);
+ const PageObjects = getPageObjects(['common', 'settings']);
const browser = getService('browser');
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
@@ -48,6 +48,10 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
};
describe('application status management', () => {
+ before(async () => {
+ await PageObjects.settings.setNavType('individual');
+ });
+
beforeEach(async () => {
await PageObjects.common.navigateToApp('app_status_start');
});
diff --git a/test/plugin_functional/test_suites/core_plugins/applications.ts b/test/plugin_functional/test_suites/core_plugins/applications.ts
index f50d460532556..6567837f65309 100644
--- a/test/plugin_functional/test_suites/core_plugins/applications.ts
+++ b/test/plugin_functional/test_suites/core_plugins/applications.ts
@@ -122,7 +122,7 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
});
it('can navigate from NP apps to legacy apps', async () => {
- await appsMenu.clickLink('Management');
+ await appsMenu.clickLink('Stack Management');
await loadingScreenShown();
await testSubjects.existOrFail('managementNav');
});
diff --git a/x-pack/legacy/plugins/apm/index.ts b/x-pack/legacy/plugins/apm/index.ts
index 0934cb0019f44..c52e6742ddae5 100644
--- a/x-pack/legacy/plugins/apm/index.ts
+++ b/x-pack/legacy/plugins/apm/index.ts
@@ -9,6 +9,7 @@ import { Server } from 'hapi';
import { resolve } from 'path';
import { APMPluginContract } from '../../../plugins/apm/server';
import { LegacyPluginInitializer } from '../../../../src/legacy/types';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
import mappings from './mappings.json';
import { makeApmUsageCollector } from './server/lib/apm_telemetry';
@@ -18,7 +19,6 @@ export const apm: LegacyPluginInitializer = kibana => {
id: 'apm',
configPrefix: 'xpack.apm',
publicDir: resolve(__dirname, 'public'),
-
uiExports: {
app: {
title: 'APM',
@@ -28,7 +28,8 @@ export const apm: LegacyPluginInitializer = kibana => {
main: 'plugins/apm/index',
icon: 'plugins/apm/icon.svg',
euiIconType: 'apmApp',
- order: 8100
+ order: 8100,
+ category: DEFAULT_APP_CATEGORIES.observability
},
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
home: ['plugins/apm/legacy_register_feature'],
diff --git a/x-pack/legacy/plugins/canvas/index.js b/x-pack/legacy/plugins/canvas/index.js
index 8e742de6de944..ebd4f35db8175 100644
--- a/x-pack/legacy/plugins/canvas/index.js
+++ b/x-pack/legacy/plugins/canvas/index.js
@@ -5,6 +5,7 @@
*/
import { resolve } from 'path';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
import { init } from './init';
import { mappings } from './server/mappings';
import { CANVAS_APP, CANVAS_TYPE, CUSTOM_ELEMENT_TYPE } from './common/lib';
@@ -23,6 +24,7 @@ export function canvas(kibana) {
icon: 'plugins/canvas/icon.svg',
euiIconType: 'canvasApp',
main: 'plugins/canvas/legacy_start',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
interpreter: [
'plugins/canvas/browser_functions',
diff --git a/x-pack/legacy/plugins/dashboard_mode/index.js b/x-pack/legacy/plugins/dashboard_mode/index.js
index 4a04249844322..94655adf981b4 100644
--- a/x-pack/legacy/plugins/dashboard_mode/index.js
+++ b/x-pack/legacy/plugins/dashboard_mode/index.js
@@ -5,15 +5,13 @@
*/
import { resolve } from 'path';
-
+import { i18n } from '@kbn/i18n';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
import { CONFIG_DASHBOARD_ONLY_MODE_ROLES } from './common';
-
import { createDashboardModeRequestInterceptor } from './server';
-import { i18n } from '@kbn/i18n';
-
// Copied largely from plugins/kibana/index.js. The dashboard viewer includes just the dashboard section of
-// the standard kibana plugin. We don't want to include code for the other links (visualize, dev tools, etc)
+// the standard kibana plugin. We don't want to include code for the other links (visualize, dev tools, etc)
// since it's view only, but we want the urls to be the same, so we are using largely the same setup.
export function dashboardMode(kibana) {
const kbnBaseUrl = '/app/kibana';
@@ -64,6 +62,7 @@ export function dashboardMode(kibana) {
}
),
icon: 'plugins/kibana/dashboard/assets/dashboard.svg',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
],
},
diff --git a/x-pack/legacy/plugins/graph/index.ts b/x-pack/legacy/plugins/graph/index.ts
index 601a239574e6b..f798fa5e9f39d 100644
--- a/x-pack/legacy/plugins/graph/index.ts
+++ b/x-pack/legacy/plugins/graph/index.ts
@@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n';
import migrations from './migrations';
import mappings from './mappings.json';
import { LegacyPluginInitializer } from '../../../../src/legacy/plugin_discovery/types';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
export const graph: LegacyPluginInitializer = kibana => {
return new kibana.Plugin({
@@ -25,6 +26,7 @@ export const graph: LegacyPluginInitializer = kibana => {
icon: 'plugins/graph/icon.png',
euiIconType: 'graphApp',
main: 'plugins/graph/index',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
mappings,
diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx
index f34b82d6bb1a3..d1fcbea2ff5b7 100644
--- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx
@@ -146,7 +146,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) {
);
if (noIndexPatterns) {
- const managementUrl = chrome.navLinks.get('kibana:management')!.url;
+ const managementUrl = chrome.navLinks.get('kibana:stack_management')!.url;
const indexPatternUrl = `${managementUrl}/kibana/index_patterns`;
const sampleDataUrl = `${application.getUrlForApp(
'kibana'
diff --git a/x-pack/legacy/plugins/infra/index.ts b/x-pack/legacy/plugins/infra/index.ts
index 196950b51be3a..d9abadcb5125c 100644
--- a/x-pack/legacy/plugins/infra/index.ts
+++ b/x-pack/legacy/plugins/infra/index.ts
@@ -18,6 +18,7 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../../plugins/fea
import { SpacesPluginSetup } from '../../../plugins/spaces/server';
import { VisTypeTimeseriesSetup } from '../../../../src/plugins/vis_type_timeseries/server';
import { APMPluginContract } from '../../../plugins/apm/server';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
export const APP_ID = 'infra';
@@ -55,6 +56,7 @@ export function infra(kibana: any) {
defaultMessage: 'Metrics',
}),
url: `/app/${APP_ID}#/infrastructure`,
+ category: DEFAULT_APP_CATEGORIES.observability,
},
{
description: i18n.translate('xpack.infra.linkLogsDescription', {
@@ -68,6 +70,7 @@ export function infra(kibana: any) {
defaultMessage: 'Logs',
}),
url: `/app/${APP_ID}#/logs`,
+ category: DEFAULT_APP_CATEGORIES.observability,
},
],
mappings: savedObjectMappings,
diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js
index 8179a15e441ac..52045ee218825 100644
--- a/x-pack/legacy/plugins/maps/index.js
+++ b/x-pack/legacy/plugins/maps/index.js
@@ -4,15 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import _ from 'lodash';
+import mappings from './mappings.json';
import { i18n } from '@kbn/i18n';
import { resolve } from 'path';
-import mappings from './mappings.json';
import { migrations } from './migrations';
import { initTelemetryCollection } from './server/maps_telemetry';
import { getAppTitle } from './common/i18n_getters';
-import _ from 'lodash';
import { MapPlugin } from './server/plugin';
import { APP_ID, APP_ICON, createMapPath, MAP_SAVED_OBJECT_TYPE } from './common/constants';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
export function maps(kibana) {
return new kibana.Plugin({
@@ -30,6 +31,7 @@ export function maps(kibana) {
main: 'plugins/maps/legacy',
icon: 'plugins/maps/icon.svg',
euiIconType: APP_ICON,
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
injectDefaultVars(server) {
const serverConfig = server.config();
diff --git a/x-pack/legacy/plugins/ml/index.ts b/x-pack/legacy/plugins/ml/index.ts
index c4289389b0d56..fc1cec7c16208 100755
--- a/x-pack/legacy/plugins/ml/index.ts
+++ b/x-pack/legacy/plugins/ml/index.ts
@@ -10,7 +10,7 @@ import KbnServer, { Server } from 'src/legacy/server/kbn_server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { plugin } from './server/new_platform';
import { CloudSetup } from '../../../plugins/cloud/server';
-
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
import {
MlInitializerContext,
MlCoreSetup,
@@ -42,6 +42,7 @@ export const ml = (kibana: any) => {
icon: 'plugins/ml/application/ml.svg',
euiIconType: 'machineLearningApp',
main: 'plugins/ml/legacy',
+ category: DEFAULT_APP_CATEGORIES.analyze,
},
styleSheetPaths: resolve(__dirname, 'public/application/index.scss'),
hacks: ['plugins/ml/application/hacks/toggle_app_link_in_nav'],
diff --git a/x-pack/legacy/plugins/monitoring/ui_exports.js b/x-pack/legacy/plugins/monitoring/ui_exports.js
index ba659aa74f10c..2b5ea21a2bb45 100644
--- a/x-pack/legacy/plugins/monitoring/ui_exports.js
+++ b/x-pack/legacy/plugins/monitoring/ui_exports.js
@@ -6,6 +6,7 @@
import { i18n } from '@kbn/i18n';
import { resolve } from 'path';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
/**
* Configuration of dependency objects for the UI, which are needed for the
@@ -26,6 +27,7 @@ export const getUiExports = () => ({
euiIconType: 'monitoringApp',
linkToLastSubUrl: false,
main: 'plugins/monitoring/monitoring',
+ category: DEFAULT_APP_CATEGORIES.management,
},
injectDefaultVars(server) {
const config = server.config();
diff --git a/x-pack/legacy/plugins/siem/index.ts b/x-pack/legacy/plugins/siem/index.ts
index edbb62feb580f..f6f2ead2d64fa 100644
--- a/x-pack/legacy/plugins/siem/index.ts
+++ b/x-pack/legacy/plugins/siem/index.ts
@@ -32,6 +32,7 @@ import {
} from './common/constants';
import { defaultIndexPattern } from './default_index_pattern';
import { initServerWithKibana } from './server/kibana.index';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const siem = (kibana: any) => {
@@ -62,6 +63,7 @@ export const siem = (kibana: any) => {
order: 9000,
title: APP_NAME,
url: `/app/${APP_ID}`,
+ category: DEFAULT_APP_CATEGORIES.security,
},
],
uiSettingDefaults: {
diff --git a/x-pack/legacy/plugins/uptime/index.ts b/x-pack/legacy/plugins/uptime/index.ts
index e090a2c85e136..cf7332f97d466 100644
--- a/x-pack/legacy/plugins/uptime/index.ts
+++ b/x-pack/legacy/plugins/uptime/index.ts
@@ -9,6 +9,7 @@ import { resolve } from 'path';
import { PluginInitializerContext } from 'src/core/server';
import { PLUGIN } from './common/constants';
import { KibanaServer, plugin } from './server';
+import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
export const uptime = (kibana: any) =>
new kibana.Plugin({
@@ -30,6 +31,7 @@ export const uptime = (kibana: any) =>
main: 'plugins/uptime/app',
order: 8900,
url: '/app/uptime#/',
+ category: DEFAULT_APP_CATEGORIES.observability,
},
home: ['plugins/uptime/register_feature'],
},
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 56b751e3ad42f..dc8a12c83c4ef 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -450,7 +450,6 @@
"common.ui.flotCharts.thuLabel": "木",
"common.ui.flotCharts.tueLabel": "火",
"common.ui.flotCharts.wedLabel": "水",
- "common.ui.management.breadcrumb": "管理",
"common.ui.modals.cancelButtonLabel": "キャンセル",
"common.ui.notify.fatalError.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。",
@@ -1898,8 +1897,6 @@
"kbn.management.landing.header": "Kibana {version} 管理",
"kbn.management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。",
"kbn.management.landing.text": "すべてのツールの一覧は、左のメニューにあります。",
- "kbn.management.managementDescription": "Elastic Stack の管理を行うセンターコンソールです。",
- "kbn.management.managementLabel": "管理",
"kbn.management.objects.confirmModalOptions.deleteButtonLabel": "削除",
"kbn.management.objects.confirmModalOptions.modalDescription": "削除されたオブジェクトは復元できません",
"kbn.management.objects.confirmModalOptions.modalTitle": "保存された Kibana オブジェクトを削除しますか?",
@@ -13256,4 +13253,4 @@
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。",
"xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。"
}
-}
+}
\ No newline at end of file
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index bc95191196fbd..1f3517cf5514e 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -450,7 +450,6 @@
"common.ui.flotCharts.thuLabel": "周四",
"common.ui.flotCharts.tueLabel": "周二",
"common.ui.flotCharts.wedLabel": "周三",
- "common.ui.management.breadcrumb": "管理",
"common.ui.modals.cancelButtonLabel": "取消",
"common.ui.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
@@ -1898,8 +1897,6 @@
"kbn.management.landing.header": "Kibana {version} 管理",
"kbn.management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。",
"kbn.management.landing.text": "在左侧菜单中可找到完整工具列表",
- "kbn.management.managementDescription": "您用于管理 Elastic Stack 的中心控制台。",
- "kbn.management.managementLabel": "管理",
"kbn.management.objects.confirmModalOptions.deleteButtonLabel": "删除",
"kbn.management.objects.confirmModalOptions.modalDescription": "您无法恢复删除的对象",
"kbn.management.objects.confirmModalOptions.modalTitle": "删除已保存 Kibana 对象?",
@@ -13255,4 +13252,4 @@
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。",
"xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。"
}
-}
+}
\ No newline at end of file
diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
index ad4f81777e780..2649c5d26309d 100644
--- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
+++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
@@ -54,7 +54,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expectSpaceSelector: false,
}
);
- await kibanaServer.uiSettings.replace({});
+ await kibanaServer.uiSettings.replace({ pageNavigation: 'individual' });
await PageObjects.settings.navigateTo();
});
@@ -68,7 +68,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Management']);
+ expect(navLinks).to.eql(['Stack Management']);
});
it(`allows settings to be changed`, async () => {
@@ -124,7 +124,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows Management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Management']);
+ expect(navLinks).to.eql(['Stack Management']);
});
it(`does not allow settings to be changed`, async () => {
@@ -175,7 +175,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows Management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Discover', 'Management']);
+ expect(navLinks).to.eql(['Discover', 'Stack Management']);
});
it(`does not allow navigation to advanced settings; redirects to Kibana home`, async () => {
diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts
index ee58be76928b3..79bb10e0bded1 100644
--- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts
+++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts
@@ -40,8 +40,9 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.contain('Management');
+ expect(navLinks).to.contain('Stack Management');
});
it(`allows settings to be changed`, async () => {
diff --git a/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts b/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts
index e2d5efac4644c..7c9c9f9c8c155 100644
--- a/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts
+++ b/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts
@@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows apm navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['APM', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['APM', 'Stack Management']);
});
it('can navigate to APM app', async () => {
@@ -109,7 +109,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows apm navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['APM', 'Management']);
+ expect(navLinks).to.eql(['APM', 'Stack Management']);
});
it('can navigate to APM app', async () => {
diff --git a/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts b/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts
index 1ac1784e0e05d..474240b201fac 100644
--- a/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts
+++ b/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts
@@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security']);
+ const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security', 'settings']);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -30,6 +30,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('APM');
});
diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
index d0e37ec8e3f35..71c10bd8248be 100644
--- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
+++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
@@ -66,7 +66,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows canvas navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Canvas', 'Management']);
+ expect(navLinks).to.eql(['Canvas', 'Stack Management']);
});
it(`landing page shows "Create new workpad" button`, async () => {
@@ -142,7 +142,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows canvas navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Canvas', 'Management']);
+ expect(navLinks).to.eql(['Canvas', 'Stack Management']);
});
it(`landing page shows disabled "Create new workpad" button`, async () => {
diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts
index 28b572401892b..5395f125bbd22 100644
--- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts
+++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts
@@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'canvas', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects(['common', 'canvas', 'security', 'spaceSelector', 'settings']);
const appsMenu = getService('appsMenu');
describe('spaces feature controls', function() {
@@ -40,6 +40,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Canvas');
});
diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts
index d25fae3c4894c..6a6e2f23785e3 100644
--- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts
+++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts
@@ -75,7 +75,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows dashboard navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['Dashboard', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['Dashboard', 'Stack Management']);
});
it(`landing page shows "Create new Dashboard" button`, async () => {
@@ -253,7 +253,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows dashboard navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Dashboard', 'Management']);
+ expect(navLinks).to.eql(['Dashboard', 'Stack Management']);
});
it(`landing page doesn't show "Create new Dashboard" button`, async () => {
diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts
index ebe08a60c2563..002ae627c488d 100644
--- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts
+++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts
@@ -13,7 +13,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'dashboard',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
@@ -43,6 +49,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Dashboard');
});
diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js
index bab798dacc453..1189fe909ca32 100644
--- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js
+++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js
@@ -39,6 +39,7 @@ export default function({ getService, getPageObjects }) {
await esArchiver.load('dashboard_view_mode');
await kibanaServer.uiSettings.replace({
defaultIndex: 'logstash-*',
+ pageNavigation: 'individual',
});
await browser.setWindowSize(1600, 1000);
@@ -199,7 +200,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.security.forceLogout();
await PageObjects.security.login('mixeduser', '123456');
- if (await appsMenu.linkExists('Management')) {
+ if (await appsMenu.linkExists('Stack Management')) {
throw new Error('Expected management nav link to not be shown');
}
});
@@ -208,7 +209,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.security.forceLogout();
await PageObjects.security.login('mysuperuser', '123456');
- if (!(await appsMenu.linkExists('Management'))) {
+ if (!(await appsMenu.linkExists('Stack Management'))) {
throw new Error('Expected management nav link to be shown');
}
});
diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts
index 494fd71ea6f34..9db9a913e9a4b 100644
--- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts
+++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts
@@ -63,7 +63,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows Dev Tools navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['Dev Tools', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['Dev Tools', 'Stack Management']);
});
describe('console', () => {
@@ -144,7 +144,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it(`shows 'Dev Tools' navlink`, async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Dev Tools', 'Management']);
+ expect(navLinks).to.eql(['Dev Tools', 'Stack Management']);
});
describe('console', () => {
diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts
index 4184d223a9686..f917792eea027 100644
--- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts
+++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts
@@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'dashboard',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
const grokDebugger = getService('grokDebugger');
@@ -40,6 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Dev Tools');
});
diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts
index 1912b16d96f36..1796858165a2b 100644
--- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts
+++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts
@@ -81,7 +81,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows discover navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['Discover', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['Discover', 'Stack Management']);
});
it('shows save button', async () => {
@@ -168,7 +168,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows discover navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Discover', 'Management']);
+ expect(navLinks).to.eql(['Discover', 'Stack Management']);
});
it(`doesn't show save button`, async () => {
diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts
index e6b6f28f8b92f..c38dda536f253 100644
--- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts
+++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts
@@ -15,6 +15,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
'timePicker',
'security',
'spaceSelector',
+ 'settings',
]);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -49,6 +50,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Discover');
});
diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts
index a2b062e6ef84f..37de93a0a7e91 100644
--- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts
+++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts
@@ -64,7 +64,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows graph navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['Graph', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['Graph', 'Stack Management']);
});
it('landing page shows "Create new graph" button', async () => {
@@ -127,7 +127,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows graph navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Graph', 'Management']);
+ expect(navLinks).to.eql(['Graph', 'Stack Management']);
});
it('does not show a "Create new Workspace" button', async () => {
diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts
index a0b0d5bef9668..d0d0232b5a8b1 100644
--- a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts
+++ b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts
@@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'graph', 'security', 'error']);
+ const PageObjects = getPageObjects(['common', 'graph', 'security', 'error', 'settings']);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -34,6 +34,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Graph');
});
diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
index 30cdc95b38e62..ed25816e68712 100644
--- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
+++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
@@ -70,7 +70,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Management']);
+ expect(navLinks).to.eql(['Stack Management']);
});
it(`index pattern listing shows create button`, async () => {
@@ -113,7 +113,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
}
);
- await kibanaServer.uiSettings.replace({});
+ await kibanaServer.uiSettings.replace({ pageNavigation: 'individual' });
await PageObjects.settings.navigateTo();
});
@@ -124,7 +124,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Management']);
+ expect(navLinks).to.eql(['Stack Management']);
});
it(`index pattern listing doesn't show create button`, async () => {
@@ -176,7 +176,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows Management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Discover', 'Management']);
+ expect(navLinks).to.eql(['Discover', 'Stack Management']);
});
it(`doesn't show Index Patterns in management side-nav`, async () => {
diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts
index 6a2b77de17f45..75020d6eab7e4 100644
--- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts
+++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts
@@ -40,8 +40,9 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.contain('Management');
+ expect(navLinks).to.contain('Stack Management');
});
it(`index pattern listing shows create button`, async () => {
diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
index dd2a479c740c3..2a694f73d486e 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
@@ -61,7 +61,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows metrics navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Metrics', 'Management']);
+ expect(navLinks).to.eql(['Metrics', 'Stack Management']);
});
describe('infrastructure landing page without data', () => {
@@ -174,7 +174,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows metrics navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Metrics', 'Management']);
+ expect(navLinks).to.eql(['Metrics', 'Stack Management']);
});
describe('infrastructure landing page without data', () => {
diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts
index 170bb28e91419..66f38ee349074 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts
@@ -12,7 +12,13 @@ const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData;
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'infraHome', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'infraHome',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
const retry = getService('retry');
@@ -31,7 +37,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
// we need to load the following in every situation as deleting
// a space deletes all of the associated saved objects
await esArchiver.load('empty_kibana');
-
await spacesService.create({
id: 'custom_space',
name: 'custom_space',
@@ -48,6 +53,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Metrics');
});
diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
index bb358ff1d0dba..164376d20712c 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
@@ -58,7 +58,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows logs navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Logs', 'Management']);
+ expect(navLinks).to.eql(['Logs', 'Stack Management']);
});
describe('logs landing page without data', () => {
@@ -121,7 +121,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows logs navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Logs', 'Management']);
+ expect(navLinks).to.eql(['Logs', 'Stack Management']);
});
describe('logs landing page without data', () => {
diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts
index 3251dc08e72dd..234cfca63b09a 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts
@@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'infraHome', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'infraHome',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -36,6 +42,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Logs');
});
diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts
index 8fb6f21c778d3..c25c1bfe4b731 100644
--- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts
+++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts
@@ -10,7 +10,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const security = getService('security');
const appsMenu = getService('appsMenu');
- const PageObjects = getPageObjects(['common', 'security']);
+ const PageObjects = getPageObjects(['common', 'security', 'settings']);
describe('security', () => {
before(async () => {
@@ -94,6 +94,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
await PageObjects.security.login('machine_learning_user', 'machine_learning_user-password');
+ await PageObjects.settings.setNavType('individual');
});
after(async () => {
diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts
index fc94688e98811..c633852a2da0a 100644
--- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts
+++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts
@@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error']);
+ const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error', 'settings']);
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
@@ -39,6 +39,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Machine Learning');
});
diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
index 804ad5725edfd..ece162cbd96cc 100644
--- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
+++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
@@ -66,7 +66,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows maps navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Maps', 'Management']);
+ expect(navLinks).to.eql(['Maps', 'Stack Management']);
});
it(`allows a map to be created`, async () => {
@@ -153,7 +153,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows Maps navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Maps', 'Management']);
+ expect(navLinks).to.eql(['Maps', 'Stack Management']);
});
it(`does not show create new button`, async () => {
@@ -248,7 +248,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('does not show Maps navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Discover', 'Management']);
+ expect(navLinks).to.eql(['Discover', 'Stack Management']);
});
it(`returns a 404`, async () => {
diff --git a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts
index d985da42ab5ed..130aefb3cae2a 100644
--- a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts
+++ b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts
@@ -10,7 +10,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const security = getService('security');
const appsMenu = getService('appsMenu');
- const PageObjects = getPageObjects(['common', 'security']);
+ const PageObjects = getPageObjects(['common', 'security', 'settings']);
describe('security', () => {
before(async () => {
@@ -97,6 +97,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
it('shows monitoring navlink', async () => {
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Stack Monitoring');
});
diff --git a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts
index 7459b53ca4a32..0465cbcf54541 100644
--- a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts
+++ b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts
@@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error']);
+ const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error', 'settings']);
const appsMenu = getService('appsMenu');
const find = getService('find');
@@ -37,10 +37,11 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await spacesService.delete('custom_space');
});
- it('shows Stack Monitoring navlink', async () => {
+ it('shows Stack Monitoring navlink fail', async () => {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Stack Monitoring');
});
diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts
index 1e79c76bf83e5..d71d197a6ea19 100644
--- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts
+++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts
@@ -16,6 +16,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
describe('security feature controls', () => {
before(async () => {
await esArchiver.load('empty_kibana');
+ await PageObjects.settings.setNavType('individual');
});
after(async () => {
@@ -56,7 +57,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.contain('Management');
+ expect(navLinks).to.contain('Stack Management');
});
it(`displays Spaces management section`, async () => {
@@ -130,7 +131,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows management navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.contain('Management');
+ expect(navLinks).to.contain('Stack Management');
});
it(`doesn't display Spaces management section`, async () => {
diff --git a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts
index dea45f161e451..62483a10552e3 100644
--- a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts
+++ b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts
@@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows timelion navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Timelion', 'Management']);
+ expect(navLinks).to.eql(['Timelion', 'Stack Management']);
});
it(`allows a timelion sheet to be created`, async () => {
@@ -112,7 +112,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows timelion navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Timelion', 'Management']);
+ expect(navLinks).to.eql(['Timelion', 'Stack Management']);
});
it(`does not allow a timelion sheet to be created`, async () => {
diff --git a/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts b/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts
index fb203a23359bd..7e0fe731301a6 100644
--- a/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts
+++ b/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts
@@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'timelion', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'timelion',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const appsMenu = getService('appsMenu');
describe('timelion', () => {
@@ -38,6 +44,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Timelion');
});
diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts b/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts
index a004f8db66823..4ff82484db91c 100644
--- a/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts
+++ b/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts
@@ -64,7 +64,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows uptime navlink', async () => {
const navLinks = await appsMenu.readLinks();
- expect(navLinks.map(link => link.text)).to.eql(['Uptime', 'Management']);
+ expect(navLinks.map(link => link.text)).to.eql(['Uptime', 'Stack Management']);
});
it('can navigate to Uptime app', async () => {
@@ -115,7 +115,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows uptime navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Uptime', 'Management']);
+ expect(navLinks).to.eql(['Uptime', 'Stack Management']);
});
it('can navigate to Uptime app', async () => {
diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts b/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts
index 77c5b323340bf..c3dcb1b27771f 100644
--- a/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts
+++ b/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts
@@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security']);
+ const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security', 'settings']);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -30,6 +30,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Uptime');
});
diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts
index d55076cb0ab43..767dbd7165567 100644
--- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts
+++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts
@@ -75,7 +75,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows visualize navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Visualize', 'Management']);
+ expect(navLinks).to.eql(['Visualize', 'Stack Management']);
});
it(`landing page shows "Create new Visualization" button`, async () => {
@@ -189,7 +189,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('shows visualize navlink', async () => {
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
- expect(navLinks).to.eql(['Visualize', 'Management']);
+ expect(navLinks).to.eql(['Visualize', 'Stack Management']);
});
it(`landing page shows "Create new Visualization" button`, async () => {
diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts
index 9193862d2ba9e..066042896c122 100644
--- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts
+++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts
@@ -10,7 +10,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const spacesService = getService('spaces');
- const PageObjects = getPageObjects(['common', 'visualize', 'security', 'spaceSelector']);
+ const PageObjects = getPageObjects([
+ 'common',
+ 'visualize',
+ 'security',
+ 'spaceSelector',
+ 'settings',
+ ]);
const testSubjects = getService('testSubjects');
const appsMenu = getService('appsMenu');
@@ -40,6 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.common.navigateToApp('home', {
basePath: '/s/custom_space',
});
+ await PageObjects.settings.setNavType('individual');
const navLinks = (await appsMenu.readLinks()).map(link => link.text);
expect(navLinks).to.contain('Visualize');
});
diff --git a/x-pack/test/ui_capabilities/common/nav_links_builder.ts b/x-pack/test/ui_capabilities/common/nav_links_builder.ts
index 8b7741469362e..aaeb22852bcc0 100644
--- a/x-pack/test/ui_capabilities/common/nav_links_builder.ts
+++ b/x-pack/test/ui_capabilities/common/nav_links_builder.ts
@@ -13,7 +13,7 @@ export class NavLinksBuilder {
...features,
// management isn't a first-class "feature", but it makes our life easier here to pretend like it is
management: {
- navLinkId: 'kibana:management',
+ navLinkId: 'kibana:stack_management',
},
};
}
diff --git a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts
index 4af7d81e5a7b4..5c13e6b0eb51e 100644
--- a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts
+++ b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts
@@ -68,7 +68,7 @@ export class UICapabilitiesService {
: {};
const response = await this.axios.post(
`${spaceUrlPrefix}/api/core/capabilities`,
- { applications: [...applications, 'kibana:management'] },
+ { applications: [...applications, 'kibana:stack_management'] },
{
headers: requestHeaders,
}