diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md new file mode 100644 index 0000000000000..eba149bf93a4c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [change](./kibana-plugin-public.chromedoctitle.change.md) + +## ChromeDocTitle.change() method + +Changes the current document title. + +Signature: + +```typescript +change(newTitle: string | string[]): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newTitle | string | string[] | | + +Returns: + +`void` + +## Example + +How to change the title of the document + +```ts +chrome.docTitle.change('My application title') +chrome.docTitle.change(['My application', 'My section']) + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md new file mode 100644 index 0000000000000..3c6cfab486288 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md @@ -0,0 +1,39 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) + +## ChromeDocTitle interface + +APIs for accessing and updating the document title. + +Signature: + +```typescript +export interface ChromeDocTitle +``` + +## Methods + +| Method | Description | +| --- | --- | +| [change(newTitle)](./kibana-plugin-public.chromedoctitle.change.md) | Changes the current document title. | +| [reset()](./kibana-plugin-public.chromedoctitle.reset.md) | Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) | + +## Example 1 + +How to change the title of the document + +```ts +chrome.docTitle.change('My application') + +``` + +## Example 2 + +How to reset the title of the document to it's initial value + +```ts +chrome.docTitle.reset() + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md new file mode 100644 index 0000000000000..4b4c6f573e006 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [reset](./kibana-plugin-public.chromedoctitle.reset.md) + +## ChromeDocTitle.reset() method + +Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) + +Signature: + +```typescript +reset(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md new file mode 100644 index 0000000000000..71eda64c24646 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [docTitle](./kibana-plugin-public.chromestart.doctitle.md) + +## ChromeStart.docTitle property + +APIs for accessing and updating the document title. + +Signature: + +```typescript +docTitle: ChromeDocTitle; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.md b/docs/development/core/public/kibana-plugin-public.chromestart.md index bc41aa10cce8f..153e06d591404 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.md @@ -16,6 +16,7 @@ export interface ChromeStart | Property | Type | Description | | --- | --- | --- | +| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | ChromeDocTitle | APIs for accessing and updating the document title. | | [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | ChromeNavControls | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | ChromeNavLinks | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | | [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | ChromeRecentlyAccessed | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index 57ab8bedde95e..253e50f0f2c2e 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` | [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | | [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | | [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | +| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | | [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | | [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 6a12b587085e1..b5942cc82941f 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1111,6 +1111,7 @@ import { npStart: { core } } from 'ui/new_platform'; | `ui/notify` | [`core.notifications`](/docs/development/core/public/kibana-plugin-public.notificationsstart.md) and [`core.overlays`](/docs/development/core/public/kibana-plugin-public.overlaystart.md) | Toast messages are in `notifications`, banners are in `overlays`. May be combined later. | | `ui/routes` | -- | There is no global routing mechanism. Each app [configures its own routing](/rfcs/text/0004_application_service_mounting.md#complete-example). | | `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md) | Client API is the same | +| `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-public.chromedoctitle.md) | | _See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-public.corestart.md)_ diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 3775989c5126b..6f61ee9dc21ba 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -43,6 +43,13 @@ const createStartContractMock = () => { get: jest.fn(), get$: jest.fn(), }, + docTitle: { + change: jest.fn(), + reset: jest.fn(), + __legacy: { + setBaseTitle: jest.fn(), + }, + }, navControls: { registerLeft: jest.fn(), registerRight: jest.fn(), diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 71279ad6fed03..87389d2c10f03 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -33,10 +33,11 @@ import { HttpStart } from '../http'; import { ChromeNavLinks, NavLinksService } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; import { NavControlsService, ChromeNavControls } from './nav_controls'; +import { DocTitleService, ChromeDocTitle } from './doc_title'; import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; -export { ChromeNavControls, ChromeRecentlyAccessed }; +export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed'; @@ -82,6 +83,7 @@ export class ChromeService { private readonly navControls = new NavControlsService(); private readonly navLinks = new NavLinksService(); private readonly recentlyAccessed = new RecentlyAccessedService(); + private readonly docTitle = new DocTitleService(); constructor(private readonly params: ConstructorParams) {} @@ -106,6 +108,7 @@ export class ChromeService { const navControls = this.navControls.start(); const navLinks = this.navLinks.start({ application, http }); const recentlyAccessed = await this.recentlyAccessed.start({ http }); + const docTitle = this.docTitle.start({ document: window.document }); if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { notifications.toasts.addWarning( @@ -119,6 +122,7 @@ export class ChromeService { navControls, navLinks, recentlyAccessed, + docTitle, getHeaderComponent: () => ( @@ -259,6 +263,8 @@ export interface ChromeStart { navControls: ChromeNavControls; /** {@inheritdoc ChromeRecentlyAccessed} */ recentlyAccessed: ChromeRecentlyAccessed; + /** {@inheritdoc ChromeDocTitle} */ + docTitle: ChromeDocTitle; /** * Sets the current app's title diff --git a/src/core/public/chrome/doc_title/doc_title_service.test.ts b/src/core/public/chrome/doc_title/doc_title_service.test.ts new file mode 100644 index 0000000000000..763e8c9ebd74a --- /dev/null +++ b/src/core/public/chrome/doc_title/doc_title_service.test.ts @@ -0,0 +1,80 @@ +/* + * 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 { DocTitleService } from './doc_title_service'; + +describe('DocTitleService', () => { + const defaultTitle = 'KibanaTest'; + const document = { title: '' }; + + const getStart = (title: string = defaultTitle) => { + document.title = title; + return new DocTitleService().start({ document }); + }; + + beforeEach(() => { + document.title = defaultTitle; + }); + + describe('#change()', () => { + it('changes the title of the document', async () => { + getStart().change('TitleA'); + expect(document.title).toEqual('TitleA - KibanaTest'); + }); + + it('appends the baseTitle to the title', async () => { + const start = getStart('BaseTitle'); + start.change('TitleA'); + expect(document.title).toEqual('TitleA - BaseTitle'); + start.change('TitleB'); + expect(document.title).toEqual('TitleB - BaseTitle'); + }); + + it('accepts string arrays as input', async () => { + const start = getStart(); + start.change(['partA', 'partB']); + expect(document.title).toEqual(`partA - partB - ${defaultTitle}`); + start.change(['partA', 'partB', 'partC']); + expect(document.title).toEqual(`partA - partB - partC - ${defaultTitle}`); + }); + }); + + describe('#reset()', () => { + it('resets the title to the initial value', async () => { + const start = getStart('InitialTitle'); + start.change('TitleA'); + expect(document.title).toEqual('TitleA - InitialTitle'); + start.reset(); + expect(document.title).toEqual('InitialTitle'); + }); + }); + + describe('#__legacy.setBaseTitle()', () => { + it('allows to change the baseTitle after startup', async () => { + const start = getStart('InitialTitle'); + start.change('WithInitial'); + expect(document.title).toEqual('WithInitial - InitialTitle'); + start.__legacy.setBaseTitle('NewBaseTitle'); + start.change('WithNew'); + expect(document.title).toEqual('WithNew - NewBaseTitle'); + start.reset(); + expect(document.title).toEqual('NewBaseTitle'); + }); + }); +}); diff --git a/src/core/public/chrome/doc_title/doc_title_service.ts b/src/core/public/chrome/doc_title/doc_title_service.ts new file mode 100644 index 0000000000000..9453abe54de66 --- /dev/null +++ b/src/core/public/chrome/doc_title/doc_title_service.ts @@ -0,0 +1,105 @@ +/* + * 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 { compact, flattenDeep, isString } from 'lodash'; + +interface StartDeps { + document: { title: string }; +} + +/** + * APIs for accessing and updating the document title. + * + * @example + * How to change the title of the document + * ```ts + * chrome.docTitle.change('My application') + * ``` + * + * @example + * How to reset the title of the document to it's initial value + * ```ts + * chrome.docTitle.reset() + * ``` + * + * @public + * */ +export interface ChromeDocTitle { + /** + * Changes the current document title. + * + * @example + * How to change the title of the document + * ```ts + * chrome.docTitle.change('My application title') + * chrome.docTitle.change(['My application', 'My section']) + * ``` + * + * @param newTitle The new title to set, either a string or string array + */ + change(newTitle: string | string[]): void; + /** + * Resets the document title to it's initial value. + * (meaning the one present in the title meta at application load.) + */ + reset(): void; + + /** @internal */ + __legacy: { + setBaseTitle(baseTitle: string): void; + }; +} + +const defaultTitle: string[] = []; +const titleSeparator = ' - '; + +/** @internal */ +export class DocTitleService { + private document = { title: '' }; + private baseTitle = ''; + + public start({ document }: StartDeps): ChromeDocTitle { + this.document = document; + this.baseTitle = document.title; + + return { + change: (title: string | string[]) => { + this.applyTitle(title); + }, + reset: () => { + this.applyTitle(defaultTitle); + }, + __legacy: { + setBaseTitle: baseTitle => { + this.baseTitle = baseTitle; + }, + }, + }; + } + + private applyTitle(title: string | string[]) { + this.document.title = this.render(title); + } + + private render(title: string | string[]) { + const parts = [...(isString(title) ? [title] : title), this.baseTitle]; + // ensuring compat with legacy that might be passing nested arrays + return compact(flattenDeep(parts)).join(titleSeparator); + } +} diff --git a/src/core/public/chrome/doc_title/index.ts b/src/core/public/chrome/doc_title/index.ts new file mode 100644 index 0000000000000..b070d01953f7a --- /dev/null +++ b/src/core/public/chrome/doc_title/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export * from './doc_title_service'; diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 6e03f9e023983..b220a81f775f8 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -29,3 +29,4 @@ export { export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; +export { ChromeDocTitle } from './doc_title'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 24201ff0253cb..7391cf7f9454c 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -45,6 +45,7 @@ import { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields, + ChromeDocTitle, ChromeStart, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, @@ -250,6 +251,7 @@ export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields, + ChromeDocTitle, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, ChromeStart, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 11a1b5c0d1d9b..416fb13cbb73e 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -105,6 +105,16 @@ export interface ChromeBrand { // @public (undocumented) export type ChromeBreadcrumb = Breadcrumb; +// @public +export interface ChromeDocTitle { + // @internal (undocumented) + __legacy: { + setBaseTitle(baseTitle: string): void; + }; + change(newTitle: string | string[]): void; + reset(): void; +} + // @public (undocumented) export type ChromeHelpExtension = (element: HTMLDivElement) => () => void; @@ -186,6 +196,7 @@ export interface ChromeRecentlyAccessedHistoryItem { // @public export interface ChromeStart { addApplicationClass(className: string): void; + docTitle: ChromeDocTitle; getApplicationClasses$(): Observable; getBadge$(): Observable; getBrand$(): Observable; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap index f59afc7165bab..286e60cca9712 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap @@ -103,6 +103,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -659,6 +666,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -1203,6 +1217,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -1756,6 +1777,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -2300,6 +2328,13 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -2853,6 +2888,13 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], diff --git a/src/legacy/ui/public/doc_title/__tests__/doc_title.js b/src/legacy/ui/public/doc_title/__tests__/doc_title.js index b4c3700e36f68..fa8b83f755957 100644 --- a/src/legacy/ui/public/doc_title/__tests__/doc_title.js +++ b/src/legacy/ui/public/doc_title/__tests__/doc_title.js @@ -20,7 +20,8 @@ import sinon from 'sinon'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { setBaseTitle, docTitle } from '../doc_title'; +import { docTitle } from '../doc_title'; +import { npStart } from '../../new_platform'; describe('docTitle Service', function () { let initialDocTitle; @@ -30,20 +31,24 @@ describe('docTitle Service', function () { beforeEach(function () { initialDocTitle = document.title; document.title = MAIN_TITLE; - setBaseTitle(MAIN_TITLE); + npStart.core.chrome.docTitle.__legacy.setBaseTitle(MAIN_TITLE); }); afterEach(function () { document.title = initialDocTitle; - setBaseTitle(initialDocTitle); + npStart.core.chrome.docTitle.__legacy.setBaseTitle(initialDocTitle); }); - beforeEach(ngMock.module('kibana', function ($provide) { - $provide.decorator('$rootScope', decorateWithSpy('$on')); - })); + beforeEach( + ngMock.module('kibana', function ($provide) { + $provide.decorator('$rootScope', decorateWithSpy('$on')); + }) + ); - beforeEach(ngMock.inject(function ($injector) { - $rootScope = $injector.get('$rootScope'); - })); + beforeEach( + ngMock.inject(function ($injector) { + $rootScope = $injector.get('$rootScope'); + }) + ); describe('setup', function () { it('resets the title when a route change begins', function () { @@ -60,13 +65,11 @@ describe('docTitle Service', function () { }); describe('#reset', function () { - it('clears the internal state, next update() will write the default', function () { + it('clears the internal state', function () { docTitle.change('some title'); - docTitle.update(); expect(document.title).to.be('some title - ' + MAIN_TITLE); docTitle.reset(); - docTitle.update(); expect(document.title).to.be(MAIN_TITLE); }); }); @@ -77,12 +80,6 @@ describe('docTitle Service', function () { docTitle.change('some secondary title'); expect(document.title).to.be('some secondary title - ' + MAIN_TITLE); }); - - it('will write just the first param if the second param is true', function () { - expect(document.title).to.be(MAIN_TITLE); - docTitle.change('entire name', true); - expect(document.title).to.be('entire name'); - }); }); function decorateWithSpy(prop) { @@ -91,5 +88,4 @@ describe('docTitle Service', function () { return $delegate; }; } - }); diff --git a/src/legacy/ui/public/doc_title/doc_title.js b/src/legacy/ui/public/doc_title/doc_title.js index 3692fd71f06cc..0edc55a0ac366 100644 --- a/src/legacy/ui/public/doc_title/doc_title.js +++ b/src/legacy/ui/public/doc_title/doc_title.js @@ -17,53 +17,28 @@ * under the License. */ -import _ from 'lodash'; +import { isArray } from 'lodash'; import { uiModules } from '../modules'; +import { npStart } from '../new_platform'; -let baseTitle = document.title; +const npDocTitle = () => npStart.core.chrome.docTitle; -// for karma test -export function setBaseTitle(str) { - baseTitle = str; -} - -let lastChange; - -function render() { - lastChange = lastChange || []; - - const parts = [lastChange[0]]; - - if (!lastChange[1]) parts.push(baseTitle); - - return _(parts).flattenDeep().compact().join(' - '); -} - -function change(title, complete) { - lastChange = [title, complete]; - update(); +function change(title) { + npDocTitle().change(isArray(title) ? title : [title]); } function reset() { - lastChange = null; -} - -function update() { - document.title = render(); + npDocTitle().reset(); } export const docTitle = { - render, change, reset, - update, }; uiModules.get('kibana') .run(function ($rootScope) { // always bind to the route events $rootScope.$on('$routeChangeStart', docTitle.reset); - $rootScope.$on('$routeChangeError', docTitle.update); - $rootScope.$on('$routeChangeSuccess', docTitle.update); });