Skip to content

Commit

Permalink
Merge branch 'master' of github.com:elastic/kibana into dev/state-man…
Browse files Browse the repository at this point in the history
…agment/state-sync-dashboard
  • Loading branch information
Dosant committed Jan 20, 2020
2 parents 23845a5 + 3e567b5 commit 3f7a2b8
Show file tree
Hide file tree
Showing 61 changed files with 1,205 additions and 585 deletions.
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-server](./kibana-plugin-server.md) &gt; [CoreSetup](./kibana-plugin-server.coresetup.md) &gt; [getStartServices](./kibana-plugin-server.coresetup.getstartservices.md)

## CoreSetup.getStartServices() method

Allows plugins to get access to APIs available in start inside async handlers. Promise will not resolve until Core and plugin dependencies have completed `start`<!-- -->. This should only be used inside handlers registered during `setup` that will only be executed after `start` lifecycle.

<b>Signature:</b>

```typescript
getStartServices(): Promise<[CoreStart, TPluginsStart]>;
```
<b>Returns:</b>

`Promise<[CoreStart, TPluginsStart]>`

58 changes: 32 additions & 26 deletions docs/development/core/server/kibana-plugin-server.coresetup.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [CoreSetup](./kibana-plugin-server.coresetup.md)

## CoreSetup interface

Context passed to the plugins `setup` method.

<b>Signature:</b>

```typescript
export interface CoreSetup
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [capabilities](./kibana-plugin-server.coresetup.capabilities.md) | <code>CapabilitiesSetup</code> | [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) |
| [context](./kibana-plugin-server.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-server.contextsetup.md) |
| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | <code>ElasticsearchServiceSetup</code> | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) |
| [http](./kibana-plugin-server.coresetup.http.md) | <code>HttpServiceSetup</code> | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) |
| [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) |
| [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) | <code>UiSettingsServiceSetup</code> | [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) |
| [uuid](./kibana-plugin-server.coresetup.uuid.md) | <code>UuidServiceSetup</code> | [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) |

<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [CoreSetup](./kibana-plugin-server.coresetup.md)

## CoreSetup interface

Context passed to the plugins `setup` method.

<b>Signature:</b>

```typescript
export interface CoreSetup<TPluginsStart extends object = object>
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [capabilities](./kibana-plugin-server.coresetup.capabilities.md) | <code>CapabilitiesSetup</code> | [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) |
| [context](./kibana-plugin-server.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-server.contextsetup.md) |
| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | <code>ElasticsearchServiceSetup</code> | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) |
| [http](./kibana-plugin-server.coresetup.http.md) | <code>HttpServiceSetup</code> | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) |
| [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) |
| [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) | <code>UiSettingsServiceSetup</code> | [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) |
| [uuid](./kibana-plugin-server.coresetup.uuid.md) | <code>UuidServiceSetup</code> | [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) |

## Methods

| Method | Description |
| --- | --- |
| [getStartServices()](./kibana-plugin-server.coresetup.getstartservices.md) | Allows plugins to get access to APIs available in start inside async handlers. Promise will not resolve until Core and plugin dependencies have completed <code>start</code>. This should only be used inside handlers registered during <code>setup</code> that will only be executed after <code>start</code> lifecycle. |

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 1 addition & 11 deletions src/core/public/application/application_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,17 +525,7 @@ describe('#start()', () => {
const { getComponent } = await service.start(startDeps);

expect(() => shallow(createElement(getComponent))).not.toThrow();
expect(getComponent()).toMatchInlineSnapshot(`
<AppRouter
history={
Object {
"push": [MockFunction],
}
}
mounters={Map {}}
setAppLeaveHandler={[Function]}
/>
`);
expect(getComponent()).toMatchSnapshot();
});

