Skip to content

Commit

Permalink
Migrate ui/doc_title to New platform (#48121)
Browse files Browse the repository at this point in the history
* create NP docTitle service and bridge LP to it

Signed-off-by: pgayvallet <[email protected]>

* properly prefix the docTitle public types

Signed-off-by: pgayvallet <[email protected]>

* update documentation

Signed-off-by: pgayvallet <[email protected]>

* replace direct NP access with closure to avoid error when importing module in tests with no usages

Signed-off-by: pgayvallet <[email protected]>

* remove arrow functions for doc generation

Signed-off-by: pgayvallet <[email protected]>

* remove get$ from the api

Signed-off-by: pgayvallet <[email protected]>

* remove apply param and excludeBase option

Signed-off-by: pgayvallet <[email protected]>

* remove removed export

Signed-off-by: pgayvallet <[email protected]>

* adapt legacy service to new api

Signed-off-by: pgayvallet <[email protected]>

* add entry about docTitle in the migration guide

Signed-off-by: pgayvallet <[email protected]>

* add link in migration guide

Signed-off-by: pgayvallet <[email protected]>

* update generated doc

Signed-off-by: pgayvallet <[email protected]>

* update chrome mock

Signed-off-by: pgayvallet <[email protected]>

* update snapshots due to api change

Signed-off-by: pgayvallet <[email protected]>

* remove ChromeDocTitleChange in favor of inline type

Signed-off-by: pgayvallet <[email protected]>
  • Loading branch information
pgayvallet authored Oct 24, 2019
1 parent 39aa439 commit ccd01a3
Show file tree
Hide file tree
Showing 18 changed files with 402 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) &gt; [change](./kibana-plugin-public.chromedoctitle.change.md)

## ChromeDocTitle.change() method

Changes the current document title.

<b>Signature:</b>

```typescript
change(newTitle: string | string[]): void;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| newTitle | <code>string &#124; string[]</code> | |

<b>Returns:</b>

`void`

## Example

How to change the title of the document

```ts
chrome.docTitle.change('My application title')
chrome.docTitle.change(['My application', 'My section'])

```

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md)

## ChromeDocTitle interface

APIs for accessing and updating the document title.

<b>Signature:</b>

```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()

```

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) &gt; [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.)

<b>Signature:</b>

```typescript
reset(): void;
```
<b>Returns:</b>

`void`

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeStart](./kibana-plugin-public.chromestart.md) &gt; [docTitle](./kibana-plugin-public.chromestart.doctitle.md)

## ChromeStart.docTitle property

APIs for accessing and updating the document title.

<b>Signature:</b>

```typescript
docTitle: ChromeDocTitle;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface ChromeStart

| Property | Type | Description |
| --- | --- | --- |
| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | <code>ChromeDocTitle</code> | APIs for accessing and updating the document title. |
| [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | <code>ChromeNavControls</code> | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. |
| [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | <code>ChromeNavLinks</code> | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. |
| [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | <code>ChromeRecentlyAccessed</code> | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. |
Expand Down
1 change: 1 addition & 0 deletions docs/development/core/public/kibana-plugin-public.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | |
Expand Down
1 change: 1 addition & 0 deletions src/core/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)_
Expand Down
7 changes: 7 additions & 0 deletions src/core/public/chrome/chrome_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
8 changes: 7 additions & 1 deletion src/core/public/chrome/chrome_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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) {}

Expand All @@ -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(
Expand All @@ -119,6 +122,7 @@ export class ChromeService {
navControls,
navLinks,
recentlyAccessed,
docTitle,

getHeaderComponent: () => (
<React.Fragment>
Expand Down Expand Up @@ -259,6 +263,8 @@ export interface ChromeStart {
navControls: ChromeNavControls;
/** {@inheritdoc ChromeRecentlyAccessed} */
recentlyAccessed: ChromeRecentlyAccessed;
/** {@inheritdoc ChromeDocTitle} */
docTitle: ChromeDocTitle;

/**
* Sets the current app's title
Expand Down
80 changes: 80 additions & 0 deletions src/core/public/chrome/doc_title/doc_title_service.test.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
});
105 changes: 105 additions & 0 deletions src/core/public/chrome/doc_title/doc_title_service.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
20 changes: 20 additions & 0 deletions src/core/public/chrome/doc_title/index.ts
Original file line number Diff line number Diff line change
@@ -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';
Loading

0 comments on commit ccd01a3

Please sign in to comment.