Skip to content

Commit

Permalink
Merge branch '7.x' into backport/7.x/pr-64689
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticmachine authored Apr 30, 2020
2 parents 5fc76a7 + 2fddf9a commit ec25eee
Show file tree
Hide file tree
Showing 899 changed files with 10,675 additions and 1,919 deletions.
95 changes: 95 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,101 @@ module.exports = {
},
},

/**
* Lists overrides
*/
{
// typescript and javascript for front and back end
files: ['x-pack/plugins/lists/**/*.{js,ts,tsx}'],
plugins: ['eslint-plugin-node'],
env: {
mocha: true,
jest: true,
},
rules: {
'accessor-pairs': 'error',
'array-callback-return': 'error',
'no-array-constructor': 'error',
complexity: 'error',
'consistent-return': 'error',
'func-style': ['error', 'expression'],
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always',
},
],
'sort-imports': [
'error',
{
ignoreDeclarationSort: true,
},
],
'node/no-deprecated-api': 'error',
'no-bitwise': 'error',
'no-continue': 'error',
'no-dupe-keys': 'error',
'no-duplicate-case': 'error',
'no-duplicate-imports': 'error',
'no-empty-character-class': 'error',
'no-empty-pattern': 'error',
'no-ex-assign': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'error',
'no-extra-boolean-cast': 'error',
'no-extra-label': 'error',
'no-func-assign': 'error',
'no-implicit-globals': 'error',
'no-implied-eval': 'error',
'no-invalid-regexp': 'error',
'no-inner-declarations': 'error',
'no-lone-blocks': 'error',
'no-multi-assign': 'error',
'no-misleading-character-class': 'error',
'no-new-symbol': 'error',
'no-obj-calls': 'error',
'no-param-reassign': ['error', { props: true }],
'no-process-exit': 'error',
'no-prototype-builtins': 'error',
'no-return-await': 'error',
'no-self-compare': 'error',
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-this-before-super': 'error',
'no-undef': 'error',
'no-unreachable': 'error',
'no-unsafe-finally': 'error',
'no-useless-call': 'error',
'no-useless-catch': 'error',
'no-useless-concat': 'error',
'no-useless-computed-key': 'error',
'no-useless-escape': 'error',
'no-useless-rename': 'error',
'no-useless-return': 'error',
'no-void': 'error',
'one-var-declaration-per-line': 'error',
'prefer-object-spread': 'error',
'prefer-promise-reject-errors': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'require-atomic-updates': 'error',
'symbol-description': 'error',
'vars-on-top': 'error',
'@typescript-eslint/explicit-member-accessibility': 'error',
'@typescript-eslint/no-this-alias': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/unified-signatures': 'error',
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-unused-vars': 'error',
'no-template-curly-in-string': 'error',
'sort-keys': 'error',
'prefer-destructuring': 'error',
},
},
/**
* Alerting Services overrides
*/
Expand Down
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-core-public](./kibana-plugin-core-public.md) &gt; [AppBase](./kibana-plugin-core-public.appbase.md) &gt; [defaultPath](./kibana-plugin-core-public.appbase.defaultpath.md)

## AppBase.defaultPath property

