diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 152a0e2c48871..5fd3ef5e8ff4b 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -141,6 +141,39 @@ function addBar(foos, foo) { } ``` +### Avoid `any` whenever possible + +Since TypeScript 3.0 and the introduction of the +[`unknown` type](https://mariusschulz.com/blog/the-unknown-type-in-typescript) there are rarely any +reasons to use `any` as a type. Nearly all places of former `any` usage can be replace by either a +generic or `unknown` (in cases the type is really not known). + +You should always prefer using those mechanisms over using `any`, since they are stricter typed and +less likely to introduce bugs in the future due to insufficient types. + +If you’re not having `any` in your plugin or are starting a new plugin, you should enable the +[`@typescript-eslint/no-explicit-any`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md) +linting rule for your plugin via the [`.eslintrc.js`](https://github.com/elastic/kibana/blob/master/.eslintrc.js) config. + +### Avoid non-null assertions + +You should try avoiding non-null assertions (`!.`) wherever possible. By using them you tell +TypeScript, that something is not null even though by it’s type it could be. Usage of non-null +assertions is most often a side-effect of you actually checked that the variable is not `null` +but TypeScript doesn’t correctly carry on that information till the usage of the variable. + +In most cases it’s possible to replace the non-null assertion by structuring your code/checks slightly different +or using [user defined type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) +to properly tell TypeScript what type a variable has. + +Using non-null assertion increases the risk for future bugs. In case the condition under which we assumed that the +variable can’t be null has changed (potentially even due to changes in compeltely different files), the non-null +assertion would now wrongly disable proper type checking for us. + +If you’re not using non-null assertions in your plugin or are starting a new plugin, consider enabling the +[`@typescript-eslint/no-non-null-assertion`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md) +linting rule for you plugin in the [`.eslintrc.js`](https://github.com/elastic/kibana/blob/master/.eslintrc.js) config. + ### Return/throw early from functions To avoid deep nesting of if-statements, always return a function's value as early diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md index 0b5bd8eeb36ec..f264ba500ed6e 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md @@ -9,7 +9,7 @@ Register a context provider for application mounting. Will only be available to Signature: ```typescript -registerMountContext(contextName: T, provider: IContextProvider): void; +registerMountContext(contextName: T, provider: IContextProvider): void; ``` ## Parameters @@ -17,7 +17,7 @@ registerMountContext(contextName: T, provider: | Parameter | Type | Description | | --- | --- | --- | | contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | -| provider | IContextProvider<AppMountContext, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | +| provider | IContextProvider<App['mount'], T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | Returns: diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md index fc86aaf658b68..62821fcbb92ba 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md @@ -9,7 +9,7 @@ Register a context provider for application mounting. Will only be available to Signature: ```typescript -registerMountContext(contextName: T, provider: IContextProvider): void; +registerMountContext(contextName: T, provider: IContextProvider): void; ``` ## Parameters @@ -17,7 +17,7 @@ registerMountContext(contextName: T, provider: | Parameter | Type | Description | | --- | --- | --- | | contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | -| provider | IContextProvider<AppMountContext, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | +| provider | IContextProvider<App['mount'], T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | Returns: diff --git a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md index 2644596354e38..5334eee842577 100644 --- a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md +++ b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md @@ -9,9 +9,9 @@ Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) f Signature: ```typescript -createContextContainer(): IContextContainer; +createContextContainer>(): IContextContainer; ``` Returns: -`IContextContainer` +`IContextContainer` diff --git a/docs/development/core/public/kibana-plugin-public.handlercontexttype.md b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md new file mode 100644 index 0000000000000..b083449d2b703 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) + +## HandlerContextType type + +Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. + +Signature: + +```typescript +export declare type HandlerContextType> = T extends HandlerFunction ? U : never; +``` diff --git a/docs/development/core/public/kibana-plugin-public.handlerfunction.md b/docs/development/core/public/kibana-plugin-public.handlerfunction.md new file mode 100644 index 0000000000000..98c342c17691d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.handlerfunction.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerFunction](./kibana-plugin-public.handlerfunction.md) + +## HandlerFunction type + +A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) + +Signature: + +```typescript +export declare type HandlerFunction = (context: T, ...args: any[]) => any; +``` diff --git a/docs/development/core/public/kibana-plugin-public.handlerparameters.md b/docs/development/core/public/kibana-plugin-public.handlerparameters.md new file mode 100644 index 0000000000000..f46c4b649e943 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.handlerparameters.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerParameters](./kibana-plugin-public.handlerparameters.md) + +## HandlerParameters type + +Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). + +Signature: + +```typescript +export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; +``` diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md index 2a995df45757f..af3b5e3fc2eb6 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md @@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin. Signature: ```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; +createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; ``` ## Parameters @@ -17,11 +17,11 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandlerPluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | -| handler | IContextHandler<TContext, THandlerReturn, THandlerParameters> | Handler function to pass context object to. | +| handler | THandler | Handler function to pass context object to. | Returns: -`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise` +`(...rest: HandlerParameters) => ShallowPromise>` A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md index 0bc7c8f3808d1..f16c07b3d7906 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md @@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler Signature: ```typescript -export interface IContextContainer +export interface IContextContainer> ``` ## Methods diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md index 2cf10a6ec841d..775f95bd7affa 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md @@ -9,7 +9,7 @@ Register a new context provider. Signature: ```typescript -registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; ``` ## Parameters @@ -18,7 +18,7 @@ registerContext(pluginOpaqueId: PluginOpaqu | --- | --- | --- | | pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | | contextName | TContextName | The key of the TContext object this provider supplies the value for. | -| provider | IContextProvider<TContext, TContextName, THandlerParameters> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. | +| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. | Returns: diff --git a/docs/development/core/public/kibana-plugin-public.icontexthandler.md b/docs/development/core/public/kibana-plugin-public.icontexthandler.md deleted file mode 100644 index 2251b1131c313..0000000000000 --- a/docs/development/core/public/kibana-plugin-public.icontexthandler.md +++ /dev/null @@ -1,18 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextHandler](./kibana-plugin-public.icontexthandler.md) - -## IContextHandler type - -A function registered by a plugin to perform some action. - -Signature: - -```typescript -export declare type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; -``` - -## Remarks - -A new `TContext` will be built for each handler before invoking. - diff --git a/docs/development/core/public/kibana-plugin-public.icontextprovider.md b/docs/development/core/public/kibana-plugin-public.icontextprovider.md index a84917d6e1442..40f0ee3782f6d 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextprovider.md +++ b/docs/development/core/public/kibana-plugin-public.icontextprovider.md @@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type Signature: ```typescript -export declare type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; +export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; ``` ## Remarks diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index e2ef807a75018..7531cf9a06333 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -91,11 +91,13 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | | [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | +| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). | | [HttpBody](./kibana-plugin-public.httpbody.md) | | | [HttpHandler](./kibana-plugin-public.httphandler.md) | | | [HttpSetup](./kibana-plugin-public.httpsetup.md) | | | [HttpStart](./kibana-plugin-public.httpstart.md) | | -| [IContextHandler](./kibana-plugin-public.icontexthandler.md) | A function registered by a plugin to perform some action. | | [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | | [OverlayBannerMount](./kibana-plugin-public.overlaybannermount.md) | A function that will mount the banner inside the provided element. | | [OverlayBannerUnmount](./kibana-plugin-public.overlaybannerunmount.md) | A function that will unmount the banner from the element. | diff --git a/docs/development/core/server/kibana-plugin-server.basepath.get.md b/docs/development/core/server/kibana-plugin-server.basepath.get.md index 2b3b6c899e8de..04feca7ccc5a8 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.get.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.get.md @@ -9,5 +9,5 @@ returns `basePath` value, specific for an incoming request. Signature: ```typescript -get: (request: KibanaRequest | LegacyRequest) => string; +get: (request: LegacyRequest | KibanaRequest) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.md b/docs/development/core/server/kibana-plugin-server.basepath.md index 45fb697b329f8..bfa1ea02aec17 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.md @@ -16,11 +16,11 @@ export declare class BasePath | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [get](./kibana-plugin-server.basepath.get.md) | | (request: KibanaRequest<unknown, unknown, unknown> | LegacyRequest) => string | returns basePath value, specific for an incoming request. | +| [get](./kibana-plugin-server.basepath.get.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown>) => string | returns basePath value, specific for an incoming request. | | [prepend](./kibana-plugin-server.basepath.prepend.md) | | (path: string) => string | returns a new basePath value, prefixed with passed url. | | [remove](./kibana-plugin-server.basepath.remove.md) | | (path: string) => string | returns a new basePath value, cleaned up from passed url. | | [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) | | string | returns the server's basePathSee [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request | -| [set](./kibana-plugin-server.basepath.set.md) | | (request: KibanaRequest<unknown, unknown, unknown> | LegacyRequest, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | +| [set](./kibana-plugin-server.basepath.set.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown>, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | ## Remarks diff --git a/docs/development/core/server/kibana-plugin-server.basepath.set.md b/docs/development/core/server/kibana-plugin-server.basepath.set.md index 1272a134ef5c4..cec70ee853bfa 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.set.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.set.md @@ -9,5 +9,5 @@ sets `basePath` value, specific for an incoming request. Signature: ```typescript -set: (request: KibanaRequest | LegacyRequest, requestSpecificBasePath: string) => void; +set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; ``` diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md index f44e6a3d7640b..7096bfc43a520 100644 --- a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md @@ -9,9 +9,9 @@ Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) f Signature: ```typescript -createContextContainer(): IContextContainer; +createContextContainer>(): IContextContainer; ``` Returns: -`IContextContainer` +`IContextContainer` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.http.md b/docs/development/core/server/kibana-plugin-server.coresetup.http.md index 254f2728abef1..8474f4ef940dc 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.http.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.http.md @@ -14,7 +14,7 @@ http: { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; basePath: HttpServiceSetup['basePath']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; - registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; + registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; createRouter: () => IRouter; }; ``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.md b/docs/development/core/server/kibana-plugin-server.coresetup.md index ed487a570f286..528557e91bd17 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.md @@ -18,5 +18,5 @@ export interface CoreSetup | --- | --- | --- | | [context](./kibana-plugin-server.coresetup.context.md) | {
createContextContainer: ContextSetup['createContextContainer'];
} | | | [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | {
adminClient$: Observable<ClusterClient>;
dataClient$: Observable<ClusterClient>;
createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ClusterClient;
} | | -| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(name: T, provider: RequestHandlerContextProvider<RequestHandlerContext>) => RequestHandlerContextContainer<RequestHandlerContext>;
createRouter: () => IRouter;
} | | +| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(name: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer;
createRouter: () => IRouter;
} | | diff --git a/docs/development/core/server/kibana-plugin-server.handlercontexttype.md b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md new file mode 100644 index 0000000000000..e8f1f346e8b8e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) + +## HandlerContextType type + +Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. + +Signature: + +```typescript +export declare type HandlerContextType> = T extends HandlerFunction ? U : never; +``` diff --git a/docs/development/core/server/kibana-plugin-server.handlerfunction.md b/docs/development/core/server/kibana-plugin-server.handlerfunction.md new file mode 100644 index 0000000000000..97acd37946fc9 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.handlerfunction.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerFunction](./kibana-plugin-server.handlerfunction.md) + +## HandlerFunction type + +A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) + +Signature: + +```typescript +export declare type HandlerFunction = (context: T, ...args: any[]) => any; +``` diff --git a/docs/development/core/server/kibana-plugin-server.handlerparameters.md b/docs/development/core/server/kibana-plugin-server.handlerparameters.md new file mode 100644 index 0000000000000..3dd7998a71a1f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.handlerparameters.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerParameters](./kibana-plugin-server.handlerparameters.md) + +## HandlerParameters type + +Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). + +Signature: + +```typescript +export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md index 92bf158ad3312..eec63cf5c8093 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md @@ -10,6 +10,6 @@ ```typescript export declare type HttpServiceSetup = Omit & { createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; - registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; + registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; }; ``` diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md index c5549ab017e53..09a9e28d6d0fe 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md @@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin. Signature: ```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; +createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; ``` ## Parameters @@ -17,11 +17,11 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandlerPluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | -| handler | IContextHandler<TContext, THandlerReturn, THandlerParameters> | Handler function to pass context object to. | +| handler | THandler | Handler function to pass context object to. | Returns: -`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise` +`(...rest: HandlerParameters) => ShallowPromise>` A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md index 1ab699be105b4..114da31442ff9 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md @@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler Signature: ```typescript -export interface IContextContainer +export interface IContextContainer> ``` ## Methods diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md index 1a63f63dc91b4..30d3fc154d1e9 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md @@ -9,7 +9,7 @@ Register a new context provider. Signature: ```typescript -registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; ``` ## Parameters @@ -18,7 +18,7 @@ registerContext(pluginOpaqueId: PluginOpaqu | --- | --- | --- | | pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | | contextName | TContextName | The key of the TContext object this provider supplies the value for. | -| provider | IContextProvider<TContext, TContextName, THandlerParameters> | A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. | +| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. | Returns: diff --git a/docs/development/core/server/kibana-plugin-server.icontexthandler.md b/docs/development/core/server/kibana-plugin-server.icontexthandler.md deleted file mode 100644 index c1f5acc22734a..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.icontexthandler.md +++ /dev/null @@ -1,18 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextHandler](./kibana-plugin-server.icontexthandler.md) - -## IContextHandler type - -A function registered by a plugin to perform some action. - -Signature: - -```typescript -export declare type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; -``` - -## Remarks - -A new `TContext` will be built for each handler before invoking. - diff --git a/docs/development/core/server/kibana-plugin-server.icontextprovider.md b/docs/development/core/server/kibana-plugin-server.icontextprovider.md index 250e6a2be3f6a..39ace8b9bc57e 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextprovider.md +++ b/docs/development/core/server/kibana-plugin-server.icontextprovider.md @@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type Signature: ```typescript -export declare type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; +export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index d943228bbea06..3c01e7aeef325 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -116,11 +116,13 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) | | | [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-server.getauthstate.md) | Get authentication state for a request. Returned by auth interceptor. | +| [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-server.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-server.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). | | [Headers](./kibana-plugin-server.headers.md) | Http request headers to read. | | [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) | Data send to the client as a response payload. | | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | | | [IBasePath](./kibana-plugin-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-server.basepath.md) | -| [IContextHandler](./kibana-plugin-server.icontexthandler.md) | A function registered by a plugin to perform some action. | | [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | | [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. | | [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | @@ -136,8 +138,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RequestHandler](./kibana-plugin-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. | | [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | | [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. | -| [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) | Parameters passed to the request handler function. | -| [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) | Expected outcome the request handler function. | | [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. | | [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. | | [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. | diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md index afdb488597069..b76a9ce7d235c 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md @@ -9,5 +9,5 @@ An object that handles registration of http request context providers. Signature: ```typescript -export declare type RequestHandlerContextContainer = IContextContainer, RequestHandlerParams>; +export declare type RequestHandlerContextContainer = IContextContainer>; ``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md index 0d9cc6b70b80c..ea7294b721aab 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md @@ -9,5 +9,5 @@ Context provider for request handler. Extends request context object with provid Signature: ```typescript -export declare type RequestHandlerContextProvider = IContextProvider; +export declare type RequestHandlerContextProvider = IContextProvider, TContextName>; ``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md b/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md deleted file mode 100644 index 7f466845b4d46..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) - -## RequestHandlerParams type - -Parameters passed to the request handler function. - -Signature: - -```typescript -export declare type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; -``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md b/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md deleted file mode 100644 index 6c01e21b6ecbe..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) - -## RequestHandlerReturn type - -Expected outcome the request handler function. - -Signature: - -```typescript -export declare type RequestHandlerReturn = KibanaResponse; -``` diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc index 25c07dc502484..8d9ef515108ed 100644 --- a/docs/management/index-patterns.asciidoc +++ b/docs/management/index-patterns.asciidoc @@ -35,8 +35,11 @@ image:management/index-patterns/images/rollup-index-pattern.png["Menu with rollu {kib} makes it easy for you to create an index pattern by walking you through the process. Just start typing in the *Index pattern* field, and {kib} looks for -the names of {es} indices that match your input. If you want to include -system indices in your search, toggle the switch in the upper right. +the names of {es} indices that match your input. Make sure that the name of the +index pattern is unique. + +If you want to include system indices in your search, toggle the switch in the +upper right. [role="screenshot"] image:management/index-patterns/images/create-index-pattern.png["Create index pattern"] diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc index 7330c7e144b60..97fb891c95bdb 100644 --- a/docs/settings/monitoring-settings.asciidoc +++ b/docs/settings/monitoring-settings.asciidoc @@ -21,7 +21,7 @@ To control how data is collected from your {es} nodes, you configure {ref}/monitoring-settings.html[`xpack.monitoring.collection` settings] in `elasticsearch.yml`. To control how monitoring data is collected from Logstash, you configure -{logstash-ref}/configuring-logstash.html#monitoring-settings[`xpack.monitoring` settings] +{logstash-ref}/monitoring-internal-collection.html#monitoring-settings[`xpack.monitoring` settings] in `logstash.yml`. For more information, see diff --git a/package.json b/package.json index 8aff95748560d..fb65efdde6912 100644 --- a/package.json +++ b/package.json @@ -240,7 +240,7 @@ "style-loader": "0.23.1", "symbol-observable": "^1.2.0", "tar": "4.4.13", - "terser-webpack-plugin": "^1.4.1", + "terser-webpack-plugin": "^2.1.2", "thread-loader": "^2.1.3", "tinygradient": "0.4.3", "tinymath": "1.2.1", diff --git a/packages/kbn-es-query/src/es_query/index.d.ts b/packages/kbn-es-query/src/es_query/index.d.ts new file mode 100644 index 0000000000000..9510a18441e53 --- /dev/null +++ b/packages/kbn-es-query/src/es_query/index.d.ts @@ -0,0 +1,39 @@ +/* + * 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 function buildQueryFromFilters(filters: unknown[], indexPattern: unknown): unknown; +export function buildEsQuery( + indexPattern: unknown, + queries: unknown, + filters: unknown, + config?: { + allowLeadingWildcards: boolean; + queryStringOptions: unknown; + ignoreFilterIfFieldNotInIndex: boolean; + dateFormatTZ?: string | null; + } +): unknown; +export function getEsQueryConfig(config: { + get: (name: string) => unknown; +}): { + allowLeadingWildcards: boolean; + queryStringOptions: unknown; + ignoreFilterIfFieldNotInIndex: boolean; + dateFormatTZ?: string | null; +}; diff --git a/packages/kbn-es-query/src/index.d.ts b/packages/kbn-es-query/src/index.d.ts index 873636a28889f..ca4455da33f45 100644 --- a/packages/kbn-es-query/src/index.d.ts +++ b/packages/kbn-es-query/src/index.d.ts @@ -17,5 +17,6 @@ * under the License. */ +export * from './es_query'; export * from './kuery'; export * from './filters'; diff --git a/renovate.json5 b/renovate.json5 index e5dd29aa63190..cd836762b817f 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -67,6 +67,17 @@ '(\\b|_)jest(\\b|_)', ], }, + { + groupSlug: '@elastic/charts', + groupName: '@elastic/charts related packages', + packageNames: [ + '@elastic/charts', + '@types/elastic__charts', + ], + reviewers: [ + 'markov00', + ], + }, { groupSlug: 'mocha', groupName: 'mocha related packages', diff --git a/rfcs/text/0006_management_section_service.md b/rfcs/text/0006_management_section_service.md new file mode 100644 index 0000000000000..bcb74b1bcd8da --- /dev/null +++ b/rfcs/text/0006_management_section_service.md @@ -0,0 +1,332 @@ +- Start Date: 2019-08-20 +- RFC PR: TBD +- Kibana Issue: [#43499](https://github.com/elastic/kibana/issues/43499) + +# Summary +Management is one of the four primary "domains" covered by @elastic/kibana-app-arch (along with Data, Embeddables, and Visualizations). There are two main purposes for this service: + +1. Own the management "framework" -- the UI that displays the management sidebar nav, the landing page, and handles rendering each of the sections +2. Expose a registry for other plugins to add their own registry sections to the UI and add nested links to them in the sidebar. + +The purpose of this RFC is to consider item 2 above -- the service for registering sections to the nav & loading them up. + +# Motivation + +## Why now? +The main driver for considering this now is that the Management API moving to the new platform is going to block other teams from completing migration, so we need to have an answer to what the new platform version of the API looks like as soon as possible in `7.x`. + +## Why not just keep the current API and redesign later? +The answer to that has to do with the items that are currently used in the management implementation which must be removed in order to migrate to NP: the framework currently registers a `uiExport`, and relies on `IndexedArray`, `uiRegistry`, and `ui/routes`. + +This means that we will basically need to rebuild the service anyway in order to migrate to the new platform. So if we are going to invest that time, we might as well invest it in building the API the way we want it to be longer term, rather than creating more work for ourselves later. + +## Technical goals +- Remove another usage of `IndexedArray` & `uiRegistry` (required for migration) +- Remove dependency on `ui/routes` (required for migration) +- Remove management section `uiExport` (required for migration) +- Simple API that is designed in keeping with new platform principles + - This includes being rendering-framework-agnostic... You should be able to build your management section UI however you'd like +- Clear separation of app/UI code and service code, even if both live within the same plugin +- Flexibility to potentially support alternate layouts in the future (see mockups in [reference section](#reference) below) + +# Basic example +This API is influenced heavily by the [application service mounting RFC](https://github.com/elastic/kibana/blob/master/rfcs/text/0004_application_service_mounting.md). The intent is to make the experience consistent with that service; the Management section is basically one big app with a bunch of registered "subapps". + +```ts +// my_plugin/public/plugin.ts + +export class MyPlugin { + setup(core, { management }) { + // Registering a new app to a new section + const mySection = management.sections.register({ + id: 'my-section', + title: 'My Main Section', // display name + order: 10, + euiIconType: 'iconName', + }); + mySection.registerApp({ + id: 'my-management-app', + title: 'My Management App', // display name + order: 20, + async mount(context, params) { + const { renderApp } = await import('./my-section'); + return renderApp(context, params); + } + }); + + // Registering a new app to an existing section + const kibanaSection = management.sections.get('kibana'); + kibanaSection.registerApp({ id: 'my-kibana-management-app', ... }); + } + + start(core, { management }) { + // access all registered sections, filtered based on capabilities + const sections = management.sections.getAvailable(); + sections.forEach(section => console.log(`${section.id} - ${section.title}`)); + // automatically navigate to any app by id + management.sections.navigateToApp('my-kibana-management-app'); + } +} + +// my_plugin/public/my-section.tsx + +export function renderApp(context, { sectionBasePath, element }) { + ReactDOM.render( + // `sectionBasePath` would be `/app/management/my-section/my-management-app` + , + element + ); + + // return value must be a function that unmounts (just like Core Application Service) + return () => ReactDOM.unmountComponentAtNode(element); +} +``` + +We can also create a utility in `kibana_react` to make it easy for folks to `mount` a React app: +```ts +// src/plugins/kibana_react/public/mount_with_react.tsx +import { KibanaContextProvider } from './context'; + +export const mountWithReact = ( + Component: React.ComponentType<{ basename: string }>, + context: AppMountContext, + params: ManagementSectionMountParams, +) => { + ReactDOM.render( + ( + + + + ), + params.element + ); + + return () => ReactDOM.unmountComponentAtNode(params.element); +} + +// my_plugin/public/plugin.ts +import { mountWithReact } from 'src/plugins/kibana_react/public'; + +export class MyPlugin { + setup(core, { management }) { + const kibanaSection = management.sections.get('kibana'); + kibanaSection.registerApp({ + id: 'my-other-kibana-management-app', + ..., + async mount(context, params) { + const { MySection } = await import('./components/my-section'); + const unmountCallback = mountWithReact(MySection, context, params); + return () => unmountCallback(); + } + }); + } +} +``` + +# Detailed design + +```ts +interface ManagementSetup { + sections: SectionsServiceSetup; +} + +interface ManagementStart { + sections: SectionsServiceStart; +} + +interface SectionsServiceSetup { + get: (sectionId: string) => Section; + getAvailable: () => Section[]; // filtered based on capabilities + register: RegisterSection; +} + +interface SectionsServiceStart { + getAvailable: () => Array>; // filtered based on capabilities + // uses `core.application.navigateToApp` under the hood, automatically prepending the `path` for the link + navigateToApp: (appId: string, options?: { path?: string; state?: any }) => void; +} + +type RegisterSection = ( + id: string, + title: string, + order?: number, + euiIconType?: string, // takes precedence over `icon` property. + icon?: string, // URL to image file; fallback if no `euiIconType` +) => Section; + +type RegisterManagementApp = ( + id: string; + title: string; + order?: number; + mount: ManagementSectionMount; +) => ManagementApp; + +type Unmount = () => Promise | void; + +interface ManagementSectionMountParams { + sectionBasePath: string; // base path for setting up your router + element: HTMLElement; // element the section should render into +} + +type ManagementSectionMount = ( + context: AppMountContext, // provided by core.ApplicationService + params: ManagementSectionMountParams, +) => Unmount | Promise; + +interface ManagementApp { + id: string; + title: string; + basePath: string; + sectionId: string; + order?: number; +} + +interface Section { + id: string; + title: string; + apps: ManagementApp[]; + registerApp: RegisterManagementApp; + order?: number; + euiIconType?: string; + icon?: string; +} +``` + +# Legacy service (what this would be replacing) + +Example of how this looks today: +```js +// myplugin/index +new Kibana.Plugin({ + uiExports: { + managementSections: ['myplugin/management'], + } +}); + +// myplugin/public/management +import { management } from 'ui/management'; + +// completely new section +const newSection = management.register('mypluginsection', { + name: 'mypluginsection', + order: 10, + display: 'My Plugin', + icon: 'iconName', +}); +newSection.register('mypluginlink', { + name: 'mypluginlink', + order: 10, + display: 'My sublink', + url: `#/management/myplugin`, +}); + +// new link in existing section +const kibanaSection = management.getSection('kibana'); +kibanaSection.register('mypluginlink', { + name: 'mypluginlink', + order: 10, + display: 'My sublink', + url: `#/management/myplugin`, +}); + +// use ui/routes to render component +import routes from 'ui/routes'; + +const renderReact = (elem) => { + render(, elem); +}; + +routes.when('management/myplugin', { + controller($scope, $http, kbnUrl) { + $scope.$on('$destroy', () => { + const elem = document.getElementById('usersReactRoot'); + if (elem) unmountComponentAtNode(elem); + }); + $scope.$$postDigest(() => { + const elem = document.getElementById('usersReactRoot'); + const changeUrl = (url) => { + kbnUrl.change(url); + $scope.$apply(); + }; + renderReact(elem, $http, changeUrl); + }); + }, +}); +``` +Current public contracts owned by the legacy service: +```js +// ui/management/index +interface API { + PAGE_TITLE_COMPONENT: string; // actually related to advanced settings? + PAGE_SUBTITLE_COMPONENT: string; // actually related to advanced settings? + PAGE_FOOTER_COMPONENT: string; // actually related to advanced settings? + SidebarNav: React.SFC; + registerSettingsComponent: ( + id: string, + component: string | React.SFC, + allowOverride: boolean + ) => void; + management: new ManagementSection(); + MANAGEMENT_BREADCRUMB: { + text: string; + href: string; + }; +} + +// ui/management/section +class ManagementSection { + get visibleItems, + addListener: (fn: function) => void, + register: (id: string, options: Options) => ManagementSection, + deregister: (id: string) => void, + hasItem: (id: string) => boolean, + getSection: (id: string) => ManagementSection, + hide: () => void, + show: () => void, + disable: () => void, + enable: () => void, +} + +interface Options { + order: number | null; + display: string | null; // defaults to id + url: string | null; // defaults to '' + visible: boolean | null; // defaults to true + disabled: boolean | null; // defaults to false + tooltip: string | null; // defaults to '' + icon: string | null; // defaults to '' +} +``` + +# Notes + +- The hide/show/disable/enable options were dropped with the assumption that we will be working with uiCapabilities to determine this instead... so people shouldn't need to manage it manually as they can look up a pre-filtered list of sections. +- This was updated to add flexibility for custom (non-EUI) icons as outlined in [#32661](https://github.com/elastic/kibana/issues/32661). Much like the Core Application Service, you either choose an EUI icon, or provide a URL to an icon. + +# Drawbacks + +- This removes the ability to infinitely nest sections within each other by making a distinction between a section header and a nav link. + - So far we didn't seem to be using this feature anyway, but would like feedback on any use cases for it. + +# Reference + +- Issues about Global vs Spaces-based management sections: https://github.com/elastic/kibana/issues/37285 https://github.com/elastic/kibana/issues/37283 +- Mockups related to above issues: https://marvelapp.com/52b8616/screen/57582729 + +# Alternatives + +An alternative design would be making everything React-specific and simply requiring consumers of the service to provide a React component to render when a route is hit, or giving them a react-router instance to work with. + +This would require slightly less work for folks using the service as it would eliminate the need for a `mount` function. However, it comes at the cost of forcing folks into a specific rendering framework, which ultimately provides less flexibility. + +# Adoption strategy + +Our strategy for implementing this should be to build the service entirely in the new platform in a `management` plugin, so that plugins can gradually cut over to the new service as they prepare to migrate to the new platform. + +One thing we would need to figure out is how to bridge the gap between the new plugin and the legacy `ui/management` service. Ideally we would find a way to integrate the two, such that the management nav could display items registered via both services. This is a strategy we'd need to work out in more detail as we got closer to implementation. + +# How we teach this + +The hope is that this will already feel familiar to Kibana application developers, as most will have already been exposed to the Core Application Service and how it handles mounting. + +A guide could also be added to the "Management" section of the Kibana docs (the legacy service is not even formally documented). diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index d1855a0370f00..935844baddf86 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -27,12 +27,9 @@ import { AppRouter } from './ui'; import { HttpStart } from '../http'; import { ContextSetup, IContextContainer } from '../context'; import { - AppMountContext, App, LegacyApp, AppMounter, - AppUnmount, - AppMountParameters, InternalApplicationSetup, InternalApplicationStart, } from './types'; @@ -64,11 +61,7 @@ export class ApplicationService { private readonly apps$ = new BehaviorSubject>(new Map()); private readonly legacyApps$ = new BehaviorSubject>(new Map()); private readonly capabilities = new CapabilitiesService(); - private mountContext?: IContextContainer< - AppMountContext, - AppUnmount | Promise, - [AppMountParameters] - >; + private mountContext?: IContextContainer; public setup({ context }: SetupDeps): InternalApplicationSetup { this.mountContext = context.createContextContainer(); @@ -98,7 +91,7 @@ export class ApplicationService { this.legacyApps$.next(new Map([...this.legacyApps$.value.entries(), [app.id, app]])); }, - registerMountContext: this.mountContext.registerContext, + registerMountContext: this.mountContext!.registerContext, }; } diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 018d7569ce411..b2d0aff26b8b0 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -193,7 +193,7 @@ export interface ApplicationSetup { */ registerMountContext( contextName: T, - provider: IContextProvider + provider: IContextProvider ): void; } @@ -224,7 +224,7 @@ export interface InternalApplicationSetup { registerMountContext( pluginOpaqueId: PluginOpaqueId, contextName: T, - provider: IContextProvider + provider: IContextProvider ): void; } @@ -261,7 +261,7 @@ export interface ApplicationStart { */ registerMountContext( contextName: T, - provider: IContextProvider + provider: IContextProvider ): void; } @@ -291,7 +291,7 @@ export interface InternalApplicationStart registerMountContext( pluginOpaqueId: PluginOpaqueId, contextName: T, - provider: IContextProvider + provider: IContextProvider ): void; // Internal APIs diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index afd9f8e4a3820..f24b0ed1681aa 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -19,7 +19,7 @@ import Url from 'url'; -import React, { Component, createRef, Fragment } from 'react'; +import React, { Component, createRef } from 'react'; import * as Rx from 'rxjs'; import { @@ -376,7 +376,7 @@ class HeaderUI extends Component { ]; return ( - +
@@ -407,11 +407,13 @@ class HeaderUI extends Component { isLocked={isLocked} onIsLockedUpdate={onIsLockedUpdate} > - - - + - +
); } diff --git a/src/core/public/context/context_service.ts b/src/core/public/context/context_service.ts index 704524d838636..dadc509c97821 100644 --- a/src/core/public/context/context_service.ts +++ b/src/core/public/context/context_service.ts @@ -18,7 +18,7 @@ */ import { PluginOpaqueId } from '../../server'; -import { IContextContainer, ContextContainer } from '../../utils/context'; +import { IContextContainer, ContextContainer, HandlerFunction } from '../../utils/context'; import { CoreContext } from '../core_system'; interface StartDeps { @@ -31,15 +31,8 @@ export class ContextService { public setup({ pluginDependencies }: StartDeps): ContextSetup { return { - createContextContainer: < - TContext extends {}, - THandlerReturn, - THandlerParameters extends any[] = [] - >() => - new ContextContainer( - pluginDependencies, - this.core.coreId - ), + createContextContainer: >() => + new ContextContainer(pluginDependencies, this.core.coreId), }; } } @@ -111,9 +104,5 @@ export interface ContextSetup { /** * Creates a new {@link IContextContainer} for a service owner. */ - createContextContainer< - TContext extends {}, - THandlerReturn, - THandlerParmaters extends any[] = [] - >(): IContextContainer; + createContextContainer>(): IContextContainer; } diff --git a/src/core/public/context/index.ts b/src/core/public/context/index.ts index 28b2641b2a5a7..f22c4168d7544 100644 --- a/src/core/public/context/index.ts +++ b/src/core/public/context/index.ts @@ -18,4 +18,10 @@ */ export { ContextService, ContextSetup } from './context_service'; -export { IContextContainer, IContextProvider, IContextHandler } from '../../utils/context'; +export { + IContextContainer, + IContextProvider, + HandlerFunction, + HandlerContextType, + HandlerParameters, +} from '../../utils/context'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 393a7076759e8..1e2dfde7496ea 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -67,7 +67,14 @@ import { UiSettingsClient, UiSettingsState, UiSettingsClientContract } from './u import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; -import { IContextContainer, IContextProvider, ContextSetup, IContextHandler } from './context'; +import { + IContextContainer, + IContextProvider, + ContextSetup, + HandlerFunction, + HandlerContextType, + HandlerParameters, +} from './context'; export { CoreContext, CoreSystem } from './core_system'; export { RecursiveReadonly } from '../utils'; @@ -217,7 +224,9 @@ export { ChromeRecentlyAccessedHistoryItem, ChromeStart, IContextContainer, - IContextHandler, + HandlerFunction, + HandlerContextType, + HandlerParameters, IContextProvider, ContextSetup, DocLinksStart, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 102e77b564a6d..e6c8f116e5782 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -9,6 +9,7 @@ import { MouseEventHandler } from 'react'; import { Observable } from 'rxjs'; import React from 'react'; import * as Rx from 'rxjs'; +import { ShallowPromise } from '@kbn/utility-types'; import { EuiGlobalToastListToast as Toast } from '@elastic/eui'; // @public @@ -31,7 +32,7 @@ export interface AppBase { // @public (undocumented) export interface ApplicationSetup { register(app: App): void; - registerMountContext(contextName: T, provider: IContextProvider): void; + registerMountContext(contextName: T, provider: IContextProvider): void; } // @public (undocumented) @@ -44,7 +45,7 @@ export interface ApplicationStart { path?: string; state?: any; }): void; - registerMountContext(contextName: T, provider: IContextProvider): void; + registerMountContext(contextName: T, provider: IContextProvider): void; } // @public @@ -213,7 +214,7 @@ export interface ChromeStart { // @public export interface ContextSetup { - createContextContainer(): IContextContainer; + createContextContainer>(): IContextContainer; } // @internal (undocumented) @@ -389,6 +390,15 @@ export interface FatalErrorsSetup { get$: () => Rx.Observable; } +// @public +export type HandlerContextType> = T extends HandlerFunction ? U : never; + +// @public +export type HandlerFunction = (context: T, ...args: any[]) => any; + +// @public +export type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; + // @public (undocumented) export type HttpBody = BodyInit | null | any; @@ -551,16 +561,13 @@ export interface I18nStart { } // @public -export interface IContextContainer { - createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; - registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +export interface IContextContainer> { + createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; + registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; } // @public -export type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; - -// @public -export type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; +export type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; // @public @deprecated export interface LegacyCoreSetup extends CoreSetup { diff --git a/src/core/server/context/context_service.ts b/src/core/server/context/context_service.ts index 80935840c5536..1c5bd41a01f0f 100644 --- a/src/core/server/context/context_service.ts +++ b/src/core/server/context/context_service.ts @@ -18,7 +18,7 @@ */ import { PluginOpaqueId } from '../../server'; -import { IContextContainer, ContextContainer } from '../../utils/context'; +import { IContextContainer, ContextContainer, HandlerFunction } from '../../utils/context'; import { CoreContext } from '../core_context'; interface SetupDeps { @@ -31,15 +31,8 @@ export class ContextService { public setup({ pluginDependencies }: SetupDeps): ContextSetup { return { - createContextContainer: < - TContext extends {}, - THandlerReturn, - THandlerParameters extends any[] = [] - >() => { - return new ContextContainer( - pluginDependencies, - this.core.coreId - ); + createContextContainer: >() => { + return new ContextContainer(pluginDependencies, this.core.coreId); }, }; } @@ -112,9 +105,5 @@ export interface ContextSetup { /** * Creates a new {@link IContextContainer} for a service owner. */ - createContextContainer< - TContext extends {}, - THandlerReturn, - THandlerParmaters extends any[] = [] - >(): IContextContainer; + createContextContainer>(): IContextContainer; } diff --git a/src/core/server/context/index.ts b/src/core/server/context/index.ts index 28b2641b2a5a7..f22c4168d7544 100644 --- a/src/core/server/context/index.ts +++ b/src/core/server/context/index.ts @@ -18,4 +18,10 @@ */ export { ContextService, ContextSetup } from './context_service'; -export { IContextContainer, IContextProvider, IContextHandler } from '../../utils/context'; +export { + IContextContainer, + IContextProvider, + HandlerFunction, + HandlerContextType, + HandlerParameters, +} from '../../utils/context'; diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index 5814991a2dd27..0ac5ad9276353 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -83,8 +83,8 @@ export type HttpServiceSetup = Omit & { registerRouteHandlerContext: ( pluginOpaqueId: PluginOpaqueId, contextName: T, - provider: RequestHandlerContextProvider - ) => RequestHandlerContextContainer; + provider: RequestHandlerContextProvider + ) => RequestHandlerContextContainer; }; /** @public */ @@ -103,7 +103,7 @@ export class HttpService implements CoreService; + private requestHandlerContext?: RequestHandlerContextContainer; constructor(private readonly coreContext: CoreContext) { this.logger = coreContext.logger; @@ -150,7 +150,7 @@ export class HttpService implements CoreService( pluginOpaqueId: PluginOpaqueId, contextName: T, - provider: RequestHandlerContextProvider + provider: RequestHandlerContextProvider ) => this.requestHandlerContext!.registerContext(pluginOpaqueId, contextName, provider), }; diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts index a391b2e2e5d45..cade4ea4d4f2c 100644 --- a/src/core/server/http/types.ts +++ b/src/core/server/http/types.ts @@ -16,30 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -import { IContextProvider, IContextContainer } from '../context'; -import { KibanaRequest, KibanaResponseFactory, KibanaResponse } from './router'; - -/** - * Parameters passed to the request handler function. - * @public - */ -export type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; -/** - * Expected outcome the request handler function. - * @public - */ -export type RequestHandlerReturn = KibanaResponse; +import { IContextProvider, IContextContainer } from '../context'; +import { RequestHandler } from './router'; +import { RequestHandlerContext } from '..'; /** * An object that handles registration of http request context providers. * @public */ -export type RequestHandlerContextContainer = IContextContainer< - TContext, - RequestHandlerReturn | Promise, - RequestHandlerParams ->; +export type RequestHandlerContextContainer = IContextContainer>; /** * Context provider for request handler. @@ -47,8 +33,6 @@ export type RequestHandlerContextContainer = IContextContainer< * * @public */ -export type RequestHandlerContextProvider = IContextProvider< - TContext, - keyof TContext, - RequestHandlerParams ->; +export type RequestHandlerContextProvider< + TContextName extends keyof RequestHandlerContext +> = IContextProvider, TContextName>; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index d3fe64ddc1e0d..ca497e0f2d32d 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -59,7 +59,13 @@ import { SavedObjectsServiceStart } from './saved_objects'; export { bootstrap } from './bootstrap'; export { ConfigPath, ConfigService } from './config'; -export { IContextContainer, IContextProvider, IContextHandler } from './context'; +export { + IContextContainer, + IContextProvider, + HandlerFunction, + HandlerContextType, + HandlerParameters, +} from './context'; export { CoreId } from './core_context'; export { CallAPIOptions, @@ -102,8 +108,6 @@ export { RequestHandler, RequestHandlerContextContainer, RequestHandlerContextProvider, - RequestHandlerParams, - RequestHandlerReturn, ResponseError, ResponseErrorAttributes, ResponseHeaders, @@ -212,8 +216,8 @@ export interface CoreSetup { isTlsEnabled: HttpServiceSetup['isTlsEnabled']; registerRouteHandlerContext: ( name: T, - provider: RequestHandlerContextProvider - ) => RequestHandlerContextContainer; + provider: RequestHandlerContextProvider + ) => RequestHandlerContextContainer; createRouter: () => IRouter; }; } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ae839644fc2e2..6451e2b9b7153 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -21,6 +21,7 @@ import { Request } from 'hapi'; import { ResponseObject } from 'hapi'; import { ResponseToolkit } from 'hapi'; import { Server } from 'hapi'; +import { ShallowPromise } from '@kbn/utility-types'; import { Stream } from 'stream'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; @@ -61,11 +62,11 @@ export interface AuthToolkit { export class BasePath { // @internal constructor(serverBasePath?: string); - get: (request: KibanaRequest | LegacyRequest) => string; + get: (request: LegacyRequest | KibanaRequest) => string; prepend: (path: string) => string; remove: (path: string) => string; readonly serverBasePath: string; - set: (request: KibanaRequest | LegacyRequest, requestSpecificBasePath: string) => void; + set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; } // Warning: (ae-forgotten-export) The symbol "BootstrapArgs" needs to be exported by the entry point index.d.ts @@ -109,7 +110,7 @@ export class ConfigService { // @public export interface ContextSetup { - createContextContainer(): IContextContainer; + createContextContainer>(): IContextContainer; } // @internal (undocumented) @@ -135,7 +136,7 @@ export interface CoreSetup { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; basePath: HttpServiceSetup['basePath']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; - registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; + registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; createRouter: () => IRouter; }; } @@ -219,6 +220,15 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) => { state: unknown; }; +// @public +export type HandlerContextType> = T extends HandlerFunction ? U : never; + +// @public +export type HandlerFunction = (context: T, ...args: any[]) => any; + +// @public +export type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; + // @public export type Headers = { [header in KnownHeaders]?: string | string[] | undefined; @@ -258,7 +268,7 @@ export interface HttpServerSetup { // @public (undocumented) export type HttpServiceSetup = Omit & { createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; - registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; + registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; }; // @public (undocumented) @@ -270,16 +280,13 @@ export interface HttpServiceStart { export type IBasePath = Pick; // @public -export interface IContextContainer { - createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; - registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +export interface IContextContainer> { + createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; + registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; } // @public -export type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; - -// @public -export type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; +export type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; // @public export interface IKibanaSocket { @@ -602,16 +609,10 @@ export interface RequestHandlerContext { } // @public -export type RequestHandlerContextContainer = IContextContainer, RequestHandlerParams>; - -// @public -export type RequestHandlerContextProvider = IContextProvider; - -// @public -export type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; +export type RequestHandlerContextContainer = IContextContainer>; // @public -export type RequestHandlerReturn = KibanaResponse; +export type RequestHandlerContextProvider = IContextProvider, TContextName>; // @public export type ResponseError = string | Error | { diff --git a/src/core/utils/context.mock.ts b/src/core/utils/context.mock.ts index 4d91c11542b2f..de844f3f0f07d 100644 --- a/src/core/utils/context.mock.ts +++ b/src/core/utils/context.mock.ts @@ -19,7 +19,7 @@ import { IContextContainer } from './context'; -export type ContextContainerMock = jest.Mocked>; +export type ContextContainerMock = jest.Mocked>; const createContextMock = () => { const contextMock: ContextContainerMock = { diff --git a/src/core/utils/context.test.ts b/src/core/utils/context.test.ts index 1249c14736fb5..4bfeddc2e08c9 100644 --- a/src/core/utils/context.test.ts +++ b/src/core/utils/context.test.ts @@ -44,7 +44,7 @@ const coreId = Symbol(); describe('ContextContainer', () => { it('does not allow the same context to be registered twice', () => { - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>(plugins, coreId); contextContainer.registerContext(coreId, 'ctxFromA', () => 'aString'); expect(() => @@ -56,7 +56,10 @@ describe('ContextContainer', () => { describe('registerContext', () => { it('throws error if called with an unknown symbol', async () => { - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); await expect(() => contextContainer.registerContext(Symbol('unknown'), 'ctxFromA', jest.fn()) ).toThrowErrorMatchingInlineSnapshot( @@ -67,7 +70,10 @@ describe('ContextContainer', () => { describe('context building', () => { it('resolves dependencies', async () => { - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); expect.assertions(8); contextContainer.registerContext(coreId, 'core1', context => { expect(context).toEqual({}); @@ -118,7 +124,10 @@ describe('ContextContainer', () => { it('exposes all core context to all providers regardless of registration order', async () => { expect.assertions(4); - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); contextContainer .registerContext(pluginA, 'ctxFromA', context => { expect(context).toEqual({ core1: 'core', core2: 101 }); @@ -146,7 +155,10 @@ describe('ContextContainer', () => { it('exposes all core context to core providers', async () => { expect.assertions(4); - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); contextContainer .registerContext(coreId, 'core1', context => { @@ -171,7 +183,10 @@ describe('ContextContainer', () => { }); it('does not expose plugin contexts to core handler', async () => { - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); contextContainer .registerContext(coreId, 'core1', context => 'core') @@ -189,10 +204,9 @@ describe('ContextContainer', () => { it('passes additional arguments to providers', async () => { expect.assertions(6); - const contextContainer = new ContextContainer( - plugins, - coreId - ); + const contextContainer = new ContextContainer< + (context: MyContext, arg1: string, arg2: number) => string + >(plugins, coreId); contextContainer.registerContext(coreId, 'core1', (context, str, num) => { expect(str).toEqual('passed string'); @@ -228,7 +242,10 @@ describe('ContextContainer', () => { describe('createHandler', () => { it('throws error if called with an unknown symbol', async () => { - const contextContainer = new ContextContainer(plugins, coreId); + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); await expect(() => contextContainer.createHandler(Symbol('unknown'), jest.fn()) ).toThrowErrorMatchingInlineSnapshot( @@ -237,8 +254,10 @@ describe('ContextContainer', () => { }); it('returns value from original handler', async () => { - const contextContainer = new ContextContainer(plugins, coreId); - + const contextContainer = new ContextContainer<(context: MyContext) => string>( + plugins, + coreId + ); const rawHandler1 = jest.fn(() => 'handler1'); const handler1 = contextContainer.createHandler(pluginA, rawHandler1); @@ -246,10 +265,9 @@ describe('ContextContainer', () => { }); it('passes additional arguments to handlers', async () => { - const contextContainer = new ContextContainer( - plugins, - coreId - ); + const contextContainer = new ContextContainer< + (context: MyContext, arg1: string, arg2: number) => string + >(plugins, coreId); const rawHandler1 = jest.fn(() => 'handler1'); const handler1 = contextContainer.createHandler(pluginA, rawHandler1); diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts index 6d1732ea06b0e..022c3e4330032 100644 --- a/src/core/utils/context.ts +++ b/src/core/utils/context.ts @@ -18,6 +18,7 @@ */ import { flatten } from 'lodash'; +import { ShallowPromise } from '@kbn/utility-types'; import { pick } from '.'; import { CoreId, PluginOpaqueId } from '../server'; @@ -35,26 +36,44 @@ import { CoreId, PluginOpaqueId } from '../server'; * @public */ export type IContextProvider< - TContext extends Record, - TContextName extends keyof TContext, - TProviderParameters extends any[] = [] + THandler extends HandlerFunction, + TContextName extends keyof HandlerContextType > = ( - context: Partial, - ...rest: TProviderParameters -) => Promise | TContext[TContextName]; + context: Partial>, + ...rest: HandlerParameters +) => + | Promise[TContextName]> + | HandlerContextType[TContextName]; /** - * A function registered by a plugin to perform some action. + * A function that accepts a context object and an optional number of additional arguments. Used for the generic types + * in {@link IContextContainer} * - * @remarks - * A new `TContext` will be built for each handler before invoking. + * @public + */ +export type HandlerFunction = (context: T, ...args: any[]) => any; + +/** + * Extracts the type of the first argument of a {@link HandlerFunction} to represent the type of the context. * * @public */ -export type IContextHandler = ( - context: TContext, - ...rest: THandlerParameters -) => TReturn; +export type HandlerContextType> = T extends HandlerFunction + ? U + : never; + +/** + * Extracts the types of the additional arguments of a {@link HandlerFunction}, excluding the + * {@link HandlerContextType}. + * + * @public + */ +export type HandlerParameters> = T extends ( + context: any, + ...args: infer U +) => any + ? U + : never; /** * An object that handles registration of context providers and configuring handlers with context. @@ -123,13 +142,12 @@ export type IContextHandler { +export interface IContextContainer> { /** * Register a new context provider. * @@ -144,10 +162,10 @@ export interface IContextContainer< * @param provider - A {@link IContextProvider} to be called each time a new context is created. * @returns The {@link IContextContainer} for method chaining. */ - registerContext( + registerContext>( pluginOpaqueId: PluginOpaqueId, contextName: TContextName, - provider: IContextProvider + provider: IContextProvider ): this; /** @@ -160,31 +178,26 @@ export interface IContextContainer< */ createHandler( pluginOpaqueId: PluginOpaqueId, - handler: IContextHandler - ): ( - ...rest: THandlerParameters - ) => THandlerReturn extends Promise ? THandlerReturn : Promise; + handler: THandler + ): (...rest: HandlerParameters) => ShallowPromise>; } /** @internal */ -export class ContextContainer< - TContext extends Record, - THandlerReturn, - THandlerParameters extends any[] = [] -> implements IContextContainer { +export class ContextContainer> + implements IContextContainer { /** * Used to map contexts to their providers and associated plugin. In registration order which is tightly coupled to * plugin load order. */ private readonly contextProviders = new Map< - keyof TContext, + keyof HandlerContextType, { - provider: IContextProvider; + provider: IContextProvider>; source: symbol; } >(); /** Used to keep track of which plugins registered which contexts for dependency resolution. */ - private readonly contextNamesBySource: Map>; + private readonly contextNamesBySource: Map>>; /** * @param pluginDependencies - A map of plugins to an array of their dependencies. @@ -193,13 +206,15 @@ export class ContextContainer< private readonly pluginDependencies: ReadonlyMap, private readonly coreId: CoreId ) { - this.contextNamesBySource = new Map>([[coreId, []]]); + this.contextNamesBySource = new Map>>([ + [coreId, []], + ]); } - public registerContext = ( + public registerContext = >( source: symbol, contextName: TContextName, - provider: IContextProvider + provider: IContextProvider ): this => { if (this.contextProviders.has(contextName)) { throw new Error(`Context provider for ${contextName} has already been registered.`); @@ -217,27 +232,22 @@ export class ContextContainer< return this; }; - public createHandler = ( - source: symbol, - handler: IContextHandler - ) => { + public createHandler = (source: symbol, handler: THandler) => { if (source !== this.coreId && !this.pluginDependencies.has(source)) { throw new Error(`Cannot create handler for unknown plugin: ${source.toString()}`); } - return (async (...args: THandlerParameters) => { + return (async (...args: HandlerParameters) => { const context = await this.buildContext(source, ...args); return handler(context, ...args); - }) as ( - ...args: THandlerParameters - ) => THandlerReturn extends Promise ? THandlerReturn : Promise; + }) as (...args: HandlerParameters) => ShallowPromise>; }; private async buildContext( source: symbol, - ...contextArgs: THandlerParameters - ): Promise { - const contextsToBuild: ReadonlySet = new Set( + ...contextArgs: HandlerParameters + ): Promise> { + const contextsToBuild: ReadonlySet> = new Set( this.getContextNamesForSource(source) ); @@ -252,18 +262,20 @@ export class ContextContainer< // registered that provider. const exposedContext = pick(resolvedContext, [ ...this.getContextNamesForSource(providerSource), - ]); + ]) as Partial>; return { ...resolvedContext, - [contextName]: await provider(exposedContext as Partial, ...contextArgs), + [contextName]: await provider(exposedContext, ...contextArgs), }; }, - Promise.resolve({}) as Promise + Promise.resolve({}) as Promise> ); } - private getContextNamesForSource(source: symbol): ReadonlySet { + private getContextNamesForSource( + source: symbol + ): ReadonlySet> { if (source === this.coreId) { return this.getContextNamesForCore(); } else { diff --git a/src/dev/register_git_hook/register_git_hook.js b/src/dev/register_git_hook/register_git_hook.js index bdb3e2d806030..a61922078e687 100644 --- a/src/dev/register_git_hook/register_git_hook.js +++ b/src/dev/register_git_hook/register_git_hook.js @@ -37,7 +37,7 @@ const writeFileAsync = promisify(writeFile); async function getPrecommitGitHookScriptPath(rootPath) { // Retrieves the correct location for the .git dir for // every git setup (including git worktree) - const gitDirPath = (await gitRevParseAsync(['--git-dir'])).trim(); + const gitDirPath = (await gitRevParseAsync(['--git-common-dir'])).trim(); return resolve(rootPath, gitDirPath, 'hooks/pre-commit'); } diff --git a/src/dev/renovate/config.ts b/src/dev/renovate/config.ts index a86c080f52710..1bf3af9fe5248 100644 --- a/src/dev/renovate/config.ts +++ b/src/dev/renovate/config.ts @@ -86,6 +86,7 @@ export const RENOVATE_CONFIG = { labels: group.extraLabels && [...DEFAULT_LABELS, ...group.extraLabels], enabled: group.enabled === false ? false : undefined, allowedVersions: group.allowedVersions || undefined, + reviewers: group.reviewers || undefined, })), // internal/local packages diff --git a/src/dev/renovate/package_groups.ts b/src/dev/renovate/package_groups.ts index 85692e94eb912..185163890f745 100644 --- a/src/dev/renovate/package_groups.ts +++ b/src/dev/renovate/package_groups.ts @@ -56,6 +56,11 @@ interface PackageGroup { * https://renovatebot.com/docs/configuration-options/#allowedversions */ readonly allowedVersions?: string; + + /** + * An array of users to request reviews from + */ + readonly reviewers?: string[]; } export const RENOVATE_PACKAGE_GROUPS: PackageGroup[] = [ @@ -75,6 +80,12 @@ export const RENOVATE_PACKAGE_GROUPS: PackageGroup[] = [ packageWords: ['jest'], }, + { + name: '@elastic/charts', + packageNames: ['@elastic/charts'], + reviewers: ['markov00'], + }, + { name: 'mocha', packageWords: ['mocha'], diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index d96e3be8d7e38..b9554310e2413 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -18,7 +18,7 @@ */ // /// Define plugin function -import { DataPlugin as Plugin, DataSetup } from './plugin'; +import { DataPlugin as Plugin, DataSetup, DataStart } from './plugin'; export function plugin() { return new Plugin(); @@ -28,6 +28,7 @@ export function plugin() { /** @public types */ export type DataSetup = DataSetup; +export type DataStart = DataStart; export { FilterBar, ApplyFiltersPopover } from './filter'; export { 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 da756275a83e9..6fdbf4fce4553 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 @@ -583,10 +583,9 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto onOutsideClick={[Function]} >
} - aria-activedescendant="" aria-autocomplete="list" - aria-controls="kbnTypeahead__items" - aria-label="You are on search box of Another Screen page. Start typing to search and filter the test" + aria-label="Start typing to search and filter the test page" autoComplete="off" autoFocus={false} compressed={false} @@ -651,10 +648,8 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto >
} - aria-activedescendant="" aria-autocomplete="list" - aria-controls="kbnTypeahead__items" - aria-label="You are on search box of Another Screen page. Start typing to search and filter the test" + aria-label="Start typing to search and filter the test page" autoComplete="off" autoFocus={true} compressed={false} @@ -1425,10 +1417,8 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 >
} - aria-activedescendant="" aria-autocomplete="list" - aria-controls="kbnTypeahead__items" - aria-label="You are on search box of Another Screen page. Start typing to search and filter the test" + aria-label="Start typing to search and filter the test page" autoComplete="off" autoFocus={true} compressed={false} @@ -2199,10 +2186,8 @@ exports[`QueryBarInput Should render the given query 1`] = ` > { } public render() { + const isSuggestionsVisible = this.state.isSuggestionsVisible && { + 'aria-controls': 'kbnTypeahead__items', + 'aria-owns': 'kbnTypeahead__items', + }; + const ariaCombobox = { ...isSuggestionsVisible, role: 'combobox' }; + return (
{ }} autoComplete="off" spellCheck={false} - aria-label={ - this.props.screenTitle - ? this.props.intl.formatMessage( - { - id: 'data.query.queryBar.searchInputAriaLabel', - defaultMessage: - 'You are on search box of {previouslyTranslatedPageTitle} page. Start typing to search and filter the {pageType}', - }, - { - previouslyTranslatedPageTitle: this.props.screenTitle, - pageType: this.services.appName, - } - ) - : undefined - } + aria-label={i18n.translate('data.query.queryBar.searchInputAriaLabel', { + defaultMessage: 'Start typing to search and filter the {pageType} page', + values: { pageType: this.services.appName }, + })} type="text" aria-autocomplete="list" - aria-controls="kbnTypeahead__items" + aria-controls={this.state.isSuggestionsVisible ? 'kbnTypeahead__items' : undefined} aria-activedescendant={ - this.state.isSuggestionsVisible ? 'suggestion-' + this.state.index : '' + this.state.isSuggestionsVisible && typeof this.state.index === 'number' + ? `suggestion-${this.state.index}` + : undefined } role="textbox" prepend={this.props.prepend} diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx index ed2a6638aba11..06ceace7e9e44 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx @@ -66,14 +66,18 @@ export interface SearchBarOwnProps { showFilterBar?: boolean; showDatePicker?: boolean; showAutoRefreshOnly?: boolean; - showSaveQuery?: boolean; - + onRefreshChange?: (options: { isPaused: boolean; refreshInterval: number }) => void; // Query bar - should be in SearchBarInjectedDeps query?: Query; + // Show when user has privileges to save + showSaveQuery?: boolean; savedQuery?: SavedQuery; onQuerySubmit?: (payload: { dateRange: TimeRange; query?: Query }) => void; + // User has saved the current state as a saved query onSaved?: (savedQuery: SavedQuery) => void; + // User has modified the saved query, your app should persist the update onSavedQueryUpdated?: (savedQuery: SavedQuery) => void; + // User has cleared the active query, your app should clear the entire query bar onClearSavedQuery?: () => void; } diff --git a/src/legacy/core_plugins/input_control_vis/public/register_vis.js b/src/legacy/core_plugins/input_control_vis/public/register_vis.js index 76320b331bb06..731cf2dac9dd2 100644 --- a/src/legacy/core_plugins/input_control_vis/public/register_vis.js +++ b/src/legacy/core_plugins/input_control_vis/public/register_vis.js @@ -24,7 +24,7 @@ import { OptionsTab } from './components/editor/options_tab'; import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message'; import { Status } from 'ui/vis/update_status'; import { i18n } from '@kbn/i18n'; -import { setup as visualizations } from '../../visualizations/public/legacy'; +import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy'; function InputControlVisProvider() { diff --git a/src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.js.snap b/src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.ts.snap similarity index 100% rename from src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.js.snap rename to src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.ts.snap diff --git a/src/legacy/core_plugins/interpreter/public/functions/__tests__/font.js b/src/legacy/core_plugins/interpreter/public/functions/__tests__/font.js deleted file mode 100644 index 4a7ebc1522f2a..0000000000000 --- a/src/legacy/core_plugins/interpreter/public/functions/__tests__/font.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 expect from '@kbn/expect'; -import { openSans } from '../../../common/lib/fonts'; -import { font } from '../font'; -import { functionWrapper } from '../../../test_helpers'; - -describe('font', () => { - const fn = functionWrapper(font); - - describe('default output', () => { - const result = fn(null); - - it('returns a style', () => { - expect(result) - .to.have.property('type', 'style') - .and.to.have.property('spec') - .and.to.have.property('css'); - }); - }); - - describe('args', () => { - describe('size', () => { - it('sets font size', () => { - const result = fn(null, { size: 20 }); - expect(result.spec).to.have.property('fontSize', '20px'); - expect(result.css).to.contain('font-size:20px'); - }); - - it('defaults to 14px', () => { - const result = fn(null); - expect(result.spec).to.have.property('fontSize', '14px'); - expect(result.css).to.contain('font-size:14px'); - }); - }); - - describe('lHeight', () => { - it('sets line height', () => { - const result = fn(null, { lHeight: 30 }); - expect(result.spec).to.have.property('lineHeight', '30px'); - expect(result.css).to.contain('line-height:30px'); - }); - - it('defaults to 1', () => { - const result = fn(null); - expect(result.spec).to.have.property('lineHeight', '1'); - expect(result.css).to.contain('line-height:1'); - }); - }); - - describe('family', () => { - it('sets font family', () => { - const result = fn(null, { family: 'Optima, serif' }); - expect(result.spec).to.have.property('fontFamily', 'Optima, serif'); - expect(result.css).to.contain('font-family:Optima, serif'); - }); - - it(`defaults to "${openSans.value}"`, () => { - const result = fn(null); - expect(result.spec).to.have.property('fontFamily', `"${openSans.value}"`); - expect(result.css).to.contain(`font-family:"${openSans.value}"`); - }); - }); - - describe('color', () => { - it('sets font color', () => { - const result = fn(null, { color: 'blue' }); - expect(result.spec).to.have.property('color', 'blue'); - expect(result.css).to.contain('color:blue'); - }); - }); - - describe('weight', () => { - it('sets font weight', () => { - let result = fn(null, { weight: 'normal' }); - expect(result.spec).to.have.property('fontWeight', 'normal'); - expect(result.css).to.contain('font-weight:normal'); - - result = fn(null, { weight: 'bold' }); - expect(result.spec).to.have.property('fontWeight', 'bold'); - expect(result.css).to.contain('font-weight:bold'); - - result = fn(null, { weight: 'bolder' }); - expect(result.spec).to.have.property('fontWeight', 'bolder'); - expect(result.css).to.contain('font-weight:bolder'); - - result = fn(null, { weight: 'lighter' }); - expect(result.spec).to.have.property('fontWeight', 'lighter'); - expect(result.css).to.contain('font-weight:lighter'); - - result = fn(null, { weight: '400' }); - expect(result.spec).to.have.property('fontWeight', '400'); - expect(result.css).to.contain('font-weight:400'); - }); - - it('defaults to \'normal\'', () => { - const result = fn(null); - expect(result.spec).to.have.property('fontWeight', 'normal'); - expect(result.css).to.contain('font-weight:normal'); - }); - - it('throws when provided an invalid weight', () => { - expect(() => fn(null, { weight: 'foo' })).to.throwException(); - }); - }); - - describe('underline', () => { - it('sets text underline', () => { - let result = fn(null, { underline: true }); - expect(result.spec).to.have.property('textDecoration', 'underline'); - expect(result.css).to.contain('text-decoration:underline'); - - result = fn(null, { underline: false }); - expect(result.spec).to.have.property('textDecoration', 'none'); - expect(result.css).to.contain('text-decoration:none'); - }); - - it('defaults to false', () => { - const result = fn(null); - expect(result.spec).to.have.property('textDecoration', 'none'); - expect(result.css).to.contain('text-decoration:none'); - }); - }); - - describe('italic', () => { - it('sets italic', () => { - let result = fn(null, { italic: true }); - expect(result.spec).to.have.property('fontStyle', 'italic'); - expect(result.css).to.contain('font-style:italic'); - - result = fn(null, { italic: false }); - expect(result.spec).to.have.property('fontStyle', 'normal'); - expect(result.css).to.contain('font-style:normal'); - }); - - it('defaults to false', () => { - const result = fn(null); - expect(result.spec).to.have.property('fontStyle', 'normal'); - expect(result.css).to.contain('font-style:normal'); - }); - }); - - describe('align', () => { - it('sets text alignment', () => { - let result = fn(null, { align: 'left' }); - expect(result.spec).to.have.property('textAlign', 'left'); - expect(result.css).to.contain('text-align:left'); - - result = fn(null, { align: 'center' }); - expect(result.spec).to.have.property('textAlign', 'center'); - expect(result.css).to.contain('text-align:center'); - - result = fn(null, { align: 'right' }); - expect(result.spec).to.have.property('textAlign', 'right'); - expect(result.css).to.contain('text-align:right'); - - result = fn(null, { align: 'justify' }); - expect(result.spec).to.have.property('textAlign', 'justify'); - expect(result.css).to.contain('text-align:justify'); - }); - - it(`defaults to 'left'`, () => { - const result = fn(null); - expect(result.spec).to.have.property('textAlign', 'left'); - expect(result.css).to.contain('text-align:left'); - }); - - it('throws when provided an invalid alignment', () => { - expect(fn) - .withArgs(null, { align: 'foo' }) - .to.throwException(); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/interpreter/public/functions/clog.js b/src/legacy/core_plugins/interpreter/public/functions/clog.ts similarity index 91% rename from src/legacy/core_plugins/interpreter/public/functions/clog.js rename to src/legacy/core_plugins/interpreter/public/functions/clog.ts index 634d166f5f0bb..4867726a42d72 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/clog.js +++ b/src/legacy/core_plugins/interpreter/public/functions/clog.ts @@ -20,8 +20,8 @@ export const clog = () => ({ name: 'clog', help: 'Outputs the context to the console', - fn: context => { - console.log(context); //eslint-disable-line no-console + fn: (context: any) => { + console.log(context); // eslint-disable-line no-console return context; }, }); diff --git a/src/legacy/core_plugins/interpreter/public/functions/font.test.ts b/src/legacy/core_plugins/interpreter/public/functions/font.test.ts new file mode 100644 index 0000000000000..dba540178777b --- /dev/null +++ b/src/legacy/core_plugins/interpreter/public/functions/font.test.ts @@ -0,0 +1,202 @@ +/* + * 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 { openSans } from '../../common/lib/fonts'; +import { font } from './font'; +import { functionWrapper } from '../../test_helpers'; + +describe('font', () => { + const fn: any = functionWrapper(font); + + describe('default output', () => { + const result = fn(null); + + it('returns a style', () => { + expect(result).toMatchObject({ + type: 'style', + spec: expect.any(Object), + css: expect.any(String), + }); + }); + }); + + describe('args', () => { + describe('size', () => { + it('sets font size', () => { + const result = fn(null, { size: 20 }); + expect(result).toMatchObject({ + spec: { + fontSize: '20px', + }, + }); + expect(result.css).toContain('font-size:20px'); + }); + + it('defaults to 14px', () => { + const result = fn(null); + expect(result).toMatchObject({ + spec: { + fontSize: '14px', + }, + }); + expect(result.css).toContain('font-size:14px'); + }); + }); + + describe('lHeight', () => { + it('sets line height', () => { + const result = fn(null, { lHeight: 30 }); + expect(result).toMatchObject({ + spec: { + lineHeight: '30px', + }, + }); + expect(result.css).toContain('line-height:30px'); + }); + + it('defaults to 1', () => { + const result = fn(null); + expect(result.spec.lineHeight).toBe('1'); + expect(result.css).toContain('line-height:1'); + }); + }); + + describe('family', () => { + it('sets font family', () => { + const result = fn(null, { family: 'Optima, serif' }); + expect(result.spec.fontFamily).toBe('Optima, serif'); + expect(result.css).toContain('font-family:Optima, serif'); + }); + + it(`defaults to "${openSans.value}"`, () => { + const result = fn(null); + expect(result.spec.fontFamily).toBe(`"${openSans.value}"`); + expect(result.css).toContain(`font-family:"${openSans.value}"`); + }); + }); + + describe('color', () => { + it('sets font color', () => { + const result = fn(null, { color: 'blue' }); + expect(result.spec.color).toBe('blue'); + expect(result.css).toContain('color:blue'); + }); + }); + + describe('weight', () => { + it('sets font weight', () => { + let result = fn(null, { weight: 'normal' }); + expect(result.spec.fontWeight).toBe('normal'); + expect(result.css).toContain('font-weight:normal'); + + result = fn(null, { weight: 'bold' }); + expect(result.spec.fontWeight).toBe('bold'); + expect(result.css).toContain('font-weight:bold'); + + result = fn(null, { weight: 'bolder' }); + expect(result.spec.fontWeight).toBe('bolder'); + expect(result.css).toContain('font-weight:bolder'); + + result = fn(null, { weight: 'lighter' }); + expect(result.spec.fontWeight).toBe('lighter'); + expect(result.css).toContain('font-weight:lighter'); + + result = fn(null, { weight: '400' }); + expect(result.spec.fontWeight).toBe('400'); + expect(result.css).toContain('font-weight:400'); + }); + + it("defaults to 'normal'", () => { + const result = fn(null); + expect(result.spec.fontWeight).toBe('normal'); + expect(result.css).toContain('font-weight:normal'); + }); + + it('throws when provided an invalid weight', () => { + expect(() => fn(null, { weight: 'foo' })).toThrow(); + }); + }); + + describe('underline', () => { + it('sets text underline', () => { + let result = fn(null, { underline: true }); + expect(result.spec.textDecoration).toBe('underline'); + expect(result.css).toContain('text-decoration:underline'); + + result = fn(null, { underline: false }); + expect(result.spec.textDecoration).toBe('none'); + expect(result.css).toContain('text-decoration:none'); + }); + + it('defaults to false', () => { + const result = fn(null); + expect(result.spec.textDecoration).toBe('none'); + expect(result.css).toContain('text-decoration:none'); + }); + }); + + describe('italic', () => { + it('sets italic', () => { + let result = fn(null, { italic: true }); + expect(result.spec.fontStyle).toBe('italic'); + expect(result.css).toContain('font-style:italic'); + + result = fn(null, { italic: false }); + expect(result.spec.fontStyle).toBe('normal'); + expect(result.css).toContain('font-style:normal'); + }); + + it('defaults to false', () => { + const result = fn(null); + expect(result.spec.fontStyle).toBe('normal'); + expect(result.css).toContain('font-style:normal'); + }); + }); + + describe('align', () => { + it('sets text alignment', () => { + let result = fn(null, { align: 'left' }); + expect(result.spec.textAlign).toBe('left'); + expect(result.css).toContain('text-align:left'); + + result = fn(null, { align: 'center' }); + expect(result.spec.textAlign).toBe('center'); + expect(result.css).toContain('text-align:center'); + + result = fn(null, { align: 'right' }); + expect(result.spec.textAlign).toBe('right'); + expect(result.css).toContain('text-align:right'); + + result = fn(null, { align: 'justify' }); + expect(result.spec.textAlign).toBe('justify'); + expect(result.css).toContain('text-align:justify'); + }); + + it(`defaults to 'left'`, () => { + const result = fn(null); + expect(result.spec.textAlign).toBe('left'); + expect(result.css).toContain('text-align:left'); + }); + + it('throws when provided an invalid alignment', () => { + expect(() => fn(null, { align: 'foo' })).toThrow(); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/interpreter/public/functions/index.js b/src/legacy/core_plugins/interpreter/public/functions/index.ts similarity index 92% rename from src/legacy/core_plugins/interpreter/public/functions/index.js rename to src/legacy/core_plugins/interpreter/public/functions/index.ts index 38c3920f91bd2..d86f033acb3d1 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/index.js +++ b/src/legacy/core_plugins/interpreter/public/functions/index.ts @@ -27,5 +27,12 @@ import { visualization } from './visualization'; import { visDimension } from './vis_dimension'; export const functions = [ - clog, esaggs, font, kibana, kibanaContext, range, visualization, visDimension, + clog, + esaggs, + font, + kibana, + kibanaContext, + range, + visualization, + visDimension, ]; diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana.test.js b/src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts similarity index 97% rename from src/legacy/core_plugins/interpreter/public/functions/kibana.test.js rename to src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts index 4757b9b12b50d..9f80449ac36be 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/kibana.test.js +++ b/src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts @@ -22,9 +22,9 @@ import { kibana } from './kibana'; describe('interpreter/functions#kibana', () => { const fn = functionWrapper(kibana); - let context; - let initialContext; - let handlers; + let context: any; + let initialContext: any; + let handlers: any; beforeEach(() => { context = { timeRange: { from: '0', to: '1' } }; diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana.js b/src/legacy/core_plugins/interpreter/public/functions/kibana.ts similarity index 93% rename from src/legacy/core_plugins/interpreter/public/functions/kibana.js rename to src/legacy/core_plugins/interpreter/public/functions/kibana.ts index e0817d8e04b02..37ff337f58b8d 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/kibana.js +++ b/src/legacy/core_plugins/interpreter/public/functions/kibana.ts @@ -24,10 +24,10 @@ export const kibana = () => ({ type: 'kibana_context', context: {}, help: i18n.translate('interpreter.functions.kibana.help', { - defaultMessage: 'Gets kibana global context' + defaultMessage: 'Gets kibana global context', }), args: {}, - fn(context, args, handlers) { + fn(context: any, args: any, handlers: any) { const initialContext = handlers.getInitialContext ? handlers.getInitialContext() : {}; if (context.query) { @@ -45,7 +45,7 @@ export const kibana = () => ({ type: 'kibana_context', query: initialContext.query, filters: initialContext.filters, - timeRange: timeRange, + timeRange, }; }, }); diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana_context.js b/src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts similarity index 87% rename from src/legacy/core_plugins/interpreter/public/functions/kibana_context.js rename to src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts index 7b7294a87831d..2f2241a367094 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/kibana_context.js +++ b/src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts @@ -24,13 +24,10 @@ export const kibanaContext = () => ({ name: 'kibana_context', type: 'kibana_context', context: { - types: [ - 'kibana_context', - 'null', - ], + types: ['kibana_context', 'null'], }, help: i18n.translate('interpreter.functions.kibana_context.help', { - defaultMessage: 'Updates kibana global context' + defaultMessage: 'Updates kibana global context', }), args: { q: { @@ -49,11 +46,11 @@ export const kibanaContext = () => ({ savedSearchId: { types: ['string', 'null'], default: null, - } + }, }, - async fn(context, args) { + async fn(context: any, args: any) { const $injector = await chrome.dangerouslyGetActiveInjector(); - const savedSearches = $injector.get('savedSearches'); + const savedSearches = $injector.get('savedSearches') as any; const queryArg = args.q ? JSON.parse(args.q) : []; let queries = Array.isArray(queryArg) ? queryArg : [queryArg]; let filters = args.filters ? JSON.parse(args.filters) : []; @@ -71,7 +68,7 @@ export const kibanaContext = () => ({ } if (context.filters) { - filters = filters.concat(context.filters).filter(f => !f.meta.disabled); + filters = filters.concat(context.filters).filter((f: any) => !f.meta.disabled); } const timeRange = args.timeRange ? JSON.parse(args.timeRange) : context.timeRange; @@ -79,8 +76,8 @@ export const kibanaContext = () => ({ return { type: 'kibana_context', query: queries, - filters: filters, - timeRange: timeRange, + filters, + timeRange, }; }, }); diff --git a/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.js b/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts similarity index 74% rename from src/legacy/core_plugins/interpreter/public/functions/vis_dimension.js rename to src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts index e1a6c41198bad..19503dbe03ae9 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.js +++ b/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts @@ -22,48 +22,48 @@ import { i18n } from '@kbn/i18n'; export const visDimension = () => ({ name: 'visdimension', help: i18n.translate('interpreter.function.visDimension.help', { - defaultMessage: 'Generates visConfig dimension object' + defaultMessage: 'Generates visConfig dimension object', }), type: 'vis_dimension', context: { - types: [ - 'kibana_datatable' - ], + types: ['kibana_datatable'], }, args: { accessor: { types: ['string', 'number'], aliases: ['_'], help: i18n.translate('interpreter.function.visDimension.accessor.help', { - defaultMessage: 'Column in your dataset to use (either column index or column name)' + defaultMessage: 'Column in your dataset to use (either column index or column name)', }), }, format: { types: ['string'], - default: 'string' + default: 'string', }, formatParams: { types: ['string'], default: '"{}"', - } + }, }, - fn: (context, args) => { - const accessor = Number.isInteger(args.accessor) ? - args.accessor : - context.columns.find(c => c.id === args.accessor); + fn: (context: any, args: any) => { + const accessor = Number.isInteger(args.accessor) + ? args.accessor + : context.columns.find((c: any) => c.id === args.accessor); if (accessor === undefined) { - throw new Error(i18n.translate('interpreter.function.visDimension.error.accessor', { - defaultMessage: 'Column name provided is invalid' - })); + throw new Error( + i18n.translate('interpreter.function.visDimension.error.accessor', { + defaultMessage: 'Column name provided is invalid', + }) + ); } return { type: 'vis_dimension', - accessor: accessor, + accessor, format: { id: args.format, params: JSON.parse(args.formatParams), - } + }, }; }, }); diff --git a/src/legacy/core_plugins/interpreter/public/functions/visualization.js b/src/legacy/core_plugins/interpreter/public/functions/visualization.ts similarity index 90% rename from src/legacy/core_plugins/interpreter/public/functions/visualization.js rename to src/legacy/core_plugins/interpreter/public/functions/visualization.ts index 7dceeaf684354..d46044b544c41 100644 --- a/src/legacy/core_plugins/interpreter/public/functions/visualization.js +++ b/src/legacy/core_plugins/interpreter/public/functions/visualization.ts @@ -20,17 +20,16 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; -import { setup as data } from '../../../data/public/legacy'; -import { start as visualizations } from '../../../visualizations/public/legacy'; - import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; import { PersistedState } from 'ui/persisted_state'; +import { setup as data } from '../../../data/public/legacy'; +import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; export const visualization = () => ({ name: 'visualization', type: 'render', help: i18n.translate('interpreter.functions.visualization.help', { - defaultMessage: 'A simple visualization' + defaultMessage: 'A simple visualization', }), args: { index: { @@ -60,17 +59,17 @@ export const visualization = () => ({ uiState: { types: ['string'], default: '"{}"', - } + }, }, - async fn(context, args, handlers) { + async fn(context: any, args: any, handlers: any) { const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private'); + const Private = $injector.get('Private') as any; const { indexPatterns } = data.indexPatterns; const queryFilter = Private(FilterBarQueryFilterProvider); const visConfigParams = JSON.parse(args.visConfig); const schemas = JSON.parse(args.schemas); - const visType = visualizations.types.get(args.type || 'histogram'); + const visType = visualizations.types.get(args.type || 'histogram') as any; const indexPattern = args.index ? await indexPatterns.get(args.index) : null; const uiStateParams = JSON.parse(args.uiState); @@ -85,7 +84,7 @@ export const visualization = () => ({ timeRange: get(context, 'timeRange', null), query: get(context, 'query', null), filters: get(context, 'filters', null), - uiState: uiState, + uiState, inspectorAdapters: handlers.inspectorAdapters, queryFilter, forceFetch: true, @@ -95,14 +94,14 @@ export const visualization = () => ({ if (typeof visType.responseHandler === 'function') { if (context.columns) { // assign schemas to aggConfigs - context.columns.forEach(column => { + context.columns.forEach((column: any) => { if (column.aggConfig) { column.aggConfig.aggConfigs.schemas = visType.schemas.all; } }); Object.keys(schemas).forEach(key => { - schemas[key].forEach(i => { + schemas[key].forEach((i: any) => { if (context.columns[i] && context.columns[i].aggConfig) { context.columns[i].aggConfig.schema = key; } @@ -119,8 +118,8 @@ export const visualization = () => ({ value: { visData: context, visType: args.type, - visConfig: visConfigParams - } + visConfig: visConfigParams, + }, }; - } + }, }); diff --git a/src/legacy/core_plugins/interpreter/public/interpreter.test.js b/src/legacy/core_plugins/interpreter/public/interpreter.test.ts similarity index 96% rename from src/legacy/core_plugins/interpreter/public/interpreter.test.js rename to src/legacy/core_plugins/interpreter/public/interpreter.test.ts index bd7dc0a47c124..1de1e8c0cc059 100644 --- a/src/legacy/core_plugins/interpreter/public/interpreter.test.js +++ b/src/legacy/core_plugins/interpreter/public/interpreter.test.ts @@ -24,9 +24,9 @@ jest.mock('ui/new_platform', () => ({ injectedMetadata: { getKibanaVersion: () => '8.0.0', getBasePath: () => '/lol', - } - } - } + }, + }, + }, })); jest.mock('uiExports/interpreter'); @@ -38,7 +38,7 @@ jest.mock('@kbn/interpreter/common', () => ({ const mockInterpreter = { interpreter: { interpretAst: jest.fn(), - } + }, }; jest.mock('./lib/interpreter', () => ({ initializeInterpreter: jest.fn().mockReturnValue(Promise.resolve(mockInterpreter)), @@ -57,9 +57,9 @@ jest.mock('./functions', () => ({ functions: [{}, {}, {}] })); jest.mock('./renderers/visualization', () => ({ visualization: {} })); describe('interpreter/interpreter', () => { - let getInterpreter; - let interpretAst; - let initializeInterpreter; + let getInterpreter: any; + let interpretAst: any; + let initializeInterpreter: any; beforeEach(() => { jest.clearAllMocks(); @@ -117,5 +117,4 @@ describe('interpreter/interpreter', () => { expect(mockInterpreter.interpreter.interpretAst).toHaveBeenCalledTimes(2); }); }); - }); diff --git a/src/legacy/core_plugins/interpreter/public/interpreter.js b/src/legacy/core_plugins/interpreter/public/interpreter.ts similarity index 87% rename from src/legacy/core_plugins/interpreter/public/interpreter.js rename to src/legacy/core_plugins/interpreter/public/interpreter.ts index 84e05bb10d9fa..8ba82d5daf759 100644 --- a/src/legacy/core_plugins/interpreter/public/interpreter.js +++ b/src/legacy/core_plugins/interpreter/public/interpreter.ts @@ -18,6 +18,7 @@ */ import 'uiExports/interpreter'; +// @ts-ignore import { register, registryFactory } from '@kbn/interpreter/common'; import { initializeInterpreter } from './lib/interpreter'; import { registries } from './registries'; @@ -27,7 +28,10 @@ import { typeSpecs } from '../../../../plugins/expressions/common'; // Expose kbnInterpreter.register(specs) and kbnInterpreter.registries() globally so that plugins // can register without a transpile step. -global.kbnInterpreter = Object.assign(global.kbnInterpreter || {}, registryFactory(registries)); +(global as any).kbnInterpreter = Object.assign( + (global as any).kbnInterpreter || {}, + registryFactory(registries) +); register(registries, { types: typeSpecs, @@ -35,7 +39,7 @@ register(registries, { renderers: [visualization], }); -let interpreterPromise; +let interpreterPromise: Promise | undefined; export const getInterpreter = async () => { if (!interpreterPromise) { @@ -44,7 +48,7 @@ export const getInterpreter = async () => { return await interpreterPromise; }; -export const interpretAst = async (...params) => { +export const interpretAst = async (...params: any) => { const { interpreter } = await getInterpreter(); return await interpreter.interpretAst(...params); }; diff --git a/src/legacy/core_plugins/interpreter/public/lib/render_function.js b/src/legacy/core_plugins/interpreter/public/lib/render_function.ts similarity index 92% rename from src/legacy/core_plugins/interpreter/public/lib/render_function.js rename to src/legacy/core_plugins/interpreter/public/lib/render_function.ts index 04aa05951be70..76d1f58b66195 100644 --- a/src/legacy/core_plugins/interpreter/public/lib/render_function.js +++ b/src/legacy/core_plugins/interpreter/public/lib/render_function.ts @@ -17,7 +17,7 @@ * under the License. */ -export function RenderFunction(config) { +export function RenderFunction(this: any, config: any) { // This must match the name of the function that is used to create the `type: render` object this.name = config.name; @@ -36,7 +36,7 @@ export function RenderFunction(config) { // the function called to render the data this.render = config.render || - function render(domNode, data, done) { + function render(domNode: any, data: any, done: any) { done(); }; } diff --git a/src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.js b/src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.ts similarity index 88% rename from src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.js rename to src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.ts index 60e823baf0fa7..427e7f7454c24 100644 --- a/src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.js +++ b/src/legacy/core_plugins/interpreter/public/lib/render_functions_registry.ts @@ -20,9 +20,9 @@ import { Registry } from '@kbn/interpreter/common'; import { RenderFunction } from './render_function'; -class RenderFunctionsRegistry extends Registry { - wrapper(obj) { - return new RenderFunction(obj); +class RenderFunctionsRegistry extends Registry { + wrapper(obj: any) { + return new (RenderFunction as any)(obj); } } diff --git a/src/legacy/core_plugins/interpreter/public/renderers/visualization.js b/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts similarity index 84% rename from src/legacy/core_plugins/interpreter/public/renderers/visualization.js rename to src/legacy/core_plugins/interpreter/public/renderers/visualization.ts index 38fe02436380c..960e925b13221 100644 --- a/src/legacy/core_plugins/interpreter/public/renderers/visualization.js +++ b/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts @@ -19,17 +19,18 @@ import chrome from 'ui/chrome'; import { visualizationLoader } from 'ui/visualize/loader/visualization_loader'; +// @ts-ignore import { VisProvider } from 'ui/visualize/loader/vis'; export const visualization = () => ({ name: 'visualization', displayName: 'visualization', reuseDomNode: true, - render: async (domNode, config, handlers) => { + render: async (domNode: HTMLElement, config: any, handlers: any) => { const { visData, visConfig, params } = config; const visType = config.visType || visConfig.type; const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private'); + const Private = $injector.get('Private') as any; const Vis = Private(VisProvider); if (handlers.vis) { @@ -49,8 +50,10 @@ export const visualization = () => ({ handlers.onDestroy(() => visualizationLoader.destroy()); - await visualizationLoader.render(domNode, handlers.vis, visData, handlers.vis.params, uiState, params).then(() => { - if (handlers.done) handlers.done(); - }); + await visualizationLoader + .render(domNode, handlers.vis, visData, handlers.vis.params, uiState, params) + .then(() => { + if (handlers.done) handlers.done(); + }); }, }); diff --git a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts similarity index 95% rename from src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js rename to src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts index a6e0e13049e1c..0088663080774 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js +++ b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts @@ -28,13 +28,13 @@ const mockServer = { plugins: { elasticsearch: { getCluster: () => ({ - callWithRequest: (...args) => Promise.resolve(args), + callWithRequest: (...args: any) => Promise.resolve(args), }), }, }, config: () => ({ has: () => false, - get: val => val, + get: (val: any) => val, }), info: { uri: 'serveruri', diff --git a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.js b/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts similarity index 88% rename from src/legacy/core_plugins/interpreter/server/lib/create_handlers.js rename to src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts index d4ea9b3dc6180..6e295d0aecaa5 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.js +++ b/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts @@ -17,7 +17,7 @@ * under the License. */ -export const createHandlers = (request, server) => { +export const createHandlers = (request: any, server: any) => { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); const config = server.config(); @@ -27,6 +27,6 @@ export const createHandlers = (request, server) => { config.has('server.rewriteBasePath') && config.get('server.rewriteBasePath') ? `${server.info.uri}${config.get('server.basePath')}` : server.info.uri, - elasticsearchClient: async (...args) => callWithRequest(request, ...args), + elasticsearchClient: async (...args: any) => callWithRequest(request, ...args), }; }; diff --git a/src/legacy/core_plugins/interpreter/server/routes/index.js b/src/legacy/core_plugins/interpreter/server/routes/index.ts similarity index 95% rename from src/legacy/core_plugins/interpreter/server/routes/index.js rename to src/legacy/core_plugins/interpreter/server/routes/index.ts index 9140f93a9bde6..50385147dd38e 100644 --- a/src/legacy/core_plugins/interpreter/server/routes/index.js +++ b/src/legacy/core_plugins/interpreter/server/routes/index.ts @@ -19,6 +19,6 @@ import { registerServerFunctions } from './server_functions'; -export function routes(server) { +export function routes(server: any) { registerServerFunctions(server); } diff --git a/src/legacy/core_plugins/interpreter/server/routes/server_functions.js b/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts similarity index 84% rename from src/legacy/core_plugins/interpreter/server/routes/server_functions.js rename to src/legacy/core_plugins/interpreter/server/routes/server_functions.ts index b64a9af006e41..740b046610d9e 100644 --- a/src/legacy/core_plugins/interpreter/server/routes/server_functions.js +++ b/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts @@ -18,16 +18,16 @@ */ import Boom from 'boom'; +import Joi from 'joi'; import { serializeProvider, API_ROUTE } from '../../common'; import { createHandlers } from '../lib/create_handlers'; -import Joi from 'joi'; /** * Register the Canvas function endopints. * * @param {*} server - The Kibana server */ -export function registerServerFunctions(server) { +export function registerServerFunctions(server: any) { getServerFunctions(server); runServerFunctions(server); } @@ -37,7 +37,7 @@ export function registerServerFunctions(server) { * * @param {*} server - The Kibana server */ -function runServerFunctions(server) { +function runServerFunctions(server: any) { server.route({ method: 'POST', path: `${API_ROUTE}/fns`, @@ -48,19 +48,20 @@ function runServerFunctions(server) { }, validate: { payload: Joi.object({ - functions: Joi.array().items( - Joi.object() - .keys({ + functions: Joi.array() + .items( + Joi.object().keys({ id: Joi.number().required(), functionName: Joi.string().required(), args: Joi.object().default({}), context: Joi.any().default(null), - }), - ).required(), + }) + ) + .required(), }).required(), }, }, - async handler(req) { + async handler(req: any) { const handlers = await createHandlers(req, server); const { functions } = req.payload; @@ -73,19 +74,19 @@ function runServerFunctions(server) { // Send the initial headers. res.writeHead(200, { 'Content-Type': 'text/plain', - 'Connection': 'keep-alive', + Connection: 'keep-alive', 'Transfer-Encoding': 'chunked', 'Cache-Control': 'no-cache', }); // Write a length-delimited response - const streamResult = (result) => { + const streamResult = (result: any) => { const payload = JSON.stringify(result) + '\n'; res.write(`${payload.length}:${payload}`); }; // Tries to run an interpreter function, and ensures a consistent error payload on failure. - const tryFunction = async (id, fnCall) => { + const tryFunction = async (id: any, fnCall: any) => { try { const result = await runFunction(server, handlers, fnCall); @@ -96,7 +97,7 @@ function runServerFunctions(server) { return { id, statusCode: 200, result }; } catch (err) { if (Boom.isBoom(err)) { - return batchError(id, err.output.payload, err.statusCode); + return batchError(id, err.output.payload, (err as any).statusCode); } else if (err instanceof Error) { return batchError(id, err.message); } @@ -107,7 +108,9 @@ function runServerFunctions(server) { }; // Process each function individually, and stream the responses back to the client - await Promise.all(functions.map(({ id, ...fnCall }) => tryFunction(id, fnCall).then(streamResult))); + await Promise.all( + functions.map(({ id, ...fnCall }: any) => tryFunction(id, fnCall).then(streamResult)) + ); // All of the responses have been written, so we can close the response. res.end(); @@ -118,7 +121,7 @@ function runServerFunctions(server) { /** * A helper function for bundling up errors. */ -function batchError(id, message, statusCode = 500) { +function batchError(id: any, message: any, statusCode = 500) { return { id, statusCode, @@ -130,7 +133,7 @@ function batchError(id, message, statusCode = 500) { * Register the endpoint that returns the list of server-only functions. * @param {*} server - The Kibana server */ -function getServerFunctions(server) { +function getServerFunctions(server: any) { server.route({ method: 'GET', path: `${API_ROUTE}/fns`, @@ -147,7 +150,7 @@ function getServerFunctions(server) { * @param {*} handlers - The Canvas handlers * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` */ -async function runFunction(server, handlers, fnCall) { +async function runFunction(server: any, handlers: any, fnCall: any) { const registries = server.plugins.interpreter.registries(); const { functionName, args, context } = fnCall; const types = registries.types.toJS(); diff --git a/src/legacy/core_plugins/interpreter/test_helpers.js b/src/legacy/core_plugins/interpreter/test_helpers.ts similarity index 86% rename from src/legacy/core_plugins/interpreter/test_helpers.js rename to src/legacy/core_plugins/interpreter/test_helpers.ts index e743b8a09280e..741cd83bb47fe 100644 --- a/src/legacy/core_plugins/interpreter/test_helpers.js +++ b/src/legacy/core_plugins/interpreter/test_helpers.ts @@ -21,8 +21,9 @@ import { mapValues } from 'lodash'; // Takes a function spec and passes in default args, // overriding with any provided args. -export const functionWrapper = fnSpec => { +export const functionWrapper = (fnSpec: any) => { const spec = fnSpec(); const defaultArgs = mapValues(spec.args, argSpec => argSpec.default); - return (context, args, handlers) => spec.fn(context, { ...defaultArgs, ...args }, handlers); + return (context: any, args: any, handlers: any) => + spec.fn(context, { ...defaultArgs, ...args }, handlers); }; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx index a24a37ca971d5..b96132fa29380 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx @@ -29,12 +29,12 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter return ( -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx index 4abfb2e604b1d..4e3b511782c9e 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx @@ -38,12 +38,12 @@ function RangesPanel({ return ( -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx index f606080afbdb2..a76171673d9a8 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx @@ -34,12 +34,12 @@ function StylePanel({ aggs, setGaugeValue, stateParams, vis }: GaugeOptionsInter return ( -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap index 6eef5047634f4..d88654cfdc0c4 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap @@ -7,13 +7,13 @@ exports[`CategoryAxisPanel component should init with the default set of props 1 -

+

-

+
-

+

-

+ -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx index 434202d64d6c3..5a455f4adde31 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx @@ -38,12 +38,12 @@ function SeriesPanel(props: SeriesPanelProps) { return ( -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx index 34a0d2cd981c5..eb0ab4333af59 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx @@ -109,12 +109,12 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx index 982c7265d5494..53dde185ec09f 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx @@ -36,12 +36,12 @@ function PieOptions(props: VisOptionsProps) { <> -

+

-

+
) { -
+

-

+
-

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx index 11034f7f7335e..8e3f66d12b9bd 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx @@ -34,12 +34,12 @@ function PointSeriesOptions(props: VisOptionsProps) { <> -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx index 9877b84345a1f..49e56e377a8d5 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx @@ -42,12 +42,12 @@ function ThresholdPanel({ stateParams, setValue, vis }: VisOptionsProps -

+

-

+
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js index b11f21a96f38d..fe2cca3b80064 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js @@ -17,7 +17,7 @@ * under the License. */ -import { setup as visualizations } from '../../visualizations/public/legacy'; +import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy'; import histogramVisTypeProvider from './histogram'; import lineVisTypeProvider from './line'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index 5ceb28e6b225b..39db357a69321 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -120,6 +120,7 @@
+

{{screenTitle}}

diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx index 741931af11c7d..22f127d12c438 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx @@ -331,7 +331,8 @@ export class DashboardAppController { getDashboardTitle( dashboardStateManager.getTitle(), dashboardStateManager.getViewMode(), - dashboardStateManager.getIsDirty(timefilter) + dashboardStateManager.getIsDirty(timefilter), + dashboardStateManager.isNew() ); // Push breadcrumbs to new header navigation diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts index c1ce5b764f2f6..7c1fc771de349 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts @@ -229,6 +229,14 @@ export class DashboardStateManager { return this.appState.title; } + public isSaved() { + return !!this.savedDashboard.id; + } + + public isNew() { + return !this.isSaved(); + } + public getDescription() { return this.appState.description; } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts index b7f9293539abd..d932116d08dc8 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts @@ -27,22 +27,31 @@ import { ViewMode } from '../../../../../../src/plugins/embeddable/public'; * end of the title. * @returns {string} A title to display to the user based on the above parameters. */ -export function getDashboardTitle(title: string, viewMode: ViewMode, isDirty: boolean): string { +export function getDashboardTitle( + title: string, + viewMode: ViewMode, + isDirty: boolean, + isNew: boolean +): string { const isEditMode = viewMode === ViewMode.EDIT; let displayTitle: string; + const newDashboardTitle = i18n.translate('kbn.dashboard.savedDashboard.newDashboardTitle', { + defaultMessage: 'New Dashboard', + }); + const dashboardTitle = isNew ? newDashboardTitle : title; if (isEditMode && isDirty) { displayTitle = i18n.translate('kbn.dashboard.strings.dashboardUnsavedEditTitle', { defaultMessage: 'Editing {title} (unsaved)', - values: { title }, + values: { title: dashboardTitle }, }); } else if (isEditMode) { displayTitle = i18n.translate('kbn.dashboard.strings.dashboardEditTitle', { defaultMessage: 'Editing {title}', - values: { title }, + values: { title: dashboardTitle }, }); } else { - displayTitle = title; + displayTitle = dashboardTitle; } return displayTitle; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/index.js b/src/legacy/core_plugins/kibana/public/dashboard/index.js index 6b7b086b16221..712e05c92e5e8 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/index.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/index.js @@ -33,13 +33,14 @@ import { DashboardConstants, createDashboardEditUrl } from './dashboard_constant import { InvalidJSONProperty, SavedObjectNotFound } from '../../../../../plugins/kibana_utils/public'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; -import { recentlyAccessed } from 'ui/persisted_log'; import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; import { uiModules } from 'ui/modules'; import 'ui/capabilities/route_setup'; import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; +import { npStart } from 'ui/new_platform'; + // load directives import '../../../data/public'; @@ -159,7 +160,7 @@ uiRoutes return savedDashboards.get(id) .then((savedDashboard) => { - recentlyAccessed.add(savedDashboard.getFullPath(), savedDashboard.title, id); + npStart.core.chrome.recentlyAccessed.add(savedDashboard.getFullPath(), savedDashboard.title, id); return savedDashboard; }) .catch((error) => { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.js b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.js index 36a083ef5a39c..fe9e7b18d5007 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.js @@ -18,7 +18,6 @@ */ import angular from 'angular'; -import { i18n } from '@kbn/i18n'; import { uiModules } from 'ui/modules'; import { createDashboardEditUrl } from '../dashboard_constants'; import { createLegacyClass } from 'ui/utils/legacy_class'; @@ -50,7 +49,7 @@ module.factory('SavedDashboard', function (Private) { // default values that will get assigned if the doc is new defaults: { - title: i18n.translate('kbn.dashboard.savedDashboard.newDashboardTitle', { defaultMessage: 'New Dashboard' }), + title: '', hits: 0, description: '', panelsJSON: '[]', diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html index 2043dc44c147e..d1a75adac5b82 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html @@ -84,7 +84,7 @@ i18n-default-message="Selected fields" >
-
    +
      { if (savedSearchId) { - recentlyAccessed.add( + npStart.core.chrome.recentlyAccessed.add( savedSearch.getFullPath(), savedSearch.title, savedSearchId); diff --git a/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap b/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap index 9f400e54899af..ed7a4b5d548ed 100644 --- a/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap @@ -377,11 +377,11 @@ Array [
      -

      Expand your time range -

      +

      One or more of the indices you’re looking at contains a date field. Your query may not match anything in the current time range, or there may not be any data at all in the currently selected time range. You can try changing the time range to one which contains data.

      diff --git a/src/legacy/core_plugins/kibana/public/discover/directives/no_results.js b/src/legacy/core_plugins/kibana/public/discover/directives/no_results.js index 9f57c49977f5a..5f6d32681b50e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/directives/no_results.js +++ b/src/legacy/core_plugins/kibana/public/discover/directives/no_results.js @@ -119,12 +119,12 @@ export class DiscoverNoResults extends Component { -

      +

      -

      +

      - +

      {{screenTitle}}

      + +

      { + $scope.recentlyAccessed = npStart.core.chrome.recentlyAccessed.get().map(item => { item.link = chrome.addBasePath(item.link); return item; }); diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html index 8513deee800e3..aa59b2d0a81c4 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html @@ -91,6 +91,16 @@
      +

      +

      { - recentlyAccessed.add( + npStart.core.chrome.recentlyAccessed.add( savedVis.getFullPath(), savedVis.title, savedVis.id); diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx index 52dcaaa05b94d..3b49287cced81 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx @@ -52,14 +52,14 @@ import { Container, EmbeddableOutput, } from '../../../../../../plugins/embeddable/public'; -import { start as visualizations } from '../../../../visualizations/public/legacy'; +import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy'; import { showNewVisModal } from '../wizard'; import { SavedVisualizations } from '../types'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { getIndexPattern } from './get_index_pattern'; import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; -import { TypesStart } from '../../../../visualizations/public/np_ready/types'; +import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js index 2c95f9c16969e..bb05ce34413db 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js +++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js @@ -29,7 +29,7 @@ import { SavedObjectsClientProvider } from 'ui/saved_objects'; import { VisualizeListingTable } from './visualize_listing_table'; import { NewVisModal } from '../wizard/new_vis_modal'; import { VisualizeConstants } from '../visualize_constants'; -import { start as visualizations } from '../../../../visualizations/public/legacy'; +import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy'; import { i18n } from '@kbn/i18n'; const app = uiModules.get('app/visualize', ['ngRoute', 'react']); diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js b/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js index cc48cbe2cb1b9..2d51fc1fa5e36 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js +++ b/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js @@ -21,7 +21,7 @@ import './_saved_vis'; import { uiModules } from 'ui/modules'; import { SavedObjectLoader, SavedObjectsClientProvider } from 'ui/saved_objects'; import { savedObjectManagementRegistry } from '../../management/saved_object_registry'; -import { start as visualizations } from '../../../../visualizations/public/legacy'; +import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy'; import { createVisualizeEditUrl } from '../visualize_constants'; import { findListItems } from './find_list_items'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx index 00c60c7718262..6b2f51c3dcf2b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx @@ -25,7 +25,7 @@ import { settingsGet } from './new_vis_modal.test.mocks'; import { NewVisModal } from './new_vis_modal'; import { VisType } from 'ui/vis'; -import { TypesStart } from '../../../../visualizations/public/np_ready/types'; +import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; describe('NewVisModal', () => { const defaultVisTypeParams = { diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx index 1279157f6a974..506f4f56d703b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx @@ -28,7 +28,7 @@ import { VisualizeConstants } from '../visualize_constants'; import { SearchSelection } from './search_selection'; import { TypeSelection } from './type_selection'; -import { TypesStart } from '../../../../visualizations/public/np_ready/types'; +import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; interface TypeSelectionProps { isOpen: boolean; diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx index 2e43d3f78631c..fa2ca6747bc40 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx @@ -22,7 +22,7 @@ import ReactDOM from 'react-dom'; import { I18nContext } from 'ui/i18n'; import { NewVisModal } from './new_vis_modal'; -import { TypesStart } from '../../../../visualizations/public/np_ready/types'; +import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; interface ShowNewVisModalParams { editorParams?: string[]; diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/type_selection.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/type_selection.tsx index a4a37e6143f62..04d5456dbf80d 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/type_selection.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/type_selection.tsx @@ -41,7 +41,7 @@ import { VisTypeAlias } from '../../../../../visualizations/public'; import { NewVisHelp } from './new_vis_help'; import { VisHelpText } from './vis_help_text'; import { VisTypeIcon } from './vis_type_icon'; -import { TypesStart } from '../../../../../visualizations/public/np_ready/types'; +import { TypesStart } from '../../../../../visualizations/public/np_ready/public/types'; interface VisTypeListEntry extends VisType { highlighted: boolean; diff --git a/src/legacy/core_plugins/region_map/index.ts b/src/legacy/core_plugins/region_map/index.ts index 258dc25f6a1e1..133d4be785d19 100644 --- a/src/legacy/core_plugins/region_map/index.ts +++ b/src/legacy/core_plugins/region_map/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const regionMapPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'region_map', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { hacks: [resolve(__dirname, 'public/legacy')], diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 3d28a209acc21..9bfa413257967 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -39,7 +39,7 @@ import afterdatachangePng from './afterdatachange.png'; import afterdatachangeandresizePng from './afterdatachangeandresize.png'; import aftercolorchangePng from './aftercolorchange.png'; import changestartupPng from './changestartup.png'; -import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createRegionMapVisualization } from '../region_map_visualization'; import { createRegionMapTypeDefinition } from '../region_map_type'; diff --git a/src/legacy/core_plugins/region_map/public/legacy.ts b/src/legacy/core_plugins/region_map/public/legacy.ts index e16a21cb78cc5..495e558e29dd7 100644 --- a/src/legacy/core_plugins/region_map/public/legacy.ts +++ b/src/legacy/core_plugins/region_map/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { RegionMapPluginSetupDependencies, RegionMapsConfig } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/tile_map/index.ts b/src/legacy/core_plugins/tile_map/index.ts index 15ce3bdb8e28b..b6ab88327f6bd 100644 --- a/src/legacy/core_plugins/tile_map/index.ts +++ b/src/legacy/core_plugins/tile_map/index.ts @@ -28,7 +28,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const tileMapPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'tile_map', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index a0cf3128ea88a..860c26bedd523 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -33,7 +33,7 @@ import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_ import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; -import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createTileMapVisualization } from '../tile_map_visualization'; import { createTileMapTypeDefinition } from '../tile_map_type'; diff --git a/src/legacy/core_plugins/tile_map/public/legacy.ts b/src/legacy/core_plugins/tile_map/public/legacy.ts index c367a5b5376ca..74be8482bfd30 100644 --- a/src/legacy/core_plugins/tile_map/public/legacy.ts +++ b/src/legacy/core_plugins/tile_map/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { TileMapPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index 29e56f77fd837..a1f4699a1282a 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -26,8 +26,8 @@ import { docTitle } from 'ui/doc_title'; import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import { fatalError, toastNotifications } from 'ui/notify'; import { timezoneProvider } from 'ui/vis/lib/timezone'; -import { recentlyAccessed } from 'ui/persisted_log'; import { timefilter } from 'ui/timefilter'; +import { npStart } from 'ui/new_platform'; import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs'; // import the uiExports that we want to "use" @@ -97,7 +97,7 @@ require('ui/routes') return savedSheets.get($route.current.params.id) .then((savedSheet) => { if ($route.current.params.id) { - recentlyAccessed.add( + npStart.core.chrome.recentlyAccessed.add( savedSheet.getFullPath(), savedSheet.title, savedSheet.id); diff --git a/src/legacy/core_plugins/timelion/public/legacy.ts b/src/legacy/core_plugins/timelion/public/legacy.ts index 8b8b5d4330b42..5d4939191a6ca 100644 --- a/src/legacy/core_plugins/timelion/public/legacy.ts +++ b/src/legacy/core_plugins/timelion/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; import { plugin } from '.'; -import { setup as visualizations } from '../../visualizations/public/legacy'; +import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy'; import { TimelionPluginSetupDependencies, TimelionPluginStartDependencies } from './plugin'; // @ts-ignore import panelRegistry from './lib/panel_registry'; diff --git a/src/legacy/core_plugins/timelion/public/plugin.ts b/src/legacy/core_plugins/timelion/public/plugin.ts index 4adfac3726b95..f7f0b48ef5011 100644 --- a/src/legacy/core_plugins/timelion/public/plugin.ts +++ b/src/legacy/core_plugins/timelion/public/plugin.ts @@ -26,7 +26,7 @@ import { HttpSetup, } from 'kibana/public'; import { Plugin as ExpressionsPlugin } from 'src/plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public/np_ready'; +import { VisualizationsSetup } from '../../visualizations/public/np_ready/public'; import { getTimelionVisualizationConfig } from './timelion_vis_fn'; import { getTimelionVisualization } from './vis'; import { getTimeChart } from './panels/timechart/timechart'; diff --git a/src/legacy/core_plugins/vis_type_markdown/index.ts b/src/legacy/core_plugins/vis_type_markdown/index.ts index 8106e5d30ddd0..1135872b24b8a 100644 --- a/src/legacy/core_plugins/vis_type_markdown/index.ts +++ b/src/legacy/core_plugins/vis_type_markdown/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const markdownPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'markdown_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts index 6074137532ae9..d4a5290df865c 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MarkdownPluginSetupDependencies } from './plugin'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.test.ts b/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.test.ts index 28021a763b287..009797905701c 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.test.ts @@ -30,7 +30,7 @@ describe('interpreter/functions#markdown', () => { }; it('returns an object with the correct structure', async () => { - const actual = await fn(undefined, args); + const actual = await fn(undefined, args, undefined); expect(actual).toMatchSnapshot(); }); }); diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx index 79628afe48531..53a7b1caef2a4 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx @@ -46,7 +46,9 @@ function MarkdownOptions({ stateParams, setValue }: VisOptionsProps -

      Markdown

      +

      + +

      diff --git a/src/legacy/core_plugins/vis_type_metric/index.ts b/src/legacy/core_plugins/vis_type_metric/index.ts index f71fc4a75461e..d5a86abfdc288 100644 --- a/src/legacy/core_plugins/vis_type_metric/index.ts +++ b/src/legacy/core_plugins/vis_type_metric/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const metricPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'metric_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts index c5fc86c7e35f5..f214bcbc82f7d 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MetricVisPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.test.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.test.ts index 5fe2ac7b7fdf0..fee6dec641842 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.test.ts @@ -67,7 +67,7 @@ describe('interpreter/functions#metric', () => { }; it('returns an object with the correct structure', () => { - const actual = fn(context, args); + const actual = fn(context, args, undefined); expect(actual).toMatchSnapshot(); }); diff --git a/src/legacy/core_plugins/vis_type_table/index.ts b/src/legacy/core_plugins/vis_type_table/index.ts index 3847dd6b58268..eba7af17c2057 100644 --- a/src/legacy/core_plugins/vis_type_table/index.ts +++ b/src/legacy/core_plugins/vis_type_table/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const tableVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'table_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js index 94c8fec650dcf..abebf8190dc9f 100644 --- a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js @@ -28,7 +28,7 @@ import { AppStateProvider } from 'ui/state_management/app_state'; import { tabifyAggResponse } from 'ui/agg_response/tabify'; import { createTableVisTypeDefinition } from '../table_vis_type'; -import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; describe('Table Vis - Controller', async function () { let $rootScope; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js index 4dad6bf5e44a0..d22ff92c4d3f6 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js @@ -31,7 +31,7 @@ import { round } from 'lodash'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { createTableVisTypeDefinition } from '../../table_vis_type'; -import { setup as visualizationsSetup } from '../../../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; describe('Table Vis - AggTable Directive', function () { let $rootScope; diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy.ts b/src/legacy/core_plugins/vis_type_table/public/legacy.ts index 5ec181f0e6974..8513622dec9aa 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts @@ -22,7 +22,7 @@ import { npSetup, npStart } from 'ui/new_platform'; import { plugin } from '.'; import { TablePluginSetupDependencies } from './plugin'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { LegacyDependenciesPlugin } from './shim'; const plugins: Readonly = { diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts index 2bdebc8a9d19e..1c1b808ffb014 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts @@ -76,12 +76,12 @@ describe('interpreter/functions#table', () => { }); it('returns an object with the correct structure', async () => { - const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }); + const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined); expect(actual).toMatchSnapshot(); }); it('calls response handler with correct values', async () => { - await fn(context, { visConfig: JSON.stringify(visConfig) }); + await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined); expect(mockResponseHandler).toHaveBeenCalledTimes(1); expect(mockResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); }); diff --git a/src/legacy/core_plugins/vis_type_tagcloud/index.ts b/src/legacy/core_plugins/vis_type_tagcloud/index.ts index a086a5af0261d..18dc8c9d78b74 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/index.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const tagCloudPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'tagcloud', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts index f173eff0aef88..66710791edc83 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { TagCloudPluginSetupDependencies } from './plugin'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_fn.test.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_fn.test.ts index d14871c6bd337..0365f7840cac4 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_fn.test.ts @@ -39,7 +39,7 @@ describe('interpreter/functions#tagcloud', () => { }; it('returns an object with the correct structure', () => { - const actual = fn(context, visConfig); + const actual = fn(context, visConfig, undefined); expect(actual).toMatchSnapshot(); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/index.ts b/src/legacy/core_plugins/vis_type_timeseries/index.ts index f302e36c046c4..215e7975d97c8 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/index.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/index.ts @@ -30,7 +30,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const metricsPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'metrics', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts b/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts index 17bfc3232c2ad..93b35ee284f18 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MetricsPluginSetupDependencies } from './plugin'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/vis_type_vega/index.ts b/src/legacy/core_plugins/vis_type_vega/index.ts index 3c18b548413f4..59d1ad6457711 100644 --- a/src/legacy/core_plugins/vis_type_vega/index.ts +++ b/src/legacy/core_plugins/vis_type_vega/index.ts @@ -28,7 +28,7 @@ const vegaPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPlugin // It is required to change the configuration property // vega.enableExternalUrls -> vis_type_vega.enableExternalUrls id: 'vega', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + require: ['kibana', 'elasticsearch', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index b3b11ffe7a951..13f4ce06f1b62 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -41,7 +41,7 @@ import vegaMapImage256 from './vega_map_image_256.png'; import { VegaParser } from '../data_model/vega_parser'; import { SearchCache } from '../data_model/search_cache'; -import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createVegaTypeDefinition } from '../vega_type'; const THRESHOLD = 0.1; diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index 73e03f6d323c2..d40212bec3b7f 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { VegaPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; diff --git a/src/legacy/core_plugins/visualizations/index.ts b/src/legacy/core_plugins/visualizations/index.ts deleted file mode 100644 index bb9ef1588bdc2..0000000000000 --- a/src/legacy/core_plugins/visualizations/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 { resolve } from 'path'; -import { Legacy } from '../../../../kibana'; - -// eslint-disable-next-line import/no-default-export -export default function VisualizationsPlugin(kibana: any) { - const config: Legacy.PluginSpecOptions = { - id: 'visualizations', - require: ['data'], - publicDir: resolve(__dirname, 'public'), - config: (Joi: any) => { - return Joi.object({ - enabled: Joi.boolean().default(true), - }).default(); - }, - init: (server: Legacy.Server) => ({}), - }; - - return new kibana.Plugin(config); -} diff --git a/src/legacy/core_plugins/visualizations/package.json b/src/legacy/core_plugins/visualizations/package.json deleted file mode 100644 index 5b436f0c2fef2..0000000000000 --- a/src/legacy/core_plugins/visualizations/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "visualizations", - "version": "kibana" -} diff --git a/src/legacy/core_plugins/visualizations/public/index.ts b/src/legacy/core_plugins/visualizations/public/index.ts index 997f18cbd5146..ad86c9ddb14c5 100644 --- a/src/legacy/core_plugins/visualizations/public/index.ts +++ b/src/legacy/core_plugins/visualizations/public/index.ts @@ -50,7 +50,7 @@ export { Status } from 'ui/vis/update_status'; * * @public */ -export * from './np_ready'; +export * from './np_ready/public'; // for backwards compatibility with 7.3 -export { setup as visualizations } from './legacy'; +export { setup as visualizations } from './np_ready/public/legacy'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json b/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json new file mode 100644 index 0000000000000..888edde44a261 --- /dev/null +++ b/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "visualizations", + "version": "kibana", + "server": false, + "ui": true, + "requiredPlugins": [ + "data", + "search" + ] +} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/filters/filters_service.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/filters/filters_service.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/filters/filters_service.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/filters/filters_service.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/filters/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/filters/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/filters/index.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/filters/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts similarity index 99% rename from src/legacy/core_plugins/visualizations/public/np_ready/index.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts index f43550676e1b2..5e1aa02712c08 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/index.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts @@ -28,6 +28,7 @@ * in the setup/start interfaces in `plugin.ts`. The remaining items exported here are * either types, or static code. */ + import { PluginInitializerContext } from 'src/core/public'; import { VisualizationsPlugin, VisualizationsSetup, VisualizationsStart } from './plugin'; diff --git a/src/legacy/core_plugins/visualizations/public/legacy.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts similarity index 62% rename from src/legacy/core_plugins/visualizations/public/legacy.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts index 088563a1970c3..16cec5d2d9e91 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts @@ -17,27 +17,13 @@ * under the License. */ -/** - * New Platform Shim - * - * In this file, we import any legacy dependencies we have, and shim them into - * our plugin by manually constructing the values that the new platform will - * eventually be passing to the `setup/start` method of our plugin definition. - * - * The idea is that our `plugin.ts` can stay "pure" and not contain any legacy - * world code. Then when it comes time to migrate to the new platform, we can - * simply delete this shim file. - * - * We are also calling `setup/start` here and exporting our public contract so that - * other legacy plugins are able to import from '../core_plugins/visualizations/legacy' - * and receive the response value of the `setup/start` contract, mimicking the - * data that will eventually be injected by the new platform. - */ - import { PluginInitializerContext } from 'src/core/public'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ import { npSetup, npStart } from 'ui/new_platform'; // @ts-ignore import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters'; +/* eslint-enable @kbn/eslint/no-restricted-paths */ import { plugin } from '.'; diff --git a/src/legacy/core_plugins/visualizations/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts similarity index 89% rename from src/legacy/core_plugins/visualizations/public/mocks.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts index 11dccbb173755..5dc0e452eea56 100644 --- a/src/legacy/core_plugins/visualizations/public/mocks.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts @@ -22,18 +22,17 @@ jest.mock('ui/vis/default_feedback_message'); jest.mock('ui/vis/index.js'); jest.mock('ui/vis/vis_factory'); jest.mock('ui/registry/vis_types'); -// @ts-ignore -import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters'; -// @ts-ignore -import { VisProvider as Vis } from 'ui/vis/index.js'; -// @ts-ignore -import { VisFactoryProvider } from 'ui/vis/vis_factory'; jest.mock('./types/vis_type_alias_registry'); -import { PluginInitializerContext } from 'src/core/public'; +import { PluginInitializerContext } from 'src/core/public'; import { VisualizationsSetup, VisualizationsStart } from './'; -import { VisualizationsPlugin } from './np_ready/plugin'; -import { coreMock } from '../../../../core/public/mocks'; +import { VisualizationsPlugin } from './plugin'; +import { coreMock } from '../../../../../../core/public/mocks'; + +/* eslint-disable */ +// @ts-ignore +import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters'; +/* eslint-enable */ const createSetupContract = (): VisualizationsSetup => ({ filters: { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/plugin.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/types/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/types/index.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/types/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/types/types_service.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/types/types_service.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/types/vis_type_alias_registry.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types/vis_type_alias_registry.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/types/vis_type_alias_registry.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/types/vis_type_alias_registry.ts diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.html b/src/legacy/ui/public/chrome/directives/kbn_chrome.html index 541082e68de58..ced89287d310f 100644 --- a/src/legacy/ui/public/chrome/directives/kbn_chrome.html +++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.html @@ -1,9 +1,9 @@
      -
      + >
      diff --git a/src/legacy/ui/public/persisted_log/directive.js b/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts similarity index 80% rename from src/legacy/ui/public/persisted_log/directive.js rename to src/legacy/ui/public/new_platform/new_platform.test.mocks.ts index 29f2f93093aeb..e660ad1f55840 100644 --- a/src/legacy/ui/public/persisted_log/directive.js +++ b/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts @@ -17,10 +17,8 @@ * under the License. */ -import { uiModules } from '../modules'; -import { PersistedLog } from './persisted_log'; +export const setRootControllerMock = jest.fn(); -uiModules.get('kibana/persisted_log') - .factory('PersistedLog', function () { - return PersistedLog; - }); +jest.doMock('ui/chrome', () => ({ + setRootController: setRootControllerMock, +})); diff --git a/src/legacy/ui/public/new_platform/new_platform.test.ts b/src/legacy/ui/public/new_platform/new_platform.test.ts new file mode 100644 index 0000000000000..cbdaccd65f94b --- /dev/null +++ b/src/legacy/ui/public/new_platform/new_platform.test.ts @@ -0,0 +1,83 @@ +/* + * 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 { setRootControllerMock } from './new_platform.test.mocks'; +import { legacyAppRegister, __reset__ } from './new_platform'; + +describe('ui/new_platform', () => { + describe('legacyAppRegister', () => { + beforeEach(() => { + setRootControllerMock.mockReset(); + __reset__(); + }); + + const registerApp = () => { + const unmountMock = jest.fn(); + const mountMock = jest.fn(() => unmountMock); + legacyAppRegister({ + id: 'test', + title: 'Test', + mount: mountMock, + }); + return { mountMock, unmountMock }; + }; + + test('sets ui/chrome root controller', () => { + registerApp(); + expect(setRootControllerMock).toHaveBeenCalledWith('test', expect.any(Function)); + }); + + test('throws if called more than once', () => { + registerApp(); + expect(registerApp).toThrowErrorMatchingInlineSnapshot( + `"core.application.register may only be called once for legacy plugins."` + ); + }); + + test('controller calls app.mount when invoked', () => { + const { mountMock } = registerApp(); + const controller = setRootControllerMock.mock.calls[0][1]; + const scopeMock = { $on: jest.fn() }; + const elementMock = [document.createElement('div')]; + + controller(scopeMock, elementMock); + expect(mountMock).toHaveBeenCalledWith(expect.any(Object), { + element: elementMock[0], + appBasePath: '', + }); + }); + + test('controller calls unmount when $scope.$destroy', async () => { + const { unmountMock } = registerApp(); + const controller = setRootControllerMock.mock.calls[0][1]; + const scopeMock = { $on: jest.fn() }; + const elementMock = [document.createElement('div')]; + + controller(scopeMock, elementMock); + // Flush promise queue. Must be done this way because the controller cannot return a Promise without breaking + // angular. + await new Promise(resolve => setTimeout(resolve, 1)); + + const [event, eventHandler] = scopeMock.$on.mock.calls[0]; + expect(event).toEqual('$destroy'); + eventHandler(); + expect(unmountMock).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index ed13af591525c..b86f9cde0125c 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ +import { IScope } from 'angular'; + import { IUiActionsStart, IUiActionsSetup } from 'src/plugins/ui_actions/public'; import { Start as EmbeddableStart, Setup as EmbeddableSetup } from 'src/plugins/embeddable/public'; -import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public'; +import { LegacyCoreSetup, LegacyCoreStart, App } from '../../../../core/public'; import { Plugin as DataPlugin } from '../../../../plugins/data/public'; import { Plugin as ExpressionsPlugin } from '../../../../plugins/expressions/public'; import { @@ -63,14 +65,44 @@ export function __reset__() { npSetup.plugins = {} as any; npStart.core = (null as unknown) as LegacyCoreStart; npStart.plugins = {} as any; + legacyAppRegistered = false; } export function __setup__(coreSetup: LegacyCoreSetup, plugins: PluginsSetup) { npSetup.core = coreSetup; npSetup.plugins = plugins; + + // Setup compatibility layer for AppService in legacy platform + npSetup.core.application.register = legacyAppRegister; } export function __start__(coreStart: LegacyCoreStart, plugins: PluginsStart) { npStart.core = coreStart; npStart.plugins = plugins; } + +/** Flag used to ensure `legacyAppRegister` is only called once. */ +let legacyAppRegistered = false; + +/** + * Exported for testing only. Use `npSetup.core.application.register` in legacy apps. + * @internal + */ +export const legacyAppRegister = (app: App) => { + if (legacyAppRegistered) { + throw new Error(`core.application.register may only be called once for legacy plugins.`); + } + legacyAppRegistered = true; + + require('ui/chrome').setRootController(app.id, ($scope: IScope, $element: JQLite) => { + const element = $element[0]; + + // Root controller cannot return a Promise so use an internal async function and call it immediately + (async () => { + const unmount = await app.mount({ core: npStart.core }, { element, appBasePath: '' }); + $scope.$on('$destroy', () => { + unmount(); + }); + })(); + }); +}; diff --git a/src/legacy/ui/public/persisted_log/index.ts b/src/legacy/ui/public/persisted_log/index.ts index 8821b4d7079a0..52de69b9c50bf 100644 --- a/src/legacy/ui/public/persisted_log/index.ts +++ b/src/legacy/ui/public/persisted_log/index.ts @@ -17,8 +17,5 @@ * under the License. */ -// @ts-ignore -import './directive'; - export { PersistedLog } from './persisted_log'; export { recentlyAccessed } from './recently_accessed'; diff --git a/src/legacy/ui/public/saved_objects/saved_object.js b/src/legacy/ui/public/saved_objects/saved_object.js index 2da1573d503a9..cf83e6ef057f8 100644 --- a/src/legacy/ui/public/saved_objects/saved_object.js +++ b/src/legacy/ui/public/saved_objects/saved_object.js @@ -39,7 +39,7 @@ import { SearchSourceProvider } from '../courier/search_source'; import { findObjectByTitle } from './find_object_by_title'; import { SavedObjectsClientProvider } from './saved_objects_client_provider'; import { migrateLegacyQuery } from '../utils/migrate_legacy_query'; -import { recentlyAccessed } from '../persisted_log'; +import { npStart } from 'ui/new_platform'; import { i18n } from '@kbn/i18n'; /** @@ -512,7 +512,7 @@ export function SavedObjectProvider(Promise, Private, confirmModalPromise, index }) .then(() => { if (this.showInRecentlyAccessed && this.getFullPath) { - recentlyAccessed.add(this.getFullPath(), this.title, this.id); + npStart.core.chrome.recentlyAccessed.add(this.getFullPath(), this.title, this.id); } this.isSaving = false; this.lastSavedTitle = this.title; diff --git a/src/legacy/ui/public/vis/__tests__/_vis.js b/src/legacy/ui/public/vis/__tests__/_vis.js index 9ecfd90b29fe5..5a2f93ab35b50 100644 --- a/src/legacy/ui/public/vis/__tests__/_vis.js +++ b/src/legacy/ui/public/vis/__tests__/_vis.js @@ -22,7 +22,7 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import { VisProvider } from '..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { start as visualizations } from '../../../../core_plugins/visualizations/public/legacy'; +import { start as visualizations } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; describe('Vis Class', function () { let indexPattern; diff --git a/src/legacy/ui/public/vis/editors/default/components/__snapshots__/agg_group.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/agg_group.test.tsx.snap index 813b7978d2667..29af0887db2b8 100644 --- a/src/legacy/ui/public/vis/editors/default/components/__snapshots__/agg_group.test.tsx.snap +++ b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/agg_group.test.tsx.snap @@ -10,9 +10,9 @@ exports[`DefaultEditorAgg component should init with the default set of props 1` -
      +

      Metrics -

      +
      -
      {groupNameLabel}
      +

      {groupNameLabel}

      diff --git a/src/legacy/ui/public/vis/editors/default/sidebar.html b/src/legacy/ui/public/vis/editors/default/sidebar.html index 0434534bddbfd..b0a03e461fc1c 100644 --- a/src/legacy/ui/public/vis/editors/default/sidebar.html +++ b/src/legacy/ui/public/vis/editors/default/sidebar.html @@ -7,7 +7,7 @@ ng-keydown="submitEditorWithKeyboard($event)" > -
      {{ vis.indexPattern.title }} -
      +