it('renders null when in legacy mode', async () => {
Expand Down
13 changes: 7 additions & 6 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import React from 'react';
import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { map, shareReplay, takeUntil } from 'rxjs/operators';
import { createBrowserHistory, History } from 'history';

import { InjectedMetadataSetup } from '../injected_metadata';
Expand Down Expand Up @@ -256,6 +256,11 @@ export class ApplicationService {
)
.subscribe(apps => applications$.next(apps));

const applicationStatuses$ = applications$.pipe(
map(apps => new Map([...apps.entries()].map(([id, app]) => [id, app.status!]))),
shareReplay(1)
);

return {
applications$,
capabilities,
Expand All @@ -264,11 +269,6 @@ export class ApplicationService {
getUrlForApp: (appId, { path }: { path?: string } = {}) =>
getAppUrl(availableMounters, appId, path),
navigateToApp: async (appId, { path, state }: { path?: string; state?: any } = {}) => {
const app = applications$.value.get(appId);
if (app && app.status !== AppStatus.accessible) {
// should probably redirect to the error page instead
throw new Error(`Trying to navigate to an inaccessible application: ${appId}`);
}
if (await this.shouldNavigate(overlays)) {
this.appLeaveHandlers.delete(this.currentAppId$.value!);
this.navigate!(getAppUrl(availableMounters, appId, path), state);
Expand All @@ -283,6 +283,7 @@ export class ApplicationService {
<AppRouter
history={this.history}
mounters={availableMounters}
appStatuses$={applicationStatuses$}
setAppLeaveHandler={this.setAppLeaveHandler}
/>
);
Expand Down
33 changes: 33 additions & 0 deletions src/core/public/application/integration_tests/router.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
*/

import React from 'react';
import { BehaviorSubject } from 'rxjs';
import { createMemoryHistory, History, createHashHistory } from 'history';

import { AppRouter, AppNotFound } from '../ui';
import { EitherApp, MockedMounterMap, MockedMounterTuple } from '../test_types';
import { createRenderer, createAppMounter, createLegacyAppMounter } from './utils';
import { AppStatus } from '../types';

describe('AppContainer', () => {
let mounters: MockedMounterMap<EitherApp>;
let history: History;
let appStatuses$: BehaviorSubject<Map<string, AppStatus>>;
let update: ReturnType<typeof createRenderer>;

const navigate = (path: string) => {
Expand All @@ -38,19 +41,34 @@ describe('AppContainer', () => {
new Map([...mounters].map(([appId, { mounter }]) => [appId, mounter]));
const setAppLeaveHandlerMock = () => undefined;

const mountersToAppStatus$ = () => {
return new BehaviorSubject(
new Map(
[...mounters.keys()].map(id => [
id,
id.startsWith('disabled') ? AppStatus.inaccessible : AppStatus.accessible,
])
)
);
};

beforeEach(() => {
mounters = new Map([
createAppMounter('app1', '<span>App 1</span>'),
createLegacyAppMounter('legacyApp1', jest.fn()),
createAppMounter('app2', '<div>App 2</div>'),
createLegacyAppMounter('baseApp:legacyApp2', jest.fn()),
createAppMounter('app3', '<div>App 3</div>', '/custom/path'),
createAppMounter('disabledApp', '<div>Disabled app</div>'),
createLegacyAppMounter('disabledLegacyApp', jest.fn()),
] as Array<MockedMounterTuple<EitherApp>>);
history = createMemoryHistory();
appStatuses$ = mountersToAppStatus$();
update = createRenderer(
<AppRouter
history={history}
mounters={mockMountersToMounters()}
appStatuses$={appStatuses$}
setAppLeaveHandler={setAppLeaveHandlerMock}
/>
);
Expand Down Expand Up @@ -89,6 +107,7 @@ describe('AppContainer', () => {
<AppRouter
history={history}
mounters={mockMountersToMounters()}
appStatuses$={mountersToAppStatus$()}
setAppLeaveHandler={setAppLeaveHandlerMock}
/>
);
Expand All @@ -107,6 +126,7 @@ describe('AppContainer', () => {
<AppRouter
history={history}
mounters={mockMountersToMounters()}
appStatuses$={mountersToAppStatus$()}
setAppLeaveHandler={setAppLeaveHandlerMock}
/>
);
Expand Down Expand Up @@ -147,6 +167,7 @@ describe('AppContainer', () => {
<AppRouter
history={history}
mounters={mockMountersToMounters()}
appStatuses$={mountersToAppStatus$()}
setAppLeaveHandler={setAppLeaveHandlerMock}
/>
);
Expand Down Expand Up @@ -202,4 +223,16 @@ describe('AppContainer', () => {

expect(dom?.exists(AppNotFound)).toBe(true);
});

it('displays error page if app is inaccessible', async () => {
const dom = await navigate('/app/disabledApp');

expect(dom?.exists(AppNotFound)).toBe(true);
});

it('displays error page if legacy app is inaccessible', async () => {
const dom = await navigate('/app/disabledLegacyApp');

expect(dom?.exists(AppNotFound)).toBe(true);
});
});
9 changes: 6 additions & 3 deletions src/core/public/application/ui/app_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,26 @@ import React, {
MutableRefObject,
} from 'react';

import { AppUnmount, Mounter, AppLeaveHandler } from '../types';
import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types';
import { AppNotFound } from './app_not_found_screen';

interface Props {
appId: string;
mounter?: Mounter;
appStatus: AppStatus;
setAppLeaveHandler: (appId: string, handler: AppLeaveHandler) => void;
}

export const AppContainer: FunctionComponent<Props> = ({
mounter,
appId,
setAppLeaveHandler,
appStatus,
}: Props) => {
const [appNotFound, setAppNotFound] = useState(false);
const elementRef = useRef<HTMLDivElement>(null);
const unmountRef: MutableRefObject<AppUnmount | null> = useRef<AppUnmount>(null);
// const appStatus = useObservable(appStatus$);

useLayoutEffect(() => {
const unmount = () => {
Expand All @@ -52,7 +55,7 @@ export const AppContainer: FunctionComponent<Props> = ({
}
};
const mount = async () => {
if (!mounter) {
if (!mounter || appStatus !== AppStatus.accessible) {
return setAppNotFound(true);
}

Expand All @@ -71,7 +74,7 @@ export const AppContainer: FunctionComponent<Props> = ({

mount();
return unmount;
}, [appId, mounter, setAppLeaveHandler]);
}, [appId, appStatus, mounter, setAppLeaveHandler]);

return (
<Fragment>
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/application/ui/app_not_found_screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';

export const AppNotFound = () => (
<EuiPage style={{ minHeight: '100%' }}>
<EuiPage style={{ minHeight: '100%' }} data-test-subj="appNotFoundPageContent">
<EuiPageBody>
<EuiPageContent verticalPosition="center" horizontalPosition="center">
<EuiEmptyPrompt
Expand Down
Loading

0 comments on commit 3f7a2b8

Please sign in to comment.