Allow to define the default path a user should be directed to when navigating to the app. When defined, this value will be used as a default for the `path` option when calling [navigateToApp](./kibana-plugin-core-public.applicationstart.navigatetoapp.md)<!-- -->\`<!-- -->, and will also be appended to the [application navLink](./kibana-plugin-core-public.chromenavlink.md) in the navigation bar.

<b>Signature:</b>

```typescript
defaultPath?: string;
```
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface AppBase
| [capabilities](./kibana-plugin-core-public.appbase.capabilities.md) | <code>Partial&lt;Capabilities&gt;</code> | Custom capabilities defined by the app. |
| [category](./kibana-plugin-core-public.appbase.category.md) | <code>AppCategory</code> | The category definition of the product See [AppCategory](./kibana-plugin-core-public.appcategory.md) See DEFAULT\_APP\_CATEGORIES for more reference |
| [chromeless](./kibana-plugin-core-public.appbase.chromeless.md) | <code>boolean</code> | Hide the UI chrome when the application is mounted. Defaults to <code>false</code>. Takes precedence over chrome service visibility settings. |
| [defaultPath](./kibana-plugin-core-public.appbase.defaultpath.md) | <code>string</code> | Allow to define the default path a user should be directed to when navigating to the app. When defined, this value will be used as a default for the <code>path</code> option when calling [navigateToApp](./kibana-plugin-core-public.applicationstart.navigatetoapp.md)<!-- -->\`<!-- -->, and will also be appended to the [application navLink](./kibana-plugin-core-public.chromenavlink.md) in the navigation bar. |
| [euiIconType](./kibana-plugin-core-public.appbase.euiicontype.md) | <code>string</code> | A EUI iconType that will be used for the app's icon. This icon takes precendence over the <code>icon</code> property. |
| [icon](./kibana-plugin-core-public.appbase.icon.md) | <code>string</code> | A URL to an image file used as an icon. Used as a fallback if <code>euiIconType</code> is not provided. |
| [id](./kibana-plugin-core-public.appbase.id.md) | <code>string</code> | The unique identifier of the application |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Defines the list of fields that can be updated via an [AppUpdater](./kibana-plug
<b>Signature:</b>

```typescript
export declare type AppUpdatableFields = Pick<AppBase, 'status' | 'navLinkStatus' | 'tooltip'>;
export declare type AppUpdatableFields = Pick<AppBase, 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath'>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ export interface ChromeNavLink
| [subUrlBase](./kibana-plugin-core-public.chromenavlink.suburlbase.md) | <code>string</code> | A url base that legacy apps can set to match deep URLs to an application. |
| [title](./kibana-plugin-core-public.chromenavlink.title.md) | <code>string</code> | The title of the application. |
| [tooltip](./kibana-plugin-core-public.chromenavlink.tooltip.md) | <code>string</code> | A tooltip shown when hovering over an app link. |
| [url](./kibana-plugin-core-public.chromenavlink.url.md) | <code>string</code> | A url that legacy apps can set to deep link into their applications. |
| [url](./kibana-plugin-core-public.chromenavlink.url.md) | <code>string</code> | The route used to open the [default path](./kibana-plugin-core-public.appbase.defaultpath.md) of an application. If unset, <code>baseUrl</code> will be used instead. |

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@

## ChromeNavLink.url property

> Warning: This API is now obsolete.
>
>
A url that legacy apps can set to deep link into their applications.
The route used to open the [default path](./kibana-plugin-core-public.appbase.defaultpath.md) of an application. If unset, `baseUrl` will be used instead.

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export interface SavedObjectsCoreFieldMapping
| [enabled](./kibana-plugin-core-server.savedobjectscorefieldmapping.enabled.md) | <code>boolean</code> | |
| [fields](./kibana-plugin-core-server.savedobjectscorefieldmapping.fields.md) | <code>{</code><br/><code> [subfield: string]: {</code><br/><code> type: string;</code><br/><code> };</code><br/><code> }</code> | |
| [index](./kibana-plugin-core-server.savedobjectscorefieldmapping.index.md) | <code>boolean</code> | |
| [null\_value](./kibana-plugin-core-server.savedobjectscorefieldmapping.null_value.md) | <code>number &#124; boolean &#124; string</code> | |
| [type](./kibana-plugin-core-server.savedobjectscorefieldmapping.type.md) | <code>string</code> | |

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

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsCoreFieldMapping](./kibana-plugin-core-server.savedobjectscorefieldmapping.md) &gt; [null\_value](./kibana-plugin-core-server.savedobjectscorefieldmapping.null_value.md)

## SavedObjectsCoreFieldMapping.null\_value property

<b>Signature:</b>

```typescript
null_value?: number | boolean | string;
```
11 changes: 3 additions & 8 deletions packages/kbn-optimizer/src/worker/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { Bundle, WorkerConfig, parseDirPath, DisallowedSyntaxPlugin } from '../c
const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');

const STATIC_BUNDLE_PLUGINS = [
// { id: 'data', dirname: 'data' },
{ id: 'data', dirname: 'data' },
{ id: 'kibanaReact', dirname: 'kibana_react' },
{ id: 'kibanaUtils', dirname: 'kibana_utils' },
{ id: 'esUiShared', dirname: 'es_ui_shared' },
Expand All @@ -58,13 +58,8 @@ function dynamicExternals(bundle: Bundle, context: string, request: string) {
return;
}

// don't allow any static bundle to rely on other static bundles
if (STATIC_BUNDLE_PLUGINS.some(p => bundle.id === p.id)) {
return;
}

// ignore requests that don't include a /data/public, /kibana_react/public, or
// /kibana_utils/public segment as a cheap way to avoid doing path resolution
// ignore requests that don't include a /{dirname}/public for one of our
// "static" bundles as a cheap way to avoid doing path resolution
// for paths that couldn't possibly resolve to what we're looking for
const reqToStaticBundle = STATIC_BUNDLE_PLUGINS.some(p =>
request.includes(`/${p.dirname}/public`)
Expand Down
87 changes: 85 additions & 2 deletions src/core/public/application/application_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('#setup()', () => {
).toThrowErrorMatchingInlineSnapshot(`"Applications cannot be registered after \\"setup\\""`);
});

it('allows to register a statusUpdater for the application', async () => {
it('allows to register an AppUpdater for the application', async () => {
const setup = service.setup(setupDeps);

const pluginId = Symbol('plugin');
Expand Down Expand Up @@ -118,6 +118,7 @@ describe('#setup()', () => {
updater$.next(app => ({
status: AppStatus.inaccessible,
tooltip: 'App inaccessible due to reason',
defaultPath: 'foo/bar',
}));

applications = await applications$.pipe(take(1)).toPromise();
Expand All @@ -128,6 +129,7 @@ describe('#setup()', () => {
legacy: false,
navLinkStatus: AppNavLinkStatus.default,
status: AppStatus.inaccessible,
defaultPath: 'foo/bar',
tooltip: 'App inaccessible due to reason',
})
);
Expand Down Expand Up @@ -209,7 +211,7 @@ describe('#setup()', () => {
});
});

describe('registerAppStatusUpdater', () => {
describe('registerAppUpdater', () => {
it('updates status fields', async () => {
const setup = service.setup(setupDeps);

Expand Down Expand Up @@ -413,6 +415,36 @@ describe('#setup()', () => {
})
);
});

it('allows to update the basePath', async () => {
const setup = service.setup(setupDeps);

const pluginId = Symbol('plugin');
setup.register(pluginId, createApp({ id: 'app1' }));

const updater = new BehaviorSubject<AppUpdater>(app => ({}));
setup.registerAppUpdater(updater);

const start = await service.start(startDeps);
await start.navigateToApp('app1');
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1', undefined);
MockHistory.push.mockClear();

updater.next(app => ({ defaultPath: 'default-path' }));
await start.navigateToApp('app1');
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/default-path', undefined);
MockHistory.push.mockClear();

updater.next(app => ({ defaultPath: 'another-path' }));
await start.navigateToApp('app1');
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/another-path', undefined);
MockHistory.push.mockClear();

updater.next(app => ({}));
await start.navigateToApp('app1');
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1', undefined);
MockHistory.push.mockClear();
});
});

it("`registerMountContext` calls context container's registerContext", () => {
Expand Down Expand Up @@ -676,6 +708,57 @@ describe('#start()', () => {
expect(MockHistory.push).toHaveBeenCalledWith('/custom/path#/hash/router/path', undefined);
});

it('preserves trailing slash when path contains a hash', async () => {
const { register } = service.setup(setupDeps);

register(Symbol(), createApp({ id: 'app2', appRoute: '/custom/app-path' }));

const { navigateToApp } = await service.start(startDeps);
await navigateToApp('app2', { path: '#/' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom/app-path#/', undefined);
MockHistory.push.mockClear();

await navigateToApp('app2', { path: '#/foo/bar/' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom/app-path#/foo/bar/', undefined);
MockHistory.push.mockClear();

await navigateToApp('app2', { path: '/path#/' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom/app-path/path#/', undefined);
MockHistory.push.mockClear();

await navigateToApp('app2', { path: '/path#/hash/' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom/app-path/path#/hash/', undefined);
MockHistory.push.mockClear();

await navigateToApp('app2', { path: '/path/' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom/app-path/path', undefined);
MockHistory.push.mockClear();
});

it('appends the defaultPath when the path parameter is not specified', async () => {
const { register } = service.setup(setupDeps);

register(Symbol(), createApp({ id: 'app1', defaultPath: 'default/path' }));
register(
Symbol(),
createApp({ id: 'app2', appRoute: '/custom-app-path', defaultPath: '/my-base' })
);

const { navigateToApp } = await service.start(startDeps);

await navigateToApp('app1', { path: 'defined-path' });
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/defined-path', undefined);

await navigateToApp('app1', {});
expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/default/path', undefined);

await navigateToApp('app2', { path: 'defined-path' });
expect(MockHistory.push).toHaveBeenCalledWith('/custom-app-path/defined-path', undefined);

await navigateToApp('app2', {});
expect(MockHistory.push).toHaveBeenCalledWith('/custom-app-path/my-base', undefined);
});

it('includes state if specified', async () => {
const { register } = service.setup(setupDeps);

Expand Down
12 changes: 5 additions & 7 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
Mounter,
} from './types';
import { getLeaveAction, isConfirmAction } from './application_leave';
import { appendAppPath } from './utils';

interface SetupDeps {
context: ContextSetup;
Expand Down Expand Up @@ -81,13 +82,7 @@ const getAppUrl = (mounters: Map<string, Mounter>, appId: string, path: string =
const appBasePath = mounters.get(appId)?.appRoute
? `/${mounters.get(appId)!.appRoute}`
: `/app/${appId}`;

// Only preppend slash if not a hash or query path
path = path.startsWith('#') || path.startsWith('?') ? path : `/${path}`;

return `${appBasePath}${path}`
.replace(/\/{2,}/g, '/') // Remove duplicate slashes
.replace(/\/$/, ''); // Remove trailing slash
return appendAppPath(appBasePath, path);
};

const allApplicationsFilter = '__ALL__';
Expand Down Expand Up @@ -290,6 +285,9 @@ export class ApplicationService {
},
navigateToApp: async (appId, { path, state }: { path?: string; state?: any } = {}) => {
if (await this.shouldNavigate(overlays)) {
if (path === undefined) {
path = applications$.value.get(appId)?.defaultPath;
}
this.appLeaveHandlers.delete(this.currentAppId$.value!);
this.navigate!(getAppUrl(availableMounters, appId, path), state);
this.currentAppId$.next(appId);
Expand Down
15 changes: 13 additions & 2 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export interface AppBase {
*/
navLinkStatus?: AppNavLinkStatus;

/**
* Allow to define the default path a user should be directed to when navigating to the app.
* When defined, this value will be used as a default for the `path` option when calling {@link ApplicationStart.navigateToApp | navigateToApp}`,
* and will also be appended to the {@link ChromeNavLink | application navLink} in the navigation bar.
*/
defaultPath?: string;

/**
* An {@link AppUpdater} observable that can be used to update the application {@link AppUpdatableFields} at runtime.
*
Expand Down Expand Up @@ -187,7 +194,10 @@ export enum AppNavLinkStatus {
* Defines the list of fields that can be updated via an {@link AppUpdater}.
* @public
*/
export type AppUpdatableFields = Pick<AppBase, 'status' | 'navLinkStatus' | 'tooltip'>;
export type AppUpdatableFields = Pick<
AppBase,
'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath'
>;

/**
* Updater for applications.
Expand Down Expand Up @@ -642,7 +652,8 @@ export interface ApplicationStart {
* Navigate to a given app
*
* @param appId
* @param options.path - optional path inside application to deep link to
* @param options.path - optional path inside application to deep link to.
* If undefined, will use {@link AppBase.defaultPath | the app's default path}` as default.
* @param options.state - optional state to forward to the application
*/
navigateToApp(appId: string, options?: { path?: string; state?: any }): Promise<void>;
Expand Down
Loading

0 comments on commit ec25eee

Please sign in to comment.