diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 85f490bc366b9..a160094a54130 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,6 +78,7 @@ # Canvas /x-pack/plugins/canvas/ @elastic/kibana-canvas +/x-pack/test/functional/apps/canvas/ @elastic/kibana-canvas # Observability UIs /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui diff --git a/docs/settings/apm-settings.asciidoc b/docs/settings/apm-settings.asciidoc index 8844fcd03ae9a..efc43e5d2f52d 100644 --- a/docs/settings/apm-settings.asciidoc +++ b/docs/settings/apm-settings.asciidoc @@ -43,29 +43,29 @@ Changing these settings may disable features of the APM App. | `xpack.apm.enabled` | Set to `false` to disable the APM app. Defaults to `true`. -| `xpack.apm.ui.enabled` +| `xpack.apm.ui.enabled` {ess-icon} | Set to `false` to hide the APM app from the menu. Defaults to `true`. | `xpack.apm.ui.transactionGroupBucketSize` | Number of top transaction groups displayed in the APM app. Defaults to `100`. -| `xpack.apm.ui.maxTraceItems` +| `xpack.apm.ui.maxTraceItems` {ess-icon} | Maximum number of child items displayed when viewing trace details. Defaults to `1000`. -| `apm_oss.indexPattern` +| `apm_oss.indexPattern` {ess-icon} | The index pattern used for integrations with Machine Learning and Query Bar. It must match all apm indices. Defaults to `apm-*`. -| `apm_oss.errorIndices` +| `apm_oss.errorIndices` {ess-icon} | Matcher for all {apm-server-ref}/error-indices.html[error indices]. Defaults to `apm-*`. | `apm_oss.onboardingIndices` | Matcher for all onboarding indices. Defaults to `apm-*`. -| `apm_oss.spanIndices` +| `apm_oss.spanIndices` {ess-icon} | Matcher for all {apm-server-ref}/span-indices.html[span indices]. Defaults to `apm-*`. -| `apm_oss.transactionIndices` +| `apm_oss.transactionIndices` {ess-icon} | Matcher for all {apm-server-ref}/transaction-indices.html[transaction indices]. Defaults to `apm-*`. | `apm_oss.metricsIndices` diff --git a/rfcs/text/0011_global_search.md b/rfcs/text/0011_global_search.md new file mode 100644 index 0000000000000..5ec368a1c2f02 --- /dev/null +++ b/rfcs/text/0011_global_search.md @@ -0,0 +1,591 @@ +- Start Date: 2020-04-19 +- RFC PR: [#64284](https://github.com/elastic/kibana/pull/64284) +- Kibana Issue: [#61657](https://github.com/elastic/kibana/issues/61657) + +# Summary + +A new Kibana plugin exposing an API on both public and server side, to allow consumers to search for various objects and +register result providers. + +Note: whether this will be an oss or xpack plugin still depends on https://github.com/elastic/dev/issues/1404. + +# Basic example + +- registering a result provider: + +```ts +setupDeps.globalSearch.registerResultProvider({ + id: 'my_provider', + find: (term, options, context) => { + const resultPromise = myService.search(term, context.core.savedObjects.client); + return from(resultPromise); + }, +}); +``` + +- using the `find` API from the client-side: + +```ts +startDeps.globalSearch.find('some term').subscribe( + ({ results }) => { + updateResults(results); + }, + () => {}, + () => { + showAsyncSearchIndicator(false); + } +); +``` + +# Motivation + +Kibana should do its best to assist users searching for and navigating to the various objects present on the Kibana platform. + +We should expose an API to make it possible for plugins to search for the various objects present on a Kibana instance. + +The first consumer of this API will be the global search bar [#57576](https://github.com/elastic/kibana/issues/57576). This API +should still be generic to answer similar needs from any other consumer, either client or server side. + +# Detailed design + +## API Design + +### Result provider API + +#### common types + +```ts +/** + * Static, non exhaustive list of the common search types. + * Only present to allow consumers and result providers to have aliases to the most common types. + */ +enum GlobalSearchCommonResultTypes { + application = 'application', + dashboard = 'dashboard', + visualization = 'visualization', + search = 'search', +} + +/** + * Options provided to {@link GlobalSearchResultProvider | result providers} `find` method. + */ +interface GlobalSearchProviderFindOptions { + /** + * A custom preference token associated with a search 'session' that should be used to get consistent scoring + * when performing calls to ES. Can also be used as a 'session' token for providers returning data from elsewhere + * than an elasticsearch cluster. + */ + preference: string; + /** + * Observable that emit once if and when the `find` call has been aborted by the consumer, or when the timeout period as been reached. + * When a `find` request is aborted, the service will stop emitting any new result to the consumer anyway, but + * this can (and should) be used to cancel any pending asynchronous task and complete the result observable. + */ + aborted$: Observable; + /** + * The total maximum number of results (including all batches / emissions) that should be returned by the provider for a given `find` request. + * Any result emitted exceeding this quota will be ignored by the service and not emitted to the consumer. + */ + maxResults: number; +} + +/** + * Representation of a result returned by a {@link GlobalSearchResultProvider | result provider} + */ +interface GlobalSearchProviderResult { + /** an id that should be unique for an individual provider's results */ + id: string; + /** the title/label of the result */ + title: string; + /** the type of result */ + type: string; + /** an optional EUI icon name to associate with the search result */ + icon?: string; + /** + * The url associated with this result. + * This can be either an absolute url, a path relative to the basePath, or a structure specifying if the basePath should be prepended. + * + * @example + * `result.url = 'https://kibana-instance:8080/base-path/app/my-app/my-result-type/id';` + * `result.url = '/app/my-app/my-result-type/id';` + * `result.url = { path: '/base-path/app/my-app/my-result-type/id', prependBasePath: false };` + */ + url: string | { path: string; prependBasePath: boolean }; + /** the score of the result, from 1 (lowest) to 100 (highest) */ + score: number; + /** an optional record of metadata for this result */ + meta?: Record; +} +``` + +Notes: + +- The `Serializable` type should be implemented and exposed from `core`. A basic implementation could be: + +```ts +type Serializable = string | number | boolean | PrimitiveArray | PrimitiveRecord; +interface PrimitiveArray extends Array {} +interface PrimitiveRecord extends Record {} +``` + +#### server + +```ts +/** + * Context passed to server-side {@GlobalSearchResultProvider | result provider}'s `find` method. + */ +export interface GlobalSearchProviderContext { + core: { + savedObjects: { + client: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + }; + elasticsearch: { + legacy: { + client: IScopedClusterClient; + }; + }; + uiSettings: { + client: IUiSettingsClient; + }; + }; +} + +/** + * GlobalSearch result provider, to be registered using the {@link GlobalSearchSetup | global search API} + */ +type GlobalSearchResultProvider = { + id: string; + find( + term: string, + options: GlobalSearchProviderFindOptions, + context: GlobalSearchProviderContext + ): Observable; +}; +``` + +Notes: + +- Initial implementation will only provide a static / non extensible `GlobalSearchProviderContext` context. + It would be possible to allow plugins to register their own context providers as it's done for `RequestHandlerContext`, + but this will not be done until the need arises. +- The performing `request` object could also be exposed on the context to allow result providers + to scope their custom services if needed. However as the previous option, this should only be done once needed. + +#### public + +```ts +/** + * GlobalSearch result provider, to be registered using the {@link GlobalSearchSetup | global search API} + */ +type GlobalSearchResultProvider = { + id: string; + find( + term: string, + options: GlobalSearchProviderFindOptions + ): Observable; +}; +``` + +Notes: + +- The client-side version of `GlobalSearchResultProvider` is slightly different than the + server one, as there is no `context` parameter on the `find` signature. + +### Plugin API + +#### server API + +```ts +/** + * Representation of a result returned by the {@link GlobalSearchPluginStart.find | `find` API} + */ +type GlobalSearchResult = Omit & { + /** + * The url associated with this result. + * This can be either an absolute url, or a relative path including the basePath + */ + url: string; +}; + +/** + * Options for the server-side {@link GlobalSearchServiceStart.find | find API} + */ +interface GlobalSearchFindOptions { + /** + * a custom preference token associated with a search 'session' that should be used to get consistent scoring + * when performing calls to ES. Can also be used as a 'session' token for providers returning data from elsewhere + * than an elasticsearch cluster. + * If not specified, a random token will be generated and used when callingn the underlying result providers. + */ + preference?: string; + /** + * Optional observable to notify that the associated `find` call should be canceled. + * If/when provided and emitting, the result observable will be completed and no further result emission will be performed. + */ + aborted$?: Observable; +} + +/** + * Response returned from the server-side {@link GlobalSearchServiceStart | global search service}'s `find` API + */ +type GlobalSearchBatchedResults = { + /** + * Results for this batch + */ + results: GlobalSearchResult[]; +}; + +/** @public */ +interface GlobalSearchPluginSetup { + registerResultProvider(provider: GlobalSearchResultProvider); +} + +/** @public */ +interface GlobalSearchPluginStart { + find( + term: string, + options: GlobalSearchFindOptions, + request: KibanaRequest + ): Observable; +} +``` + +#### public API + +```ts +/** + * Options for the client-side {@link GlobalSearchServiceStart.find | find API} + */ +interface GlobalSearchFindOptions { + /** + * Optional observable to notify that the associated `find` call should be canceled. + * If/when provided and emitting, the result observable will be completed and no further result emission will be performed. + */ + aborted$?: Observable; +} + +/** + * Enhanced {@link GlobalSearchResult | result type} for the client-side, + * to allow navigating to a given result. + */ +interface NavigableGlobalSearchResult extends GlobalSearchResult { + /** + * Navigate to this result's associated url. If the result is on this kibana instance, user will be redirected to it + * in a SPA friendly way using `application.navigateToApp`, else, a full page refresh will be performed. + */ + navigate: () => Promise; +} + +/** + * Response returned from the client-side {@link GlobalSearchServiceStart | global search service}'s `find` API + */ +type GlobalSearchBatchedResults = { + /** + * Results for this batch + */ + results: NavigableGlobalSearchResult[]; +}; + +/** @public */ +interface GlobalSearchPluginSetup { + registerResultProvider(provider: GlobalSearchResultProvider); +} + +/** @public */ +interface GlobalSearchPluginStart { + find(term: string, options: GlobalSearchFindOptions): Observable; +} +``` + +Notes: + +- The public API is very similar to its server counterpart. The differences are: + - The `registerResultProvider` setup APIs share the same signature, however the input `GlobalSearchResultProvider` + types are different on the client and server. + - The `find` start API signature got a `KibanaRequest` for `server`, when this parameter is not present for `public`. +- The `find` API returns a observable of `NavigableGlobalSearchResult` instead of plain `GlobalSearchResult`. This type + is here to enhance results with a `navigate` method to let the `GlobalSearch` plugin handle the navigation logic, which is + non-trivial. See the [Redirecting to a result](#redirecting-to-a-result) section for more info. + +#### http API + +An internal HTTP API will be exposed on `/internal/global_search/find` to allow the client-side `GlobalSearch` plugin +to fetch results from the server-side result providers. + +It should be very close to: + +```ts +router.post( + { + path: '/internal/global_search/find', + validate: { + body: schema.object({ + term: schema.string(), + options: schema.maybe( + schema.object({ + preference: schema.maybe(schema.string()), + }) + ), + }), + }, + }, + async (ctx, req, res) => { + const { term, options } = req.body; + const results = await ctx.globalSearch + .find(term, { ...options, $aborted: req.events.aborted$ }) + .pipe(reduce((acc, results) => [...acc, ...results])) + .toPromise(); + return res.ok({ + body: { + results, + }, + }); + } +); +``` + +Notes: + +- This API is only for internal use and communication between the client and the server parts of the `GS` API. When + the need to expose an API for external consumers will appear, a new public API will be exposed for that. +- A new `globalSearch` context will be exposed on core's `RequestHandlerContext` to wrap a `find` call with current request. +- Example implementation is awaiting for all results and then returns them as a single response. Ideally, we would + leverage the `bfetch` plugin to stream the results to the client instead. + +## Functional behavior + +### summary + +- the `GlobalSearch` plugin setup contract exposes an API to be able to register result providers (`GlobalSearchResultProvider`). + These providers can be registered from either public or server side, even if the interface for each side is not + exactly the same. +- the `GlobalSearch` plugin start contract exposes an API to be able to search for objects. This API is available from both public + and server sides. + - When using the server `find` API, only results from providers registered from the server will be returned. + - When using the public `find` API, results from provider registered from both server and public sides will be returned. +- During a `find` call, the service will call all the registered result providers and collect their result observables. + Every time a result provider emits some new results, the `globalSearch` service will: + - process them to convert their url to the expected output format + - emit the processed results + +### result provider registration + +Due to the fact that some kind of results (i.e `application`, and maybe later `management_section`) only exists on +the public side of Kibana and therefor are not known on the server side, the `registerResultProvider` API will be +available both from the public and the server counterpart of the `GlobalSearchPluginSetup` contract. + +However, as results from providers registered from the client-side will not be available from the server's `find` API, +registering result providers from the client should only be done to answer this specific use case and will be +discouraged, by providing appropriated jsdoc and documentation explaining that it should only +be used when it is not technically possible to register it from the server side instead. + +### results url processing + +When retrieving results from providers, the GS service will convert them from the provider's `GlobalSearchProviderResult` +result type to `GlobalSeachResult`, which is the structure returned from the `GlobalSearchPluginStart.find` observable. + +In current specification, the only conversion step is to transform the `result.url` property following this logic: + +- if `url` is an absolute url, it will not be modified +- if `url` is a relative path, the basePath will be prepended using `basePath.prepend` +- if `url` is a `{ path: string; prependBasePath: boolean }` structure: + - if `prependBasePath` is true, the basePath will be prepended to the given `path` using `basePath.prepend` + - if `prependBasePath` is false, the given `path` will be returned unmodified + +#### redirecting to a result + +Parsing a relative or absolute result url to perform SPA navigation can be non trivial, and should remains the responsibility +of the GlobalSearch plugin API. + +This is why `NavigableGlobalSearchResult.navigate` has been introduced on the client-side version of the `find` API + +When using `navigate` from a result instance, the following logic will be executed: + +If all these criteria are true for `result.url`: + +- (only for absolute URLs) The origin of the URL matches the origin of the browser's current location +- The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) +- The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) + +Then: match the pathname segment to the corresponding application and do the SPA navigation to that application using +`application.navigateToApp` using the remaining pathname segment for the `path` option. + +Otherwise: do a full page navigation using `window.location.assign` + +### searching from the server side + +When calling `GlobalSearchPluginStart.find` from the server-side service: + +- the service will call `find` on each server-side registered result provider and collect the resulting result observables + +- then, the service will merge every result observable and trigger the next step on every emission until either + - A predefined timeout duration is reached + - All result observables are completed + +- on every emission of the merged observable, the results will be processed then emitted. + +A very naive implementation of this behavior would be: + +```ts +search( + term: string, + options: GlobalSearchFindOptions, + request: KibanaRequest +): Observable { + const aborted$ = merge(timeout$, options.$aborted).pipe(first()) + const fromProviders$ = this.providers.map(p => + p.find(term, { ...options, aborted$ }, contextFromRequest(request)) + ); + return merge([...fromProviders$]).pipe( + takeUntil(aborted$), + map(newResults => { + return process(newResults); + }), + ); +} +``` + +### searching from the client side + +When calling `GlobalSearchPluginStart.find` from the public-side service: + +- The service will call: + + - the server-side API via an http call to fetch results from the server-side result providers + - `find` on each client-side registered result provider and collect the resulting observables + +- Then, the service will merge every result observable and trigger the next step on every emission until either + + - A predefined timeout duration is reached + - All result observables are completed + +- on every emission of the merged observable, the results will be processed then emitted. + +A very naive implementation of this behavior would be: + +``` +search( + term: string, + options: GlobalSearchFindOptions, +): Observable { + const aborted$ = merge(timeout$, options.$aborted).pipe(first()) + const fromProviders$ = this.providers.map(p => + p.find(term, { ...options, aborted$ }) + ); + const fromServer$ = of(this.fetchServerResults(term, options, aborted$)) + return merge([...fromProviders$, fromServer$]).pipe( + takeUntil(aborted$), + map(newResults => { + return process(newResults); + }), + ); +} +``` + +Notes: + +- The example implementation is not streaming results from the server, meaning that all results from server-side + registered providers will all be fetched and emitted in a single batch. Ideally, we would leverage the `bfetch` plugin + to stream the results to the client instead. + +### results sorting + +As the GS `find` API is 'streaming' the results from the result providers by emitting the results in batches, sorting results in +each individual batch, even if technically possible, wouldn't provide much value as the consumer will need to sort the +aggregated results on each emission anyway. This is why the results emitted by the `find` API should be considered as +unsorted. Consumers should implement sorting themselves, using either the `score` attribute, or any other arbitrary logic. + +#### Note on score value + +Due to the fact that the results will be coming from various providers, from multiple ES queries or even not from ES, +using a centralized scoring mechanism is not possible. + +the `GlobalSearchResult` contains a `score` field, with an expected value going from 1 (lowest) to 100 (highest). +How this field is populated from each individual provider is considered an implementation detail. + +### Search cancellation + +Consumers can cancel a `find` call at any time by providing a cancellation observable with +the `GlobalSearchFindOptions.aborted$` option and then emitting from it. + +When this observable is provided and emitting, the GS service will complete the result observable. + +This observable will also be passed down to the underlying result providers, that can leverage it to cancel any pending +asynchronous task and perform cleanup if necessary. + +# Drawbacks + +See alternatives. + +# Alternatives + +## Result providers could be only registrable from the server-side API + +The fact that some kinds of results, and therefore some result providers, must be on the client-side makes the API more complex, +while making these results not available from the server-side and HTTP APIs. + +We could decide to only allow providers registration from the server-side. It would reduce API exposure, while simplifying +the service implementation. However to do that, we would need to find a solution to be able to implement a server-side +result provider for `application` (and later `management_section`) type provider. + +I will directly exclude the option to move the `application` registration (`core.application.register`) from client +to server-side, as it's a very heavy impacting (and breaking) change to `core` APIs that would requires more reasons +than just this RFC/API to consider. + +### AST parsing + +One option to make the `application` results 'visible' from the server-side would be to parse the client code at build time +using AST to find all usages to `application.register` inspect the parameters, and generates a server file +containing the applications. The server-side `application` result provider would then just read this file and uses it +to return application results. + +However + +- At the parsing would be done at build time, we would not be able to generate entries for any 3rd party plugins +- As entries for every existing applications would be generated, the search provider would to be able to know which + applications are actually enabled/accessible at runtime to filter them, which is all but easy +- It will also not contains test plugin apps, making it really hard to FTR +- AST parsing is a complex mechanism for an already unsatisfactory alternative + +### Duplicated server-side `application.register` API + +One other option would be to duplicate the `application.register` API on the server side, with a subset of the +client-side metadata. + +```ts +core.application.register({ + id: 'app_status', + title: 'App Status', + euiIconType: 'snowflake', +}); +``` + +This way, the applications could be searchable from the server using this server-side `applications` registry. + +However + +- It forces plugin developers to add this API call. In addition to be a very poor developer experience, it can also + very easily be forgotten, making a given app non searchable +- client-side only plugins would need to add a server-side part to their plugin just to register their application on + the server side + +# Adoption strategy + +The `globalSearch` service is a new feature provided by the `core` API. Also, the base providers +used to search for saved objects and applications will be implemented by the platform team, meaning +that by default, plugin developers won't have to do anything. + +Plugins that wish to expose additional result providers will easily be able to do so by using the exposed APIs and +documentation. + +# How we teach this + +This follows the same patterns we have used for other Core APIs: Observables subscriptions, etc. + +This should be taught using the same channels we've leveraged for other Kibana Platform APIs, API documentation and +example plugins. + +# Unresolved questions + +N/A diff --git a/src/cli/cluster/run_kbn_optimizer.ts b/src/cli/cluster/run_kbn_optimizer.ts index b811fc1f6b294..e4bd6b98dd2b9 100644 --- a/src/cli/cluster/run_kbn_optimizer.ts +++ b/src/cli/cluster/run_kbn_optimizer.ts @@ -35,6 +35,7 @@ export function runKbnOptimizer(opts: Record, config: LegacyConfig) repoRoot: REPO_ROOT, watch: true, includeCoreBundle: true, + cache: !!opts.cache, oss: !!opts.oss, examples: !!opts.runExamples, pluginPaths: config.get('plugins.paths'), diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 471939121143a..6b0daebd5a042 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -218,6 +218,7 @@ export default function(program) { "Don't put a proxy in front of the dev server, which adds a random basePath" ) .option('--no-watch', 'Prevents automatic restarts of the server in --dev mode') + .option('--no-cache', 'Disable the kbn/optimizer cache') .option('--no-dev-config', 'Prevents loading the kibana.dev.yml file in --dev mode'); } diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 02d46b1583b59..ce2d652257e1f 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1240,6 +1240,7 @@ import { npStart: { plugins } } from 'ui/new_platform'; | `ui/filter_manager` | `plugins.data.filter` | -- | | `ui/index_patterns` | `plugins.data.indexPatterns` | | `import 'ui/management'` | `plugins.management.sections` | | +| `import 'ui/registry/field_format_editors'` | `plugins.indexPatternManagement.fieldFormatEditors` | | | `ui/registry/field_formats` | `plugins.data.fieldFormats` | | | `ui/registry/feature_catalogue` | `plugins.home.featureCatalogue.register` | Must add `home` as a dependency in your kibana.json. | | `ui/registry/vis_types` | `plugins.visualizations` | -- | diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index aad7e6dcf270a..4317ede547202 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -87,6 +87,8 @@ export const AppContainer: FunctionComponent = ({ })) || null; } catch (e) { // TODO: add error UI + // eslint-disable-next-line no-console + console.error(e); } finally { setShowSpinner(false); setIsMounting(false); diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index 327be61cc63e3..b5cf900d9c39f 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -97,7 +97,9 @@ describe('start', () => { expect(startDeps.notifications.toasts.addWarning.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "Your browser does not meet the security requirements for Kibana.", + Object { + "title": [Function], + }, ], ] `); @@ -146,18 +148,18 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Object {}, - Object { - "logo": "big logo", - "smallLogo": "not so big logo", - }, - Object { - "logo": "big logo without small logo", - "smallLogo": undefined, - }, - ] - `); + Array [ + Object {}, + Object { + "logo": "big logo", + "smallLogo": "not so big logo", + }, + Object { + "logo": "big logo without small logo", + "smallLogo": undefined, + }, + ] + `); }); }); @@ -175,13 +177,13 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - false, - false, - ] - `); + Array [ + false, + false, + false, + false, + ] + `); }); it('emits false until manually overridden when in embed mode', async () => { @@ -203,13 +205,13 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - true, - false, - ] - `); + Array [ + false, + false, + true, + false, + ] + `); }); it('application-specified visibility on mount', async () => { @@ -230,13 +232,13 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - true, - false, - true, - ] - `); + Array [ + false, + true, + false, + true, + ] + `); }); it('changing visibility has no effect on chrome-hiding application', async () => { @@ -253,12 +255,12 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - false, - ] - `); + Array [ + false, + false, + false, + ] + `); }); }); @@ -280,36 +282,36 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Array [], - Array [ - "foo", - ], - Array [ - "foo", - ], - Array [ - "foo", - "bar", - ], - Array [ - "foo", - "bar", - ], - Array [ - "foo", - "bar", - "baz", - ], - Array [ - "foo", - "baz", - ], - Array [ - "baz", - ], - ] - `); + Array [ + Array [], + Array [ + "foo", + ], + Array [ + "foo", + ], + Array [ + "foo", + "bar", + ], + Array [ + "foo", + "bar", + ], + Array [ + "foo", + "bar", + "baz", + ], + Array [ + "foo", + "baz", + ], + Array [ + "baz", + ], + ] + `); }); }); @@ -327,19 +329,19 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - undefined, - Object { - "text": "foo", - "tooltip": "foo's tooltip", - }, - Object { - "text": "bar", - "tooltip": "bar's tooltip", - }, - undefined, - ] - `); + Array [ + undefined, + Object { + "text": "foo", + "tooltip": "foo's tooltip", + }, + Object { + "text": "bar", + "tooltip": "bar's tooltip", + }, + undefined, + ] + `); }); }); @@ -358,29 +360,29 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Array [], - Array [ - Object { - "text": "foo", - }, - Object { - "text": "bar", - }, - ], - Array [ - Object { - "text": "foo", - }, - ], - Array [ - Object { - "text": "bar", - }, - ], - Array [], - ] - `); + Array [ + Array [], + Array [ + Object { + "text": "foo", + }, + Object { + "text": "bar", + }, + ], + Array [ + Object { + "text": "foo", + }, + ], + Array [ + Object { + "text": "bar", + }, + ], + Array [], + ] + `); }); }); diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index bf1a764e85882..a921e514050b2 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -18,11 +18,13 @@ */ import { Breadcrumb as EuiBreadcrumb, IconType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { BehaviorSubject, combineLatest, merge, Observable, of, ReplaySubject } from 'rxjs'; import { flatMap, map, takeUntil } from 'rxjs/operators'; import { parse } from 'url'; +import { EuiLink } from '@elastic/eui'; +import { mountReactNode } from '../utils/mount'; import { InternalApplicationStart } from '../application'; import { DocLinksStart } from '../doc_links'; import { HttpStart } from '../http'; @@ -165,12 +167,44 @@ export class ChromeService { // Can delete const getNavType$ = uiSettings.get$('pageNavigation').pipe(takeUntil(this.stop$)); + const isIE = () => { + const ua = window.navigator.userAgent; + const msie = ua.indexOf('MSIE '); // IE 10 or older + const trident = ua.indexOf('Trident/'); // IE 11 + + return msie > 0 || trident > 0; + }; + if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { - notifications.toasts.addWarning( - i18n.translate('core.chrome.legacyBrowserWarning', { - defaultMessage: 'Your browser does not meet the security requirements for Kibana.', - }) - ); + notifications.toasts.addWarning({ + title: mountReactNode( + + ), + }); + + if (isIE()) { + notifications.toasts.addWarning({ + title: mountReactNode( + + + + ), + }} + /> + ), + }); + } } return { diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index 8032bc458822f..1f9e35e62ddcc 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -75,6 +75,12 @@ margin: 0 auto; min-height: calc(100vh - #{$euiHeaderHeightCompensation}); + @include internetExplorerOnly { + // IE specific bug with min-height in flex container, described in the next link + // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items + height: calc(100vh - #{$euiHeaderHeightCompensation}); + } + &.hidden-chrome { min-height: 100vh; } diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js index 2cba9fab7be22..ff253629a4825 100644 --- a/src/legacy/core_plugins/kibana/public/management/index.js +++ b/src/legacy/core_plugins/kibana/public/management/index.js @@ -21,7 +21,6 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { FormattedMessage } from '@kbn/i18n/react'; -import './sections'; import uiRoutes from 'ui/routes'; import { I18nContext } from 'ui/i18n'; import { uiModules } from 'ui/modules'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/angular_template.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/angular_template.html deleted file mode 100644 index a2bc83db904a4..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/angular_template.html +++ /dev/null @@ -1,5 +0,0 @@ - -
-
-
-
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.tsx deleted file mode 100644 index 928c1ef2b6299..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.tsx +++ /dev/null @@ -1,110 +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 React, { Fragment } from 'react'; - -import { - EuiBetaBadge, - EuiSpacer, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiTextColor, - EuiSwitch, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export const Header = ({ - prompt, - indexPatternName, - showSystemIndices = false, - isIncludingSystemIndices, - onChangeIncludingSystemIndices, - isBeta = false, -}: { - prompt?: React.ReactNode; - indexPatternName: string; - showSystemIndices?: boolean; - isIncludingSystemIndices: boolean; - onChangeIncludingSystemIndices: () => void; - isBeta?: boolean; -}) => ( -
- -

- - {isBeta ? ( - - {' '} - - - ) : null} -

-
- - - -

- - - -

-
-
- {showSystemIndices ? ( - - - } - id="checkboxShowSystemIndices" - checked={isIncludingSystemIndices} - onChange={onChangeIncludingSystemIndices} - /> - - ) : null} -
- {prompt ? ( - - - {prompt} - - ) : null} - -
-); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js deleted file mode 100644 index 2762a4f6e8726..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js +++ /dev/null @@ -1,58 +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 uiRoutes from 'ui/routes'; -import angularTemplate from './angular_template.html'; -import { npStart } from 'ui/new_platform'; -import { getCreateBreadcrumbs } from '../breadcrumbs'; - -import { renderCreateIndexPatternWizard, destroyCreateIndexPatternWizard } from './render'; - -uiRoutes.when('/management/kibana/index_pattern', { - template: angularTemplate, - k7Breadcrumbs: getCreateBreadcrumbs, - controller: function($scope, $injector) { - // Wait for the directives to execute - const kbnUrl = $injector.get('kbnUrl'); - $scope.$$postDigest(() => { - const $routeParams = $injector.get('$routeParams'); - const indexPatternCreationType = npStart.plugins.indexPatternManagement.creation.getType( - $routeParams.type - ); - const services = { - uiSettings: npStart.core.uiSettings, - es: npStart.plugins.data.search.__LEGACY.esClient, - indexPatterns: npStart.plugins.data.indexPatterns, - savedObjectsClient: npStart.core.savedObjects.client, - indexPatternCreationType, - changeUrl: url => { - $scope.$evalAsync(() => kbnUrl.changePath(url)); - }, - openConfirm: npStart.core.overlays.openConfirm, - prependBasePath: npStart.core.http.basePath.prepend, - }; - - const initialQuery = $routeParams.id ? decodeURIComponent($routeParams.id) : undefined; - - renderCreateIndexPatternWizard(initialQuery, services); - }); - - $scope.$on('$destroy', destroyCreateIndexPatternWizard); - }, -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.js deleted file mode 100644 index d09ad3f63f0a2..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.js +++ /dev/null @@ -1,45 +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 React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { CreateIndexPatternWizard } from './create_index_pattern_wizard'; - -import { I18nContext } from 'ui/i18n'; - -const CREATE_INDEX_PATTERN_DOM_ELEMENT_ID = 'createIndexPatternReact'; - -export function renderCreateIndexPatternWizard(initialQuery, services) { - const node = document.getElementById(CREATE_INDEX_PATTERN_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - - - , - node - ); -} - -export function destroyCreateIndexPatternWizard() { - const node = document.getElementById(CREATE_INDEX_PATTERN_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.test.js deleted file mode 100644 index 1b9dafb6daf23..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/render.test.js +++ /dev/null @@ -1,63 +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. - */ - -const render = jest.fn(); -const unmountComponentAtNode = jest.fn(); - -jest.doMock('react-dom', () => ({ render, unmountComponentAtNode })); - -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: () => ({ - get: () => '', - }), - addBasePath: () => {}, -})); - -jest.mock('ui/i18n', () => ({ - I18nContext: () => {}, -})); - -const { renderCreateIndexPatternWizard, destroyCreateIndexPatternWizard } = require('./render'); - -describe('CreateIndexPatternWizardRender', () => { - beforeEach(() => { - jest.spyOn(document, 'getElementById').mockImplementation(() => ({})); - render.mockClear(); - unmountComponentAtNode.mockClear(); - }); - - it('should call render', () => { - renderCreateIndexPatternWizard('', { - es: {}, - indexPatterns: {}, - savedObjectsClient: {}, - config: {}, - changeUrl: () => {}, - indexPatternCreationType: {}, - openConfirm: jest.fn(), - }); - - expect(render.mock.calls.length).toBe(1); - }); - - it('should call unmountComponentAtNode', () => { - destroyCreateIndexPatternWizard(); - expect(unmountComponentAtNode.mock.calls.length).toBe(1); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field.html deleted file mode 100644 index 2decaf423183e..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field.html +++ /dev/null @@ -1,5 +0,0 @@ - -
-
-
-
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.html deleted file mode 100644 index 0bf7c7f0bdfbe..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.html +++ /dev/null @@ -1,12 +0,0 @@ - -
-
-
-
-
-
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index.js deleted file mode 100644 index ab1fa546e5ea8..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index.js +++ /dev/null @@ -1,177 +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 React from 'react'; -import { HashRouter } from 'react-router-dom'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors'; -import uiRoutes from 'ui/routes'; -import { uiModules } from 'ui/modules'; -import { I18nContext } from 'ui/i18n'; -import { npStart } from 'ui/new_platform'; -import template from './edit_index_pattern.html'; -import createEditFieldtemplate from './create_edit_field.html'; -import { - getEditBreadcrumbs, - getEditFieldBreadcrumbs, - getCreateFieldBreadcrumbs, -} from '../breadcrumbs'; -import { EditIndexPattern } from './edit_index_pattern'; -import { CreateEditField } from './create_edit_field'; - -const REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID = 'reactEditIndexPattern'; - -function destroyEditIndexPattern() { - const node = document.getElementById(REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -} - -function renderEditIndexPattern($scope, config, $route) { - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - - - - - , - node - ); - }); -} - -uiRoutes.when('/management/kibana/index_patterns/:indexPatternId', { - template, - k7Breadcrumbs: getEditBreadcrumbs, - resolve: { - indexPattern: function($route, Promise, redirectWhenMissing) { - const { indexPatterns } = npStart.plugins.data; - return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch( - redirectWhenMissing('/management/kibana/index_patterns') - ); - }, - }, -}); - -uiModules - .get('apps/management') - .controller('managementIndexPatternsEdit', function($scope, $route, config) { - $scope.$on('$destroy', () => { - destroyEditIndexPattern(); - }); - - renderEditIndexPattern($scope, config, $route); - }); - -// routes for create edit field. Will be removed after migartion all component to react. -const REACT_FIELD_EDITOR_ID = 'reactFieldEditor'; -const renderCreateEditField = ($scope, $route, getConfig, fieldFormatEditors) => { - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_FIELD_EDITOR_ID); - if (!node) { - return; - } - - render( - - - npStart.core.http, - notifications: npStart.core.notifications, - docTitle: npStart.core.chrome.docTitle, - docLinksScriptedFields: npStart.core.docLinks.links.scriptedFields, - }} - /> - - , - node - ); - }); -}; - -const destroyCreateEditField = () => { - const node = document.getElementById(REACT_FIELD_EDITOR_ID); - node && unmountComponentAtNode(node); -}; - -uiRoutes - .when('/management/kibana/index_patterns/:indexPatternId/field/:fieldName*', { - mode: 'edit', - k7Breadcrumbs: getEditFieldBreadcrumbs, - }) - .when('/management/kibana/index_patterns/:indexPatternId/create-field/', { - mode: 'create', - k7Breadcrumbs: getCreateFieldBreadcrumbs, - }) - .defaults(/management\/kibana\/index_patterns\/[^\/]+\/(field|create-field)(\/|$)/, { - template: createEditFieldtemplate, - mapBreadcrumbs($route, breadcrumbs) { - const { indexPattern } = $route.current.locals; - return breadcrumbs.map(crumb => { - if (crumb.id !== indexPattern.id) { - return crumb; - } - - return { - ...crumb, - display: indexPattern.title, - }; - }); - }, - resolve: { - indexPattern: function($route, Promise, redirectWhenMissing) { - const { indexPatterns } = npStart.plugins.data; - return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch( - redirectWhenMissing('/management/kibana/index_patterns') - ); - }, - }, - controllerAs: 'fieldSettings', - controller: function FieldEditorPageController($scope, $route, Private, config) { - const getConfig = (...args) => config.get(...args); - const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider); - - renderCreateEditField($scope, $route, getConfig, fieldFormatEditors); - - $scope.$on('$destroy', () => { - destroyCreateEditField(); - }); - }, - }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap deleted file mode 100644 index 2e694b6363117..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Header should render normally 1`] = ` - - - -

- -

-
- -

- -

-
-
- - - - - -
-`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.html deleted file mode 100644 index 1af0fc2c33782..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.html +++ /dev/null @@ -1,5 +0,0 @@ -
-
-
-
-
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js deleted file mode 100644 index 24bc4ba8fba5b..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js +++ /dev/null @@ -1,173 +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 { management } from 'ui/management'; -import { ManagementSectionId } from '../../../../../../../plugins/management/public'; -import './create_index_pattern_wizard'; -import './edit_index_pattern'; -import uiRoutes from 'ui/routes'; -import { uiModules } from 'ui/modules'; -import indexTemplate from './index.html'; -import indexPatternListTemplate from './list.html'; -import { IndexPatternTable } from './index_pattern_table'; -import { npStart } from 'ui/new_platform'; -import { i18n } from '@kbn/i18n'; -import { I18nContext } from 'ui/i18n'; -import { UICapabilitiesProvider } from 'ui/capabilities/react'; -import { getListBreadcrumbs } from './breadcrumbs'; - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; - -const INDEX_PATTERN_LIST_DOM_ELEMENT_ID = 'indexPatternListReact'; - -export function updateIndexPatternList(indexPatterns, kbnUrl, indexPatternCreationOptions) { - const node = document.getElementById(INDEX_PATTERN_LIST_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - - - - - , - node - ); -} - -export const destroyIndexPatternList = () => { - const node = document.getElementById(INDEX_PATTERN_LIST_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -}; - -const indexPatternsResolutions = { - indexPatterns: function() { - const savedObjectsClient = npStart.core.savedObjects.client; - - return savedObjectsClient - .find({ - type: 'index-pattern', - fields: ['title', 'type'], - perPage: 10000, - }) - .then(response => response.savedObjects); - }, -}; - -// add a dependency to all of the subsection routes -uiRoutes.defaults(/management\/kibana\/(index_patterns|index_pattern)/, { - resolve: indexPatternsResolutions, - requireUICapability: 'management.kibana.index_patterns', - badge: uiCapabilities => { - if (uiCapabilities.indexPatterns.save) { - return undefined; - } - - return { - text: i18n.translate('kbn.management.indexPatterns.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('kbn.management.indexPatterns.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save index patterns', - }), - iconType: 'glasses', - }; - }, -}); - -uiRoutes.when('/management/kibana/index_patterns', { - template: indexPatternListTemplate, - k7Breadcrumbs: getListBreadcrumbs, -}); - -// wrapper directive, which sets some global stuff up like the left nav -uiModules - .get('apps/management') - .directive('kbnManagementIndexPatterns', function($route, config, kbnUrl) { - return { - restrict: 'E', - transclude: true, - template: indexTemplate, - link: async function($scope) { - const indexPatternCreationOptions = await npStart.plugins.indexPatternManagement.creation.getIndexPatternCreationOptions( - url => { - $scope.$evalAsync(() => kbnUrl.change(url)); - } - ); - - const renderList = () => { - $scope.indexPatternList = - $route.current.locals.indexPatterns - .map(pattern => { - const id = pattern.id; - const title = pattern.get('title'); - const isDefault = $scope.defaultIndex === id; - const tags = npStart.plugins.indexPatternManagement.list.getIndexPatternTags( - pattern, - isDefault - ); - - return { - id, - title, - url: kbnUrl.eval('#/management/kibana/index_patterns/{{id}}', { id: id }), - active: $scope.editingId === id, - default: isDefault, - tags, - //the prepending of 0 at the default pattern takes care of prioritization - //so the sorting will but the default index on top - //or on bottom of a the table - sort: `${isDefault ? '0' : '1'}${title}`, - }; - }) - .sort((a, b) => { - if (a.sort < b.sort) { - return -1; - } else if (a.sort > b.sort) { - return 1; - } else { - return 0; - } - }) || []; - - updateIndexPatternList($scope.indexPatternList, kbnUrl, indexPatternCreationOptions); - }; - - $scope.$on('$destroy', destroyIndexPatternList); - $scope.editingId = $route.current.params.indexPatternId; - $scope.$watch('defaultIndex', () => renderList()); - config.bindToScope($scope, 'defaultIndex'); - $scope.$apply(); - }, - }; - }); - -management.getSection(ManagementSectionId.Kibana).register('index_patterns', { - display: i18n.translate('kbn.management.indexPattern.sectionsHeader', { - defaultMessage: 'Index Patterns', - }), - order: 0, - url: '#/management/kibana/index_patterns/', -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx deleted file mode 100644 index f254a6bc22a0d..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx +++ /dev/null @@ -1,154 +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 { - EuiBadge, - EuiButtonEmpty, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - // @ts-ignore - EuiInMemoryTable, - EuiPanel, - EuiSpacer, - EuiText, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; -import { CreateButton } from '../create_button'; -import { CreateIndexPatternPrompt } from '../create_index_pattern_prompt'; -import { IndexPattern, IndexPatternCreationOption } from '../types'; - -const columns = [ - { - field: 'title', - name: 'Pattern', - render: ( - name: string, - index: { - id: string; - tags?: Array<{ - key: string; - name: string; - }>; - } - ) => ( - - {name} - {index.tags && - index.tags.map(({ key: tagKey, name: tagName }) => ( - - {tagName} - - ))} - - ), - dataType: 'string' as const, - sortable: ({ sort }: { sort: string }) => sort, - }, -]; - -const pagination = { - initialPageSize: 10, - pageSizeOptions: [5, 10, 25, 50], -}; - -const sorting = { - sort: { - field: 'title', - direction: 'asc' as const, - }, -}; - -const search = { - box: { - incremental: true, - schema: { - fields: { title: { type: 'string' } }, - }, - }, -}; - -interface Props { - indexPatterns: IndexPattern[]; - indexPatternCreationOptions: IndexPatternCreationOption[]; -} - -interface State { - showFlyout: boolean; -} - -export class IndexPatternTable extends React.Component { - public readonly state = { - showFlyout: this.props.indexPatterns.length === 0, - }; - - public render() { - return ( - - {this.state.showFlyout && ( - this.setState({ showFlyout: false })} /> - )} - - - - - -

- -

-
-
- - this.setState({ showFlyout: true })} - aria-label="Help" - /> - -
-
- - - - - -
- - -
- ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/list.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/list.html deleted file mode 100644 index 928fb75384be1..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/list.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js index e5d43fec4e59c..64676b1bce75c 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js @@ -65,11 +65,11 @@ const savedObjectsManagement = getManagementaMock({ return obj.attributes.title; }, getEditUrl(obj) { - return `/management/kibana/index_patterns/${encodeURIComponent(obj.id)}`; + return `/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`; }, getInAppUrl(obj) { return { - path: `/app/kibana#/management/kibana/index_patterns/${encodeURIComponent(obj.id)}`, + path: `/app/kibana#/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, uiCapabilitiesPath: 'management.kibana.index_patterns', }; }, @@ -323,9 +323,9 @@ describe('findRelationships', () => { meta: { icon: 'indexPatternApp', title: 'My Index Pattern', - editUrl: '/management/kibana/index_patterns/1', + editUrl: '/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/app/kibana#/management/kibana/index_patterns/1', + path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, @@ -437,9 +437,9 @@ describe('findRelationships', () => { meta: { icon: 'indexPatternApp', title: 'My Index Pattern', - editUrl: '/management/kibana/index_patterns/1', + editUrl: '/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/app/kibana#/management/kibana/index_patterns/1', + path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss index 15a70e0ef7f5a..d258ef190a100 100644 --- a/src/legacy/ui/public/_index.scss +++ b/src/legacy/ui/public/_index.scss @@ -11,5 +11,3 @@ @import './accessibility/index'; @import './directives/index'; @import './error_url_overflow/index'; -@import './field_editor/index'; -@import '../../../plugins/management/public/components/index'; diff --git a/src/legacy/ui/public/field_editor/_index.scss b/src/legacy/ui/public/field_editor/_index.scss deleted file mode 100644 index 39f69c013d428..0000000000000 --- a/src/legacy/ui/public/field_editor/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './components/field_format_editor/samples/index'; -@import './components/scripting_help/test_script'; diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/index.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/index.js deleted file mode 100644 index 2dc9a1835f582..0000000000000 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/index.js +++ /dev/null @@ -1,26 +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 '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/go.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/stop.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/de.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/ne.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/us.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/ni.png'; -import '!!file-loader?name=[path][name].[ext]!ui/field_editor/components/field_format_editor/editors/url/icons/cv.png'; diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/register.ts b/src/legacy/ui/public/field_editor/components/field_format_editor/register.ts deleted file mode 100644 index 3062a3ba8ac14..0000000000000 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/register.ts +++ /dev/null @@ -1,43 +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 { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors'; -import { BytesFormatEditor } from './editors/bytes'; -import { ColorFormatEditor } from './editors/color'; -import { DateFormatEditor } from './editors/date'; -import { DateNanosFormatEditor } from './editors/date_nanos'; -import { DurationFormatEditor } from './editors/duration'; -import { NumberFormatEditor } from './editors/number'; -import { PercentFormatEditor } from './editors/percent'; -import { StaticLookupFormatEditor } from './editors/static_lookup'; -import { StringFormatEditor } from './editors/string'; -import { TruncateFormatEditor } from './editors/truncate'; -import { UrlFormatEditor } from './editors/url/url'; - -RegistryFieldFormatEditorsProvider.register(() => BytesFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => ColorFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => DateFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => DateNanosFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => DurationFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => NumberFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => PercentFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => StaticLookupFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => StringFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => TruncateFormatEditor); -RegistryFieldFormatEditorsProvider.register(() => UrlFormatEditor); diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/_index.scss b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/_index.scss deleted file mode 100644 index 7a50cd118bfb2..0000000000000 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './samples'; diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js index 35e1f8b7d2127..1341777bc0991 100644 --- a/src/legacy/ui/ui_exports/ui_export_defaults.js +++ b/src/legacy/ui/ui_exports/ui_export_defaults.js @@ -43,7 +43,5 @@ export const UI_EXPORT_DEFAULTS = { }, })), - appExtensions: { - fieldFormatEditors: ['ui/field_editor/components/field_format_editor/register'], - }, + appExtensions: {}, }; diff --git a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx index 2a6ef13f66dda..9115e523f5302 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx +++ b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx @@ -61,7 +61,7 @@ export const createEnsureDefaultIndexPattern = (core: CoreStart) => { core.uiSettings.set('defaultIndex', defaultId); } else { const canManageIndexPatterns = core.application.capabilities.management.kibana.index_patterns; - const redirectTarget = canManageIndexPatterns ? 'management' : 'home'; + const redirectTarget = canManageIndexPatterns ? '/management/kibana/indexPatterns' : '/home'; if (timeoutId) { clearTimeout(timeoutId); @@ -88,11 +88,11 @@ export const createEnsureDefaultIndexPattern = (core: CoreStart) => { timeoutId = undefined; }, 15000); - if (redirectTarget === 'home') { + if (redirectTarget === '/home') { core.application.navigateToApp('home'); } else { window.location.href = core.http.basePath.prepend( - `/app/kibana#/management/kibana/index_pattern?bannerMessage=${bannerMessage}` + `/app/kibana#/management/kibana/indexPatterns?bannerMessage=${bannerMessage}` ); } diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts index ecbfceac14b66..3780557db50d3 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -174,7 +174,7 @@ export class IndexPattern implements IIndexPattern { private updateFromElasticSearch(response: any, forceFieldRefresh: boolean = false) { if (!response.found) { - throw new SavedObjectNotFound(type, this.id, '#/management/kibana/index_pattern'); + throw new SavedObjectNotFound(type, this.id, '#/management/kibana/indexPatterns'); } _.forOwn(this.mapping, (fieldMapping: FieldMappingSpec, name: string | undefined) => { diff --git a/src/plugins/data/server/saved_objects/index_patterns.ts b/src/plugins/data/server/saved_objects/index_patterns.ts index 497dbb7d6f630..a212d7f88e4eb 100644 --- a/src/plugins/data/server/saved_objects/index_patterns.ts +++ b/src/plugins/data/server/saved_objects/index_patterns.ts @@ -32,11 +32,11 @@ export const indexPatternSavedObjectType: SavedObjectsType = { return obj.attributes.title; }, getEditUrl(obj) { - return `/management/kibana/index_patterns/${encodeURIComponent(obj.id)}`; + return `/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`; }, getInAppUrl(obj) { return { - path: `/app/kibana#/management/kibana/index_patterns/${encodeURIComponent(obj.id)}`, + path: `/app/kibana#/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, uiCapabilitiesPath: 'management.kibana.index_patterns', }; }, diff --git a/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx b/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx index 0bae2456f743c..880a493983adf 100644 --- a/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx +++ b/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx @@ -42,7 +42,7 @@ const DiscoverFetchError = ({ fetchError }: Props) => { const { chrome } = getServices(); const mangagementUrlObj = chrome.navLinks.get('kibana:stack_management'); const managementUrl = mangagementUrlObj ? mangagementUrlObj.url : ''; - const url = `${managementUrl}/kibana/index_patterns`; + const url = `${managementUrl}/kibana/indexPatterns`; body = (

diff --git a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap index dea33022fa429..924de9bbd0994 100644 --- a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap @@ -277,7 +277,7 @@ exports[`apmUiEnabled 1`] = ` /> { void; }>; - uiCapabilities: UICapabilities; } -class CreateButtonComponent extends Component { +export class CreateButton extends Component { public state = { isPopoverOpen: false, }; public render() { - const { options, children, uiCapabilities } = this.props; + const { options, children } = this.props; const { isPopoverOpen } = this.state; if (!options || !options.length) { return null; } - if (!uiCapabilities.indexPatterns.save) { - return null; - } - if (options.length === 1) { return ( { return ( ); }; } - -export const CreateButton = injectUICapabilities(CreateButtonComponent); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_button/index.ts b/src/plugins/index_pattern_management/public/components/create_button/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_button/index.ts rename to src/plugins/index_pattern_management/public/components/create_button/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_prompt/index.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_prompt/index.tsx similarity index 84% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_prompt/index.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_prompt/index.tsx index 174b3af930550..ab3b90177bcfd 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_prompt/index.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_prompt/index.tsx @@ -37,7 +37,7 @@ export const CreateIndexPatternPrompt = ({ onClose }: { onClose: () => void }) =

@@ -47,7 +47,7 @@ export const CreateIndexPatternPrompt = ({ onClose }: { onClose: () => void }) =

@@ -57,7 +57,7 @@ export const CreateIndexPatternPrompt = ({ onClose }: { onClose: () => void }) =

@@ -66,38 +66,38 @@ export const CreateIndexPatternPrompt = ({ onClose }: { onClose: () => void }) = diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap index 9763cd9f638fd..9a390f84ef5dc 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap @@ -1,9 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`CreateIndexPatternWizard defaults to the loading state 1`] = ` - +
- + `; exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = ` - +
- + `; exports[`CreateIndexPatternWizard renders the empty state when there are no indices 1`] = ` - +
-
+ `; exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = ` - +
- + `; exports[`CreateIndexPatternWizard renders when there are no indices but there are remote clusters 1`] = ` - +
- + `; exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = ` - +
- + `; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap index 3ecab05a8459b..4ebb5db05753b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/__snapshots__/empty_state.test.tsx.snap @@ -7,7 +7,7 @@ exports[`EmptyState should render normally 1`] = ` title={ } @@ -15,7 +15,7 @@ exports[`EmptyState should render normally 1`] = `

, @@ -32,7 +32,7 @@ exports[`EmptyState should render normally 1`] = ` > , @@ -41,7 +41,7 @@ exports[`EmptyState should render normally 1`] = ` > , @@ -57,7 +57,7 @@ exports[`EmptyState should render normally 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/empty_state.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/empty_state.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/empty_state.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/empty_state.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/empty_state.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/empty_state.tsx similarity index 82% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/empty_state.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/empty_state.tsx index 3ee5d1a0e96f1..43c3bf79026fe 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/empty_state.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/empty_state.tsx @@ -36,20 +36,20 @@ export const EmptyState = ({ color="warning" title={ } >

@@ -57,7 +57,7 @@ export const EmptyState = ({ learnHowLink: ( @@ -65,7 +65,7 @@ export const EmptyState = ({ getStartedLink: ( @@ -81,7 +81,7 @@ export const EmptyState = ({ color="warning" > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/empty_state/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap similarity index 71% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap index a6b22ebf32a43..bdfdd2e7ad0a6 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/__snapshots__/header.test.tsx.snap @@ -4,15 +4,7 @@ exports[`Header should render a different name, prompt, and beta tag if provided

- + Create test index pattern @@ -59,15 +51,7 @@ exports[`Header should render normally 1`] = `

- + Create test index pattern

@@ -104,15 +88,7 @@ exports[`Header should render without including system indices 1`] = `

- + Create test index pattern

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.test.tsx similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.test.tsx index 06b8b38e2d8bc..d70746dd930e4 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/header.test.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.test.tsx @@ -29,6 +29,7 @@ describe('Header', () => { indexPatternName={indexPatternName} isIncludingSystemIndices={true} onChangeIncludingSystemIndices={() => {}} + changeTitle={() => {}} /> ); @@ -41,6 +42,7 @@ describe('Header', () => { indexPatternName={indexPatternName} isIncludingSystemIndices={false} onChangeIncludingSystemIndices={() => {}} + changeTitle={() => {}} /> ); @@ -55,6 +57,7 @@ describe('Header', () => { prompt={
Test prompt
} indexPatternName={indexPatternName} isBeta={true} + changeTitle={() => {}} /> ); diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.tsx new file mode 100644 index 0000000000000..1be33e3edc3bc --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/header.tsx @@ -0,0 +1,118 @@ +/* + * 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 React, { Fragment } from 'react'; + +import { + EuiBetaBadge, + EuiSpacer, + EuiTitle, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiTextColor, + EuiSwitch, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +export const Header = ({ + prompt, + indexPatternName, + showSystemIndices = false, + isIncludingSystemIndices, + onChangeIncludingSystemIndices, + isBeta = false, + changeTitle, +}: { + prompt?: React.ReactNode; + indexPatternName: string; + showSystemIndices?: boolean; + isIncludingSystemIndices: boolean; + onChangeIncludingSystemIndices: () => void; + isBeta?: boolean; + changeTitle: (title: string) => void; +}) => { + const createIndexPatternHeader = i18n.translate( + 'indexPatternManagement.createIndexPatternHeader', + { + defaultMessage: 'Create {indexPatternName}', + values: { indexPatternName }, + } + ); + + changeTitle(createIndexPatternHeader); + + return ( +
+ +

+ {createIndexPatternHeader} + {isBeta ? ( + + {' '} + + + ) : null} +

+
+ + + +

+ + + +

+
+
+ {showSystemIndices ? ( + + + } + id="checkboxShowSystemIndices" + checked={isIncludingSystemIndices} + onChange={onChangeIncludingSystemIndices} + /> + + ) : null} +
+ {prompt ? ( + + + {prompt} + + ) : null} + +
+ ); +}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/header/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap index 3adc497a639c4..1e6ac56d437e1 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/__snapshots__/loading_state.test.tsx.snap @@ -22,7 +22,7 @@ exports[`LoadingState should render normally 1`] = ` >

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/loading_state.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/loading_state.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/loading_state.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/loading_state.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/loading_state.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/loading_state.tsx similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/loading_state.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/loading_state.tsx index e9b68033090cf..26653adfd14a6 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/loading_state/loading_state.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/loading_state/loading_state.tsx @@ -29,7 +29,7 @@ export const LoadingState = () => (

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/__snapshots__/step_index_pattern.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/__snapshots__/step_index_pattern.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/__snapshots__/step_index_pattern.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/__snapshots__/step_index_pattern.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap index f2fb17cdb0d60..3021292953ff5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/__snapshots__/header.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Header should mark the input as invalid 1`] = `

@@ -42,7 +42,7 @@ exports[`Header should mark the input as invalid 1`] = `

@@ -55,7 +55,7 @@ exports[`Header should mark the input as invalid 1`] = `

@@ -71,7 +71,7 @@ exports[`Header should mark the input as invalid 1`] = ` label={ } @@ -99,7 +99,7 @@ exports[`Header should mark the input as invalid 1`] = ` > @@ -116,7 +116,7 @@ exports[`Header should render normally 1`] = `

@@ -146,7 +146,7 @@ exports[`Header should render normally 1`] = `

@@ -159,7 +159,7 @@ exports[`Header should render normally 1`] = `

@@ -175,7 +175,7 @@ exports[`Header should render normally 1`] = ` label={ } @@ -203,7 +203,7 @@ exports[`Header should render normally 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/header.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/header.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/header.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx similarity index 87% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx index f9d86d5d9d53d..9ce72aeeea6e3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/header.tsx @@ -57,7 +57,7 @@ export const Header: React.FC = ({

@@ -69,7 +69,7 @@ export const Header: React.FC = ({ } @@ -79,14 +79,14 @@ export const Header: React.FC = ({

* }} />

{characterList} }} /> @@ -97,7 +97,7 @@ export const Header: React.FC = ({ = ({ data-test-subj="createIndexPatternGoToStep2Button" > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap similarity index 97% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap index a759b3b3e9881..598de4d90e893 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/indices_list/__snapshots__/indices_list.test.tsx.snap @@ -44,7 +44,7 @@ exports[`IndicesList should change pages 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap index d8b4253de78bb..9d67ca913d415 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/__snapshots__/loading_indices.test.tsx.snap @@ -21,7 +21,7 @@ exports[`LoadingIndices should render normally 1`] = ` > @@ -39,7 +39,7 @@ exports[`LoadingIndices should render normally 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx similarity index 91% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx index 2f91f961b6c18..16e8d1a9f3e98 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/loading_indices/loading_indices.tsx @@ -33,7 +33,7 @@ export const LoadingIndices = ({ ...rest }) => ( @@ -42,7 +42,7 @@ export const LoadingIndices = ({ ...rest }) => ( diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap similarity index 80% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap index eb99424cb12a8..4a063f1430d1c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/__snapshots__/status_message.test.tsx.snap @@ -15,13 +15,13 @@ exports[`StatusMessage should render with exact matches 1`] = `   , @@ -55,14 +55,14 @@ exports[`StatusMessage should render with no partial matches 1`] = ` @@ -149,7 +149,7 @@ exports[`StatusMessage should show that no indices exist 1`] = ` @@ -168,7 +168,7 @@ exports[`StatusMessage should show that system indices exist 1`] = ` diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx similarity index 83% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx index ad7f58fa4e879..ccdd1833ea9bf 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/components/status_message/status_message.tsx @@ -55,7 +55,7 @@ export const StatusMessage: React.FC = ({ statusMessage = ( {allIndicesLength} indices }} /> @@ -65,7 +65,7 @@ export const StatusMessage: React.FC = ({ statusMessage = ( @@ -75,7 +75,7 @@ export const StatusMessage: React.FC = ({ statusMessage = ( @@ -88,13 +88,13 @@ export const StatusMessage: React.FC = ({   @@ -102,7 +102,7 @@ export const StatusMessage: React.FC = ({ strongIndices: ( @@ -118,7 +118,7 @@ export const StatusMessage: React.FC = ({ statusMessage = ( = ({ strongIndices: ( @@ -142,14 +142,14 @@ export const StatusMessage: React.FC = ({ statusMessage = ( diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx index 40471b95d774c..68afd64ae848c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.test.tsx @@ -21,10 +21,10 @@ import React from 'react'; import { StepIndexPattern } from '../step_index_pattern'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; import { Header } from './components/header'; -import { IndexPatternCreationConfig } from '../../../../../../../../../../plugins/index_pattern_management/public'; -import { coreMock } from '../../../../../../../../../../core/public/mocks'; -import { dataPluginMock } from '../../../../../../../../../../plugins/data/public/mocks'; -import { SavedObjectsFindResponsePublic } from '../../../../../../../../../../core/public'; +import { IndexPatternCreationConfig } from '../../../../../../../plugins/index_pattern_management/public'; +import { coreMock } from '../../../../../../../core/public/mocks'; +import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks'; +import { SavedObjectsFindResponsePublic } from 'src/core/public'; jest.mock('../../lib/ensure_minimum_time', () => ({ ensureMinimumTime: async (promises: Array>) => diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx index d8f677b7f6089..5c8fa92d355a3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx @@ -25,8 +25,8 @@ import { indexPatterns, DataPublicPluginStart, IndexPatternAttributes, -} from '../../../../../../../../../../plugins/data/public'; -import { SavedObjectsClient, IUiSettingsClient } from '../../../../../../../../../../core/public'; +} from '../../../../../../../plugins/data/public'; +import { SavedObjectsClientContract, IUiSettingsClient } from '../../../../../../../core/public'; import { MAX_SEARCH_SIZE } from '../../constants'; import { getIndices, @@ -39,14 +39,14 @@ import { LoadingIndices } from './components/loading_indices'; import { StatusMessage } from './components/status_message'; import { IndicesList } from './components/indices_list'; import { Header } from './components/header'; -import { IndexPatternCreationConfig } from '../../../../../../../../../../plugins/index_pattern_management/public'; +import { IndexPatternCreationConfig } from '../../../../../../../plugins/index_pattern_management/public'; import { MatchedIndex } from '../../types'; interface StepIndexPatternProps { allIndices: MatchedIndex[]; isIncludingSystemIndices: boolean; esService: DataPublicPluginStart['search']['__LEGACY']['esClient']; - savedObjectsClient: SavedObjectsClient; + savedObjectsClient: SavedObjectsClientContract; indexPatternCreationType: IndexPatternCreationConfig; goToNextStep: (query: string) => void; initialQuery?: string; @@ -237,7 +237,7 @@ export class StepIndexPattern extends Component @@ -270,7 +270,7 @@ export class StepIndexPattern extends Component } @@ -60,7 +60,7 @@ exports[`StepTimeField should render "Custom index pattern ID already exists" wh

@@ -92,7 +92,7 @@ exports[`StepTimeField should render a loading state when creating the index pat @@ -269,7 +269,7 @@ exports[`StepTimeField should render any error message 1`] = ` title={ } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx similarity index 91% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx index 342876712eb28..d7c55f2573a17 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/action_buttons/action_buttons.tsx @@ -36,7 +36,7 @@ export const ActionButtons = ({ @@ -49,7 +49,7 @@ export const ActionButtons = ({ onClick={createIndexPattern} > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/action_buttons/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/action_buttons/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/action_buttons/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/action_buttons/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap similarity index 81% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap index 02ceed3454a00..d1b10fb532020 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/__snapshots__/advanced_options.test.tsx.snap @@ -8,7 +8,7 @@ exports[`AdvancedOptions should hide if not showing 1`] = ` > @@ -26,7 +26,7 @@ exports[`AdvancedOptions should render normally 1`] = ` > @@ -43,14 +43,14 @@ exports[`AdvancedOptions should render normally 1`] = ` helpText={ } label={ } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx index fd2c1db1eacd7..b8f34095743ba 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/advanced_options.tsx @@ -44,12 +44,12 @@ export const AdvancedOptions: React.FC = ({ > {isVisible ? ( ) : ( )} @@ -60,13 +60,13 @@ export const AdvancedOptions: React.FC = ({ } helpText={ @@ -78,7 +78,7 @@ export const AdvancedOptions: React.FC = ({ value={indexPatternId} onChange={onChangeIndexPatternId} placeholder={i18n.translate( - 'kbn.management.createIndexPattern.stepTime.options.patternPlaceholder', + 'indexPatternManagement.createIndexPattern.stepTime.options.patternPlaceholder', { defaultMessage: 'custom-index-pattern-id', } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/advanced_options/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/advanced_options/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap similarity index 83% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap index 5c53558286b0d..63008ec5b52e7 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/__snapshots__/header.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Header should render normally 1`] = `

@@ -21,7 +21,7 @@ exports[`Header should render normally 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/header.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/header.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/header.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx index 5c2f184e8038b..22e245f7ac137 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/header.tsx @@ -33,7 +33,7 @@ export const Header: React.FC = ({ indexPattern, indexPatternName }

@@ -41,7 +41,7 @@ export const Header: React.FC = ({ indexPattern, indexPatternName } {indexPattern}
, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/header/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap similarity index 84% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap index e997cb80a2a14..7d056433f55df 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/__snapshots__/time_field.test.tsx.snap @@ -13,14 +13,14 @@ exports[`TimeField should render a loading state 1`] = `

@@ -38,7 +38,7 @@ exports[`TimeField should render a loading state 1`] = ` @@ -84,14 +84,14 @@ exports[`TimeField should render a selected time field 1`] = `

@@ -109,7 +109,7 @@ exports[`TimeField should render a selected time field 1`] = ` @@ -123,7 +123,7 @@ exports[`TimeField should render a selected time field 1`] = ` > @@ -165,14 +165,14 @@ exports[`TimeField should render normally 1`] = `

@@ -190,7 +190,7 @@ exports[`TimeField should render normally 1`] = ` @@ -204,7 +204,7 @@ exports[`TimeField should render normally 1`] = ` > @@ -239,7 +239,7 @@ exports[`TimeField should render something if hiding time field 1`] = `

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.css b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.scss similarity index 84% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.css rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.scss index d0a2652d7e045..5bd60e8b76afc 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.css +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.scss @@ -1,6 +1,7 @@ /** * 1. Bring the line-height down or else this link expands its container when it becomes visible. */ - .timeFieldRefreshButton { + +.timeFieldRefreshButton { line-height: 1 !important; /* 1 */ } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx similarity index 87% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx index 876a3b79a8812..b4ed37118966b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/components/time_field/time_field.tsx @@ -17,9 +17,9 @@ * under the License. */ -import React from 'react'; +import './time_field.scss'; -import './time_field.css'; +import React from 'react'; import { EuiForm, @@ -60,7 +60,7 @@ export const TimeField: React.FC = ({ @@ -71,7 +71,7 @@ export const TimeField: React.FC = ({ ) : ( @@ -83,13 +83,13 @@ export const TimeField: React.FC = ({

@@ -103,7 +103,7 @@ export const TimeField: React.FC = ({ options={[ { text: i18n.translate( - 'kbn.management.createIndexPattern.stepTime.field.loadingDropDown', + 'indexPatternManagement.createIndexPattern.stepTime.field.loadingDropDown', { defaultMessage: 'Loading…', } @@ -129,7 +129,7 @@ export const TimeField: React.FC = ({

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx index b23b1e3ad9051..939b0d006b4aa 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.test.tsx @@ -19,8 +19,8 @@ import React from 'react'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { IndexPatternCreationConfig } from '../../../../../../../../../../plugins/index_pattern_management/public'; -import { IFieldType } from '../../../../../../../../../../plugins/data/public'; +import { IndexPatternCreationConfig } from '../../../../../../../plugins/index_pattern_management/public'; +import { IFieldType } from '../../../../../../../plugins/data/public'; import { StepTimeField } from '../step_time_field'; @@ -32,9 +32,6 @@ jest.mock('./../../lib', () => ({ extractTimeFields: require.requireActual('./../../lib').extractTimeFields, ensureMinimumTime: async (fields: IFieldType) => Promise.resolve(fields), })); -jest.mock('ui/chrome', () => ({ - addBasePath: () => {}, -})); const mockIndexPatternCreationType = new IndexPatternCreationConfig({ type: 'default', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx index a58bf10c9dab8..d22b503937290 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx @@ -34,8 +34,8 @@ import { Header } from './components/header'; import { TimeField } from './components/time_field'; import { AdvancedOptions } from './components/advanced_options'; import { ActionButtons } from './components/action_buttons'; -import { IndexPatternCreationConfig } from '../../../../../../../../../../plugins/index_pattern_management/public'; -import { DataPublicPluginStart } from '../../../../../../../../../../plugins/data/public'; +import { IndexPatternCreationConfig } from '../../../..'; +import { DataPublicPluginStart } from '../../../../../../data/public'; interface StepTimeFieldProps { indexPattern: string; @@ -157,7 +157,7 @@ export class StepTimeField extends Component ) : ( @@ -187,7 +187,7 @@ export class StepTimeField extends Component @@ -218,7 +218,7 @@ export class StepTimeField extends Component } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/constants/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/constants/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/constants/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/constants/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx similarity index 73% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx index 36d251e4f41a6..f526aa35c2afe 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx @@ -20,12 +20,15 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { CreateIndexPatternWizard } from './create_index_pattern_wizard'; -import { coreMock } from '../../../../../../../../core/public/mocks'; -import { dataPluginMock } from '../../../../../../../../plugins/data/public/mocks'; -import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public'; -import { IndexPattern } from '../../../../../../../../plugins/data/public'; -import { SavedObjectsClient } from '../../../../../../../../core/public'; +import { + CreateIndexPatternWizard, + CreateIndexPatternWizardProps, +} from './create_index_pattern_wizard'; +import { coreMock } from '../../../../../core/public/mocks'; +import { dataPluginMock } from '../../../../../plugins/data/public/mocks'; +import { IndexPattern } from '../../../../../plugins/data/public'; +import { SavedObjectsClient } from '../../../../../core/public'; +import { IndexPatternCreationConfig } from '../../service/creation'; jest.mock('./components/step_index_pattern', () => ({ StepIndexPattern: 'StepIndexPattern' })); jest.mock('./components/step_time_field', () => ({ StepTimeField: 'StepTimeField' })); @@ -37,33 +40,42 @@ jest.mock('./lib/get_indices', () => ({ return [{ name: 'kibana' }]; }, })); -jest.mock('ui/chrome', () => ({ - addBasePath: () => {}, -})); -const { savedObjects, overlays, uiSettings } = coreMock.createStart(); +const { savedObjects, overlays, uiSettings, chrome, http } = coreMock.createStart(); const { indexPatterns, search } = dataPluginMock.createStartContract(); + const mockIndexPatternCreationType = new IndexPatternCreationConfig({ type: 'default', name: 'name', }); -const initialQuery = ''; -const services = { +const services = ({ + indexPatternCreation: { + getType: jest.fn(() => mockIndexPatternCreationType), + }, es: search.__LEGACY.esClient, indexPatterns, savedObjectsClient: savedObjects.client as SavedObjectsClient, uiSettings, changeUrl: jest.fn(), openConfirm: overlays.openConfirm, - indexPatternCreationType: mockIndexPatternCreationType, - prependBasePath: jest.fn(x => x), + setBreadcrumbs: jest.fn(), + docTitle: chrome.docTitle, + prependBasePath: http.basePath.prepend, +} as unknown) as CreateIndexPatternWizardProps['services']; + +const routeComponentPropsMock = { + history: { + push: jest.fn(), + } as any, + location: {} as any, + match: {} as any, }; describe('CreateIndexPatternWizard', () => { test(`defaults to the loading state`, () => { const component = shallow( - + ); expect(component).toMatchSnapshot(); @@ -71,7 +83,7 @@ describe('CreateIndexPatternWizard', () => { test('renders the empty state when there are no indices', async () => { const component = shallow( - + ); component.setState({ @@ -86,7 +98,7 @@ describe('CreateIndexPatternWizard', () => { test('renders when there are no indices but there are remote clusters', async () => { const component = shallow( - + ); component.setState({ @@ -101,7 +113,7 @@ describe('CreateIndexPatternWizard', () => { test('shows system indices even if there are no other indices if the include system indices is toggled', async () => { const component = shallow( - + ); component.setState({ @@ -116,7 +128,7 @@ describe('CreateIndexPatternWizard', () => { test('renders index pattern step when there are indices', async () => { const component = shallow( - + ); component.setState({ @@ -130,7 +142,7 @@ describe('CreateIndexPatternWizard', () => { test('renders time field step when step is set to 2', async () => { const component = shallow( - + ); component.setState({ @@ -159,7 +171,7 @@ describe('CreateIndexPatternWizard', () => { }; const component = shallow( - + ); component.setState({ indexPattern: 'foo' }); @@ -167,6 +179,6 @@ describe('CreateIndexPatternWizard', () => { expect(services.uiSettings.get).toBeCalled(); expect(create).toBeCalled(); expect(clear).toBeCalledWith('id'); - expect(services.changeUrl).toBeCalledWith(`/management/kibana/index_patterns/id`); + expect(routeComponentPropsMock.history.push).toBeCalledWith(`/patterns/id`); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx similarity index 68% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx index a1a263fe88923..62bf47546e103 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -19,38 +19,42 @@ import React, { ReactElement, Component } from 'react'; -import { EuiGlobalToastList, EuiGlobalToastListToast } from '@elastic/eui'; +import { EuiGlobalToastList, EuiGlobalToastListToast, EuiPanel } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { + SavedObjectsClientContract, + IUiSettingsClient, + OverlayStart, + ChromeDocTitle, + IBasePath, +} from 'src/core/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { ManagementAppMountParams } from '../../../../management/public'; import { StepIndexPattern } from './components/step_index_pattern'; import { StepTimeField } from './components/step_time_field'; import { Header } from './components/header'; import { LoadingState } from './components/loading_state'; import { EmptyState } from './components/empty_state'; +import { getCreateBreadcrumbs } from '../breadcrumbs'; import { MAX_SEARCH_SIZE } from './constants'; import { ensureMinimumTime, getIndices } from './lib'; -import { - SavedObjectsClient, - IUiSettingsClient, - OverlayStart, - IBasePath, -} from '../../../../../../../../core/public'; -import { DataPublicPluginStart } from '../../../../../../../../plugins/data/public'; -import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public'; +import { IndexPatternCreationConfig, IndexPatternManagementStart } from '../..'; import { MatchedIndex } from './types'; -interface CreateIndexPatternWizardProps { - initialQuery: string; +export interface CreateIndexPatternWizardProps extends RouteComponentProps { services: { - indexPatternCreationType: IndexPatternCreationConfig; + indexPatternCreation: IndexPatternManagementStart['creation']; es: DataPublicPluginStart['search']['__LEGACY']['esClient']; indexPatterns: DataPublicPluginStart['indexPatterns']; - savedObjectsClient: SavedObjectsClient; + savedObjectsClient: SavedObjectsClientContract; uiSettings: IUiSettingsClient; - changeUrl: (url: string) => void; openConfirm: OverlayStart['openConfirm']; + setBreadcrumbs: ManagementAppMountParams['setBreadcrumbs']; + docTitle: ChromeDocTitle; prependBasePath: IBasePath['prepend']; }; } @@ -63,21 +67,35 @@ interface CreateIndexPatternWizardState { isInitiallyLoadingIndices: boolean; isIncludingSystemIndices: boolean; toasts: EuiGlobalToastListToast[]; + indexPatternCreationType: IndexPatternCreationConfig; } export class CreateIndexPatternWizard extends Component< CreateIndexPatternWizardProps, CreateIndexPatternWizardState > { - state = { - step: 1, - indexPattern: '', - allIndices: [], - remoteClustersExist: false, - isInitiallyLoadingIndices: true, - isIncludingSystemIndices: false, - toasts: [], - }; + constructor(props: CreateIndexPatternWizardProps) { + super(props); + const { + services: { indexPatternCreation, setBreadcrumbs }, + location, + } = props; + + setBreadcrumbs(getCreateBreadcrumbs()); + + const type = new URLSearchParams(location.search).get('type') || undefined; + + this.state = { + step: 1, + indexPattern: '', + allIndices: [], + remoteClustersExist: false, + isInitiallyLoadingIndices: true, + isIncludingSystemIndices: false, + toasts: [], + indexPatternCreationType: indexPatternCreation.getType(type), + }; + } async UNSAFE_componentWillMount() { this.fetchData(); @@ -116,14 +134,14 @@ export class CreateIndexPatternWizard extends Component< const indicesFailMsg = ( ); const clustersFailMsg = ( ); @@ -131,7 +149,7 @@ export class CreateIndexPatternWizard extends Component< // query local and remote indices, updating state independently ensureMinimumTime( this.catchAndWarn( - getIndices(services.es, services.indexPatternCreationType, `*`, MAX_SEARCH_SIZE), + getIndices(services.es, this.state.indexPatternCreationType, `*`, MAX_SEARCH_SIZE), [], indicesFailMsg ) @@ -142,7 +160,7 @@ export class CreateIndexPatternWizard extends Component< this.catchAndWarn( // if we get an error from remote cluster query, supply fallback value that allows user entry. // ['a'] is fallback value - getIndices(services.es, services.indexPatternCreationType, `*:*`, 1), + getIndices(services.es, this.state.indexPatternCreationType, `*:*`, 1), ['a'], clustersFailMsg ).then((remoteIndices: string[] | MatchedIndex[]) => @@ -151,7 +169,7 @@ export class CreateIndexPatternWizard extends Component< }; createIndexPattern = async (timeFieldName: string | undefined, indexPatternId: string) => { - const { services } = this.props; + const { services, history } = this.props; const { indexPattern } = this.state; const emptyPattern = await services.indexPatterns.make(); @@ -160,24 +178,30 @@ export class CreateIndexPatternWizard extends Component< id: indexPatternId, title: indexPattern, timeFieldName, - ...services.indexPatternCreationType.getIndexPatternMappings(), + ...this.state.indexPatternCreationType.getIndexPatternMappings(), }); const createdId = await emptyPattern.create(); if (!createdId) { - const confirmMessage = i18n.translate('kbn.management.indexPattern.titleExistsLabel', { - values: { title: emptyPattern.title }, - defaultMessage: "An index pattern with the title '{title}' already exists.", - }); + const confirmMessage = i18n.translate( + 'indexPatternManagement.indexPattern.titleExistsLabel', + { + values: { title: emptyPattern.title }, + defaultMessage: "An index pattern with the title '{title}' already exists.", + } + ); const isConfirmed = await services.openConfirm(confirmMessage, { - confirmButtonText: i18n.translate('kbn.management.indexPattern.goToPatternButtonLabel', { - defaultMessage: 'Go to existing pattern', - }), + confirmButtonText: i18n.translate( + 'indexPatternManagement.indexPattern.goToPatternButtonLabel', + { + defaultMessage: 'Go to existing pattern', + } + ), }); if (isConfirmed) { - return services.changeUrl(`/management/kibana/index_patterns/${indexPatternId}`); + return history.push(`/patterns/${indexPatternId}`); } else { return false; } @@ -188,7 +212,7 @@ export class CreateIndexPatternWizard extends Component< } services.indexPatterns.clearCache(createdId); - services.changeUrl(`/management/kibana/index_patterns/${createdId}`); + history.push(`/patterns/${createdId}`); }; goToTimeFieldStep = (indexPattern: string) => { @@ -211,12 +235,13 @@ export class CreateIndexPatternWizard extends Component< return (
); } @@ -246,7 +271,9 @@ export class CreateIndexPatternWizard extends Component< } if (step === 1) { - const { services, initialQuery } = this.props; + const { services, location } = this.props; + const initialQuery = new URLSearchParams(location.search).get('id') || undefined; + return ( @@ -269,7 +296,7 @@ export class CreateIndexPatternWizard extends Component< indexPatternsService={services.indexPatterns} goToPreviousStep={this.goToIndexPatternStep} createIndexPattern={this.createIndexPattern} - indexPatternCreationType={services.indexPatternCreationType} + indexPatternCreationType={this.state.indexPatternCreationType} /> ); } @@ -288,7 +315,7 @@ export class CreateIndexPatternWizard extends Component< const content = this.renderContent(); return ( - +
{header} {content} @@ -300,7 +327,9 @@ export class CreateIndexPatternWizard extends Component< }} toastLifeTimeMs={6000} /> - + ); } } + +export const CreateIndexPatternWizardWithRouter = withRouter(CreateIndexPatternWizard); diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/index.ts new file mode 100644 index 0000000000000..893021141aa24 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { CreateIndexPatternWizardWithRouter } from './create_index_pattern_wizard'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/can_append_wildcard.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/can_append_wildcard.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/can_append_wildcard.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/can_append_wildcard.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/can_append_wildcard.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/can_append_wildcard.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/can_append_wildcard.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/can_append_wildcard.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/contains_illegal_characters.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/contains_illegal_characters.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/contains_illegal_characters.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/contains_illegal_characters.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/contains_invalid_characters.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/contains_invalid_characters.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/contains_invalid_characters.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/contains_invalid_characters.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/ensure_minimum_time.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/ensure_minimum_time.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/ensure_minimum_time.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/ensure_minimum_time.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/ensure_minimum_time.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/ensure_minimum_time.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/ensure_minimum_time.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/ensure_minimum_time.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/extract_time_fields.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/extract_time_fields.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/extract_time_fields.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/extract_time_fields.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/extract_time_fields.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/extract_time_fields.ts similarity index 80% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/extract_time_fields.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/extract_time_fields.ts index 0b95ec0a120da..809c9f77b2832 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/extract_time_fields.ts +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/extract_time_fields.ts @@ -18,13 +18,16 @@ */ import { i18n } from '@kbn/i18n'; -import { IFieldType } from '../../../../../../../../../plugins/data/public'; +import { IFieldType } from '../../../../../../plugins/data/public'; export function extractTimeFields(fields: IFieldType[]) { const dateFields = fields.filter(field => field.type === 'date'); - const label = i18n.translate('kbn.management.createIndexPattern.stepTime.noTimeFieldsLabel', { - defaultMessage: "The indices which match this index pattern don't contain any time fields.", - }); + const label = i18n.translate( + 'indexPatternManagement.createIndexPattern.stepTime.noTimeFieldsLabel', + { + defaultMessage: "The indices which match this index pattern don't contain any time fields.", + } + ); if (dateFields.length === 0) { return [ @@ -40,7 +43,7 @@ export function extractTimeFields(fields: IFieldType[]) { fieldName: '', }; const noTimeFieldLabel = i18n.translate( - 'kbn.management.createIndexPattern.stepTime.noTimeFieldOptionLabel', + 'indexPatternManagement.createIndexPattern.stepTime.noTimeFieldOptionLabel', { defaultMessage: "I don't want to use the Time Filter", } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.test.ts similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.test.ts index b1500f8303b66..1c67fea9fa352 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.test.ts @@ -18,9 +18,9 @@ */ import { getIndices } from './get_indices'; -import { IndexPatternCreationConfig } from '../../../../../../../../../plugins/index_pattern_management/public'; +import { IndexPatternCreationConfig } from '../../../../../index_pattern_management/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { LegacyApiCaller } from '../../../../../../../../../plugins/data/public/search/legacy'; +import { LegacyApiCaller } from '../../../../../data/public/search/legacy'; export const successfulResponse = { hits: { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.ts index 3b1b7a3b52a5b..9f75dc39a654c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.ts +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_indices.ts @@ -18,8 +18,8 @@ */ import { get, sortBy } from 'lodash'; -import { IndexPatternCreationConfig } from '../../../../../../../../../plugins/index_pattern_management/public'; -import { DataPublicPluginStart } from '../../../../../../../../../plugins/data/public'; +import { IndexPatternCreationConfig } from '../../../../../index_pattern_management/public'; +import { DataPublicPluginStart } from '../../../../../data/public'; import { MatchedIndex } from '../types'; export async function getIndices( diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_matched_indices.test.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_matched_indices.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_matched_indices.test.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_matched_indices.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_matched_indices.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_matched_indices.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_matched_indices.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/get_matched_indices.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/index.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/types.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/types.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/types.ts rename to src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/types.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/constants.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/constants.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx similarity index 52% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx index 3b865f7d5e1ea..fb5c27774f506 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx @@ -18,34 +18,36 @@ */ import React from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -// @ts-ignore -import { FieldEditor } from 'ui/field_editor'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { HttpStart, DocLinksStart } from 'src/core/public'; -import { IndexPattern, DataPublicPluginStart } from 'src/plugins/data/public'; +import { ChromeDocTitle, NotificationsStart, IUiSettingsClient } from 'src/core/public'; +import { IndexPattern, DataPublicPluginStart } from '../../../../../../plugins/data/public'; import { IndexHeader } from '../index_header'; -import { ChromeDocTitle, NotificationsStart } from '../../../../../../../../../core/public'; import { TAB_SCRIPTED_FIELDS, TAB_INDEXED_FIELDS } from '../constants'; +import { FieldEditor } from '../../field_editor'; + interface CreateEditFieldProps extends RouteComponentProps { indexPattern: IndexPattern; mode?: string; fieldName?: string; fieldFormatEditors: any; - getConfig: (name: string) => any; services: { - dataStart: DataPublicPluginStart; - notifications: NotificationsStart; + uiSettings: IUiSettingsClient; docTitle: ChromeDocTitle; - getHttpStart: () => HttpStart; + http: HttpStart; docLinksScriptedFields: DocLinksStart['links']['scriptedFields']; + SearchBar: DataPublicPluginStart['ui']['SearchBar']; + toasts: NotificationsStart['toasts']; + fieldFormats: DataPublicPluginStart['fieldFormats']; + indexPatterns: DataPublicPluginStart['indexPatterns']; }; } const newFieldPlaceholder = i18n.translate( - 'kbn.management.editIndexPattern.scripted.newFieldPlaceholder', + 'indexPatternManagement.editIndexPattern.scripted.newFieldPlaceholder', { defaultMessage: 'New Scripted Field', } @@ -57,14 +59,13 @@ export const CreateEditField = withRouter( mode, fieldName, fieldFormatEditors, - getConfig, services, history, }: CreateEditFieldProps) => { const field = mode === 'edit' && fieldName ? indexPattern.fields.getByName(fieldName) - : services.dataStart.indexPatterns.createField( + : services.indexPatterns.createField( indexPattern, { scripted: true, @@ -73,15 +74,18 @@ export const CreateEditField = withRouter( false ); - const url = `/management/kibana/index_patterns/${indexPattern.id}`; + const url = `/patterns/${indexPattern.id}`; if (mode === 'edit' && !field) { - const message = i18n.translate('kbn.management.editIndexPattern.scripted.noFieldLabel', { - defaultMessage: - "'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'", - values: { indexPatternTitle: indexPattern.title, fieldName }, - }); - services.notifications.toasts.addWarning(message); + const message = i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.noFieldLabel', + { + defaultMessage: + "'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'", + values: { indexPatternTitle: indexPattern.title, fieldName }, + } + ); + services.toasts.addWarning(message); history.push(url); } @@ -95,24 +99,33 @@ export const CreateEditField = withRouter( if (field) { return ( - - - - - - - - + + + + + + + + + + ); } else { return <>; diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx new file mode 100644 index 0000000000000..70851b712d756 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx @@ -0,0 +1,95 @@ +/* + * 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 React, { useEffect, useState } from 'react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; + +import { + HttpStart, + DocLinksStart, + ChromeDocTitle, + NotificationsStart, + IUiSettingsClient, +} from 'src/core/public'; + +import { IndexPattern, DataPublicPluginStart } from '../../../../../../plugins/data/public'; +import { ManagementAppMountParams } from '../../../../../management/public'; +import { getEditFieldBreadcrumbs, getCreateFieldBreadcrumbs } from '../../breadcrumbs'; +import { CreateEditField } from './create_edit_field'; + +export interface CreateEditFieldContainerProps + extends RouteComponentProps<{ id: string; fieldName: string }> { + getIndexPattern: (id: string) => Promise; + fieldFormatEditors: any; + getConfig: IUiSettingsClient; + services: { + uiSettings: IUiSettingsClient; + notifications: NotificationsStart; + docTitle: ChromeDocTitle; + http: HttpStart; + docLinksScriptedFields: DocLinksStart['links']['scriptedFields']; + SearchBar: DataPublicPluginStart['ui']['SearchBar']; + toasts: NotificationsStart['toasts']; + fieldFormats: DataPublicPluginStart['fieldFormats']; + indexPatterns: DataPublicPluginStart['indexPatterns']; + setBreadcrumbs: ManagementAppMountParams['setBreadcrumbs']; + }; +} + +const CreateEditFieldCont: React.FC = ({ ...props }) => { + const [indexPattern, setIndexPattern] = useState(); + + useEffect(() => { + props.getIndexPattern(props.match.params.id).then((ip: IndexPattern) => { + setIndexPattern(ip); + if (ip) { + props.services.setBreadcrumbs( + props.match.params.fieldName + ? getEditFieldBreadcrumbs(ip, props.match.params.fieldName) + : getCreateFieldBreadcrumbs(ip) + ); + } + }); + }, [props.match.params.id, props.getIndexPattern, props]); + + if (indexPattern) { + return ( + + ); + } else { + return <>; + } +}; + +export const CreateEditFieldContainer = withRouter(CreateEditFieldCont); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/index.ts new file mode 100644 index 0000000000000..84dce3b0f8301 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/index.ts @@ -0,0 +1,21 @@ +/* + * 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 { CreateEditField } from './create_edit_field'; +export { CreateEditFieldContainer } from './create_edit_field_container'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx similarity index 51% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx index e869ac84c2db2..f1c020cc409e0 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx @@ -29,69 +29,75 @@ import { EuiLink, EuiIcon, EuiCallOut, + EuiPanel, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { IndexPattern, IndexPatternField } from '../../../../../../../../plugins/data/public'; import { ChromeDocTitle, NotificationsStart, OverlayStart, -} from '../../../../../../../../core/public'; -import { IndexPatternManagementStart } from '../../../../../../../../plugins/index_pattern_management/public'; + IUiSettingsClient, + SavedObjectsClientContract, +} from 'src/core/public'; +import { IndexPattern, IndexPatternField } from '../../../../../plugins/data/public'; +import { IndexPatternManagementStart } from '../..'; import { Tabs } from './tabs'; import { IndexHeader } from './index_header'; +import { IndexPatternTableItem } from '../types'; +import { getIndexPatterns } from '../utils'; interface EditIndexPatternProps extends RouteComponentProps { indexPattern: IndexPattern; - indexPatterns: IndexPattern[]; - config: Record; + config: IUiSettingsClient; services: { notifications: NotificationsStart; docTitle: ChromeDocTitle; overlays: OverlayStart; + savedObjectsClient: SavedObjectsClientContract; indexPatternManagement: IndexPatternManagementStart; + painlessDocLink: string; }; } const mappingAPILink = i18n.translate( - 'kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink', + 'indexPatternManagement.editIndexPattern.timeFilterLabel.mappingAPILink', { defaultMessage: 'Mapping API', } ); const mappingConflictHeader = i18n.translate( - 'kbn.management.editIndexPattern.mappingConflictHeader', + 'indexPatternManagement.editIndexPattern.mappingConflictHeader', { defaultMessage: 'Mapping conflict', } ); -const confirmMessage = i18n.translate('kbn.management.editIndexPattern.refreshLabel', { +const confirmMessage = i18n.translate('indexPatternManagement.editIndexPattern.refreshLabel', { defaultMessage: 'This action resets the popularity counter of each field.', }); const confirmModalOptionsRefresh = { - confirmButtonText: i18n.translate('kbn.management.editIndexPattern.refreshButton', { + confirmButtonText: i18n.translate('indexPatternManagement.editIndexPattern.refreshButton', { defaultMessage: 'Refresh', }), - title: i18n.translate('kbn.management.editIndexPattern.refreshHeader', { + title: i18n.translate('indexPatternManagement.editIndexPattern.refreshHeader', { defaultMessage: 'Refresh field list?', }), }; const confirmModalOptionsDelete = { - confirmButtonText: i18n.translate('kbn.management.editIndexPattern.deleteButton', { + confirmButtonText: i18n.translate('indexPatternManagement.editIndexPattern.deleteButton', { defaultMessage: 'Delete', }), - title: i18n.translate('kbn.management.editIndexPattern.deleteHeader', { + title: i18n.translate('indexPatternManagement.editIndexPattern.deleteHeader', { defaultMessage: 'Delete index pattern?', }), }; export const EditIndexPattern = withRouter( - ({ indexPattern, indexPatterns, config, services, history, location }: EditIndexPatternProps) => { + ({ indexPattern, config, services, history, location }: EditIndexPatternProps) => { const [fields, setFields] = useState(indexPattern.getNonScriptedFields()); const [conflictedFields, setConflictedFields] = useState( indexPattern.fields.filter(field => field.type === 'conflict') @@ -102,7 +108,7 @@ export const EditIndexPattern = withRouter( useEffect(() => { setFields(indexPattern.getNonScriptedFields()); setConflictedFields(indexPattern.fields.filter(field => field.type === 'conflict')); - }, [indexPattern, indexPattern.fields]); + }, [indexPattern]); useEffect(() => { const indexPatternTags = @@ -129,9 +135,14 @@ export const EditIndexPattern = withRouter( }); }; - const removePattern = () => { - function doRemove() { + const removePatternClick = () => { + async function doRemove() { if (indexPattern.id === defaultIndex) { + const indexPatterns: IndexPatternTableItem[] = await getIndexPatterns( + services.savedObjectsClient, + config.get('defaultIndex'), + services.indexPatternManagement + ); config.remove('defaultIndex'); const otherPatterns = filter(indexPatterns, pattern => { return pattern.id !== indexPattern.id; @@ -143,7 +154,7 @@ export const EditIndexPattern = withRouter( } Promise.resolve(indexPattern.destroy()).then(function() { - history.push('/management/kibana/index_patterns'); + history.push(''); }); } @@ -154,13 +165,16 @@ export const EditIndexPattern = withRouter( }); }; - const timeFilterHeader = i18n.translate('kbn.management.editIndexPattern.timeFilterHeader', { - defaultMessage: "Time Filter field name: '{timeFieldName}'", - values: { timeFieldName: indexPattern.timeFieldName }, - }); + const timeFilterHeader = i18n.translate( + 'indexPatternManagement.editIndexPattern.timeFilterHeader', + { + defaultMessage: "Time Filter field name: '{timeFieldName}'", + values: { timeFieldName: indexPattern.timeFieldName }, + } + ); const mappingConflictLabel = i18n.translate( - 'kbn.management.editIndexPattern.mappingConflictLabel', + 'indexPatternManagement.editIndexPattern.mappingConflictLabel', { defaultMessage: '{conflictFieldsLength, plural, one {A field is} other {# fields are}} defined as several types (string, integer, etc) across the indices that match this pattern. You may still be able to use these conflict fields in parts of Kibana, but they will be unavailable for functions that require Kibana to know their type. Correcting this issue will require reindexing your data.', @@ -168,71 +182,80 @@ export const EditIndexPattern = withRouter( } ); + const headingAriaLabel = i18n.translate('indexPatternManagement.editIndexPattern.detailsAria', { + defaultMessage: 'Index pattern details', + }); + services.docTitle.change(indexPattern.title); const showTagsSection = Boolean(indexPattern.timeFieldName || (tags && tags.length > 0)); return ( - - - - - {showTagsSection && ( - - {Boolean(indexPattern.timeFieldName) && ( - - {timeFilterHeader} - + +
+ + + + + {showTagsSection && ( + + {Boolean(indexPattern.timeFieldName) && ( + + {timeFilterHeader} + + )} + {tags.map((tag: any) => ( + + {tag.name} + + ))} + + )} + + +

+ {indexPattern.title} }} + />{' '} + + {mappingAPILink} + + +

+ + {conflictedFields.length > 0 && ( + +

{mappingConflictLabel}

+
)} - {tags.map((tag: any) => ( - - {tag.name} - - ))} - - )} - - -

- {indexPattern.title} }} - />{' '} - - {mappingAPILink} - - -

-
- {conflictedFields.length > 0 && ( - -

{mappingConflictLabel}

-
- )} - - - - - + + + + + +
+ ); } ); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx new file mode 100644 index 0000000000000..2f02765cd0596 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx @@ -0,0 +1,73 @@ +/* + * 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 React, { useEffect, useState } from 'react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { + ChromeDocTitle, + NotificationsStart, + OverlayStart, + IUiSettingsClient, + SavedObjectsClientContract, +} from 'src/core/public'; +import { IndexPattern } from '../../../../../plugins/data/public'; +import { ManagementAppMountParams } from '../../../../management/public'; +import { IndexPatternManagementStart } from '../..'; +import { getEditBreadcrumbs } from '../breadcrumbs'; + +import { EditIndexPattern } from '../edit_index_pattern'; + +interface EditIndexPatternContainerProps extends RouteComponentProps<{ id: string }> { + getIndexPattern: (id: string) => Promise; + config: IUiSettingsClient; + services: { + notifications: NotificationsStart; + docTitle: ChromeDocTitle; + overlays: OverlayStart; + savedObjectsClient: SavedObjectsClientContract; + setBreadcrumbs: ManagementAppMountParams['setBreadcrumbs']; + indexPatternManagement: IndexPatternManagementStart; + painlessDocLink: string; + }; +} + +const EditIndexPatternCont: React.FC = ({ ...props }) => { + const [indexPattern, setIndexPattern] = useState(); + + useEffect(() => { + props.getIndexPattern(props.match.params.id).then((ip: IndexPattern) => { + setIndexPattern(ip); + props.services.setBreadcrumbs(getEditBreadcrumbs(ip)); + }); + }, [props.match.params.id, props.getIndexPattern, props]); + + if (indexPattern) { + return ( + + ); + } else { + return <>; + } +}; + +export const EditIndexPatternContainer = withRouter(EditIndexPatternCont); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern_state_container.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_state_container.ts similarity index 97% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern_state_container.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_state_container.ts index 5723a596f95d5..f99a5b072b423 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern_state_container.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_state_container.ts @@ -22,7 +22,7 @@ import { createStateContainer, syncState, createKbnUrlStateStorage, -} from '../../../../../../../../plugins/kibana_utils/public'; +} from '../../../../../plugins/kibana_utils/public'; interface IEditIndexPatternState { tab: string; diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/index.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/index.tsx new file mode 100644 index 0000000000000..288ce115a7803 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/index.tsx @@ -0,0 +1,23 @@ +/* + * 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 { EditIndexPattern } from './edit_index_pattern'; +export { EditIndexPatternContainer } from './edit_index_pattern_container'; +export { CreateEditField } from './create_edit_field'; +export { CreateEditFieldContainer } from './create_edit_field/create_edit_field_container'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/index_header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/index_header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/index_header/index_header.tsx similarity index 78% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/index_header/index_header.tsx index a06671ef6a470..4cf43d63d5839 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/index_header/index_header.tsx @@ -27,37 +27,43 @@ import { EuiTitle, EuiButtonIcon, } from '@elastic/eui'; -import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; interface IndexHeaderProps { indexPattern: IIndexPattern; defaultIndex?: string; setDefault?: () => void; refreshFields?: () => void; - deleteIndexPattern?: () => void; + deleteIndexPatternClick?: () => void; } -const setDefaultAriaLabel = i18n.translate('kbn.management.editIndexPattern.setDefaultAria', { - defaultMessage: 'Set as default index.', -}); +const setDefaultAriaLabel = i18n.translate( + 'indexPatternManagement.editIndexPattern.setDefaultAria', + { + defaultMessage: 'Set as default index.', + } +); -const setDefaultTooltip = i18n.translate('kbn.management.editIndexPattern.setDefaultTooltip', { - defaultMessage: 'Set as default index.', -}); +const setDefaultTooltip = i18n.translate( + 'indexPatternManagement.editIndexPattern.setDefaultTooltip', + { + defaultMessage: 'Set as default index.', + } +); -const refreshAriaLabel = i18n.translate('kbn.management.editIndexPattern.refreshAria', { +const refreshAriaLabel = i18n.translate('indexPatternManagement.editIndexPattern.refreshAria', { defaultMessage: 'Reload field list.', }); -const refreshTooltip = i18n.translate('kbn.management.editIndexPattern.refreshTooltip', { +const refreshTooltip = i18n.translate('indexPatternManagement.editIndexPattern.refreshTooltip', { defaultMessage: 'Refresh field list.', }); -const removeAriaLabel = i18n.translate('kbn.management.editIndexPattern.removeAria', { +const removeAriaLabel = i18n.translate('indexPatternManagement.editIndexPattern.removeAria', { defaultMessage: 'Remove index pattern.', }); -const removeTooltip = i18n.translate('kbn.management.editIndexPattern.removeTooltip', { +const removeTooltip = i18n.translate('indexPatternManagement.editIndexPattern.removeTooltip', { defaultMessage: 'Remove index pattern.', }); @@ -66,7 +72,7 @@ export function IndexHeader({ indexPattern, setDefault, refreshFields, - deleteIndexPattern, + deleteIndexPatternClick, }: IndexHeaderProps) { return ( @@ -114,12 +120,12 @@ export function IndexHeader({ )} - {deleteIndexPattern && ( + {deleteIndexPatternClick && ( ({ diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx index c69063967b1e2..6b1048d3c9d0c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx @@ -23,7 +23,7 @@ import { IndexPatternField, IIndexPattern, IFieldType, -} from '../../../../../../../../../plugins/data/public'; +} from '../../../../../../plugins/data/public'; import { Table } from './components/table'; import { getFieldFormat } from './lib'; import { IndexedFieldItem } from './types'; @@ -108,7 +108,6 @@ export class IndexedFieldsTable extends Component< render() { const { indexPattern } = this.props; - const fields = this.getFilteredFields(this.state, this.props); return ( diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts index fc7477c074ac2..2786df641fdb2 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IIndexPattern } from '../../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from '../../../../../../data/public'; import { getFieldFormat } from './get_field_format'; const indexPattern = ({ diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts index 1d6f267430f07..861017d99962e 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/get_field_format.ts @@ -18,7 +18,7 @@ */ import { get } from 'lodash'; -import { IIndexPattern } from '../../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from '../../../../../../data/public'; export function getFieldFormat(indexPattern?: IIndexPattern, fieldName?: string): string { return indexPattern && fieldName diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/lib/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/lib/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/types.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/types.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/types.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/types.ts index f27f4608bf5d5..30466bc57bada 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/types.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IFieldType } from '../../../../../../../../../plugins/data/public'; +import { IFieldType } from '../../../../../../plugins/data/public'; export interface IndexedFieldItem extends IFieldType { info: string[]; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap similarity index 82% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap index 202b09ddc6066..c0ecc441e9018 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap @@ -3,7 +3,7 @@ exports[`ScriptedFieldsTable should filter based on the lang filter 1`] = `
} @@ -16,7 +16,7 @@ exports[`CallOuts should render normally 1`] = `

, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx similarity index 87% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx index 8e38b569a32fa..31d1e4e40bcd5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx @@ -37,7 +37,7 @@ export const CallOuts = ({ deprecatedLangsInUse, painlessDocLink }: CallOutsProp } @@ -46,7 +46,7 @@ export const CallOuts = ({ deprecatedLangsInUse, painlessDocLink }: CallOutsProp >

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx similarity index 83% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx index 1e82174f863b0..ece706798a55f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx @@ -35,16 +35,19 @@ export const DeleteScritpedFieldConfirmationModal = ({ hideDeleteConfirmationModal, deleteField, }: DeleteScritpedFieldConfirmationModalProps) => { - const title = i18n.translate('kbn.management.editIndexPattern.scripted.deleteFieldLabel', { - defaultMessage: "Delete scripted field '{fieldName}'?", - values: { fieldName: field.name }, - }); + const title = i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.deleteFieldLabel', + { + defaultMessage: "Delete scripted field '{fieldName}'?", + values: { fieldName: field.name }, + } + ); const cancelButtonText = i18n.translate( - 'kbn.management.editIndexPattern.scripted.deleteField.cancelButton', + 'indexPatternManagement.editIndexPattern.scripted.deleteField.cancelButton', { defaultMessage: 'Cancel' } ); const confirmButtonText = i18n.translate( - 'kbn.management.editIndexPattern.scripted.deleteField.deleteButton', + 'indexPatternManagement.editIndexPattern.scripted.deleteField.deleteButton', { defaultMessage: 'Delete' } ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap new file mode 100644 index 0000000000000..6261ea2c90793 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Header should render normally 1`] = ` +

+
+

+ + Scripted fields + +

+
+

+ + You can use scripted fields in visualizations and display them in your documents. However, you cannot search scripted fields. + +

+
+
+
+ +
+
+`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx similarity index 71% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx index 19479de8f2aa4..11fdae39aee3c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx @@ -18,13 +18,21 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { render } from 'enzyme'; +import { RouteComponentProps } from 'react-router-dom'; import { Header } from './header'; describe('Header', () => { test('should render normally', () => { - const component = shallow(
); + const component = render( + + ); expect(component).toMatchSnapshot(); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx similarity index 72% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx index b8f832dad72af..dc48f61d1aa65 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx @@ -18,21 +18,22 @@ */ import React from 'react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -interface HeaderProps { - addScriptedFieldUrl: string; +interface HeaderProps extends RouteComponentProps { + indexPatternId: string; } -export const Header = ({ addScriptedFieldUrl }: HeaderProps) => ( +export const Header = withRouter(({ indexPatternId, history }: HeaderProps) => (

@@ -40,7 +41,7 @@ export const Header = ({ addScriptedFieldUrl }: HeaderProps) => (

@@ -49,12 +50,17 @@ export const Header = ({ addScriptedFieldUrl }: HeaderProps) => ( - + { + history.push(`${indexPatternId}/create-field/`); + }} + > -); +)); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx similarity index 97% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx index 13b3875f58687..26044f910159a 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx @@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; import { Table } from '../table'; import { ScriptedFieldItem } from '../../types'; -import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IIndexPattern); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.tsx similarity index 68% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.tsx index 14aed11b32203..51ca59ee7b032 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/table/table.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { EuiInMemoryTable, EuiBasicTableColumn } from '@elastic/eui'; import { ScriptedFieldItem } from '../../types'; -import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from '../../../../../../../data/public'; interface TableProps { indexPattern: IIndexPattern; @@ -46,11 +46,11 @@ export class Table extends PureComponent { const columns: Array> = [ { field: 'displayName', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.nameHeader', { + name: i18n.translate('indexPatternManagement.editIndexPattern.scripted.table.nameHeader', { defaultMessage: 'Name', }), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.nameDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.nameDescription', { defaultMessage: 'Name of the field' } ), dataType: 'string', @@ -59,11 +59,11 @@ export class Table extends PureComponent { }, { field: 'lang', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.langHeader', { + name: i18n.translate('indexPatternManagement.editIndexPattern.scripted.table.langHeader', { defaultMessage: 'Lang', }), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.langDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.langDescription', { defaultMessage: 'Language used for the field' } ), dataType: 'string', @@ -72,11 +72,14 @@ export class Table extends PureComponent { }, { field: 'script', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.scriptHeader', { - defaultMessage: 'Script', - }), + name: i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.table.scriptHeader', + { + defaultMessage: 'Script', + } + ), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.scriptDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.scriptDescription', { defaultMessage: 'Script for the field' } ), dataType: 'string', @@ -84,11 +87,14 @@ export class Table extends PureComponent { }, { field: 'name', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.formatHeader', { - defaultMessage: 'Format', - }), + name: i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.table.formatHeader', + { + defaultMessage: 'Format', + } + ), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.formatDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.formatDescription', { defaultMessage: 'Format used for the field' } ), render: this.renderFormatCell, @@ -99,11 +105,14 @@ export class Table extends PureComponent { actions: [ { type: 'icon', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.editHeader', { - defaultMessage: 'Edit', - }), + name: i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.table.editHeader', + { + defaultMessage: 'Edit', + } + ), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.editDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.editDescription', { defaultMessage: 'Edit this field' } ), icon: 'pencil', @@ -111,11 +120,14 @@ export class Table extends PureComponent { }, { type: 'icon', - name: i18n.translate('kbn.management.editIndexPattern.scripted.table.deleteHeader', { - defaultMessage: 'Delete', - }), + name: i18n.translate( + 'indexPatternManagement.editIndexPattern.scripted.table.deleteHeader', + { + defaultMessage: 'Delete', + } + ), description: i18n.translate( - 'kbn.management.editIndexPattern.scripted.table.deleteDescription', + 'indexPatternManagement.editIndexPattern.scripted.table.deleteDescription', { defaultMessage: 'Delete this field' } ), icon: 'trash', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx index 914d80f9f61d7..80132167b7f58 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { ScriptedFieldsTable } from '../scripted_fields_table'; -import { IIndexPattern } from '../../../../../../../../../plugins/data/common/index_patterns'; +import { IIndexPattern } from '../../../../../../plugins/data/common/index_patterns'; jest.mock('@elastic/eui', () => ({ EuiTitle: 'eui-title', @@ -46,11 +46,6 @@ jest.mock('./components/table', () => ({ }, })); -jest.mock('ui/scripting_languages', () => ({ - getSupportedScriptingLanguages: () => ['painless'], - getDeprecatedScriptingLanguages: () => [], -})); - jest.mock('ui/documentation_links', () => ({ documentationLinks: { scriptedFields: { @@ -80,7 +75,11 @@ describe('ScriptedFieldsTable', () => { test('should render normally', async () => { const component = shallow( - + ); // Allow the componentWillMount code to execute @@ -93,7 +92,11 @@ describe('ScriptedFieldsTable', () => { test('should filter based on the query bar', async () => { const component = shallow( - + ); // Allow the componentWillMount code to execute @@ -117,6 +120,7 @@ describe('ScriptedFieldsTable', () => { { name: 'Bad', lang: 'somethingElse', script: 'z++' }, ], })} + painlessDocLink={'painlessDoc'} helpers={helpers} /> ); @@ -138,6 +142,7 @@ describe('ScriptedFieldsTable', () => { indexPattern={getIndexPatternMock({ getScriptedFields: () => [], })} + painlessDocLink={'painlessDoc'} helpers={helpers} /> ); @@ -152,7 +157,11 @@ describe('ScriptedFieldsTable', () => { test('should show a delete modal', async () => { const component = shallow( - + ); await component.update(); // Fire `componentWillMount()` @@ -172,6 +181,7 @@ describe('ScriptedFieldsTable', () => { removeScriptedField, }} helpers={helpers} + painlessDocLink={'painlessDoc'} /> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx index f2c2727c5c0bb..32520eadaf199 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx @@ -18,18 +18,16 @@ */ import React, { Component } from 'react'; +import { EuiSpacer } from '@elastic/eui'; import { getSupportedScriptingLanguages, getDeprecatedScriptingLanguages, -} from 'ui/scripting_languages'; -import { documentationLinks } from 'ui/documentation_links'; - -import { EuiSpacer } from '@elastic/eui'; +} from '../../../scripting_languages'; import { Table, Header, CallOuts, DeleteScritpedFieldConfirmationModal } from './components'; import { ScriptedFieldItem } from './types'; -import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from '../../../../../../plugins/data/public'; interface ScriptedFieldsTableProps { indexPattern: IIndexPattern; @@ -40,6 +38,7 @@ interface ScriptedFieldsTableProps { getRouteHref?: Function; }; onRemoveField?: () => void; + painlessDocLink: string; } interface ScriptedFieldsTableState { @@ -136,24 +135,16 @@ export class ScriptedFieldsTable extends Component< }; render() { - const { indexPattern } = this.props; + const { indexPattern, painlessDocLink } = this.props; const { fieldToDelete, deprecatedLangsInUse } = this.state; const items = this.getFilteredItems(); return ( <> -

+
- + diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap index 879ea555d3300..92998bc3f07e3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap @@ -19,7 +19,7 @@ exports[`AddFilter should ignore strings with just spaces 1`] = ` > @@ -46,7 +46,7 @@ exports[`AddFilter should render normally 1`] = ` > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx index d0f397637de33..2a5e29827ccc5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx @@ -27,10 +27,13 @@ interface AddFilterProps { onAddFilter: (filter: string) => void; } -const sourcePlaceholder = i18n.translate('kbn.management.editIndexPattern.sourcePlaceholder', { - defaultMessage: - "source filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')", -}); +const sourcePlaceholder = i18n.translate( + 'indexPatternManagement.editIndexPattern.sourcePlaceholder', + { + defaultMessage: + "source filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')", + } +); export const AddFilter = ({ onAddFilter }: AddFilterProps) => { const [filter, setFilter] = useState(''); @@ -53,7 +56,7 @@ export const AddFilter = ({ onAddFilter }: AddFilterProps) => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/add_filter/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap similarity index 72% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap index 62376b498d887..0020adb19983d 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap @@ -7,14 +7,14 @@ exports[`Header should render normally 1`] = ` cancelButtonText={ } confirmButtonText={ } @@ -24,7 +24,7 @@ exports[`Header should render normally 1`] = ` title={ } buttonColor="danger" confirmButtonText={ } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap index cde0de79caacd..1f380d68a5af5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Header should render normally 1`] = `

@@ -17,14 +17,14 @@ exports[`Header should render normally 1`] = `

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/header.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/header.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/header.tsx similarity index 90% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/header.tsx index 7b37f75043dd5..709908a1bb253 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/header.tsx @@ -27,7 +27,7 @@ export const Header = () => (

@@ -35,7 +35,7 @@ export const Header = () => (

diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap index c70d0871bb854..cb8abdefec266 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap @@ -29,7 +29,7 @@ exports[`Table editing should update the matches dynamically as input value is c diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx similarity index 99% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx index 4705ecd2d1685..421b5b67c2288 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx @@ -22,7 +22,7 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { Table, TableProps, TableState } from './table'; import { EuiTableFieldDataColumnType, keyCodes } from '@elastic/eui'; -import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; import { SourceFiltersTableFilter } from '../../types'; const indexPattern = {} as IIndexPattern; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx index db2b74bbc9824..04998d9f7dafe 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx @@ -30,43 +30,54 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { IIndexPattern } from 'src/plugins/data/public'; import { SourceFiltersTableFilter } from '../../types'; -import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; - -const filterHeader = i18n.translate('kbn.management.editIndexPattern.source.table.filterHeader', { - defaultMessage: 'Filter', -}); +const filterHeader = i18n.translate( + 'indexPatternManagement.editIndexPattern.source.table.filterHeader', + { + defaultMessage: 'Filter', + } +); const filterDescription = i18n.translate( - 'kbn.management.editIndexPattern.source.table.filterDescription', + 'indexPatternManagement.editIndexPattern.source.table.filterDescription', { defaultMessage: 'Filter name' } ); -const matchesHeader = i18n.translate('kbn.management.editIndexPattern.source.table.matchesHeader', { - defaultMessage: 'Matches', -}); +const matchesHeader = i18n.translate( + 'indexPatternManagement.editIndexPattern.source.table.matchesHeader', + { + defaultMessage: 'Matches', + } +); const matchesDescription = i18n.translate( - 'kbn.management.editIndexPattern.source.table.matchesDescription', + 'indexPatternManagement.editIndexPattern.source.table.matchesDescription', { defaultMessage: 'Language used for the field' } ); -const editAria = i18n.translate('kbn.management.editIndexPattern.source.table.editAria', { +const editAria = i18n.translate('indexPatternManagement.editIndexPattern.source.table.editAria', { defaultMessage: 'Edit', }); -const saveAria = i18n.translate('kbn.management.editIndexPattern.source.table.saveAria', { +const saveAria = i18n.translate('indexPatternManagement.editIndexPattern.source.table.saveAria', { defaultMessage: 'Save', }); -const deleteAria = i18n.translate('kbn.management.editIndexPattern.source.table.deleteAria', { - defaultMessage: 'Delete', -}); +const deleteAria = i18n.translate( + 'indexPatternManagement.editIndexPattern.source.table.deleteAria', + { + defaultMessage: 'Delete', + } +); -const cancelAria = i18n.translate('kbn.management.editIndexPattern.source.table.cancelAria', { - defaultMessage: 'Cancel', -}); +const cancelAria = i18n.translate( + 'indexPatternManagement.editIndexPattern.source.table.cancelAria', + { + defaultMessage: 'Cancel', + } +); export interface TableProps { indexPattern: IIndexPattern; @@ -161,7 +172,7 @@ export class Table extends Component { return ( diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.test.tsx similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.test.tsx index 1b68dd13566d3..fa048af7c7a70 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { SourceFiltersTable } from './source_filters_table'; -import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; jest.mock('@elastic/eui', () => ({ EuiButton: 'eui-button', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx index dcf8ae9e1323f..ccdda3915e979 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx @@ -22,7 +22,7 @@ import { createSelector } from 'reselect'; import { EuiSpacer } from '@elastic/eui'; import { AddFilter, Table, Header, DeleteFilterConfirmationModal } from './components'; -import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; +import { IIndexPattern } from '../../../../../../plugins/data/public'; import { SourceFiltersTableFilter } from './types'; export interface SourceFiltersTableProps { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/types.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/types.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/index.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/index.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/tabs.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/tabs.tsx rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx index c727dcd3e3c65..5cf7fd9b2af06 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -30,10 +30,10 @@ import { EuiSelectOption, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { fieldWildcardMatcher } from '../../../../../../../../../plugins/kibana_utils/public'; -import { IndexPatternManagementStart } from '../../../../../../../../../plugins/index_pattern_management/public'; -import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public'; -import { META_FIELDS_SETTING } from '../../../../../../../../../plugins/data/common'; +import { fieldWildcardMatcher } from '../../../../../kibana_utils/public'; +import { IndexPatternManagementStart } from '../../../../../index_pattern_management/public'; +import { IndexPattern, IndexPatternField } from '../../../../../data/public'; +import { META_FIELDS_SETTING } from '../../../../../data/common'; import { createEditIndexPatternPageStateContainer } from '../edit_index_pattern_state_container'; import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from '../constants'; import { SourceFiltersTable } from '../source_filters_table'; @@ -47,19 +47,26 @@ interface TabsProps extends Pick { fields: IndexPatternField[]; services: { indexPatternManagement: IndexPatternManagementStart; + painlessDocLink: string; }; } -const searchAriaLabel = i18n.translate('kbn.management.editIndexPattern.fields.searchAria', { - defaultMessage: 'Search fields', -}); +const searchAriaLabel = i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.searchAria', + { + defaultMessage: 'Search fields', + } +); -const filterAriaLabel = i18n.translate('kbn.management.editIndexPattern.fields.filterAria', { - defaultMessage: 'Filter field types', -}); +const filterAriaLabel = i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.filterAria', + { + defaultMessage: 'Filter field types', + } +); const filterPlaceholder = i18n.translate( - 'kbn.management.editIndexPattern.fields.filterPlaceholder', + 'indexPatternManagement.editIndexPattern.fields.filterPlaceholder', { defaultMessage: 'Search', } @@ -189,6 +196,7 @@ export function Tabs({ config, indexPattern, fields, services, history, location }, }} onRemoveField={refreshFilters} + painlessDocLink={services.painlessDocLink} /> ); @@ -219,6 +227,7 @@ export function Tabs({ config, indexPattern, fields, services, history, location refreshFilters, scriptedFieldLanguageFilter, services.indexPatternManagement.list.getFieldInfo, + services.painlessDocLink, ] ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/utils.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts similarity index 82% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/utils.ts rename to src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts index 83335a6fabfeb..b9b59142290dc 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/tabs/utils.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts @@ -19,8 +19,8 @@ import { Dictionary, countBy, defaults, unique } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public'; -import { IndexPatternManagementStart } from '../../../../../../../../../plugins/index_pattern_management/public'; +import { IndexPattern, IndexPatternField } from '../../../../../../plugins/data/public'; +import { IndexPatternManagementStart } from '../../../../../../plugins/index_pattern_management/public'; import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from '../constants'; function filterByName(items: IndexPatternField[], filter: string) { @@ -56,17 +56,17 @@ function getTitle(type: string, filteredCount: Dictionary, totalCount: D let title = ''; switch (type) { case 'indexed': - title = i18n.translate('kbn.management.editIndexPattern.tabs.fieldsHeader', { + title = i18n.translate('indexPatternManagement.editIndexPattern.tabs.fieldsHeader', { defaultMessage: 'Fields', }); break; case 'scripted': - title = i18n.translate('kbn.management.editIndexPattern.tabs.scriptedHeader', { + title = i18n.translate('indexPatternManagement.editIndexPattern.tabs.scriptedHeader', { defaultMessage: 'Scripted fields', }); break; case 'sourceFilters': - title = i18n.translate('kbn.management.editIndexPattern.tabs.sourceHeader', { + title = i18n.translate('indexPatternManagement.editIndexPattern.tabs.sourceHeader', { defaultMessage: 'Source filters', }); break; @@ -117,16 +117,22 @@ export function getTabs( } export function getPath(field: IndexPatternField) { - return `/management/kibana/index_patterns/${field.indexPattern?.id}/field/${field.name}`; + return `${field.indexPattern?.id}/field/${field.name}`; } -const allTypesDropDown = i18n.translate('kbn.management.editIndexPattern.fields.allTypesDropDown', { - defaultMessage: 'All field types', -}); +const allTypesDropDown = i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.allTypesDropDown', + { + defaultMessage: 'All field types', + } +); -const allLangsDropDown = i18n.translate('kbn.management.editIndexPattern.fields.allLangsDropDown', { - defaultMessage: 'All languages', -}); +const allLangsDropDown = i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.allLangsDropDown', + { + defaultMessage: 'All languages', + } +); export function convertToEuiSelectOption(options: string[], type: string) { const euiOptions = diff --git a/src/legacy/ui/public/field_editor/__snapshots__/field_editor.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap similarity index 72% rename from src/legacy/ui/public/field_editor/__snapshots__/field_editor.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap index dc11bdfefa46b..a7ed4e1c9cafd 100644 --- a/src/legacy/ui/public/field_editor/__snapshots__/field_editor.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap @@ -6,7 +6,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = `

@@ -19,31 +19,14 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` isVisible={false} /> } label={ } @@ -168,7 +152,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` error={ } @@ -188,7 +172,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` @@ -205,7 +189,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` > @@ -224,7 +208,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` > @@ -238,7 +222,7 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` > @@ -258,7 +242,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = `

} label={ } @@ -435,7 +403,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` @@ -452,7 +420,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` > @@ -471,7 +439,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` > @@ -485,7 +453,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` > @@ -503,7 +471,7 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` > @@ -525,7 +493,7 @@ exports[`FieldEditor should show conflict field warning 1`] = `

@@ -538,31 +506,14 @@ exports[`FieldEditor should show conflict field warning 1`] = ` isVisible={false} /> @@ -614,7 +566,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` "mappingConflict": , @@ -690,14 +642,14 @@ exports[`FieldEditor should show conflict field warning 1`] = ` helpText={ } label={ } @@ -731,7 +683,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` error={ } @@ -751,7 +703,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` @@ -768,7 +720,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` > @@ -787,7 +739,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` > @@ -801,7 +753,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` > @@ -821,7 +773,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = `

  testlang , "painlessLink": , @@ -1032,14 +967,14 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` helpText={ } label={ } @@ -1088,7 +1023,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` @@ -1105,7 +1040,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` > @@ -1124,7 +1059,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` > @@ -1138,7 +1073,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` > @@ -1156,7 +1091,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` > @@ -1178,7 +1113,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai

@@ -1191,31 +1126,14 @@ exports[`FieldEditor should show multiple type field warning with a table contai isVisible={false} /> @@ -1267,7 +1186,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai "mappingConflict": , @@ -1350,14 +1269,14 @@ exports[`FieldEditor should show multiple type field warning with a table contai title={ } > @@ -1399,14 +1318,14 @@ exports[`FieldEditor should show multiple type field warning with a table contai helpText={ } label={ } @@ -1440,7 +1359,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai error={ } @@ -1460,7 +1379,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai @@ -1477,7 +1396,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai > @@ -1496,7 +1415,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai > @@ -1510,7 +1429,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai > diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/__snapshots__/field_format_editor.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/__snapshots__/field_format_editor.test.tsx.snap similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/__snapshots__/field_format_editor.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/__snapshots__/field_format_editor.test.tsx.snap diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap similarity index 92% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap index bf1682faf9a9d..f3e529a8a1e1b 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.tsx.snap @@ -16,7 +16,7 @@ exports[`BytesFormatEditor should render normally 1`] = ` >   @@ -30,7 +30,7 @@ exports[`BytesFormatEditor should render normally 1`] = ` label={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx index 40443ec262182..99c3d3d55a8bc 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/bytes/bytes.test.tsx @@ -44,7 +44,6 @@ describe('BytesFormatEditor', () => { it('should render normally', async () => { const component = shallow( , "render": [Function], @@ -18,7 +18,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = ` "field": "text", "name": , "render": [Function], @@ -27,7 +27,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = ` "field": "background", "name": , "render": [Function], @@ -35,7 +35,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = ` Object { "name": , "render": [Function], @@ -89,7 +89,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = ` > @@ -108,7 +108,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = "field": "range", "name": , "render": [Function], @@ -117,7 +117,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = "field": "text", "name": , "render": [Function], @@ -126,7 +126,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = "field": "background", "name": , "render": [Function], @@ -134,7 +134,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = Object { "name": , "render": [Function], @@ -181,7 +181,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] = > @@ -200,7 +200,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`] "field": "regex", "name": , "render": [Function], @@ -209,7 +209,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`] "field": "text", "name": , "render": [Function], @@ -218,7 +218,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`] "field": "background", "name": , "render": [Function], @@ -226,7 +226,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`] Object { "name": , "render": [Function], @@ -273,7 +273,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`] > diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/color/color.test.tsx similarity index 94% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/color/color.test.tsx index 549831e9c3fb2..f13cb0975c8d2 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/color/color.test.tsx @@ -22,7 +22,7 @@ import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; import { FieldFormat } from 'src/plugins/data/public'; import { ColorFormatEditor } from './color'; -import { fieldFormats } from '../../../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../../../data/public'; const fieldType = 'string'; const format = { @@ -42,7 +42,6 @@ describe('ColorFormatEditor', () => { it('should render string type normally (regex field)', async () => { const component = shallowWithI18nProvider( { it('should render other type normally (range field)', async () => { const component = shallowWithI18nProvider( { it('should render multiple colors', async () => { const component = shallowWithI18nProvider( ), @@ -121,7 +121,7 @@ export class ColorFormatEditor extends DefaultFormatEditor ), @@ -145,7 +145,7 @@ export class ColorFormatEditor extends DefaultFormatEditor ), @@ -169,7 +169,7 @@ export class ColorFormatEditor extends DefaultFormatEditor ), @@ -192,7 +192,7 @@ export class ColorFormatEditor extends DefaultFormatEditor ), @@ -211,15 +211,15 @@ export class ColorFormatEditor extends DefaultFormatEditor { @@ -240,7 +240,7 @@ export class ColorFormatEditor extends DefaultFormatEditor diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/color/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/color/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap similarity index 93% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap index 2d73f775e316c..a4d780c59ca74 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/__snapshots__/date.test.tsx.snap @@ -16,7 +16,7 @@ exports[`DateFormatEditor should render normally 1`] = ` >   @@ -30,7 +30,7 @@ exports[`DateFormatEditor should render normally 1`] = ` label={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/date.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/date.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/date.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/date.test.tsx index 746cb7c7fe302..c3114dacd118d 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/date.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/date.test.tsx @@ -44,7 +44,6 @@ describe('DateFormatEditor', () => { it('should render normally', async () => { const component = shallow( {defaultPattern}, @@ -69,7 +69,7 @@ export class DateFormatEditor extends DefaultFormatEditor   diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap similarity index 93% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap index 1456deaa13e47..8c6397ea3adeb 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.tsx.snap @@ -16,7 +16,7 @@ exports[`DateFormatEditor should render normally 1`] = ` >   @@ -30,7 +30,7 @@ exports[`DateFormatEditor should render normally 1`] = ` label={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx similarity index 94% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx index e6b15c741af4e..bc9a8704e7c7d 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/date_nanos.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { FieldFormat } from '../../../../../../../../plugins/data/public'; +import { FieldFormat } from '../../../../../../../../data/public'; import { DateNanosFormatEditor } from './date_nanos'; @@ -46,7 +46,6 @@ describe('DateFormatEditor', () => { it('should render normally', async () => { const component = shallow( {defaultPattern}, @@ -64,7 +64,7 @@ export class DateNanosFormatEditor extends DefaultFormatEditor   diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/date_nanos/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/__snapshots__/default.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/__snapshots__/default.test.tsx.snap similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/__snapshots__/default.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/__snapshots__/default.test.tsx.snap diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/default.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/default.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/default.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/default.test.tsx index 3f30af97dc063..6af441b9ba751 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/default.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/default.test.tsx @@ -69,7 +69,6 @@ describe('DefaultFormatEditor', () => { it('should render nothing', async () => { const component = shallow( { it('should call prop onChange()', async () => { const component = shallow( { shallow( { formatParams: { type?: string } & P; onChange: (newParams: Record) => void; onError: FieldFormatEditorProps['onError']; - basePath: string; } export interface FormatEditorState { @@ -86,6 +85,7 @@ export class DefaultFormatEditor

extends PureComponent< FormatEditorProps

, FormatEditorState & S > { + static formatId = 'default'; state = defaultState as FormatEditorState & S; static getDerivedStateFromProps(nextProps: FormatEditorProps<{}>, state: FormatEditorState) { diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/default/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap similarity index 94% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap index dbebd324b16b6..b606e60949af5 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap @@ -12,7 +12,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] = label={ } @@ -42,7 +42,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] = label={ } @@ -124,7 +124,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1 label={ } @@ -154,7 +154,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1 label={ } @@ -189,7 +189,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1 label={ } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/duration.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/duration.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/duration.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/duration.test.tsx index 3ab69d12d8c0e..b181d6fa4466d 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/duration.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/duration.test.tsx @@ -71,7 +71,6 @@ describe('DurationFormatEditor', () => { it('should render human readable output normally', async () => { const component = shallow( { }; const component = shallow( 20 ) { - error = i18n.translate('common.ui.fieldEditor.durationErrorMessage', { + error = i18n.translate('indexPatternManagement.durationErrorMessage', { defaultMessage: 'Decimal places must be between 0 and 20', }); nextProps.onError(error); @@ -101,7 +101,7 @@ export class DurationFormatEditor extends DefaultFormatEditor< } @@ -125,7 +125,7 @@ export class DurationFormatEditor extends DefaultFormatEditor< } @@ -149,7 +149,7 @@ export class DurationFormatEditor extends DefaultFormatEditor< } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/index.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/index.tsx similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/index.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/duration/index.tsx diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/index.ts new file mode 100644 index 0000000000000..6961cbf8d831c --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/index.ts @@ -0,0 +1,31 @@ +/* + * 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 { DefaultFormatEditor } from './default'; + +export { BytesFormatEditor } from './bytes'; +export { ColorFormatEditor } from './color'; +export { DateFormatEditor } from './date'; +export { DateNanosFormatEditor } from './date_nanos'; +export { DurationFormatEditor } from './duration'; +export { NumberFormatEditor } from './number'; +export { PercentFormatEditor } from './percent'; +export { StaticLookupFormatEditor } from './static_lookup'; +export { StringFormatEditor } from './string'; +export { TruncateFormatEditor } from './truncate'; +export { UrlFormatEditor } from './url'; diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap similarity index 92% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap index cf04dd19428e5..42c2323e56979 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/__snapshots__/number.test.tsx.snap @@ -16,7 +16,7 @@ exports[`NumberFormatEditor should render normally 1`] = ` >   @@ -30,7 +30,7 @@ exports[`NumberFormatEditor should render normally 1`] = ` label={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/number.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/number.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/number.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/number.test.tsx index c07c866359305..fddd1d5a8c7c3 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/number/number.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/number/number.test.tsx @@ -44,7 +44,6 @@ describe('NumberFormatEditor', () => { it('should render normally', async () => { const component = shallow( {defaultPattern} }} /> @@ -56,7 +56,7 @@ export class NumberFormatEditor extends DefaultFormatEditor   diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap similarity index 92% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap index 0784a3f5e407d..ac512402b4d41 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap @@ -16,7 +16,7 @@ exports[`PercentFormatEditor should render normally 1`] = ` >   @@ -30,7 +30,7 @@ exports[`PercentFormatEditor should render normally 1`] = ` label={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/percent.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/percent.test.tsx similarity index 94% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/percent.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/percent.test.tsx index ddeb79538cda1..c23e940dadea7 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/percent.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/percent/percent.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { FieldFormat } from '../../../../../../../../plugins/data/public'; +import { FieldFormat } from '../../../../../../../../data/public'; import { PercentFormatEditor } from './percent'; @@ -44,7 +44,6 @@ describe('PercentFormatEditor', () => { it('should render normally', async () => { const component = shallow( , "render": [Function], @@ -18,7 +18,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn "field": "value", "name": , "render": [Function], @@ -73,7 +73,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn > @@ -89,7 +89,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn label={ } @@ -116,7 +116,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = ` "field": "key", "name": , "render": [Function], @@ -125,7 +125,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = ` "field": "value", "name": , "render": [Function], @@ -174,7 +174,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = ` > @@ -190,7 +190,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = ` label={ } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/static_lookup/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/static_lookup/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx similarity index 93% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx index 2e2b1c3ae2357..a8356923eb381 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.test.tsx @@ -18,9 +18,9 @@ */ import React from 'react'; -import { shallowWithI18nProvider } from '../../../../../../../../test_utils/public/enzyme_helpers'; +import { shallowWithI18nProvider } from '../../../../../../../../../test_utils/public/enzyme_helpers'; import { StaticLookupFormatEditorFormatParams } from './static_lookup'; -import { FieldFormat } from '../../../../../../../../plugins/data/public'; +import { FieldFormat } from '../../../../../../../../data/public'; import { StaticLookupFormatEditor } from './static_lookup'; @@ -43,7 +43,6 @@ describe('StaticLookupFormatEditor', () => { it('should render normally', async () => { const component = shallowWithI18nProvider( { it('should render multiple lookup entries and unknown key value', async () => { const component = shallowWithI18nProvider( + ), render: (value: number, item: StaticLookupItem) => { return ( @@ -106,7 +109,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor< field: 'value', name: ( ), @@ -128,15 +131,15 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor< }, { field: 'actions', - name: i18n.translate('common.ui.fieldEditor.staticLookup.actions', { + name: i18n.translate('indexPatternManagement.staticLookup.actions', { defaultMessage: 'actions', }), actions: [ { - name: i18n.translate('common.ui.fieldEditor.staticLookup.deleteAria', { + name: i18n.translate('indexPatternManagement.staticLookup.deleteAria', { defaultMessage: 'Delete', }), - description: i18n.translate('common.ui.fieldEditor.staticLookup.deleteTitle', { + description: i18n.translate('indexPatternManagement.staticLookup.deleteTitle', { defaultMessage: 'Delete entry', }), onClick: (item: StaticLookupItem) => { @@ -158,7 +161,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor< @@ -166,7 +169,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor< } @@ -174,7 +177,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor< } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.test.tsx index d0fa0935b2664..ccaa12222281f 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.test.tsx @@ -52,7 +52,6 @@ describe('StringFormatEditor', () => { it('should render normally', async () => { const component = shallow( } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap similarity index 96% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap index f646d5b4afca8..2d1ee496d2786 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap @@ -12,7 +12,7 @@ exports[`TruncateFormatEditor should render normally 1`] = ` label={ } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/sample.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/sample.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/sample.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/sample.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx index bb723386ff777..149b78c85e5da 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/truncate/truncate.test.tsx @@ -50,7 +50,6 @@ describe('TruncateFormatEditor', () => { it('should render normally', async () => { const component = shallow( { it('should fire error, when input is invalid', async () => { const component = shallow( { it('should fire change, when input changed and is valid', async () => { const component = shallow( } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap similarity index 90% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap index f0766df176c0d..69b192a81d097 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap @@ -11,14 +11,14 @@ exports[`LabelTemplateFlyout should render normally 1`] = `

@@ -36,7 +36,7 @@ exports[`LabelTemplateFlyout should render normally 1`] = ` —  @@ -47,7 +47,7 @@ exports[`LabelTemplateFlyout should render normally 1`] = ` —  @@ -55,7 +55,7 @@ exports[`LabelTemplateFlyout should render normally 1`] = `

diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap similarity index 89% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap index a3418077ad258..aa69b8da6cf60 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap @@ -19,7 +19,7 @@ exports[`UrlFormatEditor should render label template help 1`] = ` label={ } @@ -58,7 +58,7 @@ exports[`UrlFormatEditor should render label template help 1`] = ` > @@ -67,7 +67,7 @@ exports[`UrlFormatEditor should render label template help 1`] = ` label={ } @@ -91,7 +91,7 @@ exports[`UrlFormatEditor should render label template help 1`] = ` > @@ -100,7 +100,7 @@ exports[`UrlFormatEditor should render label template help 1`] = ` label={ } @@ -138,7 +138,7 @@ exports[`UrlFormatEditor should render normally 1`] = ` label={ } @@ -177,7 +177,7 @@ exports[`UrlFormatEditor should render normally 1`] = ` > @@ -186,7 +186,7 @@ exports[`UrlFormatEditor should render normally 1`] = ` label={ } @@ -210,7 +210,7 @@ exports[`UrlFormatEditor should render normally 1`] = ` > @@ -219,7 +219,7 @@ exports[`UrlFormatEditor should render normally 1`] = ` label={ } @@ -257,7 +257,7 @@ exports[`UrlFormatEditor should render url template help 1`] = ` label={ } @@ -296,7 +296,7 @@ exports[`UrlFormatEditor should render url template help 1`] = ` > @@ -305,7 +305,7 @@ exports[`UrlFormatEditor should render url template help 1`] = ` label={ } @@ -329,7 +329,7 @@ exports[`UrlFormatEditor should render url template help 1`] = ` > @@ -338,7 +338,7 @@ exports[`UrlFormatEditor should render url template help 1`] = ` label={ } @@ -376,7 +376,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` label={ } @@ -416,7 +416,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` > @@ -425,7 +425,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` label={ } @@ -449,7 +449,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` > @@ -458,7 +458,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` label={ } @@ -479,7 +479,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` label={ } @@ -500,7 +500,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = ` label={ } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap similarity index 88% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap index fd697a2a4c70a..14e5012e9a554 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap @@ -11,14 +11,14 @@ exports[`UrlTemplateFlyout should render normally 1`] = `

@@ -27,7 +27,7 @@ exports[`UrlTemplateFlyout should render normally 1`] = ` "strongUrlTemplate": , @@ -43,7 +43,7 @@ exports[`UrlTemplateFlyout should render normally 1`] = ` —  @@ -54,7 +54,7 @@ exports[`UrlTemplateFlyout should render normally 1`] = ` —  @@ -62,7 +62,7 @@ exports[`UrlTemplateFlyout should render normally 1`] = `

diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/label_template_flyout.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.test.tsx similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/label_template_flyout.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.test.tsx diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx similarity index 80% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx index 1ce7bec579e16..d04ee58f26b0a 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx @@ -35,13 +35,13 @@ const items: LabelTemplateExampleItem[] = [ { input: 1234, urlTemplate: 'http://company.net/profiles?user_id={{value}}', - labelTemplate: i18n.translate('common.ui.fieldEditor.labelTemplate.example.idLabel', { + labelTemplate: i18n.translate('indexPatternManagement.labelTemplate.example.idLabel', { defaultMessage: 'User #{value}', values: { value: '{{value}}' }, }), output: '' + - i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.idLabel', { + i18n.translate('indexPatternManagement.labelTemplate.example.output.idLabel', { defaultMessage: 'User', }) + ' #1234', @@ -49,12 +49,12 @@ const items: LabelTemplateExampleItem[] = [ { input: '/assets/main.css', urlTemplate: 'http://site.com{{rawValue}}', - labelTemplate: i18n.translate('common.ui.fieldEditor.labelTemplate.example.pathLabel', { + labelTemplate: i18n.translate('indexPatternManagement.labelTemplate.example.pathLabel', { defaultMessage: 'View Asset', }), output: '' + - i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.pathLabel', { + i18n.translate('indexPatternManagement.labelTemplate.example.output.pathLabel', { defaultMessage: 'View Asset', }) + '', @@ -68,13 +68,13 @@ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =

{} }) =

  • value — 
  • url — 
  • @@ -108,26 +108,26 @@ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) = columns={[ { field: 'input', - name: i18n.translate('common.ui.fieldEditor.labelTemplate.inputHeader', { + name: i18n.translate('indexPatternManagement.labelTemplate.inputHeader', { defaultMessage: 'Input', }), width: '160px', }, { field: 'urlTemplate', - name: i18n.translate('common.ui.fieldEditor.labelTemplate.urlHeader', { + name: i18n.translate('indexPatternManagement.labelTemplate.urlHeader', { defaultMessage: 'URL Template', }), }, { field: 'labelTemplate', - name: i18n.translate('common.ui.fieldEditor.labelTemplate.labelHeader', { + name: i18n.translate('indexPatternManagement.labelTemplate.labelHeader', { defaultMessage: 'Label Template', }), }, { field: 'output', - name: i18n.translate('common.ui.fieldEditor.labelTemplate.outputHeader', { + name: i18n.translate('indexPatternManagement.labelTemplate.outputHeader', { defaultMessage: 'Output', }), render: (value: LabelTemplateExampleItem['output']) => { diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx similarity index 94% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx index 4d09da84edfb6..a1a1655949432 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx @@ -46,10 +46,6 @@ const formatParams = { const onChange = jest.fn(); const onError = jest.fn(); -jest.mock('ui/chrome', () => ({ - getBasePath: () => 'http://localhost/', -})); - describe('UrlFormatEditor', () => { it('should have a formatId', () => { expect(UrlFormatEditor.formatId).toEqual('url'); @@ -58,7 +54,6 @@ describe('UrlFormatEditor', () => { it('should render normally', async () => { const component = shallow( { it('should render url template help', async () => { const component = shallow( { it('should render label template help', async () => { const component = shallow( { it('should render width and height fields if image', async () => { const component = shallow( ) { super(props); - this.iconPattern = `${props.basePath}/bundles/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/{{value}}.png`; + this.iconPattern = `/plugins/indexPatternManagement/assets/icons/{{value}}.png`; + this.state = { ...this.state, sampleInputsByType: { @@ -146,7 +145,7 @@ export class UrlFormatEditor extends DefaultFormatEditor< + } > + } > + } > } @@ -220,9 +219,9 @@ export class UrlFormatEditor extends DefaultFormatEditor< + ) : ( - + ) } checked={!formatParams.openLinkInCurrentTab} @@ -236,14 +235,14 @@ export class UrlFormatEditor extends DefaultFormatEditor< } helpText={ @@ -263,14 +262,14 @@ export class UrlFormatEditor extends DefaultFormatEditor< } helpText={ diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx similarity index 84% rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx index 8194bb731ad14..c1b144b0d9eac 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx @@ -31,13 +31,13 @@ export const UrlTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =>

    {} }) => strongUrlTemplate: ( @@ -58,21 +58,21 @@ export const UrlTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =>

  • value — 
  • rawValue — 
  • @@ -97,20 +97,20 @@ export const UrlTemplateFlyout = ({ isVisible = false, onClose = () => {} }) => columns={[ { field: 'input', - name: i18n.translate('common.ui.fieldEditor.urlTemplate.inputHeader', { + name: i18n.translate('indexPatternManagement.urlTemplate.inputHeader', { defaultMessage: 'Input', }), width: '160px', }, { field: 'template', - name: i18n.translate('common.ui.fieldEditor.urlTemplate.templateHeader', { + name: i18n.translate('indexPatternManagement.urlTemplate.templateHeader', { defaultMessage: 'Template', }), }, { field: 'output', - name: i18n.translate('common.ui.fieldEditor.urlTemplate.outputHeader', { + name: i18n.translate('indexPatternManagement.urlTemplate.outputHeader', { defaultMessage: 'Output', }), }, diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx similarity index 98% rename from src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx index f6e631c8b7ac0..c94d2e2f861dc 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx @@ -37,6 +37,7 @@ const formatEditors = { ip: TestEditor, number: TestEditor, }, + getById: jest.fn(() => TestEditor), }; describe('FieldFormatEditor', () => { diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx similarity index 93% rename from src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx index 2de6dff5d251a..05aeba1ca107b 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx @@ -49,13 +49,13 @@ export class FieldFormatEditor extends PureComponent< constructor(props: FieldFormatEditorProps) { super(props); this.state = { - EditorComponent: props.fieldFormatEditors.byFormatId[props.fieldFormatId], + EditorComponent: props.fieldFormatEditors.getById(props.fieldFormatId), }; } static getDerivedStateFromProps(nextProps: FieldFormatEditorProps) { return { - EditorComponent: nextProps.fieldFormatEditors.byFormatId[nextProps.fieldFormatId] || null, + EditorComponent: nextProps.fieldFormatEditors.getById(nextProps.fieldFormatId) || null, }; } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/index.ts similarity index 96% rename from src/legacy/ui/public/field_editor/components/field_format_editor/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/index.ts index ccfc98b2d5882..83b36274f40e2 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/index.ts +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/index.ts @@ -18,3 +18,4 @@ */ export { FieldFormatEditor } from './field_format_editor'; +export * from './editors'; diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap similarity index 96% rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap index 2883ffb6bc8a1..ce8c9e70433c8 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap @@ -10,7 +10,7 @@ exports[`FormatEditorSamples should render normally 1`] = ` label={ } diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/index.ts diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/_samples.scss b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.scss similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/_samples.scss rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.scss diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.test.tsx similarity index 100% rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.test.tsx diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.tsx similarity index 90% rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.tsx index d63674bf4d205..f2814664c185d 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/samples/samples.tsx @@ -17,6 +17,8 @@ * under the License. */ +import './samples.scss'; + import React, { PureComponent } from 'react'; import { EuiBasicTable, EuiFormRow } from '@elastic/eui'; @@ -41,7 +43,7 @@ export class FormatEditorSamples extends PureComponent const columns = [ { field: 'input', - name: i18n.translate('common.ui.fieldEditor.samples.inputHeader', { + name: i18n.translate('indexPatternManagement.samples.inputHeader', { defaultMessage: 'Input', }), render: (input: {} | string) => { @@ -50,7 +52,7 @@ export class FormatEditorSamples extends PureComponent }, { field: 'output', - name: i18n.translate('common.ui.fieldEditor.samples.outputHeader', { + name: i18n.translate('indexPatternManagement.samples.outputHeader', { defaultMessage: 'Output', }), render: (output: string) => { @@ -72,7 +74,7 @@ export class FormatEditorSamples extends PureComponent return samples.length ? ( + } > diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap similarity index 87% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap index 87e1341b47355..648f68edcbb10 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap @@ -9,7 +9,7 @@ exports[`ScriptingDisabledCallOut should render normally 1`] = ` } @@ -17,7 +17,7 @@ exports[`ScriptingDisabledCallOut should render normally 1`] = `

    diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap similarity index 82% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap index b331c1e38eb34..c9b5c84939bc6 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap @@ -8,7 +8,7 @@ exports[`ScriptingWarningCallOut should render normally 1`] = ` title={ } @@ -16,7 +16,7 @@ exports[`ScriptingWarningCallOut should render normally 1`] = `

      @@ -37,7 +37,7 @@ exports[`ScriptingWarningCallOut should render normally 1`] = ` >   @@ -52,7 +52,7 @@ exports[`ScriptingWarningCallOut should render normally 1`] = `

    diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/disabled_call_out.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/disabled_call_out.test.tsx similarity index 100% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/disabled_call_out.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/disabled_call_out.test.tsx diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/disabled_call_out.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/disabled_call_out.tsx similarity index 93% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/disabled_call_out.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/disabled_call_out.tsx index 9abca813fe434..0bfec7a54a662 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/disabled_call_out.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/disabled_call_out.tsx @@ -29,7 +29,7 @@ export const ScriptingDisabledCallOut = ({ isVisible = false }) => { @@ -39,7 +39,7 @@ export const ScriptingDisabledCallOut = ({ isVisible = false }) => { >

    diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/index.ts diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.test.tsx similarity index 93% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.test.tsx index 8568c2c79816b..d659ac83d7b79 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.test.tsx @@ -22,7 +22,7 @@ import { shallow } from 'enzyme'; import { ScriptingWarningCallOut } from './warning_call_out'; // eslint-disable-next-line -import { docLinksServiceMock } from '../../../../../../core/public/doc_links/doc_links_service.mock'; +import { docLinksServiceMock } from '../../../../../../../core/public/doc_links/doc_links_service.mock'; describe('ScriptingWarningCallOut', () => { const docLinksScriptedFields = docLinksServiceMock.createStartContract().links.scriptedFields; diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.tsx similarity index 88% rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.tsx index 7dac6681fa1ea..fed756f11f08b 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_call_outs/warning_call_out.tsx @@ -38,7 +38,7 @@ export const ScriptingWarningCallOut = ({ } @@ -47,13 +47,13 @@ export const ScriptingWarningCallOut = ({ >

      @@ -63,7 +63,7 @@ export const ScriptingWarningCallOut = ({ scriptsInAggregation: (   @@ -75,7 +75,7 @@ export const ScriptingWarningCallOut = ({

    , "data-test-subj": "testTab", "id": "test", @@ -76,10 +94,28 @@ exports[`ScriptingHelpFlyout should render nothing if not visible 1`] = ` }, Object { "content": , "data-test-subj": "testTab", "id": "test", diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.test.tsx similarity index 77% rename from src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.test.tsx index 4106eb7b283ee..fa2d97be60000 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.test.tsx @@ -21,20 +21,26 @@ import React from 'react'; import { shallow } from 'enzyme'; import { HttpStart } from 'src/core/public'; // eslint-disable-next-line -import { docLinksServiceMock } from '../../../../../../core/public/doc_links/doc_links_service.mock'; +import { docLinksServiceMock } from '../../../../../../../core/public/doc_links/doc_links_service.mock'; import { ScriptingHelpFlyout } from './help_flyout'; -import { IndexPattern } from '../../../../../../plugins/data/public'; +import { IndexPattern } from '../../../../../../data/public'; import { ExecuteScript } from '../../types'; +import { coreMock } from '../../../../../../../core/public/mocks'; +import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks'; + jest.mock('./test_script', () => ({ TestScript: () => { return `

    mockTestScript
    `; }, })); +const { uiSettings } = coreMock.createStart(); +const { ui } = dataPluginMock.createStartContract(); + const indexPatternMock = {} as IndexPattern; describe('ScriptingHelpFlyout', () => { @@ -47,9 +53,10 @@ describe('ScriptingHelpFlyout', () => { lang="painless" executeScript={((() => {}) as unknown) as ExecuteScript} onClose={() => {}} - getHttpStart={() => (({} as unknown) as HttpStart)} - // docLinksScriptedFields={docLinksScriptedFields} + http={({} as unknown) as HttpStart} docLinksScriptedFields={{} as typeof docLinksScriptedFields} + uiSettings={uiSettings} + SearchBar={ui.SearchBar} /> ); @@ -64,8 +71,10 @@ describe('ScriptingHelpFlyout', () => { lang="painless" executeScript={((() => {}) as unknown) as ExecuteScript} onClose={() => {}} - getHttpStart={() => (({} as unknown) as HttpStart)} + http={({} as unknown) as HttpStart} docLinksScriptedFields={{} as typeof docLinksScriptedFields} + uiSettings={uiSettings} + SearchBar={ui.SearchBar} /> ); diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.tsx similarity index 85% rename from src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.tsx index 6f51379c796d4..b74d56e1c2878 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/help_flyout.tsx @@ -18,15 +18,15 @@ */ import React from 'react'; -import { HttpStart, DocLinksStart } from 'src/core/public'; +import { HttpStart, DocLinksStart, IUiSettingsClient } from 'src/core/public'; import { EuiFlyout, EuiFlyoutBody, EuiTabbedContent } from '@elastic/eui'; import { ScriptingSyntax } from './scripting_syntax'; import { TestScript } from './test_script'; -import { IndexPattern } from '../../../../../../plugins/data/public'; import { ExecuteScript } from '../../types'; +import { IndexPattern, DataPublicPluginStart } from '../../../../../../data/public'; interface ScriptingHelpFlyoutProps { indexPattern: IndexPattern; @@ -36,8 +36,10 @@ interface ScriptingHelpFlyoutProps { executeScript: ExecuteScript; isVisible: boolean; onClose: () => void; - getHttpStart: () => HttpStart; + http: HttpStart; docLinksScriptedFields: DocLinksStart['links']['scriptedFields']; + uiSettings: IUiSettingsClient; + SearchBar: DataPublicPluginStart['ui']['SearchBar']; } export const ScriptingHelpFlyout: React.FC = ({ @@ -48,8 +50,10 @@ export const ScriptingHelpFlyout: React.FC = ({ name, script, executeScript, - getHttpStart, + http, docLinksScriptedFields, + uiSettings, + SearchBar, }) => { const tabs = [ { @@ -69,7 +73,9 @@ export const ScriptingHelpFlyout: React.FC = ({ name={name} script={script} executeScript={executeScript} - getHttpStart={getHttpStart} + http={http} + uiSettings={uiSettings} + SearchBar={SearchBar} /> ), }, diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/components/scripting_help/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/index.ts diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/scripting_syntax.tsx similarity index 79% rename from src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/scripting_syntax.tsx index 8158c6881acf9..9a78c3695ea7c 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/scripting_syntax.tsx @@ -33,18 +33,18 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps

    - +

    {' '} @@ -56,21 +56,21 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps

      @@ -80,7 +80,7 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps syntax: (   @@ -92,21 +92,21 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps

      @@ -118,26 +118,26 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps

    • @@ -145,21 +145,21 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps

    • + - * / % }} />
    • | & ^ ~ << >> >>>, @@ -168,28 +168,28 @@ export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps
    • && || ! ?: }} />
    • < <= == >= > }} />
    • abs ceil exp floor ln log10 logn max min sqrt pow }} />
    • haversin }} />
    • min, max }} /> diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/_test_script.scss b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.scss similarity index 100% rename from src/legacy/ui/public/field_editor/components/scripting_help/_test_script.scss rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.scss diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/test_script.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx similarity index 85% rename from src/legacy/ui/public/field_editor/components/scripting_help/test_script.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx index 8d3a83a155553..0e324a67bac36 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/test_script.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx @@ -17,8 +17,11 @@ * under the License. */ +import './test_script.scss'; + import React, { Component, Fragment } from 'react'; -import { HttpStart } from 'src/core/public'; +import { HttpStart, IUiSettingsClient } from 'src/core/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { EuiButton, @@ -34,12 +37,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -const { SearchBar } = npStart.plugins.data.ui; - -const { uiSettings } = npStart.core; - -import { esQuery, IndexPattern, Query } from '../../../../../../plugins/data/public'; +import { esQuery, IndexPattern, Query } from '../../../../../../../plugins/data/public'; import { ExecuteScript } from '../../types'; interface TestScriptProps { @@ -48,7 +46,9 @@ interface TestScriptProps { name?: string; script?: string; executeScript: ExecuteScript; - getHttpStart: () => HttpStart; + http: HttpStart; + uiSettings: IUiSettingsClient; + SearchBar: DataPublicPluginStart['ui']['SearchBar']; } interface AdditionalField { @@ -80,7 +80,7 @@ export class TestScript extends Component { } previewScript = async (searchContext?: { query?: Query | undefined }) => { - const { indexPattern, lang, name, script, executeScript, getHttpStart } = this.props; + const { indexPattern, lang, name, script, executeScript, http } = this.props; if (!script || script.length === 0) { return; @@ -92,7 +92,7 @@ export class TestScript extends Component { let query; if (searchContext) { - const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings); + const esQueryConfigs = esQuery.getEsQueryConfig(this.props.uiSettings); query = esQuery.buildEsQuery( this.props.indexPattern, searchContext.query || [], @@ -108,7 +108,7 @@ export class TestScript extends Component { indexPatternTitle: indexPattern.title, query, additionalFields: this.state.additionalFields.map((option: AdditionalField) => option.value), - getHttpStart, + http, }); if (scriptResponse.status !== 200) { @@ -143,7 +143,7 @@ export class TestScript extends Component { if (previewData.error) { return ( {

      @@ -182,7 +182,7 @@ export class TestScript extends Component { ); } - renderToolbar() { + renderToolbar(SearchBar: DataPublicPluginStart['ui']['SearchBar']) { const fieldsByTypeMap = new Map(); const fields: EuiComboBoxOptionOption[] = []; @@ -219,13 +219,13 @@ export class TestScript extends Component { return ( { showFilterBar={false} showDatePicker={false} showQueryInput={true} - query={{ language: uiSettings.get('search:queryLanguage'), query: '' }} + query={{ language: this.props.uiSettings.get('search:queryLanguage'), query: '' }} onQuerySubmit={this.previewScript} indexPatterns={[this.props.indexPattern]} customSubmitButton={ @@ -252,7 +252,7 @@ export class TestScript extends Component { data-test-subj="runScriptButton" > @@ -264,19 +264,20 @@ export class TestScript extends Component { } render() { + const { SearchBar } = this.props; return (

      {

      - {this.renderToolbar()} + {this.renderToolbar(SearchBar)} {this.renderPreview(this.state.previewData)}
      diff --git a/src/legacy/ui/public/field_editor/constants/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/constants/index.ts similarity index 93% rename from src/legacy/ui/public/field_editor/constants/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/constants/index.ts index 9bf93f39f5315..cc15380d89d4c 100644 --- a/src/legacy/ui/public/field_editor/constants/index.ts +++ b/src/plugins/index_pattern_management/public/components/field_editor/constants/index.ts @@ -17,7 +17,7 @@ * under the License. */ -import { getKbnTypeNames } from '../../../../../plugins/data/public'; +import { getKbnTypeNames } from '../../../../../data/public'; export const FIELD_TYPES_BY_LANG = { painless: ['number', 'string', 'date', 'boolean'], diff --git a/src/legacy/ui/public/field_editor/field_editor.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx similarity index 84% rename from src/legacy/ui/public/field_editor/field_editor.test.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx index ced7aa27e5065..21b0e793bbaf0 100644 --- a/src/legacy/ui/public/field_editor/field_editor.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx @@ -19,7 +19,6 @@ import React from 'react'; -import { npStart } from 'ui/new_platform'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; import { IndexPattern, @@ -27,14 +26,13 @@ import { IIndexPatternFieldList, FieldFormatInstanceType, } from 'src/plugins/data/public'; -import { HttpStart } from '../../../../core/public'; -// eslint-disable-next-line -import { docLinksServiceMock } from '../../../../core/public/doc_links/doc_links_service.mock'; + +import { coreMock } from '../../../../../core/public/mocks'; jest.mock('brace/mode/groovy', () => ({})); -jest.mock('ui/new_platform'); -import { FieldEditor } from './field_editor'; +import { FieldEdiorProps, FieldEditor } from './field_editor'; +import { dataPluginMock } from '../../../../data/public/mocks'; jest.mock('@elastic/eui', () => ({ EuiBasicTable: 'eui-basic-table', @@ -60,7 +58,7 @@ jest.mock('@elastic/eui', () => ({ euiPaletteColorBlind: () => ['red'], })); -jest.mock('ui/scripting_languages', () => ({ +jest.mock('../../scripting_languages', () => ({ getEnabledScriptingLanguages: () => ['painless', 'testlang'], getSupportedScriptingLanguages: () => ['painless'], getDeprecatedScriptingLanguages: () => ['testlang'], @@ -100,27 +98,36 @@ const field = { format: new Format(), }; -const helpers = { - Field: () => {}, - getConfig: () => {}, - getHttpStart: () => (({} as unknown) as HttpStart), - fieldFormatEditors: [], - redirectAway: () => {}, - docLinksScriptedFields: docLinksServiceMock.createStartContract().links.scriptedFields, -}; - describe('FieldEditor', () => { + const dataStartServices = dataPluginMock.createStartContract(); + const coreStartServices = coreMock.createStart(); + let indexPattern: IndexPattern; + const services: FieldEdiorProps['services'] = ({ + Field: () => {}, + getConfig: () => {}, + fieldFormatEditors: [], + redirectAway: () => {}, + docLinksScriptedFields: {}, + fieldFormats: dataStartServices.fieldFormats, + toasts: coreStartServices.notifications.toasts, + http: {}, + uiSettings: {}, + SearchBar: dataStartServices.ui.SearchBar, + indexPatterns: dataStartServices.indexPatterns, + } as unknown) as FieldEdiorProps['services']; + beforeEach(() => { indexPattern = ({ fields: fields as IIndexPatternFieldList, } as unknown) as IndexPattern; - npStart.plugins.data.fieldFormats.getDefaultType = jest.fn( + services.fieldFormats.getDefaultType = jest.fn( () => (({} as unknown) as FieldFormatInstanceType) ); - npStart.plugins.data.fieldFormats.getByFieldType = jest.fn(fieldType => { + + services.fieldFormats.getByFieldType = jest.fn(fieldType => { if (fieldType === 'number') { return [({} as unknown) as FieldFormatInstanceType]; } else { @@ -134,7 +141,7 @@ describe('FieldEditor', () => { ); @@ -161,7 +168,7 @@ describe('FieldEditor', () => { ); @@ -189,7 +196,7 @@ describe('FieldEditor', () => { ); @@ -204,7 +211,7 @@ describe('FieldEditor', () => { ); @@ -227,7 +234,7 @@ describe('FieldEditor', () => { ); diff --git a/src/legacy/ui/public/field_editor/field_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx similarity index 81% rename from src/legacy/ui/public/field_editor/field_editor.tsx rename to src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx index 7de70f5d956e8..635772fbbfe5c 100644 --- a/src/legacy/ui/public/field_editor/field_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx @@ -19,15 +19,7 @@ import React, { PureComponent, Fragment } from 'react'; import { intersection, union, get } from 'lodash'; -import { HttpStart, DocLinksStart } from 'src/core/public'; - -import { - getEnabledScriptingLanguages, - getDeprecatedScriptingLanguages, - getSupportedScriptingLanguages, -} from 'ui/scripting_languages'; - -import { npStart } from 'ui/new_platform'; +import { HttpStart, DocLinksStart, NotificationsStart, IUiSettingsClient } from 'src/core/public'; import { EuiBasicTable, @@ -54,6 +46,11 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { + getEnabledScriptingLanguages, + getDeprecatedScriptingLanguages, + getSupportedScriptingLanguages, +} from '../../scripting_languages'; import { IndexPatternField, FieldFormatInstanceType, @@ -61,17 +58,16 @@ import { IFieldType, KBN_FIELD_TYPES, ES_FIELD_TYPES, -} from '../../../../plugins/data/public'; + DataPublicPluginStart, +} from '../../../../../plugins/data/public'; import { ScriptingDisabledCallOut, ScriptingWarningCallOut, } from './components/scripting_call_outs'; import { ScriptingHelpFlyout } from './components/scripting_help'; - import { FieldFormatEditor } from './components/field_format_editor'; - -import { DefaultFormatEditor } from './components/field_format_editor/editors/default'; +import { IndexPatternManagementStart } from '../../plugin'; import { FIELD_TYPES_BY_LANG, DEFAULT_FIELD_TYPES } from './constants'; import { executeScript, isScriptValid } from './lib'; @@ -79,13 +75,11 @@ import { executeScript, isScriptValid } from './lib'; // This loads Ace editor's "groovy" mode, used below to highlight the script. import 'brace/mode/groovy'; -const getFieldFormats = () => npStart.plugins.data.fieldFormats; - const getFieldTypeFormatsList = ( field: IFieldType, - defaultFieldFormat: FieldFormatInstanceType + defaultFieldFormat: FieldFormatInstanceType, + fieldFormats: DataPublicPluginStart['fieldFormats'] ) => { - const fieldFormats = getFieldFormats(); const formatsByType = fieldFormats .getByFieldType(field.type as KBN_FIELD_TYPES) .map(({ id, title }) => ({ @@ -97,7 +91,7 @@ const getFieldTypeFormatsList = ( { id: '', defaultFieldFormat, - title: i18n.translate('common.ui.fieldEditor.defaultFormatDropDown', { + title: i18n.translate('indexPatternManagement.defaultFormatDropDown', { defaultMessage: '- Default -', }), }, @@ -140,12 +134,16 @@ export interface FieldEditorState { export interface FieldEdiorProps { indexPattern: IndexPattern; field: IndexPatternField; - helpers: { - getConfig: (key: string) => any; - getHttpStart: () => HttpStart; - fieldFormatEditors: DefaultFormatEditor[]; + services: { + http: HttpStart; + fieldFormatEditors: IndexPatternManagementStart['fieldFormatEditors']; redirectAway: () => void; docLinksScriptedFields: DocLinksStart['links']['scriptedFields']; + fieldFormats: DataPublicPluginStart['fieldFormats']; + toasts: NotificationsStart['toasts']; + uiSettings: IUiSettingsClient; + SearchBar: DataPublicPluginStart['ui']['SearchBar']; + indexPatterns: DataPublicPluginStart['indexPatterns']; }; } @@ -180,11 +178,11 @@ export class FieldEditor extends PureComponent { - const { getConfig } = this.props.helpers; + const { uiSettings } = this.props.services; const { field } = this.state; - const fieldFormats = getFieldFormats(); - const DefaultFieldFormat = fieldFormats.getDefaultType(type) as FieldFormatInstanceType; + const DefaultFieldFormat = this.props.services.fieldFormats.getDefaultType( + type + ) as FieldFormatInstanceType; field.type = type; - field.format = new DefaultFieldFormat(null, getConfig); + + field.format = new DefaultFieldFormat(null, key => uiSettings.get(key)); this.setState({ - fieldTypeFormats: getFieldTypeFormatsList(field, DefaultFieldFormat), + fieldTypeFormats: getFieldTypeFormatsList( + field, + DefaultFieldFormat, + this.props.services.fieldFormats + ), fieldFormatId: DefaultFieldFormat.id, fieldFormatParams: field.format.params(), }); @@ -250,13 +254,14 @@ export class FieldEditor extends PureComponent { - const fieldFormats = getFieldFormats(); const { field, fieldTypeFormats } = this.state; + const { uiSettings, fieldFormats } = this.props.services; + const FieldFormat = fieldFormats.getType( formatId || (fieldTypeFormats[0] as InitialFieldTypeFormat).defaultFieldFormat.id ) as FieldFormatInstanceType; - field.format = new FieldFormat(params, this.props.helpers.getConfig); + field.format = new FieldFormat(params, key => uiSettings.get(key)); this.setState({ fieldFormatId: FieldFormat.id, @@ -286,21 +291,21 @@ export class FieldEditor extends PureComponent   @@ -314,7 +319,7 @@ export class FieldEditor extends PureComponent   @@ -397,7 +402,7 @@ export class FieldEditor extends PureComponent } size="s" > @@ -472,19 +477,19 @@ export class FieldEditor extends PureComponent{defaultFormat}, }} /> ) : ( - + ); return ( @@ -493,7 +498,7 @@ export class FieldEditor extends PureComponent @@ -530,7 +535,7 @@ export class FieldEditor extends PureComponent ) : ( ); @@ -575,7 +580,7 @@ export class FieldEditor extends PureComponent @@ -593,7 +598,7 @@ export class FieldEditor extends PureComponent {`doc['some_field'].value`} }} /> @@ -601,7 +606,7 @@ export class FieldEditor extends PureComponent @@ -629,7 +634,7 @@ export class FieldEditor extends PureComponent

      @@ -695,12 +700,12 @@ export class FieldEditor extends PureComponent {isCreating ? ( ) : ( )} @@ -709,7 +714,7 @@ export class FieldEditor extends PureComponent @@ -720,7 +725,7 @@ export class FieldEditor extends PureComponent @@ -745,7 +750,7 @@ export class FieldEditor extends PureComponent ); }; deleteField = () => { - const { redirectAway } = this.props.helpers; + const { redirectAway } = this.props.services; const { indexPattern } = this.props; const { field } = this.state; const remove = indexPattern.removeScriptedField(field); if (remove) { remove.then(() => { - const message = i18n.translate('common.ui.fieldEditor.deleteField.deletedHeader', { + const message = i18n.translate('indexPatternManagement.deleteField.deletedHeader', { defaultMessage: "Deleted '{fieldName}'", values: { fieldName: field.name }, }); - npStart.core.notifications.toasts.addSuccess(message); + this.props.services.toasts.addSuccess(message); redirectAway(); }); } else { @@ -797,7 +804,7 @@ export class FieldEditor extends PureComponent f.name === field.name); if (index > -1) { @@ -824,12 +831,12 @@ export class FieldEditor extends PureComponent { + const message = i18n.translate('indexPatternManagement.deleteField.savedHeader', { defaultMessage: "Saved '{fieldName}'", values: { fieldName: field.name }, }); - npStart.core.notifications.toasts.addSuccess(message); + this.props.services.toasts.addSuccess(message); redirectAway(); }); }; @@ -859,12 +866,12 @@ export class FieldEditor extends PureComponent {isCreating ? ( ) : ( diff --git a/src/legacy/ui/public/field_editor/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/index.ts diff --git a/src/legacy/ui/public/field_editor/lib/index.ts b/src/plugins/index_pattern_management/public/components/field_editor/lib/index.ts similarity index 100% rename from src/legacy/ui/public/field_editor/lib/index.ts rename to src/plugins/index_pattern_management/public/components/field_editor/lib/index.ts diff --git a/src/legacy/ui/public/field_editor/lib/validate_script.ts b/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts similarity index 95% rename from src/legacy/ui/public/field_editor/lib/validate_script.ts rename to src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts index 4db827a4229fd..518cf1086e1d7 100644 --- a/src/legacy/ui/public/field_editor/lib/validate_script.ts +++ b/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts @@ -28,7 +28,7 @@ export const executeScript = async ({ indexPatternTitle, query, additionalFields = [], - getHttpStart, + http, }: ExecuteScriptParams): Promise => { // Using _msearch because _search with index name in path dorks everything up const header = { @@ -62,7 +62,6 @@ export const executeScript = async ({ } const body = `${JSON.stringify(header)}\n${JSON.stringify(search)}\n`; - const http = await getHttpStart(); const esResp = await http.fetch('/elasticsearch/_msearch', { method: 'POST', body }); // unwrap _msearch response return esResp.responses[0]; @@ -73,20 +72,20 @@ export const isScriptValid = async ({ lang, script, indexPatternTitle, - getHttpStart, + http, }: { name: string; lang: string; script: string; indexPatternTitle: string; - getHttpStart: () => HttpStart; + http: HttpStart; }) => { const scriptResponse = await executeScript({ name, lang, script, indexPatternTitle, - getHttpStart, + http, }); if (scriptResponse.status !== 200) { diff --git a/src/legacy/ui/public/field_editor/types.ts b/src/plugins/index_pattern_management/public/components/field_editor/types.ts similarity index 97% rename from src/legacy/ui/public/field_editor/types.ts rename to src/plugins/index_pattern_management/public/components/field_editor/types.ts index 174cb7da73ceb..7519cc05e7fae 100644 --- a/src/legacy/ui/public/field_editor/types.ts +++ b/src/plugins/index_pattern_management/public/components/field_editor/types.ts @@ -33,7 +33,7 @@ export interface ExecuteScriptParams { indexPatternTitle: string; query?: Query['query']; additionalFields?: string[]; - getHttpStart: () => HttpStart; + http: HttpStart; } export interface ExecuteScriptResult { diff --git a/src/plugins/index_pattern_management/public/components/index.ts b/src/plugins/index_pattern_management/public/components/index.ts new file mode 100644 index 0000000000000..e0acb9d05bc84 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/index.ts @@ -0,0 +1,27 @@ +/* + * 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 { IndexPatternTableWithRouter } from './index_pattern_table'; +export { + EditIndexPattern, + EditIndexPatternContainer, + CreateEditField, + CreateEditFieldContainer, +} from './edit_index_pattern'; +export { CreateIndexPatternWizardWithRouter } from './create_index_pattern_wizard'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index.js b/src/plugins/index_pattern_management/public/components/index_pattern_table/index.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index.js rename to src/plugins/index_pattern_management/public/components/index_pattern_table/index.ts index adc1741f57263..29d1c886bab58 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index.js +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index.ts @@ -17,4 +17,4 @@ * under the License. */ -import './index_patterns'; +export { IndexPatternTableWithRouter } from './index_pattern_table'; diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx new file mode 100644 index 0000000000000..599ed1fa04ee2 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -0,0 +1,207 @@ +/* + * 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 { + EuiBadge, + EuiButtonEmpty, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiInMemoryTable, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import React, { useState, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + SavedObjectsClientContract, + IUiSettingsClient, + ChromeDocTitle, +} from '../../../../../core/public'; +import { ManagementAppMountParams } from '../../../../management/public'; +import { CreateButton } from '../create_button'; +import { CreateIndexPatternPrompt } from '../create_index_pattern_prompt'; +import { IndexPatternTableItem, IndexPatternCreationOption } from '../types'; +import { IndexPatternManagementStart } from '../../plugin'; +import { getIndexPatterns } from '../utils'; +import { getListBreadcrumbs } from '../breadcrumbs'; + +const columns = [ + { + field: 'title', + name: 'Pattern', + render: ( + name: string, + index: { + id: string; + tags?: Array<{ + key: string; + name: string; + }>; + } + ) => ( + + {name} + {index.tags && + index.tags.map(({ key: tagKey, name: tagName }) => ( + + {tagName} + + ))} + + ), + dataType: 'string' as const, + sortable: ({ sort }: { sort: string }) => sort, + }, +]; + +const pagination = { + initialPageSize: 10, + pageSizeOptions: [5, 10, 25, 50], +}; + +const sorting = { + sort: { + field: 'title', + direction: 'asc' as const, + }, +}; + +const search = { + box: { + incremental: true, + schema: { + fields: { title: { type: 'string' } }, + }, + }, +}; + +const ariaRegion = i18n.translate('indexPatternManagement.editIndexPatternLiveRegionAriaLabel', { + defaultMessage: 'Index patterns', +}); + +const title = i18n.translate('indexPatternManagement.indexPatternTable.title', { + defaultMessage: 'Index patterns', +}); + +interface Props extends RouteComponentProps { + getIndexPatternCreationOptions: IndexPatternManagementStart['creation']['getIndexPatternCreationOptions']; + canSave: boolean; + services: { + savedObjectsClient: SavedObjectsClientContract; + uiSettings: IUiSettingsClient; + setBreadcrumbs: ManagementAppMountParams['setBreadcrumbs']; + indexPatternManagement: IndexPatternManagementStart; + docTitle: ChromeDocTitle; + }; +} + +export const IndexPatternTable = ({ + getIndexPatternCreationOptions, + canSave, + history, + services, +}: Props) => { + const [showFlyout, setShowFlyout] = useState(false); + const [indexPatterns, setIndexPatterns] = useState([]); + const [creationOptions, setCreationOptions] = useState([]); + + services.setBreadcrumbs(getListBreadcrumbs()); + + useEffect(() => { + (async function() { + const options = await getIndexPatternCreationOptions(history.push); + const gettedIndexPatterns: IndexPatternTableItem[] = await getIndexPatterns( + services.savedObjectsClient, + services.uiSettings.get('defaultIndex'), + services.indexPatternManagement + ); + setCreationOptions(options); + setIndexPatterns(gettedIndexPatterns); + setShowFlyout(gettedIndexPatterns.length === 0); + })(); + }, [ + getIndexPatternCreationOptions, + history.push, + indexPatterns.length, + services.indexPatternManagement, + services.savedObjectsClient, + services.uiSettings, + ]); + + services.docTitle.change(title); + + const createButton = canSave ? ( + + + + ) : ( + <> + ); + + return ( + + {showFlyout && setShowFlyout(false)} />} + + + + + +

      {title}

      +
      + + + setShowFlyout(true)} + aria-label="Help" + /> + + + + {createButton} + + + + + ); +}; + +export const IndexPatternTableWithRouter = withRouter(IndexPatternTable); diff --git a/src/plugins/index_pattern_management/public/components/types.ts b/src/plugins/index_pattern_management/public/components/types.ts new file mode 100644 index 0000000000000..2a820dd5f2c7a --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/types.ts @@ -0,0 +1,32 @@ +/* + * 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 interface IndexPatternCreationOption { + text: string; + description?: string; + onClick: () => void; +} + +export interface IndexPatternTableItem { + id: string; + title: string; + default: boolean; + tag?: string[]; + sort: string; +} diff --git a/src/plugins/index_pattern_management/public/components/utils.test.ts b/src/plugins/index_pattern_management/public/components/utils.test.ts new file mode 100644 index 0000000000000..2d6224c9fc36b --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/utils.test.ts @@ -0,0 +1,51 @@ +/* + * 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 { getIndexPatterns } from './utils'; +import { coreMock } from '../../../../core/public/mocks'; +import { mockManagementPlugin } from '../mocks'; + +const { savedObjects } = coreMock.createStart(); +const mockManagementPluginStart = mockManagementPlugin.createStartContract(); + +(savedObjects.client.find as jest.Mock).mockResolvedValue({ + savedObjects: [ + { + id: 'test', + get: () => { + return 'test name'; + }, + }, + { + id: 'test1', + get: () => { + return 'test name 1'; + }, + }, + ], +}); + +test('getting index patterns', async () => { + const indexPatterns = await getIndexPatterns( + savedObjects.client, + 'test', + mockManagementPluginStart + ); + expect(indexPatterns).toMatchSnapshot(); +}); diff --git a/src/plugins/index_pattern_management/public/components/utils.ts b/src/plugins/index_pattern_management/public/components/utils.ts new file mode 100644 index 0000000000000..11da73aafb7b1 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/utils.ts @@ -0,0 +1,69 @@ +/* + * 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 { IIndexPattern } from 'src/plugins/data/public'; +import { SavedObjectsClientContract } from 'src/core/public'; +import { IndexPatternManagementStart } from '../plugin'; + +export async function getIndexPatterns( + savedObjectsClient: SavedObjectsClientContract, + defaultIndex: string, + indexPatternManagementStart: IndexPatternManagementStart +) { + return ( + savedObjectsClient + .find({ + type: 'index-pattern', + fields: ['title', 'type'], + perPage: 10000, + }) + .then(response => + response.savedObjects + .map(pattern => { + const id = pattern.id; + const title = pattern.get('title'); + const isDefault = defaultIndex === id; + + const tags = (indexPatternManagementStart as IndexPatternManagementStart).list.getIndexPatternTags( + pattern, + isDefault + ); + + return { + id, + title, + default: isDefault, + tags, + // the prepending of 0 at the default pattern takes care of prioritization + // so the sorting will but the default index on top + // or on bottom of a the table + sort: `${isDefault ? '0' : '1'}${title}`, + }; + }) + .sort((a, b) => { + if (a.sort < b.sort) { + return -1; + } else if (a.sort > b.sort) { + return 1; + } else { + return 0; + } + }) + ) || [] + ); +} diff --git a/src/plugins/index_pattern_management/public/index.ts b/src/plugins/index_pattern_management/public/index.ts index da482c0c51f0a..2d6db13757eea 100644 --- a/src/plugins/index_pattern_management/public/index.ts +++ b/src/plugins/index_pattern_management/public/index.ts @@ -36,4 +36,8 @@ export function plugin(initializerContext: PluginInitializerContext) { return new IndexPatternManagementPlugin(initializerContext); } -export { IndexPatternCreationConfig, IndexPatternListConfig } from './service'; +export { + IndexPatternCreationConfig, + IndexPatternCreationOption, + IndexPatternListConfig, +} from './service'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index.js b/src/plugins/index_pattern_management/public/management_app/index.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index.js rename to src/plugins/index_pattern_management/public/management_app/index.tsx index cd258eb033915..9883d28dcede9 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index.js +++ b/src/plugins/index_pattern_management/public/management_app/index.tsx @@ -17,4 +17,4 @@ * under the License. */ -export { IndexPatternTable } from './index_pattern_table'; +export { mountManagementSection } from './mount_management_section'; diff --git a/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx new file mode 100644 index 0000000000000..b6b58d8f006c8 --- /dev/null +++ b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx @@ -0,0 +1,143 @@ +/* + * 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 React from 'react'; +import ReactDOM from 'react-dom'; +import { HashRouter, Switch, Route } from 'react-router-dom'; + +import { i18n } from '@kbn/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; +import { StartServicesAccessor } from 'src/core/public'; + +import { ManagementAppMountParams } from '../../../management/public'; +import { + IndexPatternTableWithRouter, + EditIndexPatternContainer, + CreateEditFieldContainer, + CreateIndexPatternWizardWithRouter, +} from '../components'; +import { IndexPatternManagementStartDependencies, IndexPatternManagementStart } from '../plugin'; + +const readOnlyBadge = { + text: i18n.translate('indexPatternManagement.indexPatterns.badge.readOnly.text', { + defaultMessage: 'Read only', + }), + tooltip: i18n.translate('indexPatternManagement.indexPatterns.badge.readOnly.tooltip', { + defaultMessage: 'Unable to save index patterns', + }), + iconType: 'glasses', +}; + +export async function mountManagementSection( + getStartServices: StartServicesAccessor, + params: ManagementAppMountParams +) { + const [ + { chrome, application, savedObjects, uiSettings, notifications, overlays, http, docLinks }, + { data }, + indexPatternManagementStart, + ] = await getStartServices(); + const canSave = Boolean(application.capabilities.indexPatterns.save); + + if (!canSave) { + chrome.setBadge(readOnlyBadge); + } + + ReactDOM.render( + + + + + + + + + + + + + + + + + + , + params.element + ); + + return () => { + ReactDOM.unmountComponentAtNode(params.element); + }; +} diff --git a/src/plugins/index_pattern_management/public/mocks.ts b/src/plugins/index_pattern_management/public/mocks.ts index bc97f46c302e3..6a2a63d776c67 100644 --- a/src/plugins/index_pattern_management/public/mocks.ts +++ b/src/plugins/index_pattern_management/public/mocks.ts @@ -19,6 +19,9 @@ import { PluginInitializerContext } from 'src/core/public'; import { coreMock } from '../../../core/public/mocks'; +import { managementPluginMock } from '../../management/public/mocks'; +import { kibanaLegacyPluginMock } from '../../kibana_legacy/public/mocks'; +import { dataPluginMock } from '../../data/public/mocks'; import { IndexPatternManagementSetup, IndexPatternManagementStart, @@ -32,6 +35,10 @@ const createSetupContract = (): IndexPatternManagementSetup => ({ list: { addListConfig: jest.fn(), } as any, + fieldFormatEditors: { + getAll: jest.fn(), + getById: jest.fn(), + } as any, }); const createStartContract = (): IndexPatternManagementStart => ({ @@ -44,13 +51,23 @@ const createStartContract = (): IndexPatternManagementStart => ({ getFieldInfo: jest.fn(), areScriptedFieldsEnabled: jest.fn(), } as any, + fieldFormatEditors: { + getAll: jest.fn(), + getById: jest.fn(), + } as any, }); const createInstance = async () => { const plugin = new IndexPatternManagementPlugin({} as PluginInitializerContext); - const setup = plugin.setup(coreMock.createSetup()); - const doStart = () => plugin.start(coreMock.createStart(), {}); + const setup = plugin.setup(coreMock.createSetup(), { + management: managementPluginMock.createSetupContract(), + kibanaLegacy: kibanaLegacyPluginMock.createSetupContract(), + }); + const doStart = () => + plugin.start(coreMock.createStart(), { + data: dataPluginMock.createStartContract(), + }); return { plugin, diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index 93bb0ead1df4a..aa28422956a38 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -16,23 +16,38 @@ * specific language governing permissions and limitations * under the License. */ + +import { i18n } from '@kbn/i18n'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { KibanaLegacySetup } from '../../kibana_legacy/public'; import { IndexPatternManagementService, IndexPatternManagementServiceSetup, IndexPatternManagementServiceStart, } from './service'; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface IndexPatternManagementSetupDependencies {} +import { ManagementSetup, ManagementApp, ManagementSectionId } from '../../management/public'; + +export interface IndexPatternManagementSetupDependencies { + management: ManagementSetup; + kibanaLegacy: KibanaLegacySetup; +} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface IndexPatternManagementStartDependencies {} +export interface IndexPatternManagementStartDependencies { + data: DataPublicPluginStart; +} export type IndexPatternManagementSetup = IndexPatternManagementServiceSetup; export type IndexPatternManagementStart = IndexPatternManagementServiceStart; +const sectionsHeader = i18n.translate('indexPatternManagement.indexPattern.sectionsHeader', { + defaultMessage: 'Index Patterns', +}); + +const IPM_APP_ID = 'indexPatterns'; + export class IndexPatternManagementPlugin implements Plugin< @@ -41,19 +56,53 @@ export class IndexPatternManagementPlugin IndexPatternManagementSetupDependencies, IndexPatternManagementStartDependencies > { - private readonly indexPattern = new IndexPatternManagementService(); + private readonly indexPatternManagementService = new IndexPatternManagementService(); + private managementApp?: ManagementApp; constructor(initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup) { - return this.indexPattern.setup({ httpClient: core.http }); + public setup( + core: CoreSetup, + { management, kibanaLegacy }: IndexPatternManagementSetupDependencies + ) { + const kibanaSection = management.sections.getSection(ManagementSectionId.Kibana); + + if (!kibanaSection) { + throw new Error('`kibana` management section not found.'); + } + + const newAppPath = `kibana#/management/kibana/${IPM_APP_ID}`; + const legacyPatternsPath = 'management/kibana/index_patterns'; + + kibanaLegacy.forwardApp('management/kibana/index_pattern', newAppPath, path => '/create'); + kibanaLegacy.forwardApp(legacyPatternsPath, newAppPath, path => { + const pathInApp = path.substr(legacyPatternsPath.length + 1); + return pathInApp && `/patterns${pathInApp}`; + }); + + this.managementApp = kibanaSection.registerApp({ + id: IPM_APP_ID, + title: sectionsHeader, + order: 0, + mount: async params => { + const { mountManagementSection } = await import('./management_app'); + + return mountManagementSection(core.getStartServices, params); + }, + }); + + return this.indexPatternManagementService.setup({ httpClient: core.http }); } public start(core: CoreStart, plugins: IndexPatternManagementStartDependencies) { - return this.indexPattern.start(); + if (!core.application.capabilities.management.kibana.index_patterns) { + this.managementApp!.disable(); + } + + return this.indexPatternManagementService.start(); } public stop() { - this.indexPattern.stop(); + this.indexPatternManagementService.stop(); } } diff --git a/src/legacy/ui/public/scripting_languages/index.ts b/src/plugins/index_pattern_management/public/scripting_languages/index.ts similarity index 80% rename from src/legacy/ui/public/scripting_languages/index.ts rename to src/plugins/index_pattern_management/public/scripting_languages/index.ts index 459e72c0c67c1..b4883a8276e41 100644 --- a/src/legacy/ui/public/scripting_languages/index.ts +++ b/src/plugins/index_pattern_management/public/scripting_languages/index.ts @@ -18,8 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { HttpStart } from 'src/core/public'; -import { toastNotifications } from '../notify'; +import { HttpStart, NotificationsStart } from 'src/core/public'; export function getSupportedScriptingLanguages(): string[] { return ['painless']; @@ -29,12 +28,16 @@ export function getDeprecatedScriptingLanguages(): string[] { return []; } -export const getEnabledScriptingLanguages = (http: HttpStart) => +export const getEnabledScriptingLanguages = ( + http: HttpStart, + toasts: NotificationsStart['toasts'] +) => http.get('/api/kibana/scripts/languages').catch(() => { - toastNotifications.addDanger( - i18n.translate('common.ui.scriptingLanguages.errorFetchingToastDescription', { + toasts.addDanger( + i18n.translate('indexPatternManagement.scriptingLanguages.errorFetchingToastDescription', { defaultMessage: 'Error getting available scripting languages from Elasticsearch', }) ); + return []; }); diff --git a/src/plugins/index_pattern_management/public/service/creation/config.ts b/src/plugins/index_pattern_management/public/service/creation/config.ts index 29ab0ebfc3d5f..95a91fd7594ca 100644 --- a/src/plugins/index_pattern_management/public/service/creation/config.ts +++ b/src/plugins/index_pattern_management/public/service/creation/config.ts @@ -18,7 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { MatchedIndex } from '../../../../../legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/types'; +import { MatchedIndex } from '../../components/create_index_pattern_wizard/types'; const indexPatternTypeName = i18n.translate( 'indexPatternManagement.editIndexPattern.createIndex.defaultTypeName', @@ -74,15 +74,13 @@ export class IndexPatternCreationConfig { this.isBeta = isBeta; } - public async getIndexPatternCreationOption( - urlHandler: UrlHandler - ): Promise { + public getIndexPatternCreationOption(urlHandler: UrlHandler): IndexPatternCreationOption { return { text: indexPatternButtonText, description: indexPatternButtonDescription, testSubj: `createStandardIndexPatternButton`, onClick: () => { - urlHandler('/management/kibana/index_pattern'); + urlHandler('/create'); }, }; } diff --git a/src/plugins/index_pattern_management/public/service/creation/index.ts b/src/plugins/index_pattern_management/public/service/creation/index.ts index 84c4c28aa2260..1df97a74c496d 100644 --- a/src/plugins/index_pattern_management/public/service/creation/index.ts +++ b/src/plugins/index_pattern_management/public/service/creation/index.ts @@ -17,5 +17,5 @@ * under the License. */ -export { IndexPatternCreationConfig } from './config'; +export { IndexPatternCreationConfig, IndexPatternCreationOption } from './config'; export { IndexPatternCreationManager } from './manager'; diff --git a/src/plugins/index_pattern_management/public/service/creation/manager.ts b/src/plugins/index_pattern_management/public/service/creation/manager.ts index 32b3e7ee7a133..c97d7a084dca3 100644 --- a/src/plugins/index_pattern_management/public/service/creation/manager.ts +++ b/src/plugins/index_pattern_management/public/service/creation/manager.ts @@ -21,52 +21,56 @@ import { HttpSetup } from '../../../../../core/public'; import { IndexPatternCreationConfig, UrlHandler, IndexPatternCreationOption } from './config'; export class IndexPatternCreationManager { - private configs: IndexPatternCreationConfig[]; + private configs: IndexPatternCreationConfig[] = []; - constructor() { - this.configs = []; - } + setup(httpClient: HttpSetup) { + return { + addCreationConfig: (Config: typeof IndexPatternCreationConfig) => { + const config = new Config({ httpClient }); - public addCreationConfig = (httpClient: HttpSetup) => ( - Config: typeof IndexPatternCreationConfig - ) => { - const config = new Config({ httpClient }); - if (this.configs.findIndex(c => c.key === config.key) !== -1) { - throw new Error(`${config.key} exists in IndexPatternCreationManager.`); - } - this.configs.push(config); - }; + if (this.configs.findIndex(c => c.key === config.key) !== -1) { + throw new Error(`${config.key} exists in IndexPatternCreationManager.`); + } - public getType(key: string | undefined): IndexPatternCreationConfig | null { - if (key) { - const index = this.configs.findIndex(config => config.key === key); - return this.configs[index] || null; - } else { - return this.getType('default'); - } + this.configs.push(config); + }, + }; } - public async getIndexPatternCreationOptions(urlHandler: UrlHandler) { - const options: IndexPatternCreationOption[] = []; - await Promise.all( - this.configs.map(async config => { - const option = config.getIndexPatternCreationOption - ? await config.getIndexPatternCreationOption(urlHandler) - : null; - if (option) { - options.push(option); + start() { + const getType = (key: string | undefined): IndexPatternCreationConfig => { + if (key) { + const index = this.configs.findIndex(config => config.key === key); + const config = this.configs[index]; + + if (config) { + return config; + } else { + throw new Error(`Index pattern creation type not found: ${key}`); } - }) - ); - return options; - } + } else { + return getType('default'); + } + }; + + return { + getType, + getIndexPatternCreationOptions: async (urlHandler: UrlHandler) => { + const options: IndexPatternCreationOption[] = []; - setup = (httpClient: HttpSetup) => ({ - addCreationConfig: this.addCreationConfig(httpClient).bind(this), - }); + await Promise.all( + this.configs.map(async config => { + const option = config.getIndexPatternCreationOption + ? await config.getIndexPatternCreationOption(urlHandler) + : null; + if (option) { + options.push(option); + } + }) + ); - start = () => ({ - getType: this.getType.bind(this), - getIndexPatternCreationOptions: this.getIndexPatternCreationOptions.bind(this), - }); + return options; + }, + }; + } } diff --git a/src/plugins/index_pattern_management/public/service/field_format_editors/field_format_editors.ts b/src/plugins/index_pattern_management/public/service/field_format_editors/field_format_editors.ts new file mode 100644 index 0000000000000..f85238c5d9622 --- /dev/null +++ b/src/plugins/index_pattern_management/public/service/field_format_editors/field_format_editors.ts @@ -0,0 +1,43 @@ +/* + * 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 { DefaultFormatEditor } from '../../components/field_editor/components/field_format_editor'; + +export class FieldFormatEditors { + private editors: Array = []; + + public setup(defaultFieldEditors: FieldFormatEditors['editors'] = []) { + this.editors = defaultFieldEditors; + + return { + register: (editor: typeof DefaultFormatEditor) => { + this.editors.push(editor); + }, + }; + } + + public start() { + return { + getAll: () => [...this.editors], + getById: (id: string) => { + return this.editors.find(editor => editor.formatId === id); + }, + }; + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts b/src/plugins/index_pattern_management/public/service/field_format_editors/index.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts rename to src/plugins/index_pattern_management/public/service/field_format_editors/index.ts index 473a8f5b57c82..799586654073c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts +++ b/src/plugins/index_pattern_management/public/service/field_format_editors/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { CreateEditField } from './create_edit_field'; +export { FieldFormatEditors } from './field_format_editors'; diff --git a/src/plugins/index_pattern_management/public/service/index.ts b/src/plugins/index_pattern_management/public/service/index.ts index 2abe13eb0e292..2c590f85fe8ea 100644 --- a/src/plugins/index_pattern_management/public/service/index.ts +++ b/src/plugins/index_pattern_management/public/service/index.ts @@ -18,5 +18,5 @@ */ export * from './index_pattern_management_service'; -export { IndexPatternCreationConfig } from './creation'; +export { IndexPatternCreationConfig, IndexPatternCreationOption } from './creation'; export { IndexPatternListConfig } from './list'; diff --git a/src/plugins/index_pattern_management/public/service/index_pattern_management_service.ts b/src/plugins/index_pattern_management/public/service/index_pattern_management_service.ts index 4780fa00ed468..d4cc9c95e76a7 100644 --- a/src/plugins/index_pattern_management/public/service/index_pattern_management_service.ts +++ b/src/plugins/index_pattern_management/public/service/index_pattern_management_service.ts @@ -20,6 +20,21 @@ import { HttpSetup } from '../../../../core/public'; import { IndexPatternCreationManager, IndexPatternCreationConfig } from './creation'; import { IndexPatternListManager, IndexPatternListConfig } from './list'; +import { FieldFormatEditors } from './field_format_editors'; + +import { + BytesFormatEditor, + ColorFormatEditor, + DateFormatEditor, + DateNanosFormatEditor, + DurationFormatEditor, + NumberFormatEditor, + PercentFormatEditor, + StaticLookupFormatEditor, + StringFormatEditor, + TruncateFormatEditor, + UrlFormatEditor, +} from '../components/field_editor/components/field_format_editor'; interface SetupDependencies { httpClient: HttpSetup; @@ -33,20 +48,41 @@ interface SetupDependencies { export class IndexPatternManagementService { indexPatternCreationManager: IndexPatternCreationManager; indexPatternListConfig: IndexPatternListManager; + fieldFormatEditors: FieldFormatEditors; constructor() { this.indexPatternCreationManager = new IndexPatternCreationManager(); this.indexPatternListConfig = new IndexPatternListManager(); + this.fieldFormatEditors = new FieldFormatEditors(); } public setup({ httpClient }: SetupDependencies) { const creationManagerSetup = this.indexPatternCreationManager.setup(httpClient); creationManagerSetup.addCreationConfig(IndexPatternCreationConfig); - this.indexPatternListConfig.setup().addListConfig(IndexPatternListConfig); + + const indexPatternListConfigSetup = this.indexPatternListConfig.setup(); + indexPatternListConfigSetup.addListConfig(IndexPatternListConfig); + + const defaultFieldFormatEditors = [ + BytesFormatEditor, + ColorFormatEditor, + DateFormatEditor, + DateNanosFormatEditor, + DurationFormatEditor, + NumberFormatEditor, + PercentFormatEditor, + StaticLookupFormatEditor, + StringFormatEditor, + TruncateFormatEditor, + UrlFormatEditor, + ]; + + const fieldFormatEditorsSetup = this.fieldFormatEditors.setup(defaultFieldFormatEditors); return { creation: creationManagerSetup, - list: this.indexPatternListConfig.setup(), + list: indexPatternListConfigSetup, + fieldFormatEditors: fieldFormatEditorsSetup, }; } @@ -54,6 +90,7 @@ export class IndexPatternManagementService { return { creation: this.indexPatternCreationManager.start(), list: this.indexPatternListConfig.start(), + fieldFormatEditors: this.fieldFormatEditors.start(), }; } diff --git a/src/plugins/index_pattern_management/public/service/list/config.ts b/src/plugins/index_pattern_management/public/service/list/config.ts index 87c246e8913e5..d90c548ac350a 100644 --- a/src/plugins/index_pattern_management/public/service/list/config.ts +++ b/src/plugins/index_pattern_management/public/service/list/config.ts @@ -19,26 +19,32 @@ import { i18n } from '@kbn/i18n'; import { IIndexPattern, IFieldType } from 'src/plugins/data/public'; +import { SimpleSavedObject } from 'src/core/public'; export interface IndexPatternTag { key: string; name: string; } +const defaultIndexPatternListName = i18n.translate( + 'indexPatternManagement.editIndexPattern.list.defaultIndexPatternListName', + { + defaultMessage: 'Default', + } +); + export class IndexPatternListConfig { public readonly key = 'default'; - public getIndexPatternTags(indexPattern: IIndexPattern, isDefault: boolean): IndexPatternTag[] { + public getIndexPatternTags( + indexPattern: IIndexPattern | SimpleSavedObject, + isDefault: boolean + ): IndexPatternTag[] { return isDefault ? [ { key: 'default', - name: i18n.translate( - 'indexPatternManagement.editIndexPattern.list.defaultIndexPatternListName', - { - defaultMessage: 'Default', - } - ), + name: defaultIndexPatternListName, }, ] : []; diff --git a/src/plugins/index_pattern_management/public/service/list/manager.ts b/src/plugins/index_pattern_management/public/service/list/manager.ts index 3a2910a222cd7..6e8b430ffdc26 100644 --- a/src/plugins/index_pattern_management/public/service/list/manager.ts +++ b/src/plugins/index_pattern_management/public/service/list/manager.ts @@ -18,50 +18,50 @@ */ import { IIndexPattern, IFieldType } from 'src/plugins/data/public'; +import { SimpleSavedObject } from 'src/core/public'; import { IndexPatternListConfig, IndexPatternTag } from './config'; export class IndexPatternListManager { - private configs: IndexPatternListConfig[]; + private configs: IndexPatternListConfig[] = []; - constructor() { - this.configs = []; - } + setup() { + return { + addListConfig: (Config: typeof IndexPatternListConfig) => { + const config = new Config(); - private addListConfig(Config: typeof IndexPatternListConfig) { - const config = new Config(); - if (this.configs.findIndex(c => c.key === config.key) !== -1) { - throw new Error(`${config.key} exists in IndexPatternListManager.`); - } - this.configs.push(config); + if (this.configs.findIndex(c => c.key === config.key) !== -1) { + throw new Error(`${config.key} exists in IndexPatternListManager.`); + } + this.configs.push(config); + }, + }; } - private getIndexPatternTags(indexPattern: IIndexPattern, isDefault: boolean) { - return this.configs.reduce((tags: IndexPatternTag[], config) => { - return config.getIndexPatternTags - ? tags.concat(config.getIndexPatternTags(indexPattern, isDefault)) - : tags; - }, []); - } + start() { + return { + getIndexPatternTags: ( + indexPattern: IIndexPattern | SimpleSavedObject, + isDefault: boolean + ) => + this.configs.reduce( + (tags: IndexPatternTag[], config) => + config.getIndexPatternTags + ? tags.concat(config.getIndexPatternTags(indexPattern, isDefault)) + : tags, + [] + ), - private getFieldInfo(indexPattern: IIndexPattern, field: IFieldType): string[] { - return this.configs.reduce((info: string[], config) => { - return config.getFieldInfo ? info.concat(config.getFieldInfo(indexPattern, field)) : info; - }, []); - } + getFieldInfo: (indexPattern: IIndexPattern, field: IFieldType): string[] => + this.configs.reduce( + (info: string[], config) => + config.getFieldInfo ? info.concat(config.getFieldInfo(indexPattern, field)) : info, + [] + ), - private areScriptedFieldsEnabled(indexPattern: IIndexPattern): boolean { - return this.configs.every(config => { - return config.areScriptedFieldsEnabled ? config.areScriptedFieldsEnabled(indexPattern) : true; - }); + areScriptedFieldsEnabled: (indexPattern: IIndexPattern): boolean => + this.configs.every(config => + config.areScriptedFieldsEnabled ? config.areScriptedFieldsEnabled(indexPattern) : true + ), + }; } - - setup = () => ({ - addListConfig: this.addListConfig.bind(this), - }); - - start = () => ({ - getIndexPatternTags: this.getIndexPatternTags.bind(this), - getFieldInfo: this.getFieldInfo.bind(this), - areScriptedFieldsEnabled: this.areScriptedFieldsEnabled.bind(this), - }); } diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts index 513c70e60048a..8db1d60f09d72 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts @@ -35,7 +35,7 @@ import { ScopedHistory } from '../../../../../core/public'; describe('kbn_url_storage', () => { describe('getStateFromUrl & setStateToUrl', () => { - const url = 'http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id'; + const url = 'http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id'; const state1 = { testStr: '123', testNumber: 0, @@ -50,14 +50,14 @@ describe('kbn_url_storage', () => { it('should set expanded state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: false }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` + `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: false }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_s=(test:'123')"` + `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=(test:'123')"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -66,14 +66,14 @@ describe('kbn_url_storage', () => { it('should set hashed state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: true }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_s=h@a897fac"` + `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=h@a897fac"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: true }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_s=h@40f94d5"` + `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=h@40f94d5"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -244,66 +244,66 @@ describe('kbn_url_storage', () => { it('should extract path relative to browser history without basename', () => { const history = createBrowserHistory(); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to browser history with basename', () => { const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const history1 = createBrowserHistory({ basename: '/oxf/app/' }); const relativePath1 = getRelativeToHistoryPath(url, history1); expect(relativePath1).toEqual( - "/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); const history2 = createBrowserHistory({ basename: '/oxf/app/kibana/' }); const relativePath2 = getRelativeToHistoryPath(url, history2); expect(relativePath2).toEqual( - "#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to browser history with basename from relative url', () => { const history = createBrowserHistory({ basename: '/oxf/app/' }); const url = - "/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to hash history without basename', () => { const history = createHashHistory(); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to hash history with basename', () => { const history = createHashHistory({ basename: 'management' }); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to hash history with basename from relative url', () => { const history = createHashHistory({ basename: 'management' }); const url = - "/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); }); diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts index 337d122e2854b..6d2570b932204 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts @@ -31,7 +31,7 @@ import { url as urlUtils } from '../../../common'; * e.g.: * * given an url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * will return object: * {_a: {tab: 'indexedFields'}, _b: {f: 'test', i: '', l: ''}}; */ @@ -57,7 +57,7 @@ export function getStatesFromKbnUrl( * e.g.: * * given an url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * and key '_a' * will return object: * {tab: 'indexedFields'} @@ -74,12 +74,12 @@ export function getStateFromKbnUrl( * Doesn't actually updates history * * e.g.: - * given a url: http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * given a url: http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * key: '_a' * and state: {tab: 'other'} * * will return url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/index_patterns/id?_a=(tab:other)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:other)&_b=(f:test,i:'',l:'') */ export function setStateToKbnUrl( key: string, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 79c9db8250d4c..78af61c20c828 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -391,10 +391,10 @@ exports[`SavedObjectsTable should render normally 1`] = ` Object { "id": "1", "meta": Object { - "editUrl": "#/management/kibana/index_patterns/1", + "editUrl": "#/management/kibana/indexPatterns/patterns/1", "icon": "indexPatternApp", "inAppUrl": Object { - "path": "/management/kibana/index_patterns/1", + "path": "/management/kibana/indexPatterns/patterns/1", "uiCapabilitiesPath": "management.kibana.index_patterns", }, "title": "MyIndexPattern*", diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap index e9ff1e12dd109..cb2a2dd0e4d1e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap @@ -452,10 +452,10 @@ exports[`Relationships should render searches normally 1`] = ` Object { "id": "1", "meta": Object { - "editUrl": "/management/kibana/index_patterns/1", + "editUrl": "/management/kibana/indexPatterns/patterns/1", "icon": "indexPatternApp", "inAppUrl": Object { - "path": "/app/kibana#/management/kibana/index_patterns/1", + "path": "/app/kibana#/management/kibana/indexPatterns/patterns/1", "uiCapabilitiesPath": "management.kibana.index_patterns", }, "title": "My Index Pattern", diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index d09dd6f8b868b..92e4e637e0d3f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -174,10 +174,10 @@ exports[`Table prevents saved objects from being deleted 1`] = ` "attributes": Object {}, "id": "1", "meta": Object { - "editUrl": "#/management/kibana/index_patterns/1", + "editUrl": "#/management/kibana/indexPatterns/patterns/1", "icon": "indexPatternApp", "inAppUrl": Object { - "path": "/management/kibana/index_patterns/1", + "path": "/management/kibana/indexPatterns/patterns/1", "uiCapabilitiesPath": "management.kibana.index_patterns", }, "title": "MyIndexPattern*", @@ -389,10 +389,10 @@ exports[`Table should render normally 1`] = ` "attributes": Object {}, "id": "1", "meta": Object { - "editUrl": "#/management/kibana/index_patterns/1", + "editUrl": "#/management/kibana/indexPatterns/patterns/1", "icon": "indexPatternApp", "inAppUrl": Object { - "path": "/management/kibana/index_patterns/1", + "path": "/management/kibana/indexPatterns/patterns/1", "uiCapabilitiesPath": "management.kibana.index_patterns", }, "title": "MyIndexPattern*", diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index 56245ab02fb43..b3372ccb6fda5 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -74,9 +74,9 @@ describe('Relationships', () => { meta: { title: 'MyIndexPattern*', icon: 'indexPatternApp', - editUrl: '#/management/kibana/index_patterns/1', + editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/management/kibana/index_patterns/1', + path: '/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, @@ -109,10 +109,10 @@ describe('Relationships', () => { id: '1', relationship: 'child', meta: { - editUrl: '/management/kibana/index_patterns/1', + editUrl: '/management/kibana/indexPatterns/patterns/1', icon: 'indexPatternApp', inAppUrl: { - path: '/app/kibana#/management/kibana/index_patterns/1', + path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, title: 'My Index Pattern', diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 356f227773610..b9dad983cb42d 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -38,9 +38,9 @@ const defaultProps: TableProps = { meta: { title: `MyIndexPattern*`, icon: 'indexPatternApp', - editUrl: '#/management/kibana/index_patterns/1', + editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/management/kibana/index_patterns/1', + path: '/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, @@ -65,9 +65,9 @@ const defaultProps: TableProps = { meta: { title: `MyIndexPattern*`, icon: 'indexPatternApp', - editUrl: '#/management/kibana/index_patterns/1', + editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/management/kibana/index_patterns/1', + path: '/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 0f385f57f0604..fc01e558f5020 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -155,9 +155,9 @@ describe('SavedObjectsTable', () => { meta: { title: `MyIndexPattern*`, icon: 'indexPatternApp', - editUrl: '#/management/kibana/index_patterns/1', + editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/management/kibana/index_patterns/1', + path: '/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index b9ebaf2b236f4..0ed6a49275f67 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -456,7 +456,7 @@ export class SavedObjectsTable extends Component .visEditorSidebar__formWrapper { + flex-basis: auto; + } } .visEditorSidebar__form { diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index 9dfeae1815d1a..68b7ab06c4875 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -177,7 +177,7 @@ function DefaultEditorSideBar({ gutterSize="none" responsive={false} > - +
      { + const rowActions = await docTable.getRowActions({ rowIndex: 0 }); + if (!rowActions.length) { + throw new Error('row actions empty, trying again'); + } + await rowActions[1].click(); + }); const hasDocHit = await testSubjects.exists('doc-hit'); expect(hasDocHit).to.be(true); diff --git a/test/functional/apps/management/_index_pattern_create_delete.js b/test/functional/apps/management/_index_pattern_create_delete.js index 2545b8f324d1b..c44541484b8d8 100644 --- a/test/functional/apps/management/_index_pattern_create_delete.js +++ b/test/functional/apps/management/_index_pattern_create_delete.js @@ -118,7 +118,7 @@ export default function({ getService, getPageObjects }) { return retry.try(function tryingForTime() { return browser.getCurrentUrl().then(function(currentUrl) { log.debug('currentUrl = ' + currentUrl); - expect(currentUrl).to.contain('management/kibana/index_patterns'); + expect(currentUrl).to.contain('management/kibana/indexPatterns'); }); }); }); diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index 17e0d1ca87fdd..cc25d10cf3257 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -341,6 +341,17 @@ export default function({ getService, getPageObjects }) { log.debug('close inspector'); await inspector.close(); }); + + after(async () => { + const timezone = await kibanaServer.uiSettings.get('dateFormat:tz'); + + // make sure the timezone was set to default correctly to avoid further failures + // for details see https://github.com/elastic/kibana/issues/63037 + if (timezone !== 'UTC') { + log.debug("set 'dateFormat:tz': 'UTC'"); + await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC' }); + } + }); }); }); } diff --git a/test/functional/apps/visualize/_visualize_listing.js b/test/functional/apps/visualize/_visualize_listing.js index e277c3c7d104d..dc07301a8ad50 100644 --- a/test/functional/apps/visualize/_visualize_listing.js +++ b/test/functional/apps/visualize/_visualize_listing.js @@ -17,8 +17,6 @@ * under the License. */ -import expect from '@kbn/expect'; - export default function({ getService, getPageObjects }) { const PageObjects = getPageObjects(['visualize', 'visEditor']); const listingTable = getService('listingTable'); @@ -37,8 +35,7 @@ export default function({ getService, getPageObjects }) { // type markdown is used for simplicity await PageObjects.visualize.createSimpleMarkdownViz(vizName); await PageObjects.visualize.gotoVisualizationLandingPage(); - const visCount = await listingTable.getItemsCount('visualize'); - expect(visCount).to.equal(1); + await listingTable.expectItemsCount('visualize', 1); }); it('delete all viz', async function() { @@ -46,12 +43,10 @@ export default function({ getService, getPageObjects }) { await PageObjects.visualize.createSimpleMarkdownViz(vizName + '2'); await PageObjects.visualize.gotoVisualizationLandingPage(); - let visCount = await listingTable.getItemsCount('visualize'); - expect(visCount).to.equal(3); + await listingTable.expectItemsCount('visualize', 3); await PageObjects.visualize.deleteAllVisualizations(); - visCount = await listingTable.getItemsCount('visualize'); - expect(visCount).to.equal(0); + await listingTable.expectItemsCount('visualize', 0); }); }); @@ -69,38 +64,32 @@ export default function({ getService, getPageObjects }) { it('matches on the first word', async function() { await listingTable.searchForItemWithName('Hello'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(1); + await listingTable.expectItemsCount('visualize', 1); }); it('matches the second word', async function() { await listingTable.searchForItemWithName('World'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(1); + await listingTable.expectItemsCount('visualize', 1); }); it('matches the second word prefix', async function() { await listingTable.searchForItemWithName('Wor'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(1); + await listingTable.expectItemsCount('visualize', 1); }); it('does not match mid word', async function() { await listingTable.searchForItemWithName('orld'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(0); + await listingTable.expectItemsCount('visualize', 0); }); it('is case insensitive', async function() { await listingTable.searchForItemWithName('hello world'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(1); + await listingTable.expectItemsCount('visualize', 1); }); it('is using AND operator', async function() { await listingTable.searchForItemWithName('hello banana'); - const itemCount = await listingTable.getItemsCount('visualize'); - expect(itemCount).to.equal(0); + await listingTable.expectItemsCount('visualize', 0); }); }); }); diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts index 215e3360bbd5b..6a503f4f73b66 100644 --- a/test/functional/page_objects/home_page.ts +++ b/test/functional/page_objects/home_page.ts @@ -53,8 +53,7 @@ export function HomePageProvider({ getService, getPageObjects }: FtrProviderCont async removeSampleDataSet(id: string) { // looks like overkill but we're hitting flaky cases where we click but it doesn't remove - await testSubjects.isDisplayed(`removeSampleDataSet${id}`); - await testSubjects.isEnabled(`removeSampleDataSet${id}`); + await testSubjects.waitForEnabled(`removeSampleDataSet${id}`); await testSubjects.click(`removeSampleDataSet${id}`); await this._waitForSampleDataLoadingAction(id); } diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index b8069b31257d3..1315b86f9c93c 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -52,7 +52,7 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider async clickKibanaIndexPatterns() { log.debug('clickKibanaIndexPatterns link'); - await testSubjects.click('index_patterns'); + await testSubjects.click('indexPatterns'); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -345,7 +345,7 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider await retry.try(async () => { const currentUrl = await browser.getCurrentUrl(); log.info('currentUrl', currentUrl); - if (!currentUrl.match(/index_patterns\/.+\?/)) { + if (!currentUrl.match(/indexPatterns\/.+\?/)) { throw new Error('Index pattern not created'); } else { log.debug('Index pattern created: ' + currentUrl); diff --git a/test/functional/services/common/test_subjects.ts b/test/functional/services/common/test_subjects.ts index e4e0e7ce70bc4..c71154ba2ec6a 100644 --- a/test/functional/services/common/test_subjects.ts +++ b/test/functional/services/common/test_subjects.ts @@ -97,12 +97,10 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { } public async append(selector: string, text: string): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.append(${selector}, ${text})`); - const input = await this.find(selector); - await input.click(); - await input.type(text); - }); + log.debug(`TestSubjects.append(${selector}, ${text})`); + const input = await this.find(selector); + await input.click(); + await input.type(text); } public async clickWhenNotDisabled( @@ -119,12 +117,10 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { } public async doubleClick(selector: string, timeout: number = FIND_TIME): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.doubleClick(${selector})`); - const element = await this.find(selector, timeout); - await element.moveMouseTo(); - await element.doubleClick(); - }); + log.debug(`TestSubjects.doubleClick(${selector})`); + const element = await this.find(selector, timeout); + await element.moveMouseTo(); + await element.doubleClick(); } async descendantExists(selector: string, parentElement: WebElementWrapper): Promise { @@ -210,27 +206,21 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { } public async isEnabled(selector: string): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.isEnabled(${selector})`); - const element = await this.find(selector); - return await element.isEnabled(); - }); + log.debug(`TestSubjects.isEnabled(${selector})`); + const element = await this.find(selector); + return await element.isEnabled(); } public async isDisplayed(selector: string): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.isDisplayed(${selector})`); - const element = await this.find(selector); - return await element.isDisplayed(); - }); + log.debug(`TestSubjects.isDisplayed(${selector})`); + const element = await this.find(selector); + return await element.isDisplayed(); } public async isSelected(selector: string): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.isSelected(${selector})`); - const element = await this.find(selector); - return await element.isSelected(); - }); + log.debug(`TestSubjects.isSelected(${selector})`); + const element = await this.find(selector); + return await element.isSelected(); } public async isSelectedAll(selectorAll: string): Promise { @@ -241,11 +231,9 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { } public async getVisibleText(selector: string): Promise { - return await retry.try(async () => { - log.debug(`TestSubjects.getVisibleText(${selector})`); - const element = await this.find(selector); - return await element.getVisibleText(); - }); + log.debug(`TestSubjects.getVisibleText(${selector})`); + const element = await this.find(selector); + return await element.getVisibleText(); } async getVisibleTextAll(selectorAll: string): Promise { @@ -298,6 +286,13 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { await find.waitForElementHidden(element, timeout); } + public async waitForEnabled(selector: string, timeout: number = TRY_TIME): Promise { + await retry.tryForTime(timeout, async () => { + const element = await this.find(selector); + return (await element.isDisplayed()) && (await element.isEnabled()); + }); + } + public getCssSelector(selector: string): string { return testSubjSelector(selector); } diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts index c7667ae7b4049..9a117458c7f76 100644 --- a/test/functional/services/listing_table.ts +++ b/test/functional/services/listing_table.ts @@ -17,6 +17,7 @@ * under the License. */ +import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function ListingTableProvider({ getService, getPageObjects }: FtrProviderContext) { @@ -85,11 +86,13 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider * Returns items count on landing page * @param appName 'visualize' | 'dashboard' */ - public async getItemsCount(appName: 'visualize' | 'dashboard'): Promise { - const elements = await find.allByCssSelector( - `[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]` - ); - return elements.length; + public async expectItemsCount(appName: 'visualize' | 'dashboard', count: number) { + await retry.try(async () => { + const elements = await find.allByCssSelector( + `[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]` + ); + expect(elements.length).to.equal(count); + }); } /** @@ -116,12 +119,18 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider * @param appName 'visualize' | 'dashboard' * @param name item name */ - public async searchAndGetItemsCount(appName: 'visualize' | 'dashboard', name: string) { + public async searchAndExpectItemsCount( + appName: 'visualize' | 'dashboard', + name: string, + count: number + ) { await this.searchForItemWithName(name); - const links = await testSubjects.findAll( - `${prefixMap[appName]}ListingTitleLink-${name.replace(/ /g, '-')}` - ); - return links.length; + await retry.try(async () => { + const links = await testSubjects.findAll( + `${prefixMap[appName]}ListingTitleLink-${name.replace(/ /g, '-')}` + ); + expect(links.length).to.equal(count); + }); } public async clickDeleteSelected() { diff --git a/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts b/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts index 0e350cb1ec011..f996a49e5eadc 100644 --- a/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts +++ b/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts @@ -5,7 +5,13 @@ */ import url from 'url'; -import { AbsoluteURLFactoryOptions } from '../types'; + +interface AbsoluteURLFactoryOptions { + defaultBasePath: string; + protocol: string; + hostname: string; + port: string | number; +} export const getAbsoluteUrlFactory = ({ protocol, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/constants.ts b/x-pack/legacy/plugins/reporting/export_types/common/constants.ts index 6c56c269017e2..76fab923978f8 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/constants.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/constants.ts @@ -4,9 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export const LayoutTypes = { - PRESERVE_LAYOUT: 'preserve_layout', - PRINT: 'print', -}; - export const DEFAULT_PAGELOAD_SELECTOR = '.application'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts index 9085fb3cbc876..fe3ac16b79fe0 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { cryptoFactory } from '../../../server/lib/crypto'; -import { Logger } from '../../../types'; +import { cryptoFactory, LevelLogger } from '../../../server/lib'; import { decryptJobHeaders } from './decrypt_job_headers'; const encryptHeaders = async (encryptionKey: string, headers: Record) => { @@ -23,7 +22,7 @@ describe('headers', () => { }, logger: ({ error: jest.fn(), - } as unknown) as Logger, + } as unknown) as LevelLogger, }); await expect(getDecryptedHeaders()).rejects.toMatchInlineSnapshot( `[Error: Failed to decrypt report job data. Please ensure that xpack.reporting.encryptionKey is set and re-generate this report. Error: Invalid IV length]` @@ -44,7 +43,7 @@ describe('headers', () => { type: 'csv', headers: encryptedHeaders, }, - logger: {} as Logger, + logger: {} as LevelLogger, }); expect(decryptedHeaders).toEqual(headers); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts index 0436f5d5bc843..a13c1fa2a9efb 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts @@ -5,8 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { cryptoFactory } from '../../../server/lib/crypto'; -import { Logger } from '../../../types'; +import { cryptoFactory, LevelLogger } from '../../../server/lib'; interface HasEncryptedHeaders { headers?: string; @@ -23,7 +22,7 @@ export const decryptJobHeaders = async < }: { encryptionKey?: string; job: JobDocPayloadType; - logger: Logger; + logger: LevelLogger; }): Promise> => { try { if (typeof job.headers !== 'string') { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts index 5f5fc94eee830..c09cc8314374e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts @@ -5,9 +5,9 @@ */ import sinon from 'sinon'; +import { ReportingConfig, ReportingCore } from '../../../server'; +import { JobDocPayload } from '../../../server/types'; import { createMockReportingCore } from '../../../test_helpers'; -import { ReportingConfig, ReportingCore } from '../../../server/types'; -import { JobDocPayload } from '../../../types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; import { getConditionalHeaders, getCustomLogo } from './index'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts index bd7999d697ca9..808d5db5c57d5 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReportingConfig } from '../../../server/types'; -import { ConditionalHeaders } from '../../../types'; +import { ReportingConfig } from '../../../server'; +import { ConditionalHeaders } from '../../../server/types'; export const getConditionalHeaders = ({ config, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts index a13f992e7867c..777de317af41e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts @@ -5,8 +5,8 @@ */ import { UI_SETTINGS_CUSTOM_PDF_LOGO } from '../../../common/constants'; -import { ReportingConfig, ReportingCore } from '../../../server/types'; -import { ConditionalHeaders } from '../../../types'; +import { ReportingConfig, ReportingCore } from '../../../server'; +import { ConditionalHeaders } from '../../../server/types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; // Logo is PDF only export const getCustomLogo = async ({ diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts index c4b6f31019fdf..59cb7ce14ca2d 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts @@ -12,7 +12,7 @@ import { } from 'url'; import { getAbsoluteUrlFactory } from '../../../common/get_absolute_url'; import { validateUrls } from '../../../common/validate_urls'; -import { ReportingConfig } from '../../../server/types'; +import { ReportingConfig } from '../../../server'; import { JobDocPayloadPNG } from '../../png/types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts index 07fceb603e451..d33760fcb4f89 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts @@ -5,8 +5,8 @@ */ import { CaptureConfig } from '../../../server/types'; -import { LayoutTypes } from '../constants'; -import { Layout, LayoutParams } from './layout'; +import { LayoutParams, LayoutTypes } from './'; +import { Layout } from './layout'; import { PreserveLayout } from './preserve_layout'; import { PrintLayout } from './print_layout'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/index.ts index fd35485779ba0..993b8f6cdc9ab 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/index.ts @@ -4,6 +4,63 @@ * you may not use this file except in compliance with the Elastic License. */ +import { HeadlessChromiumDriver } from '../../../server/browsers'; +import { LevelLogger } from '../../../server/lib'; +import { Layout } from './layout'; + export { createLayout } from './create_layout'; -export { PrintLayout } from './print_layout'; +export { Layout } from './layout'; export { PreserveLayout } from './preserve_layout'; +export { PrintLayout } from './print_layout'; + +export const LayoutTypes = { + PRESERVE_LAYOUT: 'preserve_layout', + PRINT: 'print', +}; + +export const getDefaultLayoutSelectors = (): LayoutSelectorDictionary => ({ + screenshot: '[data-shared-items-container]', + renderComplete: '[data-shared-item]', + itemsCountAttribute: 'data-shared-items-count', + timefilterDurationAttribute: 'data-shared-timefilter-duration', +}); + +export interface PageSizeParams { + pageMarginTop: number; + pageMarginBottom: number; + pageMarginWidth: number; + tableBorderWidth: number; + headingHeight: number; + subheadingHeight: number; +} + +export interface LayoutSelectorDictionary { + screenshot: string; + renderComplete: string; + itemsCountAttribute: string; + timefilterDurationAttribute: string; +} + +export interface PdfImageSize { + width: number; + height?: number; +} + +export interface Size { + width: number; + height: number; +} + +export interface LayoutParams { + id: string; + dimensions: Size; +} + +interface LayoutSelectors { + // Fields that are not part of Layout: the instances + // independently implement these fields on their own + selectors: LayoutSelectorDictionary; + positionElements?: (browser: HeadlessChromiumDriver, logger: LevelLogger) => Promise; +} + +export type LayoutInstance = Layout & LayoutSelectors & Size; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/layout.ts index 5cd2f3e636a93..433edb35df4cd 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/layout.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HeadlessChromiumDriver } from '../../../server/browsers/chromium/driver'; -import { LevelLogger } from '../../../server/lib'; +import { PageSizeParams, PdfImageSize, Size } from './'; export interface ViewZoomWidthHeight { zoom: number; @@ -13,34 +12,6 @@ export interface ViewZoomWidthHeight { height: number; } -export interface PageSizeParams { - pageMarginTop: number; - pageMarginBottom: number; - pageMarginWidth: number; - tableBorderWidth: number; - headingHeight: number; - subheadingHeight: number; -} - -export interface LayoutSelectorDictionary { - screenshot: string; - renderComplete: string; - itemsCountAttribute: string; - timefilterDurationAttribute: string; -} - -export interface PdfImageSize { - width: number; - height?: number; -} - -export const getDefaultLayoutSelectors = (): LayoutSelectorDictionary => ({ - screenshot: '[data-shared-items-container]', - renderComplete: '[data-shared-item]', - itemsCountAttribute: 'data-shared-items-count', - timefilterDurationAttribute: 'data-shared-timefilter-duration', -}); - export abstract class Layout { public id: string = ''; @@ -62,22 +33,3 @@ export abstract class Layout { public abstract getCssOverridesPath(): string; } - -export interface Size { - width: number; - height: number; -} - -export interface LayoutParams { - id: string; - dimensions: Size; -} - -interface LayoutSelectors { - // Fields that are not part of Layout: the instances - // independently implement these fields on their own - selectors: LayoutSelectorDictionary; - positionElements?: (browser: HeadlessChromiumDriver, logger: LevelLogger) => Promise; -} - -export type LayoutInstance = Layout & LayoutSelectors & Size; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/preserve_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/preserve_layout.ts index 07dbba7d25883..9041055ddce2d 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/preserve_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/preserve_layout.ts @@ -3,15 +3,16 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import path from 'path'; -import { LayoutTypes } from '../constants'; import { getDefaultLayoutSelectors, Layout, LayoutSelectorDictionary, + LayoutTypes, PageSizeParams, Size, -} from './layout'; +} from './'; // We use a zoom of two to bump up the resolution of the screenshot a bit. const ZOOM: number = 2; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts index f6974379253fb..759f07a33e2b6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts @@ -6,11 +6,11 @@ import path from 'path'; import { EvaluateFn, SerializableOrJSHandle } from 'puppeteer'; -import { HeadlessChromiumDriver } from '../../../server/browsers'; import { LevelLogger } from '../../../server/lib'; +import { HeadlessChromiumDriver } from '../../../server/browsers'; import { CaptureConfig } from '../../../server/types'; -import { LayoutTypes } from '../constants'; -import { getDefaultLayoutSelectors, Layout, LayoutSelectorDictionary, Size } from './layout'; +import { getDefaultLayoutSelectors, LayoutSelectorDictionary, Size, LayoutTypes } from './'; +import { Layout } from './layout'; export class PrintLayout extends Layout { public readonly selectors: LayoutSelectorDictionary = { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_element_position_data.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_element_position_data.ts index 3999393600e48..d02e852a3c1b6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_element_position_data.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_element_position_data.ts @@ -5,16 +5,16 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; -import { LevelLogger as Logger, startTrace } from '../../../../server/lib'; -import { LayoutInstance } from '../../layouts/layout'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; +import { LevelLogger, startTrace } from '../../../../server/lib'; +import { AttributesMap, ElementsPositionAndAttribute } from '../../../../server/types'; +import { LayoutInstance } from '../../layouts'; import { CONTEXT_ELEMENTATTRIBUTES } from './constants'; -import { AttributesMap, ElementsPositionAndAttribute } from './types'; export const getElementPositionAndAttributes = async ( - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, layout: LayoutInstance, - logger: Logger + logger: LevelLogger ): Promise => { const endTrace = startTrace('get_element_position_data', 'read'); const { screenshot: screenshotSelector } = layout.selectors; // data-shared-items-container diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_number_of_items.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_number_of_items.ts index d0c1a2a3ce672..9e446f499ab3a 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_number_of_items.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_number_of_items.ts @@ -5,15 +5,15 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { CaptureConfig } from '../../../../server/types'; -import { LayoutInstance } from '../../layouts/layout'; +import { LayoutInstance } from '../../layouts'; import { CONTEXT_GETNUMBEROFITEMS, CONTEXT_READMETADATA } from './constants'; export const getNumberOfItems = async ( captureConfig: CaptureConfig, - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, layout: LayoutInstance, logger: LevelLogger ): Promise => { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_screenshots.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_screenshots.ts index bc9e17854b27d..578a4dd0b975c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_screenshots.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_screenshots.ts @@ -5,12 +5,12 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; -import { Screenshot, ElementsPositionAndAttribute } from './types'; +import { ElementsPositionAndAttribute, Screenshot } from '../../../../server/types'; export const getScreenshots = async ( - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, elementsPositionAndAttributes: ElementsPositionAndAttribute[], logger: LevelLogger ): Promise => { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_time_range.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_time_range.ts index bcd4cf9000df4..7bdb38298c383 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_time_range.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/get_time_range.ts @@ -4,21 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; -import { LayoutInstance } from '../../layouts/layout'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; +import { LayoutInstance } from '../../layouts'; import { CONTEXT_GETTIMERANGE } from './constants'; -import { TimeRange } from './types'; export const getTimeRange = async ( - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, layout: LayoutInstance, logger: LevelLogger -): Promise => { +): Promise => { const endTrace = startTrace('get_time_range', 'read'); logger.debug('getting timeRange'); - const timeRange: TimeRange | null = await browser.evaluate( + const timeRange = await browser.evaluate( { fn: durationAttribute => { const durationElement = document.querySelector(`[${durationAttribute}]`); @@ -32,7 +31,7 @@ export const getTimeRange = async ( return null; } - return { duration }; + return duration; // user-friendly date string }, args: [layout.selectors.timefilterDurationAttribute], }, @@ -41,7 +40,7 @@ export const getTimeRange = async ( ); if (timeRange) { - logger.info(`timeRange: ${timeRange.duration}`); + logger.info(`timeRange: ${timeRange}`); } else { logger.debug('no timeRange'); } diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts index 0d75b067fbe63..5a04f1a497abf 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { screenshotsObservableFactory, ScreenshotsObservableFn } from './observable'; +export { screenshotsObservableFactory } from './observable'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/inject_css.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/inject_css.ts index 40bb84870b16d..dae6f3cc6350f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/inject_css.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/inject_css.ts @@ -7,15 +7,15 @@ import { i18n } from '@kbn/i18n'; import fs from 'fs'; import { promisify } from 'util'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { Layout } from '../../layouts/layout'; import { CONTEXT_INJECTCSS } from './constants'; const fsp = { readFile: promisify(fs.readFile) }; export const injectCustomCss = async ( - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, layout: Layout, logger: LevelLogger ): Promise => { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.test.ts index 796bccb360ebd..cc8b438310430 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.test.ts @@ -18,13 +18,16 @@ jest.mock('../../../../server/browsers/chromium/puppeteer', () => ({ import * as Rx from 'rxjs'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { loggingServiceMock } from '../../../../../../../../src/core/server/mocks'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { LevelLogger } from '../../../../server/lib'; +import { + CaptureConfig, + ConditionalHeaders, + ElementsPositionAndAttribute, +} from '../../../../server/types'; import { createMockBrowserDriverFactory, createMockLayoutInstance } from '../../../../test_helpers'; -import { ConditionalHeaders, HeadlessChromiumDriver } from '../../../../types'; -import { CaptureConfig } from '../../../../server/types'; import * as contexts from './constants'; import { screenshotsObservableFactory } from './observable'; -import { ElementsPositionAndAttribute } from './types'; /* * Mocks diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.ts index 282490a28d591..de27d5ad30014 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/observable.ts @@ -16,29 +16,32 @@ import { tap, toArray, } from 'rxjs/operators'; -import { CaptureConfig } from '../../../../server/types'; +import { HeadlessChromiumDriverFactory } from '../../../../server/browsers'; +import { + CaptureConfig, + ElementsPositionAndAttribute, + ScreenshotObservableOpts, + ScreenshotResults, + ScreenshotsObservableFn, +} from '../../../../server/types'; import { DEFAULT_PAGELOAD_SELECTOR } from '../../constants'; -import { HeadlessChromiumDriverFactory } from '../../../../types'; import { getElementPositionAndAttributes } from './get_element_position_data'; import { getNumberOfItems } from './get_number_of_items'; import { getScreenshots } from './get_screenshots'; import { getTimeRange } from './get_time_range'; import { injectCustomCss } from './inject_css'; import { openUrl } from './open_url'; -import { ScreenSetupData, ScreenshotObservableOpts, ScreenshotResults } from './types'; import { waitForRenderComplete } from './wait_for_render'; import { waitForVisualizations } from './wait_for_visualizations'; const DEFAULT_SCREENSHOT_CLIP_HEIGHT = 1200; const DEFAULT_SCREENSHOT_CLIP_WIDTH = 1800; -export type ScreenshotsObservableFn = ({ - logger, - urls, - conditionalHeaders, - layout, - browserTimezone, -}: ScreenshotObservableOpts) => Rx.Observable; +interface ScreenSetupData { + elementsPositionAndAttributes: ElementsPositionAndAttribute[] | null; + timeRange: string | null; + error?: Error; +} export function screenshotsObservableFactory( captureConfig: CaptureConfig, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/open_url.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/open_url.ts index a0708b7dba36b..3cf962b8178fd 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/open_url.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/open_url.ts @@ -5,14 +5,13 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; -import { CaptureConfig } from '../../../../server/types'; -import { ConditionalHeaders } from '../../../../types'; +import { CaptureConfig, ConditionalHeaders } from '../../../../server/types'; export const openUrl = async ( captureConfig: CaptureConfig, - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, url: string, pageLoadSelector: string, conditionalHeaders: ConditionalHeaders, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/types.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/types.ts deleted file mode 100644 index 13ddf5eb74fcf..0000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/types.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { LevelLogger } from '../../../../server/lib'; -import { ConditionalHeaders, ElementPosition } from '../../../../types'; -import { LayoutInstance } from '../../layouts/layout'; - -export interface ScreenshotObservableOpts { - logger: LevelLogger; - urls: string[]; - conditionalHeaders: ConditionalHeaders; - layout: LayoutInstance; - browserTimezone: string; -} - -export interface TimeRange { - duration: string; -} - -export interface AttributesMap { - [key: string]: any; -} - -export interface ElementsPositionAndAttribute { - position: ElementPosition; - attributes: AttributesMap; -} - -export interface Screenshot { - base64EncodedData: string; - title: string; - description: string; -} - -export interface ScreenSetupData { - elementsPositionAndAttributes: ElementsPositionAndAttribute[] | null; - timeRange: TimeRange | null; - error?: Error; -} - -export interface ScreenshotResults { - timeRange: TimeRange | null; - screenshots: Screenshot[]; - error?: Error; - elementsPositionAndAttributes?: ElementsPositionAndAttribute[]; // NOTE: for testing -} diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts index fe92fbc9077e6..0e02fa2dacfad 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts @@ -5,15 +5,15 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { CaptureConfig } from '../../../../server/types'; -import { LayoutInstance } from '../../layouts/layout'; +import { LayoutInstance } from '../../layouts'; import { CONTEXT_WAITFORRENDER } from './constants'; export const waitForRenderComplete = async ( captureConfig: CaptureConfig, - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, layout: LayoutInstance, logger: LevelLogger ) => { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_visualizations.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_visualizations.ts index d456c4089ecee..ff84d06956dbc 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_visualizations.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_visualizations.ts @@ -5,10 +5,10 @@ */ import { i18n } from '@kbn/i18n'; -import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers'; import { LevelLogger, startTrace } from '../../../../server/lib'; +import { HeadlessChromiumDriver } from '../../../../server/browsers'; import { CaptureConfig } from '../../../../server/types'; -import { LayoutInstance } from '../../layouts/layout'; +import { LayoutInstance } from '../../layouts'; import { CONTEXT_WAITFORELEMENTSTOBEINDOM } from './constants'; type SelectorArgs = Record; @@ -24,7 +24,7 @@ const getCompletedItemsCount = ({ renderCompleteSelector }: SelectorArgs) => { */ export const waitForVisualizations = async ( captureConfig: CaptureConfig, - browser: HeadlessBrowser, + browser: HeadlessChromiumDriver, itemsCount: number, layout: LayoutInstance, logger: LevelLogger diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/index.ts b/x-pack/legacy/plugins/reporting/export_types/csv/index.ts index 942cb954785ac..cdb4c36dba3df 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/index.ts @@ -6,18 +6,22 @@ import { CSV_JOB_TYPE as jobType, - LICENSE_TYPE_TRIAL, LICENSE_TYPE_BASIC, - LICENSE_TYPE_STANDARD, + LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, - LICENSE_TYPE_ENTERPRISE, + LICENSE_TYPE_STANDARD, + LICENSE_TYPE_TRIAL, } from '../../common/constants'; -import { ExportTypeDefinition, ESQueueCreateJobFn, ESQueueWorkerExecuteFn } from '../../types'; +import { + ESQueueCreateJobFn, + ESQueueWorkerExecuteFn, + ExportTypeDefinition, +} from '../../server/types'; import { metadata } from './metadata'; import { createJobFactory } from './server/create_job'; import { executeJobFactory } from './server/execute_job'; -import { JobParamsDiscoverCsv, JobDocPayloadDiscoverCsv } from './types'; +import { JobDocPayloadDiscoverCsv, JobParamsDiscoverCsv } from './types'; export const getExportType = (): ExportTypeDefinition< JobParamsDiscoverCsv, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts index 0e704a041452a..8320cd05aa2e7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts @@ -5,13 +5,13 @@ */ import { ReportingCore } from '../../../server'; -import { cryptoFactory } from '../../../server/lib/crypto'; +import { cryptoFactory } from '../../../server/lib'; import { ConditionalHeaders, CreateJobFactory, ESQueueCreateJobFn, RequestFacade, -} from '../../../types'; +} from '../../../server/types'; import { JobParamsDiscoverCsv } from '../types'; export const createJobFactory: CreateJobFactory new Promise(resolve => setTimeout(() => resolve(), ms)); @@ -65,6 +65,7 @@ describe('CSV Execute Job', function() { beforeEach(async function() { configGetStub = sinon.stub(); + configGetStub.withArgs('index').returns('.reporting-foo-test'); configGetStub.withArgs('encryptionKey').returns(encryptionKey); configGetStub.withArgs('csv', 'maxSizeBytes').returns(1024 * 1000); // 1mB configGetStub.withArgs('csv', 'scroll').returns({}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index dbe305bc452db..7d95c45d5d233 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -7,18 +7,18 @@ import { i18n } from '@kbn/i18n'; import Hapi from 'hapi'; import { IUiSettingsClient, KibanaRequest } from '../../../../../../../src/core/server'; -import { CSV_JOB_TYPE, CSV_BOM_CHARS } from '../../../common/constants'; -import { ReportingCore } from '../../../server/core'; -import { cryptoFactory } from '../../../server/lib'; +import { CSV_BOM_CHARS, CSV_JOB_TYPE } from '../../../common/constants'; +import { ReportingCore } from '../../../server'; +import { cryptoFactory, LevelLogger } from '../../../server/lib'; import { getFieldFormats } from '../../../server/services'; -import { ESQueueWorkerExecuteFn, ExecuteJobFactory, Logger } from '../../../types'; +import { ESQueueWorkerExecuteFn, ExecuteJobFactory } from '../../../server/types'; import { JobDocPayloadDiscoverCsv } from '../types'; import { fieldFormatMapFactory } from './lib/field_format_map'; import { createGenerateCsv } from './lib/generate_csv'; export const executeJobFactory: ExecuteJobFactory> = async function executeJobFactoryFn(reporting: ReportingCore, parentLogger: Logger) { +>> = async function executeJobFactoryFn(reporting: ReportingCore, parentLogger: LevelLogger) { const config = reporting.getConfig(); const crypto = cryptoFactory(config.get('encryptionKey')); const logger = parentLogger.clone([CSV_JOB_TYPE, 'execute-job']); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts index 60e75d74b2f98..344091ee18268 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RawValue } from './types'; +import { RawValue } from '../../types'; import { cellHasFormulas } from './cell_has_formula'; const nonAlphaNumRE = /[^a-zA-Z0-9]/; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts index dac963635c469..e1459e195d9f6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts @@ -9,7 +9,15 @@ import { FieldFormatConfig, IFieldFormatsRegistry, } from '../../../../../../../../src/plugins/data/server'; -import { IndexPatternSavedObject } from '../../../../types'; + +interface IndexPatternSavedObject { + attributes: { + fieldFormatMap: string; + }; + id: string; + type: string; + version: string; +} /** * Create a map of FieldFormat instances for index pattern fields diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts index 0bcf0fc31beae..35093f45fdd5b 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isObject, isNull, isUndefined } from 'lodash'; -import { RawValue } from './types'; +import { isNull, isObject, isUndefined } from 'lodash'; +import { RawValue } from '../../types'; export function createFormatCsvValues( escapeValue: (value: RawValue, index: number, array: RawValue[]) => string, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts index c7996ebf832a1..a8fdd8d1a5bbc 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { Logger } from '../../../../types'; +import { LevelLogger } from '../../../../server/lib'; import { GenerateCsvParams, SavedSearchGeneratorResult } from '../../types'; import { createFlattenHit } from './flatten_hit'; import { createFormatCsvValues } from './format_csv_values'; @@ -14,7 +14,7 @@ import { createHitIterator } from './hit_iterator'; import { MaxSizeStringBuilder } from './max_size_string_builder'; import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; -export function createGenerateCsv(logger: Logger) { +export function createGenerateCsv(logger: LevelLogger) { const hitIterator = createHitIterator(logger); return async function generateCsv({ diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts index a9f0015e49360..905d9cd68b128 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts @@ -6,16 +6,16 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; -import { CancellationToken } from '../../../../common/cancellation_token'; +import { CancellationToken } from '../../../../../../../plugins/reporting/common'; +import { LevelLogger } from '../../../../server/lib'; import { ScrollConfig } from '../../../../server/types'; -import { Logger } from '../../../../types'; import { createHitIterator } from './hit_iterator'; const mockLogger = { error: new Function(), debug: new Function(), warning: new Function(), -} as Logger; +} as LevelLogger; const debugLogStub = sinon.stub(mockLogger, 'debug'); const warnLogStub = sinon.stub(mockLogger, 'warning'); const errorLogStub = sinon.stub(mockLogger, 'error'); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts index 2ca19dd07a627..803161910443e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts @@ -6,8 +6,9 @@ import { i18n } from '@kbn/i18n'; import { SearchParams, SearchResponse } from 'elasticsearch'; +import { CancellationToken } from '../../../../../../../plugins/reporting/common'; +import { LevelLogger } from '../../../../server/lib'; import { ScrollConfig } from '../../../../server/types'; -import { CancellationToken, Logger } from '../../../../types'; async function parseResponse(request: SearchResponse) { const response = await request; @@ -35,7 +36,7 @@ async function parseResponse(request: SearchResponse) { }; } -export function createHitIterator(logger: Logger) { +export function createHitIterator(logger: LevelLogger) { return async function* hitIterator( scrollSettings: ScrollConfig, callEndpoint: Function, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 40a42db352635..0f6223d8553de 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CancellationToken } from '../../common/cancellation_token'; -import { ScrollConfig } from '../../server/types'; -import { JobDocPayload, JobParamPostPayload } from '../../types'; +import { CancellationToken } from '../../../../../plugins/reporting/common'; +import { JobDocPayload, JobParamPostPayload, ScrollConfig } from '../../server/types'; + +export type RawValue = string | object | null | undefined; interface DocValueField { field: string; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/index.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/index.ts index 606630944c604..570b91600cbe0 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/index.ts @@ -6,25 +6,25 @@ import { CSV_FROM_SAVEDOBJECT_JOB_TYPE, - LICENSE_TYPE_TRIAL, LICENSE_TYPE_BASIC, - LICENSE_TYPE_STANDARD, + LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, - LICENSE_TYPE_ENTERPRISE, + LICENSE_TYPE_STANDARD, + LICENSE_TYPE_TRIAL, } from '../../common/constants'; -import { ExportTypeDefinition, ImmediateCreateJobFn, ImmediateExecuteFn } from '../../types'; -import { createJobFactory } from './server/create_job'; -import { executeJobFactory } from './server/execute_job'; +import { ExportTypeDefinition } from '../../server/types'; import { metadata } from './metadata'; +import { createJobFactory, ImmediateCreateJobFn } from './server/create_job'; +import { executeJobFactory, ImmediateExecuteFn } from './server/execute_job'; import { JobParamsPanelCsv } from './types'; /* * These functions are exported to share with the API route handler that * generates csv from saved object immediately on request. */ -export { executeJobFactory } from './server/execute_job'; export { createJobFactory } from './server/create_job'; +export { executeJobFactory } from './server/execute_job'; export const getExportType = (): ExportTypeDefinition< JobParamsPanelCsv, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts index 8e0376a190267..ed0e17454260f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts @@ -8,8 +8,8 @@ import { notFound, notImplemented } from 'boom'; import { get } from 'lodash'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; import { ReportingCore } from '../../../../server'; -import { cryptoFactory } from '../../../../server/lib'; -import { CreateJobFactory, ImmediateCreateJobFn, Logger, RequestFacade } from '../../../../types'; +import { cryptoFactory, LevelLogger } from '../../../../server/lib'; +import { CreateJobFactory, RequestFacade, TimeRangeParams } from '../../../../server/types'; import { JobDocPayloadPanelCsv, JobParamsPanelCsv, @@ -17,11 +17,20 @@ import { SavedObjectServiceError, SavedSearchObjectAttributesJSON, SearchPanel, - TimeRangeParams, VisObjectAttributesJSON, } from '../../types'; import { createJobSearch } from './create_job_search'; +export type ImmediateCreateJobFn = ( + jobParams: JobParamsType, + headers: Record, + req: RequestFacade +) => Promise<{ + type: string | null; + title: string; + jobParams: JobParamsType; +}>; + interface VisData { title: string; visType: string; @@ -30,7 +39,7 @@ interface VisData { export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(reporting: ReportingCore, parentLogger: Logger) { +>> = function createJobFactoryFn(reporting: ReportingCore, parentLogger: LevelLogger) { const config = reporting.getConfig(); const crypto = cryptoFactory(config.get('encryptionKey')); const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'create-job']); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job_search.ts index 69ffce57489b1..19204ef81c5eb 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job_search.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { TimeRangeParams } from '../../../../server/types'; import { SavedObjectMeta, SavedObjectReference, SavedSearchObjectAttributes, SearchPanel, - TimeRangeParams, } from '../../types'; interface SearchPanelData { diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/index.ts index e129e3e5f47ec..a3674d69ae6a5 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createJobFactory } from './create_job'; +export { createJobFactory, ImmediateCreateJobFn } from './create_job'; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index 8efcdc3bd9f30..5761a98ed160c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -7,21 +7,30 @@ import { i18n } from '@kbn/i18n'; import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; import { ReportingCore } from '../../../server'; -import { cryptoFactory } from '../../../server/lib'; +import { cryptoFactory, LevelLogger } from '../../../server/lib'; import { ExecuteJobFactory, - ImmediateExecuteFn, JobDocOutput, - Logger, + JobDocPayload, RequestFacade, -} from '../../../types'; +} from '../../../server/types'; import { CsvResultFromSearch } from '../../csv/types'; import { FakeRequest, JobDocPayloadPanelCsv, JobParamsPanelCsv, SearchPanel } from '../types'; import { createGenerateCsv } from './lib'; +/* + * ImmediateExecuteFn receives the job doc payload because the payload was + * generated in the CreateFn + */ +export type ImmediateExecuteFn = ( + jobId: null, + job: JobDocPayload, + request: RequestFacade +) => Promise; + export const executeJobFactory: ExecuteJobFactory> = async function executeJobFactoryFn(reporting: ReportingCore, parentLogger: Logger) { +>> = async function executeJobFactoryFn(reporting: ReportingCore, parentLogger: LevelLogger) { const config = reporting.getConfig(); const crypto = cryptoFactory(config.get('encryptionKey')); const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'execute-job']); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts index c81060d8ca05d..8dcdee7ef24c1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts @@ -5,12 +5,13 @@ */ import { badRequest } from 'boom'; -import { ReportingCore } from '../../../../server/types'; -import { Logger, RequestFacade } from '../../../../types'; +import { ReportingCore } from '../../../../server'; +import { LevelLogger } from '../../../../server/lib'; +import { RequestFacade } from '../../../../server/types'; import { FakeRequest, JobParamsPanelCsv, SearchPanel, VisPanel } from '../../types'; import { generateCsvSearch } from './generate_csv_search'; -export function createGenerateCsv(reporting: ReportingCore, logger: Logger) { +export function createGenerateCsv(reporting: ReportingCore, logger: LevelLogger) { return async function generateCsv( request: RequestFacade | FakeRequest, visType: string, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts index 2611b74c83de9..506208e4e1aad 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts @@ -11,13 +11,11 @@ import { Filter, IIndexPattern, Query, - // Reporting uses an unconventional directory structure so the linter marks this as a violation, server files should - // be moved under reporting/server/ - // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../../../src/plugins/data/server'; -import { CancellationToken } from '../../../../common/cancellation_token'; +import { CancellationToken } from '../../../../../../../plugins/reporting/common'; import { ReportingCore } from '../../../../server'; -import { Logger, RequestFacade } from '../../../../types'; +import { LevelLogger } from '../../../../server/lib'; +import { RequestFacade } from '../../../../server/types'; import { createGenerateCsv } from '../../../csv/server/lib/generate_csv'; import { CsvResultFromSearch, @@ -58,7 +56,7 @@ const getUiSettings = async (config: IUiSettingsClient) => { export async function generateCsvSearch( req: RequestFacade, reporting: ReportingCore, - logger: Logger, + logger: LevelLogger, searchPanel: SearchPanel, jobParams: JobParamsDiscoverCsv ): Promise { diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.test.ts index 1acb269e75493..110ce91ddfd79 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.test.ts @@ -4,12 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - QueryFilter, - SavedSearchObjectAttributes, - SearchSourceFilter, - TimeRangeParams, -} from '../../types'; +import { TimeRangeParams } from '../../../../server/types'; +import { QueryFilter, SavedSearchObjectAttributes, SearchSourceFilter } from '../../types'; import { getFilters } from './get_filters'; interface Args { diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.ts index 0e510eeb4073b..071427f4dab64 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_filters.ts @@ -6,14 +6,8 @@ import { badRequest } from 'boom'; import moment from 'moment-timezone'; - -import { - Filter, - QueryFilter, - SavedSearchObjectAttributes, - SearchSourceFilter, - TimeRangeParams, -} from '../../types'; +import { TimeRangeParams } from '../../../../server/types'; +import { Filter, QueryFilter, SavedSearchObjectAttributes, SearchSourceFilter } from '../../types'; export function getFilters( indexPatternId: string, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts index 8e5440b700d1e..57d74ee0e1383 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestFacade } from '../../../../types'; -import { JobParamsPostPayloadPanelCsv, JobParamsPanelCsv } from '../../types'; +import { RequestFacade } from '../../../../server/types'; +import { JobParamsPanelCsv, JobParamsPostPayloadPanelCsv } from '../../types'; export function getJobParamsFromRequest( request: RequestFacade, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts index ab14d2dd8a660..f838268078503 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { JobDocPayload, JobParamPostPayload } from '../../types'; +import { JobDocPayload, JobParamPostPayload, TimeRangeParams } from '../../server/types'; export interface FakeRequest { headers: Record; @@ -114,12 +114,6 @@ export interface IndexPatternSavedObject { }; } -export interface TimeRangeParams { - timezone: string; - min: Date | string | number; - max: Date | string | number; -} - export interface VisPanel { indexPatternSavedObjectId?: string; savedSearchObjectId?: string; diff --git a/x-pack/legacy/plugins/reporting/export_types/png/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/index.ts index b6206a8bf9599..04f56185d4910 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/index.ts @@ -5,18 +5,22 @@ */ import { - PNG_JOB_TYPE as jobType, - LICENSE_TYPE_TRIAL, - LICENSE_TYPE_STANDARD, + LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, - LICENSE_TYPE_ENTERPRISE, + LICENSE_TYPE_STANDARD, + LICENSE_TYPE_TRIAL, + PNG_JOB_TYPE as jobType, } from '../../common/constants'; -import { ExportTypeDefinition, ESQueueCreateJobFn, ESQueueWorkerExecuteFn } from '../../types'; +import { + ESQueueCreateJobFn, + ESQueueWorkerExecuteFn, + ExportTypeDefinition, +} from '../../server/types'; +import { metadata } from './metadata'; import { createJobFactory } from './server/create_job'; import { executeJobFactory } from './server/execute_job'; -import { metadata } from './metadata'; -import { JobParamsPNG, JobDocPayloadPNG } from './types'; +import { JobDocPayloadPNG, JobParamsPNG } from './types'; export const getExportType = (): ExportTypeDefinition< JobParamsPNG, diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts index 1f834bde88a2d..b19513de29eee 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts @@ -6,13 +6,13 @@ import { validateUrls } from '../../../../common/validate_urls'; import { ReportingCore } from '../../../../server'; -import { cryptoFactory } from '../../../../server/lib/crypto'; +import { cryptoFactory } from '../../../../server/lib'; import { ConditionalHeaders, CreateJobFactory, ESQueueCreateJobFn, RequestFacade, -} from '../../../../types'; +} from '../../../../server/types'; import { JobParamsPNG } from '../../types'; export const createJobFactory: CreateJobFactory { const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); - const generatePngObservable = (await generatePngObservableFactory(mockReporting)) as jest.Mock; - generatePngObservable.mockReturnValue(Rx.of('foo')); + const generatePngObservable = await generatePngObservableFactory(mockReporting); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of('foo')); const { content_type: contentType } = await executeJob( 'pngJobId', @@ -138,9 +137,8 @@ test(`returns content_type of application/png`, async () => { test(`returns content of generatePng getBuffer base64 encoded`, async () => { const testContent = 'raw string from get_screenhots'; - - const generatePngObservable = (await generatePngObservableFactory(mockReporting)) as jest.Mock; - generatePngObservable.mockReturnValue(Rx.of({ base64: testContent })); + const generatePngObservable = await generatePngObservableFactory(mockReporting); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ base64: testContent })); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts index 88c2d8a9fe4bb..c1a2c12cd9f82 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts @@ -9,7 +9,8 @@ import * as Rx from 'rxjs'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; import { PNG_JOB_TYPE } from '../../../../common/constants'; import { ReportingCore } from '../../../../server'; -import { ESQueueWorkerExecuteFn, ExecuteJobFactory, JobDocOutput, Logger } from '../../../../types'; +import { LevelLogger } from '../../../../server/lib'; +import { ESQueueWorkerExecuteFn, ExecuteJobFactory, JobDocOutput } from '../../../../server/types'; import { decryptJobHeaders, getConditionalHeaders, @@ -23,7 +24,7 @@ type QueuedPngExecutorFactory = ExecuteJobFactory ({ generatePdfObservableFactory: jest.fn() })); + import * as Rx from 'rxjs'; -import { createMockReportingCore } from '../../../../test_helpers'; -import { cryptoFactory } from '../../../../server/lib/crypto'; -import { LevelLogger } from '../../../../server/lib'; -import { CancellationToken } from '../../../../types'; +import { CancellationToken } from '../../../../../../../plugins/reporting/common'; import { ReportingCore } from '../../../../server'; -import { generatePdfObservableFactory } from '../lib/generate_pdf'; +import { cryptoFactory, LevelLogger } from '../../../../server/lib'; +import { createMockReportingCore } from '../../../../test_helpers'; import { JobDocPayloadPDF } from '../../types'; +import { generatePdfObservableFactory } from '../lib/generate_pdf'; import { executeJobFactory } from './index'; -jest.mock('../lib/generate_pdf', () => ({ generatePdfObservableFactory: jest.fn() })); - let mockReporting: ReportingCore; const cancellationToken = ({ @@ -44,6 +43,7 @@ beforeEach(async () => { 'server.basePath': '/sbp', }; const reportingConfig = { + index: '.reports-test', encryptionKey: mockEncryptionKey, 'kibanaServer.hostname': 'localhost', 'kibanaServer.port': 5601, diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts index 5aad66c53a998..619e3e9db70ad 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts @@ -9,7 +9,8 @@ import * as Rx from 'rxjs'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; import { PDF_JOB_TYPE } from '../../../../common/constants'; import { ReportingCore } from '../../../../server'; -import { ESQueueWorkerExecuteFn, ExecuteJobFactory, JobDocOutput, Logger } from '../../../../types'; +import { LevelLogger } from '../../../../server/lib'; +import { ESQueueWorkerExecuteFn, ExecuteJobFactory, JobDocOutput } from '../../../../server/types'; import { decryptJobHeaders, getConditionalHeaders, @@ -24,7 +25,7 @@ type QueuedPdfExecutorFactory = ExecuteJobFactory { const grouped = groupBy(urlScreenshots.map(u => u.timeRange)); @@ -62,7 +60,7 @@ export async function generatePdfObservableFactory(reporting: ReportingCore) { const pdfOutput = pdf.create(layout, logo); if (title) { const timeRange = getTimeRange(results); - title += timeRange ? ` - ${timeRange.duration}` : ''; + title += timeRange ? ` - ${timeRange}` : ''; pdfOutput.setTitle(title); } tracker.endSetup(); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts index e8dd3c5207d92..0df01fdc16d1c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { JobDocPayload } from '../../types'; -import { LayoutInstance, LayoutParams } from '../common/layouts/layout'; +import { JobDocPayload } from '../../server/types'; +import { LayoutInstance, LayoutParams } from '../common/layouts'; // Job params: structure of incoming user request data, after being parsed from RISON export interface JobParamsPDF { diff --git a/x-pack/legacy/plugins/reporting/index.ts b/x-pack/legacy/plugins/reporting/index.ts index fb95e2c2edc24..1ae971b6566b0 100644 --- a/x-pack/legacy/plugins/reporting/index.ts +++ b/x-pack/legacy/plugins/reporting/index.ts @@ -9,7 +9,8 @@ import { Legacy } from 'kibana'; import { resolve } from 'path'; import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; import { legacyInit } from './server/legacy'; -import { ReportingPluginSpecOptions } from './types'; + +export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions; const kbToBase64Length = (kb: number) => Math.floor((kb * 1024 * 8) / 6); diff --git a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts index dd20e849d97a9..3dce8bf4e6819 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts @@ -7,18 +7,12 @@ import { i18n } from '@kbn/i18n'; import { map, trunc } from 'lodash'; import open from 'opn'; -import { ElementHandle, EvaluateFn, Page, SerializableOrJSHandle, Response } from 'puppeteer'; +import { ElementHandle, EvaluateFn, Page, Response, SerializableOrJSHandle } from 'puppeteer'; import { parse as parseUrl } from 'url'; import { ViewZoomWidthHeight } from '../../../../export_types/common/layouts/layout'; -import { LevelLogger } from '../../../../server/lib'; -import { - ConditionalHeaders, - ConditionalHeadersConditions, - ElementPosition, - InterceptedRequest, - NetworkPolicy, -} from '../../../../types'; -import { allowRequest } from '../../network_policy'; +import { LevelLogger } from '../../../lib'; +import { ConditionalHeaders, ElementPosition } from '../../../types'; +import { allowRequest, NetworkPolicy } from '../../network_policy'; export interface ChromiumDriverOptions { inspect: boolean; @@ -38,6 +32,23 @@ interface EvaluateMetaOpts { context: string; } +type ConditionalHeadersConditions = ConditionalHeaders['conditions']; + +interface InterceptedRequest { + requestId: string; + request: { + url: string; + method: string; + headers: { + [key: string]: string; + }; + initialPriority: string; + referrerPolicy: string; + }; + frameId: string; + resourceType: string; +} + const WAIT_FOR_DELAY_MS: number = 100; export class HeadlessChromiumDriver { diff --git a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts index cb228150efbcd..3189b262ea1bd 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts @@ -21,7 +21,7 @@ import { InnerSubscriber } from 'rxjs/internal/InnerSubscriber'; import { ignoreElements, map, mergeMap, tap } from 'rxjs/operators'; import { BROWSER_TYPE } from '../../../../common/constants'; import { CaptureConfig } from '../../../../server/types'; -import { LevelLogger as Logger } from '../../../lib/level_logger'; +import { LevelLogger } from '../../../lib'; import { safeChildProcess } from '../../safe_child_process'; import { HeadlessChromiumDriver } from '../driver'; import { getChromeLogLocation } from '../paths'; @@ -39,7 +39,7 @@ export class HeadlessChromiumDriverFactory { private userDataDir: string; private getChromiumArgs: (viewport: ViewportConfig) => string[]; - constructor(binaryPath: binaryPath, logger: Logger, captureConfig: CaptureConfig) { + constructor(binaryPath: binaryPath, logger: LevelLogger, captureConfig: CaptureConfig) { this.binaryPath = binaryPath; this.captureConfig = captureConfig; this.browserConfig = captureConfig.browser.chromium; @@ -56,7 +56,7 @@ export class HeadlessChromiumDriverFactory { type = BROWSER_TYPE; - test(logger: Logger) { + test(logger: LevelLogger) { const chromiumArgs = args({ userDataDir: this.userDataDir, viewport: { width: 800, height: 600 }, @@ -84,7 +84,7 @@ export class HeadlessChromiumDriverFactory { */ createPage( { viewport, browserTimezone }: { viewport: ViewportConfig; browserTimezone: string }, - pLogger: Logger + pLogger: LevelLogger ): Rx.Observable<{ driver: HeadlessChromiumDriver; exit$: Rx.Observable }> { return Rx.Observable.create(async (observer: InnerSubscriber) => { const logger = pLogger.clone(['browser-driver']); @@ -172,7 +172,7 @@ export class HeadlessChromiumDriverFactory { }); } - getBrowserLogger(page: Page, logger: Logger): Rx.Observable { + getBrowserLogger(page: Page, logger: LevelLogger): Rx.Observable { const consoleMessages$ = Rx.fromEvent(page, 'console').pipe( map(line => { if (line.type() === 'error') { @@ -197,7 +197,7 @@ export class HeadlessChromiumDriverFactory { return Rx.merge(consoleMessages$, pageRequestFailed$); } - getProcessLogger(browser: Browser, logger: Logger): Rx.Observable { + getProcessLogger(browser: Browser, logger: LevelLogger): Rx.Observable { const childProcess = browser.process(); // NOTE: The browser driver can not observe stdout and stderr of the child process // Puppeteer doesn't give a handle to the original ChildProcess object diff --git a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts index af3b86919dc50..7b4407890652c 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger } from '../../types'; -import { ReportingConfig } from '../types'; +import { ReportingConfig } from '../'; +import { LevelLogger } from '../lib'; import { HeadlessChromiumDriverFactory } from './chromium/driver_factory'; import { ensureBrowserDownloaded } from './download'; import { chromium } from './index'; @@ -13,7 +13,7 @@ import { installBrowser } from './install'; export async function createBrowserDriverFactory( config: ReportingConfig, - logger: Logger + logger: LevelLogger ): Promise { const captureConfig = config.get('capture'); const browserConfig = captureConfig.browser.chromium; diff --git a/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts b/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts index 3697c4b86ce3c..1170e53669e33 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts @@ -6,9 +6,8 @@ import { existsSync } from 'fs'; import { resolve as resolvePath } from 'path'; +import { BrowserDownload, chromium } from '../'; import { BROWSER_TYPE } from '../../../common/constants'; -import { chromium } from '../index'; -import { BrowserDownload } from '../types'; import { md5 } from './checksum'; import { clean } from './clean'; import { download } from './download'; diff --git a/x-pack/legacy/plugins/reporting/server/browsers/index.ts b/x-pack/legacy/plugins/reporting/server/browsers/index.ts index 7f902c84308f6..7f6e40fb433b6 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/index.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/index.ts @@ -16,3 +16,17 @@ export const chromium = { paths: chromiumDefinition.paths, createDriverFactory: chromiumDefinition.createDriverFactory, }; + +export interface BrowserDownload { + paths: { + archivesPath: string; + baseUrl: string; + packages: Array<{ + archiveChecksum: string; + archiveFilename: string; + binaryChecksum: string; + binaryRelativePath: string; + platforms: string[]; + }>; + }; +} diff --git a/x-pack/legacy/plugins/reporting/server/browsers/install.ts b/x-pack/legacy/plugins/reporting/server/browsers/install.ts index 6f099c36e69f2..01526af307022 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/install.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/install.ts @@ -7,12 +7,12 @@ import fs from 'fs'; import path from 'path'; import { promisify } from 'util'; -import { LevelLogger as Logger } from '../lib/level_logger'; -// @ts-ignore -import { extract } from './extract'; +import { LevelLogger } from '../lib'; +import { BrowserDownload } from './'; // @ts-ignore import { md5 } from './download/checksum'; -import { BrowserDownload } from './types'; +// @ts-ignore +import { extract } from './extract'; const chmod = promisify(fs.chmod); @@ -28,7 +28,7 @@ interface PathResponse { * archive. If there is an error extracting the archive an `ExtractError` is thrown */ export async function installBrowser( - logger: Logger, + logger: LevelLogger, browser: BrowserDownload, installsPath: string ): Promise { diff --git a/x-pack/legacy/plugins/reporting/server/browsers/network_policy.ts b/x-pack/legacy/plugins/reporting/server/browsers/network_policy.ts index 9714c5965a5db..158362cee3c7e 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/network_policy.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/network_policy.ts @@ -6,7 +6,17 @@ import * as _ from 'lodash'; import { parse } from 'url'; -import { NetworkPolicyRule } from '../../types'; + +interface NetworkPolicyRule { + allow: boolean; + protocol?: string; + host?: string; +} + +export interface NetworkPolicy { + enabled: boolean; + rules: NetworkPolicyRule[]; +} const isHostMatch = (actualHost: string, ruleHost: string) => { const hostParts = actualHost.split('.').reverse(); diff --git a/x-pack/legacy/plugins/reporting/server/browsers/safe_child_process.ts b/x-pack/legacy/plugins/reporting/server/browsers/safe_child_process.ts index e22d3662a33b4..6f86a62c21575 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/safe_child_process.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/safe_child_process.ts @@ -6,7 +6,7 @@ import * as Rx from 'rxjs'; import { take, share, mapTo, delay, tap } from 'rxjs/operators'; -import { Logger } from '../../types'; +import { LevelLogger } from '../lib'; interface IChild { kill: (signal: string) => Promise; @@ -15,7 +15,7 @@ interface IChild { // Our process can get sent various signals, and when these occur we wish to // kill the subprocess and then kill our process as long as the observer isn't cancelled export function safeChildProcess( - logger: Logger, + logger: LevelLogger, childProcess: IChild ): { terminate$: Rx.Observable } { const ownTerminateSignal$ = Rx.merge( diff --git a/x-pack/legacy/plugins/reporting/server/browsers/types.d.ts b/x-pack/legacy/plugins/reporting/server/browsers/types.d.ts deleted file mode 100644 index f096073ec2f5f..0000000000000 --- a/x-pack/legacy/plugins/reporting/server/browsers/types.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export interface BrowserDownload { - paths: { - archivesPath: string; - baseUrl: string; - packages: Array<{ - archiveChecksum: string; - archiveFilename: string; - binaryChecksum: string; - binaryRelativePath: string; - platforms: string[]; - }>; - }; -} diff --git a/x-pack/legacy/plugins/reporting/server/config/index.ts b/x-pack/legacy/plugins/reporting/server/config/index.ts index c6b915be3a94a..3ec5aab4d451b 100644 --- a/x-pack/legacy/plugins/reporting/server/config/index.ts +++ b/x-pack/legacy/plugins/reporting/server/config/index.ts @@ -5,10 +5,9 @@ */ import { Legacy } from 'kibana'; -import { CoreSetup } from 'src/core/server'; import { get } from 'lodash'; +import { CoreSetup } from 'src/core/server'; import { ConfigType as ReportingConfigType } from '../../../../../plugins/reporting/server'; -export { ReportingConfigType }; // make config.get() aware of the value type it returns interface Config { @@ -85,3 +84,5 @@ export const buildConfig = ( }, }; }; + +export { ReportingConfigType }; diff --git a/x-pack/legacy/plugins/reporting/server/core.ts b/x-pack/legacy/plugins/reporting/server/core.ts index 0b243f13adb80..8fb948a253c16 100644 --- a/x-pack/legacy/plugins/reporting/server/core.ts +++ b/x-pack/legacy/plugins/reporting/server/core.ts @@ -8,26 +8,25 @@ import * as Rx from 'rxjs'; import { first, mapTo } from 'rxjs/operators'; import { ElasticsearchServiceSetup, - IUiSettingsClient, KibanaRequest, SavedObjectsClient, SavedObjectsServiceStart, UiSettingsServiceStart, } from 'src/core/server'; +import { ReportingPluginSpecOptions } from '../'; // @ts-ignore no module definition import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; import { PLUGIN_ID } from '../common/constants'; -import { EnqueueJobFn, ESQueueInstance, ReportingPluginSpecOptions, ServerFacade } from '../types'; +import { screenshotsObservableFactory } from '../export_types/common/lib/screenshots'; +import { ServerFacade } from '../server/types'; +import { ReportingConfig } from './'; import { HeadlessChromiumDriverFactory } from './browsers/chromium/driver_factory'; -import { ReportingConfig, ReportingConfigType } from './config'; import { checkLicenseFactory, getExportTypesRegistry, LevelLogger } from './lib'; +import { ESQueueInstance } from './lib/create_queue'; +import { EnqueueJobFn } from './lib/enqueue_job'; import { registerRoutes } from './routes'; import { ReportingSetupDeps } from './types'; -import { - screenshotsObservableFactory, - ScreenshotsObservableFn, -} from '../export_types/common/lib/screenshots'; interface ReportingInternalSetup { browserDriverFactory: HeadlessChromiumDriverFactory; @@ -40,8 +39,6 @@ interface ReportingInternalStart { uiSettings: UiSettingsServiceStart; } -export { ReportingConfig, ReportingConfigType }; - export class ReportingCore { private pluginSetupDeps?: ReportingInternalSetup; private pluginStartDeps?: ReportingInternalStart; @@ -91,18 +88,18 @@ export class ReportingCore { return this.exportTypesRegistry; } - public async getEsqueue(): Promise { + public async getEsqueue() { return (await this.getPluginStartDeps()).esqueue; } - public async getEnqueueJob(): Promise { + public async getEnqueueJob() { return (await this.getPluginStartDeps()).enqueueJob; } - public getConfig(): ReportingConfig { + public getConfig() { return this.config; } - public async getScreenshotsObservable(): Promise { + public async getScreenshotsObservable() { const { browserDriverFactory } = await this.getPluginSetupDeps(); return screenshotsObservableFactory(this.config.get('capture'), browserDriverFactory); } @@ -110,32 +107,30 @@ export class ReportingCore { /* * Outside dependencies */ - private async getPluginSetupDeps(): Promise { + private async getPluginSetupDeps() { if (this.pluginSetupDeps) { return this.pluginSetupDeps; } return await this.pluginSetup$.pipe(first()).toPromise(); } - private async getPluginStartDeps(): Promise { + private async getPluginStartDeps() { if (this.pluginStartDeps) { return this.pluginStartDeps; } return await this.pluginStart$.pipe(first()).toPromise(); } - public async getElasticsearchService(): Promise { + public async getElasticsearchService() { return (await this.getPluginSetupDeps()).elasticsearch; } - public async getSavedObjectsClient(fakeRequest: KibanaRequest): Promise { + public async getSavedObjectsClient(fakeRequest: KibanaRequest) { const { savedObjects } = await this.getPluginStartDeps(); return savedObjects.getScopedClient(fakeRequest) as SavedObjectsClient; } - public async getUiSettingsServiceFactory( - savedObjectsClient: SavedObjectsClient - ): Promise { + public async getUiSettingsServiceFactory(savedObjectsClient: SavedObjectsClient) { const { uiSettings: uiSettingsService } = await this.getPluginStartDeps(); const scopedUiSettingsService = uiSettingsService.asScopedToClient(savedObjectsClient); return scopedUiSettingsService; diff --git a/x-pack/legacy/plugins/reporting/server/index.ts b/x-pack/legacy/plugins/reporting/server/index.ts index 4288a37fe6adc..2388eac48f8cc 100644 --- a/x-pack/legacy/plugins/reporting/server/index.ts +++ b/x-pack/legacy/plugins/reporting/server/index.ts @@ -5,8 +5,9 @@ */ import { PluginInitializerContext } from 'src/core/server'; +import { ReportingConfig } from './config'; +import { ReportingCore } from './core'; import { ReportingPlugin as Plugin } from './plugin'; -import { ReportingConfig, ReportingCore } from './core'; export const plugin = (context: PluginInitializerContext, config: ReportingConfig) => { return new Plugin(context, config); @@ -14,5 +15,3 @@ export const plugin = (context: PluginInitializerContext, config: ReportingConfi export { ReportingPlugin } from './plugin'; export { ReportingConfig, ReportingCore }; - -export { PreserveLayout, PrintLayout } from '../export_types/common/layouts'; diff --git a/x-pack/legacy/plugins/reporting/server/legacy.ts b/x-pack/legacy/plugins/reporting/server/legacy.ts index d044dc866ed0e..87ffe75e454b1 100644 --- a/x-pack/legacy/plugins/reporting/server/legacy.ts +++ b/x-pack/legacy/plugins/reporting/server/legacy.ts @@ -7,9 +7,9 @@ import { Legacy } from 'kibana'; import { take } from 'rxjs/operators'; import { PluginInitializerContext } from 'src/core/server'; +import { ReportingPluginSpecOptions } from '../'; import { PluginsSetup } from '../../../../plugins/reporting/server'; import { SecurityPluginSetup } from '../../../../plugins/security/server'; -import { ReportingPluginSpecOptions } from '../types'; import { buildConfig } from './config'; import { plugin } from './index'; import { LegacySetup, ReportingStartDeps } from './types'; diff --git a/x-pack/legacy/plugins/reporting/server/lib/check_license.ts b/x-pack/legacy/plugins/reporting/server/lib/check_license.ts index 02e1196f1d00d..b25021c2ed09b 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/check_license.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/check_license.ts @@ -6,7 +6,8 @@ import { XPackInfo } from '../../../xpack_main/server/lib/xpack_info'; import { XPackInfoLicense } from '../../../xpack_main/server/lib/xpack_info_license'; -import { ExportTypesRegistry, ExportTypeDefinition } from '../../types'; +import { ExportTypeDefinition } from '../types'; +import { ExportTypesRegistry } from './export_types_registry'; interface LicenseCheckResult { showLinks: boolean; diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 560cc943ed45e..2cac4bd654487 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -4,16 +4,42 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESQueueInstance, Logger } from '../../types'; import { ReportingCore } from '../core'; +import { JobDocOutput, JobSource } from '../types'; import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed import { createWorkerFactory } from './create_worker'; +import { Job } from './enqueue_job'; // @ts-ignore import { Esqueue } from './esqueue'; +import { LevelLogger } from './level_logger'; + +interface ESQueueWorker { + on: (event: string, handler: any) => void; +} + +export interface ESQueueInstance { + addJob: (type: string, payload: unknown, options: object) => Job; + registerWorker: ( + pluginId: string, + workerFn: GenericWorkerFn, + workerOptions: { + kibanaName: string; + kibanaId: string; + interval: number; + intervalErrorMultiplier: number; + } + ) => ESQueueWorker; +} + +// GenericWorkerFn is a generic for ImmediateExecuteFn | ESQueueWorkerExecuteFn, +type GenericWorkerFn = ( + jobSource: JobSource, + ...workerRestArgs: any[] +) => void | Promise; export async function createQueueFactory( reporting: ReportingCore, - logger: Logger + logger: LevelLogger ): Promise { const config = reporting.getConfig(); const queueIndexInterval = config.get('queue', 'indexInterval'); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts index 97b34dfe40830..aaed46e629ccc 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger } from '../../types'; +import { LevelLogger } from './level_logger'; -export function createTaggedLogger(logger: Logger, tags: string[]) { +export function createTaggedLogger(logger: LevelLogger, tags: string[]) { return (msg: string, additionalTags = []) => { const allTags = [...tags, ...additionalTags]; diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index ad8db3201844e..1193091075e3e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -5,7 +5,7 @@ */ import * as sinon from 'sinon'; -import { ReportingConfig, ReportingCore } from '../../server/types'; +import { ReportingConfig, ReportingCore } from '../../server'; import { createMockReportingCore } from '../../test_helpers'; import { createWorkerFactory } from './create_worker'; // @ts-ignore diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index ad0f05c02a1f4..57bd61aee7195 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -4,20 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CancellationToken } from '../../common/cancellation_token'; +import { CancellationToken } from '../../../../../plugins/reporting/common'; import { PLUGIN_ID } from '../../common/constants'; -import { ReportingCore } from '../../server/types'; -import { - ESQueueInstance, - ESQueueWorkerExecuteFn, - ExportTypeDefinition, - JobSource, - Logger, -} from '../../types'; +import { ReportingCore } from '../../server'; +import { LevelLogger } from '../../server/lib'; +import { ESQueueWorkerExecuteFn, ExportTypeDefinition, JobSource } from '../../server/types'; +import { ESQueueInstance } from './create_queue'; // @ts-ignore untyped dependency import { events as esqueueEvents } from './esqueue'; -export function createWorkerFactory(reporting: ReportingCore, logger: Logger) { +export function createWorkerFactory(reporting: ReportingCore, logger: LevelLogger) { const config = reporting.getConfig(); const queueConfig = config.get('queue'); const kibanaName = config.kbnConfig.get('server', 'name'); diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index 8f33d9b73566c..8ffb99f7a14c8 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -4,18 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { EventEmitter } from 'events'; import { get } from 'lodash'; -import { - ConditionalHeaders, - EnqueueJobFn, - ESQueueCreateJobFn, - Job, - Logger, - RequestFacade, -} from '../../types'; +import { ConditionalHeaders, ESQueueCreateJobFn, RequestFacade } from '../../server/types'; import { ReportingCore } from '../core'; // @ts-ignore import { events as esqueueEvents } from './esqueue'; +import { LevelLogger } from './level_logger'; interface ConfirmedJob { id: string; @@ -24,7 +19,25 @@ interface ConfirmedJob { _primary_term: number; } -export function enqueueJobFactory(reporting: ReportingCore, parentLogger: Logger): EnqueueJobFn { +export type Job = EventEmitter & { + id: string; + toJSON: () => { + id: string; + }; +}; + +export type EnqueueJobFn = ( + exportTypeId: string, + jobParams: JobParamsType, + user: string, + headers: Record, + request: RequestFacade +) => Promise; + +export function enqueueJobFactory( + reporting: ReportingCore, + parentLogger: LevelLogger +): EnqueueJobFn { const config = reporting.getConfig(); const queueTimeout = config.get('queue', 'timeout'); const browserType = config.get('capture', 'browser', 'type'); diff --git a/x-pack/legacy/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js b/x-pack/legacy/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js deleted file mode 100644 index 4b77b936db8a8..0000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { CancellationToken } from '../../../../../common/cancellation_token'; - -describe('CancellationToken', function() { - let cancellationToken; - beforeEach(function() { - cancellationToken = new CancellationToken(); - }); - - describe('on', function() { - [true, null, undefined, 1, 'string', {}, []].forEach(function(value) { - it(`should throw an Error if value is ${value}`, function() { - expect(cancellationToken.on) - .withArgs(value) - .to.throwError(); - }); - }); - - it('accepts a function', function() { - expect(cancellationToken.on) - .withArgs(function() {}) - .not.to.throwError(); - }); - - it(`calls function if cancel has previously been called`, function() { - const spy = sinon.spy(); - cancellationToken.cancel(); - cancellationToken.on(spy); - expect(spy.calledOnce).to.be(true); - }); - }); - - describe('cancel', function() { - it('should be a function accepting no parameters', function() { - expect(cancellationToken.cancel) - .withArgs() - .to.not.throwError(); - }); - - it('should call a single callback', function() { - const spy = sinon.spy(); - cancellationToken.on(spy); - cancellationToken.cancel(); - expect(spy.calledOnce).to.be(true); - }); - - it('should call two callbacks', function() { - const spy1 = sinon.spy(); - const spy2 = sinon.spy(); - cancellationToken.on(spy1); - cancellationToken.on(spy2); - cancellationToken.cancel(); - expect(spy1.calledOnce).to.be(true); - expect(spy2.calledOnce).to.be(true); - }); - }); - - describe('isCancelled', function() { - it('should default to false', function() { - expect(cancellationToken.isCancelled()).to.be(false); - }); - - it('should switch to true after call to cancel', function() { - cancellationToken.cancel(); - expect(cancellationToken.isCancelled()).to.be(true); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/server/lib/esqueue/worker.js b/x-pack/legacy/plugins/reporting/server/lib/esqueue/worker.js index ab0bb6740f078..17a7fd0e9a26f 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/esqueue/worker.js +++ b/x-pack/legacy/plugins/reporting/server/lib/esqueue/worker.js @@ -5,12 +5,12 @@ */ import events from 'events'; -import Puid from 'puid'; import moment from 'moment'; -import { constants } from './constants'; -import { WorkerTimeoutError, UnspecifiedWorkerError } from './helpers/errors'; -import { CancellationToken } from '../../../common/cancellation_token'; +import Puid from 'puid'; +import { CancellationToken } from '../../../../../../plugins/reporting/common'; import { Poller } from '../../../../../common/poller'; +import { constants } from './constants'; +import { UnspecifiedWorkerError, WorkerTimeoutError } from './helpers/errors'; const puid = new Puid(); diff --git a/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts b/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts index d553cc07ae3ef..ecaabb305e23e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import memoizeOne from 'memoize-one'; import { isString } from 'lodash'; +import memoizeOne from 'memoize-one'; import { getExportType as getTypeCsv } from '../../export_types/csv'; import { getExportType as getTypeCsvFromSavedObject } from '../../export_types/csv_from_savedobject'; import { getExportType as getTypePng } from '../../export_types/png'; import { getExportType as getTypePrintablePdf } from '../../export_types/printable_pdf'; -import { ExportTypeDefinition } from '../../types'; +import { ExportTypeDefinition } from '../types'; type GetCallbackFn = ( item: ExportTypeDefinition diff --git a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts index 5e73fe77ecb79..8e8b1c83d5a40 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts @@ -6,10 +6,10 @@ import { Legacy } from 'kibana'; import { KibanaRequest } from '../../../../../../src/core/server'; -import { Logger } from '../../types'; import { ReportingSetupDeps } from '../types'; +import { LevelLogger } from './level_logger'; -export function getUserFactory(security: ReportingSetupDeps['security'], logger: Logger) { +export function getUserFactory(security: ReportingSetupDeps['security'], logger: LevelLogger) { /* * Legacy.Request because this is called from routing middleware */ diff --git a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts index 0affc111c1368..e0c9fc05ea2b4 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts @@ -9,8 +9,8 @@ import Boom from 'boom'; import { errors as elasticsearchErrors } from 'elasticsearch'; import { ElasticsearchServiceSetup } from 'kibana/server'; import { get } from 'lodash'; -import { JobSource } from '../../types'; -import { ReportingConfig } from '../types'; +import { ReportingConfig } from '../'; +import { JobSource } from '../types'; const esErrors = elasticsearchErrors as Record; const defaultSize = 10; diff --git a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts b/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts deleted file mode 100644 index ae3636079a9bb..0000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { memoize, MemoizedFunction } from 'lodash'; -import { ServerFacade } from '../../types'; - -type ServerFn = (server: ServerFacade) => any; -type Memo = ((server: ServerFacade) => any) & MemoizedFunction; - -/** - * allow this function to be called multiple times, but - * ensure that it only received one argument, the server, - * and cache the return value so that subsequent calls get - * the exact same value. - * - * This is intended to be used by service factories like getObjectQueueFactory - * - * @param {Function} fn - the factory function - * @return {any} - */ -export function oncePerServer(fn: ServerFn) { - const memoized: Memo = memoize(function(server: ServerFacade) { - if (arguments.length !== 1) { - throw new TypeError('This function expects to be called with a single argument'); - } - - // @ts-ignore - return fn.call(this, server); - }); - - // @ts-ignore - // Type 'WeakMap' is not assignable to type 'MapCache - - // use a weak map a the cache so that: - // 1. return values mapped to the actual server instance - // 2. return value lifecycle matches that of the server - memoized.cache = new WeakMap(); - - return memoized; -} diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts index 85d9f727d7fa7..404cbcda31a09 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts @@ -6,9 +6,9 @@ import { i18n } from '@kbn/i18n'; import { ElasticsearchServiceSetup } from 'kibana/server'; -import { Logger } from '../../../types'; +import { ReportingConfig } from '../../'; +import { LevelLogger } from '../../lib'; import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_factory'; -import { ReportingConfig } from '../../types'; import { validateBrowser } from './validate_browser'; import { validateMaxContentLength } from './validate_max_content_length'; @@ -16,7 +16,7 @@ export async function runValidations( config: ReportingConfig, elasticsearch: ElasticsearchServiceSetup, browserFactory: HeadlessChromiumDriverFactory, - logger: Logger + logger: LevelLogger ) { try { await Promise.all([ diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts index d6512d5eb718b..d29aa522dad90 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts @@ -6,8 +6,8 @@ import { Browser } from 'puppeteer'; import { BROWSER_TYPE } from '../../../common/constants'; -import { Logger } from '../../../types'; import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_factory'; +import { LevelLogger } from '../'; /* * Validate the Reporting headless browser can launch, and that it can connect @@ -15,7 +15,7 @@ import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_fa */ export const validateBrowser = async ( browserFactory: HeadlessChromiumDriverFactory, - logger: Logger + logger: LevelLogger ) => { if (browserFactory.type === BROWSER_TYPE) { return browserFactory.test(logger).then((browser: Browser | null) => { diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts index a20905ba093d4..f6acf72612e01 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts @@ -7,8 +7,8 @@ import numeral from '@elastic/numeral'; import { ElasticsearchServiceSetup } from 'kibana/server'; import { defaults, get } from 'lodash'; -import { Logger } from '../../../types'; -import { ReportingConfig } from '../../types'; +import { ReportingConfig } from '../../'; +import { LevelLogger } from '../../lib'; const KIBANA_MAX_SIZE_BYTES_PATH = 'csv.maxSizeBytes'; const ES_MAX_SIZE_BYTES_PATH = 'http.max_content_length'; @@ -16,7 +16,7 @@ const ES_MAX_SIZE_BYTES_PATH = 'http.max_content_length'; export async function validateMaxContentLength( config: ReportingConfig, elasticsearch: ElasticsearchServiceSetup, - logger: Logger + logger: LevelLogger ) { const { callAsInternalUser } = elasticsearch.dataClient; diff --git a/x-pack/legacy/plugins/reporting/server/plugin.ts b/x-pack/legacy/plugins/reporting/server/plugin.ts index e0fa99106a93e..78c2ce5b9b106 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -6,7 +6,8 @@ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/server'; import { createBrowserDriverFactory } from './browsers'; -import { ReportingCore, ReportingConfig } from './core'; +import { ReportingConfig } from './config'; +import { ReportingCore } from './core'; import { createQueueFactory, enqueueJobFactory, LevelLogger, runValidations } from './lib'; import { setFieldFormats } from './services'; import { ReportingSetup, ReportingSetupDeps, ReportingStart, ReportingStartDeps } from './types'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts index 6b4f5dbd9203a..70a1a32e76a65 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts @@ -8,16 +8,17 @@ import boom from 'boom'; import Joi from 'joi'; import { Legacy } from 'kibana'; import rison from 'rison-node'; +import { ReportingCore } from '../'; import { API_BASE_URL } from '../../common/constants'; -import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { LevelLogger as Logger } from '../lib'; +import { ReportingSetupDeps, ServerFacade } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { GetRouteConfigFactoryFn, getRouteConfigFactoryReportingPre, RouteConfigFactory, } from './lib/route_config_factories'; -import { HandlerErrorFunction, HandlerFunction } from './types'; +import { HandlerErrorFunction, HandlerFunction, ReportingResponseToolkit } from './types'; const BASE_GENERATE = `${API_BASE_URL}/generate`; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts index 830953d532243..03a893d1abeb4 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts @@ -6,13 +6,19 @@ import { Legacy } from 'kibana'; import { get } from 'lodash'; +import { ReportingCore } from '../'; import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; -import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { LevelLogger as Logger } from '../lib'; +import { ReportingSetupDeps, ServerFacade } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { getRouteOptionsCsv } from './lib/route_config_factories'; -import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types'; +import { + HandlerErrorFunction, + HandlerFunction, + QueuedJobPayload, + ReportingResponseToolkit, +} from './types'; /* * This function registers API Endpoints for queuing Reporting jobs. The API inputs are: diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts index 519e49f56c377..22aebb05cdf49 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts @@ -4,21 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ResponseObject } from 'hapi'; import { Legacy } from 'kibana'; +import { ReportingCore } from '../'; import { API_BASE_GENERATE_V1 } from '../../common/constants'; import { createJobFactory, executeJobFactory } from '../../export_types/csv_from_savedobject'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; import { JobDocPayloadPanelCsv } from '../../export_types/csv_from_savedobject/types'; -import { - JobDocOutput, - Logger, - ReportingResponseToolkit, - ResponseFacade, - ServerFacade, -} from '../../types'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { LevelLogger as Logger } from '../lib'; +import { JobDocOutput, ReportingSetupDeps, ServerFacade } from '../types'; import { makeRequestFacade } from './lib/make_request_facade'; import { getRouteOptionsCsv } from './lib/route_config_factories'; +import { ReportingResponseToolkit } from './types'; + +type ResponseFacade = ResponseObject & { + isBoom: boolean; +}; /* * This function registers API Endpoints for immediate Reporting jobs. The API inputs are: diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.test.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.test.ts index 8e54feac3c8a6..74401f8228f7d 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.test.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.test.ts @@ -5,9 +5,11 @@ */ import Hapi from 'hapi'; +import { ReportingConfig, ReportingCore } from '../'; import { createMockReportingCore } from '../../test_helpers'; -import { Logger, ServerFacade } from '../../types'; -import { ReportingConfig, ReportingCore, ReportingSetupDeps } from '../types'; +import { LevelLogger as Logger } from '../lib'; +import { ReportingSetupDeps, ServerFacade } from '../types'; +import { registerJobGenerationRoutes } from './generation'; jest.mock('./lib/authorized_user_pre_routing', () => ({ authorizedUserPreRoutingFactory: () => () => ({}), @@ -18,8 +20,6 @@ jest.mock('./lib/reporting_feature_pre_routing', () => ({ }), })); -import { registerJobGenerationRoutes } from './generation'; - let mockServer: Hapi.Server; let mockReportingPlugin: ReportingCore; let mockReportingConfig: ReportingConfig; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 1c6129313db4b..56faa37d5fcbd 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -7,13 +7,15 @@ import boom from 'boom'; import { errors as elasticsearchErrors } from 'elasticsearch'; import { Legacy } from 'kibana'; +import { ReportingCore } from '../'; import { API_BASE_URL } from '../../common/constants'; -import { Logger, ReportingResponseToolkit, ServerFacade } from '../../types'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { LevelLogger as Logger } from '../lib'; +import { ReportingSetupDeps, ServerFacade } from '../types'; import { registerGenerateFromJobParams } from './generate_from_jobparams'; import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject'; import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_savedobject_immediate'; import { makeRequestFacade } from './lib/make_request_facade'; +import { ReportingResponseToolkit } from './types'; const esErrors = elasticsearchErrors as Record; diff --git a/x-pack/legacy/plugins/reporting/server/routes/index.ts b/x-pack/legacy/plugins/reporting/server/routes/index.ts index 610ab4907d369..556f4e12b077e 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/index.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/index.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, ServerFacade } from '../../types'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { ReportingCore } from '../'; +import { LevelLogger as Logger } from '../lib'; +import { ReportingSetupDeps, ServerFacade } from '../types'; import { registerJobGenerationRoutes } from './generation'; import { registerJobInfoRoutes } from './jobs'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts index 5c58a7dfa0110..4f597bcee858e 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts @@ -5,11 +5,12 @@ */ import Hapi from 'hapi'; +import { ReportingConfig, ReportingCore } from '../'; +import { LevelLogger } from '../lib'; import { createMockReportingCore } from '../../test_helpers'; -import { ExportTypeDefinition } from '../../types'; import { ExportTypesRegistry } from '../lib/export_types_registry'; -import { LevelLogger } from '../lib/level_logger'; -import { ReportingConfig, ReportingCore, ReportingSetupDeps } from '../types'; +import { ExportTypeDefinition, ReportingSetupDeps } from '../types'; +import { registerJobInfoRoutes } from './jobs'; jest.mock('./lib/authorized_user_pre_routing', () => ({ authorizedUserPreRoutingFactory: () => () => ({}), @@ -20,8 +21,6 @@ jest.mock('./lib/reporting_feature_pre_routing', () => ({ }), })); -import { registerJobInfoRoutes } from './jobs'; - let mockServer: any; let exportTypesRegistry: ExportTypesRegistry; let mockReportingPlugin: ReportingCore; diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index f6f98b2377db6..59090961998af 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -7,17 +7,11 @@ import Boom from 'boom'; import { ResponseObject } from 'hapi'; import { Legacy } from 'kibana'; +import { ReportingCore } from '../'; import { API_BASE_URL } from '../../common/constants'; -import { - JobDocOutput, - JobSource, - ListQuery, - Logger, - ReportingResponseToolkit, - ServerFacade, -} from '../../types'; +import { LevelLogger as Logger } from '../lib'; import { jobsQueryFactory } from '../lib/jobs_query'; -import { ReportingCore, ReportingSetupDeps } from '../types'; +import { JobDocOutput, JobSource, ReportingSetupDeps, ServerFacade } from '../types'; import { deleteJobResponseHandlerFactory, downloadJobResponseHandlerFactory, @@ -28,7 +22,13 @@ import { getRouteConfigFactoryDownloadPre, getRouteConfigFactoryManagementPre, } from './lib/route_config_factories'; +import { ReportingResponseToolkit } from './types'; +interface ListQuery { + page: string; + size: string; + ids?: string; // optional field forbids us from extending RequestQuery +} const MAIN_ENTRY = `${API_BASE_URL}/jobs`; function isResponse(response: Boom | ResponseObject): response is ResponseObject { diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts index 1ca28ca62a7f2..0d297a60a3559 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -8,9 +8,9 @@ import Boom from 'boom'; import { Legacy } from 'kibana'; import { AuthenticatedUser } from '../../../../../../plugins/security/server'; import { ReportingConfig } from '../../../server'; -import { Logger } from '../../../types'; +import { LevelLogger as Logger } from '../../../server/lib'; +import { ReportingSetupDeps } from '../../../server/types'; import { getUserFactory } from '../../lib/get_user'; -import { ReportingSetupDeps } from '../../types'; const superuserRole = 'superuser'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts index c243d0b4266ea..6a228c1915615 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts @@ -8,8 +8,9 @@ import contentDisposition from 'content-disposition'; import * as _ from 'lodash'; import { CSV_JOB_TYPE } from '../../../common/constants'; -import { ExportTypeDefinition, ExportTypesRegistry, JobDocOutput, JobSource } from '../../../types'; import { statuses } from '../../lib/esqueue/constants/statuses'; +import { ExportTypesRegistry } from '../../lib/export_types_registry'; +import { ExportTypeDefinition, JobDocOutput, JobSource } from '../../types'; interface ICustomHeaders { [x: string]: any; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts index e7e7c866db96a..59aa7d904dcf4 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts @@ -7,10 +7,10 @@ import Boom from 'boom'; import { ResponseToolkit } from 'hapi'; import { ElasticsearchServiceSetup } from 'kibana/server'; +import { ReportingConfig } from '../../'; import { WHITELISTED_JOB_CONTENT_TYPES } from '../../../common/constants'; -import { ExportTypesRegistry } from '../../../types'; +import { ExportTypesRegistry } from '../../lib/export_types_registry'; import { jobsQueryFactory } from '../../lib/jobs_query'; -import { ReportingConfig } from '../../types'; import { getDocumentPayloadFactory } from './get_document_payload'; interface JobResponseHandlerParams { diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts index fb8a2dbbff17b..5dd62711f2565 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts @@ -11,7 +11,7 @@ import { ReportingRequestPayload, ReportingRequestPre, ReportingRequestQuery, -} from '../../../types'; +} from '../../../server/types'; export function makeRequestFacade(request: Legacy.Request): RequestFacade { // This condition is for unit tests diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts index 8a79566aafae2..f9c7571e25bac 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts @@ -6,8 +6,9 @@ import Boom from 'boom'; import { Legacy } from 'kibana'; -import { Logger } from '../../../types'; -import { ReportingConfig, ReportingSetupDeps } from '../../types'; +import { ReportingConfig } from '../../'; +import { LevelLogger as Logger } from '../../lib'; +import { ReportingSetupDeps } from '../../types'; export type GetReportingFeatureIdFn = (request: Legacy.Request) => string; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index 06f7efaa9dcbb..0ee9db4678684 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -5,9 +5,10 @@ */ import Joi from 'joi'; +import { ReportingConfig } from '../../'; +import { LevelLogger as Logger } from '../../lib'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; -import { Logger } from '../../../types'; -import { ReportingConfig, ReportingSetupDeps } from '../../types'; +import { ReportingSetupDeps } from '../../types'; import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; import { GetReportingFeatureIdFn, diff --git a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts index 28862a765d666..2ebe1ada418dc 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts @@ -5,7 +5,7 @@ */ import { Legacy } from 'kibana'; -import { JobDocPayload, ReportingResponseToolkit } from '../../types'; +import { JobDocPayload } from '../types'; export type HandlerFunction = ( exportType: string, @@ -24,3 +24,5 @@ export interface QueuedJobPayload { }; }; } + +export type ReportingResponseToolkit = Legacy.ResponseToolkit; diff --git a/x-pack/legacy/plugins/reporting/server/types.d.ts b/x-pack/legacy/plugins/reporting/server/types.d.ts deleted file mode 100644 index fb77eae4e7eea..0000000000000 --- a/x-pack/legacy/plugins/reporting/server/types.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Legacy } from 'kibana'; -import { ElasticsearchServiceSetup } from 'src/core/server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server'; -import { SecurityPluginSetup } from '../../../../plugins/security/server'; -import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; -import { ReportingPluginSpecOptions } from '../types'; -import { ReportingConfigType } from './core'; - -export interface ReportingSetupDeps { - elasticsearch: ElasticsearchServiceSetup; - security: SecurityPluginSetup; - usageCollection?: UsageCollectionSetup; - __LEGACY: LegacySetup; -} - -export interface ReportingStartDeps { - data: DataPluginStart; - __LEGACY: LegacySetup; -} - -export type ReportingSetup = object; - -export type ReportingStart = object; - -export interface LegacySetup { - plugins: { - xpack_main: XPackMainPlugin & { - status?: any; - }; - reporting: ReportingPluginSpecOptions; - }; - route: Legacy.Server['route']; -} - -export { ReportingConfig, ReportingConfigType, ReportingCore } from './core'; - -export type CaptureConfig = ReportingConfigType['capture']; -export type ScrollConfig = ReportingConfigType['csv']['scroll']; diff --git a/x-pack/legacy/plugins/reporting/server/types.ts b/x-pack/legacy/plugins/reporting/server/types.ts new file mode 100644 index 0000000000000..1417f1d7b50cb --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/types.ts @@ -0,0 +1,243 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Legacy } from 'kibana'; +import { ElasticsearchServiceSetup } from 'kibana/server'; +import * as Rx from 'rxjs'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DataPluginStart } from 'src/plugins/data/server/plugin'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { ReportingPluginSpecOptions } from '../'; +import { CancellationToken } from '../../../../plugins/reporting/common'; +import { JobStatus } from '../../../../plugins/reporting/common/types'; +import { SecurityPluginSetup } from '../../../../plugins/security/server'; +import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; +import { LayoutInstance } from '../export_types/common/layouts'; +import { ReportingConfigType } from './config'; +import { ReportingCore } from './core'; +import { LevelLogger } from './lib'; + +/* + * Routing / API types + */ + +interface ListQuery { + page: string; + size: string; + ids?: string; // optional field forbids us from extending RequestQuery +} + +interface GenerateQuery { + jobParams: string; +} + +export type ReportingRequestQuery = ListQuery | GenerateQuery; + +export interface ReportingRequestPre { + management: { + jobTypes: any; + }; + user: string; +} + +// generate a report with unparsed jobParams +export interface GenerateExportTypePayload { + jobParams: string; +} + +export type ReportingRequestPayload = GenerateExportTypePayload | JobParamPostPayload; + +export interface TimeRangeParams { + timezone: string; + min: Date | string | number; + max: Date | string | number; +} + +export interface JobParamPostPayload { + timerange: TimeRangeParams; +} + +export interface JobDocPayload { + headers?: string; // serialized encrypted headers + jobParams: JobParamsType; + title: string; + type: string | null; +} + +export interface JobSource { + _id: string; + _index: string; + _source: { + jobtype: string; + output: JobDocOutput; + payload: JobDocPayload; + status: JobStatus; + }; +} + +export interface JobDocOutput { + content_type: string; + content: string | null; + size: number; + max_size_reached?: boolean; + warnings?: string[]; +} + +interface ConditionalHeadersConditions { + protocol: string; + hostname: string; + port: number; + basePath: string; +} + +export interface ConditionalHeaders { + headers: Record; + conditions: ConditionalHeadersConditions; +} + +/* + * Screenshots + */ + +export interface ScreenshotObservableOpts { + logger: LevelLogger; + urls: string[]; + conditionalHeaders: ConditionalHeaders; + layout: LayoutInstance; + browserTimezone: string; +} + +export interface AttributesMap { + [key: string]: any; +} + +export interface ElementPosition { + boundingClientRect: { + // modern browsers support x/y, but older ones don't + top: number; + left: number; + width: number; + height: number; + }; + scroll: { + x: number; + y: number; + }; +} + +export interface ElementsPositionAndAttribute { + position: ElementPosition; + attributes: AttributesMap; +} + +export interface Screenshot { + base64EncodedData: string; + title: string; + description: string; +} + +export interface ScreenshotResults { + timeRange: string | null; + screenshots: Screenshot[]; + error?: Error; + elementsPositionAndAttributes?: ElementsPositionAndAttribute[]; // NOTE: for testing +} + +export type ScreenshotsObservableFn = ({ + logger, + urls, + conditionalHeaders, + layout, + browserTimezone, +}: ScreenshotObservableOpts) => Rx.Observable; + +/* + * Plugin Contract + */ + +export interface ReportingSetupDeps { + elasticsearch: ElasticsearchServiceSetup; + security: SecurityPluginSetup; + usageCollection?: UsageCollectionSetup; + __LEGACY: LegacySetup; +} + +export interface ReportingStartDeps { + data: DataPluginStart; + __LEGACY: LegacySetup; +} + +export type ReportingStart = object; +export type ReportingSetup = object; + +export interface LegacySetup { + plugins: { + xpack_main: XPackMainPlugin & { + status?: any; + }; + reporting: ReportingPluginSpecOptions; + }; + route: Legacy.Server['route']; +} + +/* + * Internal Types + */ + +export interface RequestFacade { + getBasePath: Legacy.Request['getBasePath']; + getSavedObjectsClient: Legacy.Request['getSavedObjectsClient']; + headers: Legacy.Request['headers']; + params: Legacy.Request['params']; + payload: JobParamPostPayload | GenerateExportTypePayload; + query: ReportingRequestQuery; + route: Legacy.Request['route']; + pre: ReportingRequestPre; + getRawRequest: () => Legacy.Request; +} + +export type ESQueueCreateJobFn = ( + jobParams: JobParamsType, + headers: Record, + request: RequestFacade +) => Promise; + +export type ESQueueWorkerExecuteFn = ( + jobId: string, + job: JobDocPayloadType, + cancellationToken?: CancellationToken +) => Promise; + +export type ServerFacade = LegacySetup; + +export type CaptureConfig = ReportingConfigType['capture']; +export type ScrollConfig = ReportingConfigType['csv']['scroll']; + +export type CreateJobFactory = ( + reporting: ReportingCore, + logger: LevelLogger +) => CreateJobFnType; + +export type ExecuteJobFactory = ( + reporting: ReportingCore, + logger: LevelLogger +) => Promise; // FIXME: does not "need" to be async + +export interface ExportTypeDefinition< + JobParamsType, + CreateJobFnType, + JobPayloadType, + ExecuteJobFnType +> { + id: string; + name: string; + jobType: string; + jobContentEncoding?: string; + jobContentExtension: string; + createJobFactory: CreateJobFactory; + executeJobFactory: ExecuteJobFactory; + validLicenses: string[]; +} diff --git a/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts b/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts index eb907d52c5f96..6771d61bf263d 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts @@ -5,23 +5,24 @@ */ import { get } from 'lodash'; +import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; +import { ReportingConfig } from '../'; import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; -import { ESCallCluster, ExportTypesRegistry } from '../../types'; -import { ReportingConfig } from '../types'; -import { decorateRangeStats } from './decorate_range_stats'; -import { getExportTypesHandler } from './get_export_type_handler'; +import { ExportTypesRegistry } from '../lib/export_types_registry'; import { AggregationResultBuckets, + AppCounts, FeatureAvailabilityMap, JobTypes, KeyCountBucket, + LayoutCounts, RangeStats, ReportingUsageType, SearchResponse, StatusByAppBucket, - AppCounts, - LayoutCounts, } from './types'; +import { decorateRangeStats } from './decorate_range_stats'; +import { getExportTypesHandler } from './get_export_type_handler'; type XPackInfo = XPackMainPlugin['info']; @@ -123,7 +124,7 @@ async function handleResponse(response: SearchResponse): Promise + fetch: (callCluster: CallCluster) => getReportingUsage(config, xpackMainInfo, callCluster, exportTypesRegistry), isReady, diff --git a/x-pack/legacy/plugins/reporting/server/usage/types.d.ts b/x-pack/legacy/plugins/reporting/server/usage/types.ts similarity index 65% rename from x-pack/legacy/plugins/reporting/server/usage/types.d.ts rename to x-pack/legacy/plugins/reporting/server/usage/types.ts index 4d7a1a33239b2..5430a1cfc33bd 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/types.d.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/types.ts @@ -107,3 +107,63 @@ export type ReportingUsageType = RangeStats & { export type ExportType = 'csv' | 'printable_pdf' | 'PNG'; export type FeatureAvailabilityMap = { [F in ExportType]: boolean }; + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export interface KeyCountBucket { + key: string; + doc_count: number; +} + +export interface AggregationBuckets { + buckets: KeyCountBucket[]; +} + +export interface StatusByAppBucket { + key: string; + doc_count: number; + jobTypes: { + buckets: Array<{ + doc_count: number; + key: string; + appNames: AggregationBuckets; + }>; + }; +} + +export interface AggregationResultBuckets { + jobTypes: AggregationBuckets; + layoutTypes: { + doc_count: number; + pdf: AggregationBuckets; + }; + objectTypes: { + doc_count: number; + pdf: AggregationBuckets; + }; + statusTypes: AggregationBuckets; + statusByApp: { + buckets: StatusByAppBucket[]; + }; + doc_count: number; +} + +export interface SearchResponse { + aggregations: { + ranges: { + buckets: { + all: AggregationResultBuckets; + last7Days: AggregationResultBuckets; + }; + }; + }; +} + +export interface AvailableTotal { + available: boolean; + total: number; +} diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts index aafe17d970187..260c94c31df1c 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts @@ -7,11 +7,10 @@ import { Page } from 'puppeteer'; import * as Rx from 'rxjs'; import * as contexts from '../export_types/common/lib/screenshots/constants'; -import { ElementsPositionAndAttribute } from '../export_types/common/lib/screenshots/types'; import { HeadlessChromiumDriver, HeadlessChromiumDriverFactory } from '../server/browsers'; import { createDriverFactory } from '../server/browsers/chromium'; -import { CaptureConfig } from '../server/types'; -import { Logger } from '../types'; +import { LevelLogger } from '../server/lib'; +import { CaptureConfig, ElementsPositionAndAttribute } from '../server/types'; interface CreateMockBrowserDriverFactoryOpts { evaluate: jest.Mock, any[]>; @@ -93,7 +92,7 @@ const defaultOpts: CreateMockBrowserDriverFactoryOpts = { }; export const createMockBrowserDriverFactory = async ( - logger: Logger, + logger: LevelLogger, opts: Partial = {} ): Promise => { const captureConfig: CaptureConfig = { diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_layoutinstance.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_layoutinstance.ts index 81090e7616501..7f4330e7f6bc6 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_layoutinstance.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_layoutinstance.ts @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LayoutTypes } from '../export_types/common/constants'; -import { createLayout } from '../export_types/common/layouts'; -import { LayoutInstance } from '../export_types/common/layouts/layout'; +import { createLayout, LayoutInstance, LayoutTypes } from '../export_types/common/layouts'; import { CaptureConfig } from '../server/types'; export const createMockLayoutInstance = (captureConfig: CaptureConfig) => { diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts index ec00023b4d449..274f7344c7261 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_reportingplugin.ts @@ -15,7 +15,7 @@ jest.mock('../server/lib/validate'); import { EventEmitter } from 'events'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { coreMock } from 'src/core/server/mocks'; -import { ReportingPlugin, ReportingCore, ReportingConfig } from '../server'; +import { ReportingConfig, ReportingCore, ReportingPlugin } from '../server'; import { ReportingSetupDeps, ReportingStartDeps } from '../server/types'; const createMockSetupDeps = (setupMock?: any): ReportingSetupDeps => { diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts index 531e1dcaf84e0..819636b714631 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ServerFacade } from '../types'; +import { ServerFacade } from '../server/types'; export const createMockServer = (): ServerFacade => { const mockServer = {}; diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts deleted file mode 100644 index 2e7da6663ab03..0000000000000 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EventEmitter } from 'events'; -import { ResponseObject } from 'hapi'; -import { Legacy } from 'kibana'; -import { CallCluster } from '../../../../src/legacy/core_plugins/elasticsearch'; -import { JobStatus } from '../../../plugins/reporting'; // reporting new platform -import { CancellationToken } from './common/cancellation_token'; -import { ReportingCore } from './server/core'; -import { LevelLogger } from './server/lib/level_logger'; -import { LegacySetup } from './server/types'; - -export type Job = EventEmitter & { - id: string; - toJSON: () => { - id: string; - }; -}; - -export interface NetworkPolicyRule { - allow: boolean; - protocol?: string; - host?: string; -} - -export interface NetworkPolicy { - enabled: boolean; - rules: NetworkPolicyRule[]; -} - -export interface ListQuery { - page: string; - size: string; - ids?: string; // optional field forbids us from extending RequestQuery -} -interface GenerateQuery { - jobParams: string; -} -interface GenerateExportTypePayload { - jobParams: string; -} - -/* - * Legacy System - * TODO: move to server/types - */ - -export type ServerFacade = LegacySetup; - -export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions; - -export type EnqueueJobFn = ( - exportTypeId: string, - jobParams: JobParamsType, - user: string, - headers: Record, - request: RequestFacade -) => Promise; - -export type ReportingRequestPayload = GenerateExportTypePayload | JobParamPostPayload; -export type ReportingRequestQuery = ListQuery | GenerateQuery; - -export interface ReportingRequestPre { - management: { - jobTypes: any; - }; - user: any; // TODO import AuthenticatedUser from security/server -} - -export interface RequestFacade { - getBasePath: Legacy.Request['getBasePath']; - getSavedObjectsClient: Legacy.Request['getSavedObjectsClient']; - headers: Legacy.Request['headers']; - params: Legacy.Request['params']; - payload: JobParamPostPayload | GenerateExportTypePayload; - query: ReportingRequestQuery; - route: Legacy.Request['route']; - pre: ReportingRequestPre; - getRawRequest: () => Legacy.Request; -} - -export type ResponseFacade = ResponseObject & { - isBoom: boolean; -}; - -export type ReportingResponseToolkit = Legacy.ResponseToolkit; - -export type ESCallCluster = CallCluster; - -export interface ElementPosition { - boundingClientRect: { - // modern browsers support x/y, but older ones don't - top: number; - left: number; - width: number; - height: number; - }; - scroll: { - x: number; - y: number; - }; -} - -export interface ConditionalHeaders { - headers: Record; - conditions: ConditionalHeadersConditions; -} - -export interface ConditionalHeadersConditions { - protocol: string; - hostname: string; - port: number; - basePath: string; -} - -export interface IndexPatternSavedObject { - attributes: { - fieldFormatMap: string; - }; - id: string; - type: string; - version: string; -} - -export interface TimeRangeParams { - timezone: string; - min: Date | string | number; - max: Date | string | number; -} - -// retain POST payload data, needed for async -export interface JobParamPostPayload { - timerange: TimeRangeParams; -} - -export interface JobDocPayload { - headers?: string; // serialized encrypted headers - jobParams: JobParamsType; - title: string; - type: string | null; -} - -export interface JobSource { - _id: string; - _index: string; - _source: { - jobtype: string; - output: JobDocOutput; - payload: JobDocPayload; - status: JobStatus; - }; -} - -export interface JobDocOutput { - content_type: string; - content: string | null; - size: number; - max_size_reached?: boolean; - warnings?: string[]; -} - -export interface ESQueueWorker { - on: (event: string, handler: any) => void; -} - -export type ESQueueCreateJobFn = ( - jobParams: JobParamsType, - headers: Record, - request: RequestFacade -) => Promise; - -export type ImmediateCreateJobFn = ( - jobParams: JobParamsType, - headers: Record, - req: RequestFacade -) => Promise<{ - type: string | null; - title: string; - jobParams: JobParamsType; -}>; - -export type ESQueueWorkerExecuteFn = ( - jobId: string, - job: JobDocPayloadType, - cancellationToken?: CancellationToken -) => Promise; - -/* - * ImmediateExecuteFn receives the job doc payload because the payload was - * generated in the CreateFn - */ -export type ImmediateExecuteFn = ( - jobId: null, - job: JobDocPayload, - request: RequestFacade -) => Promise; - -export interface ESQueueWorkerOptions { - kibanaName: string; - kibanaId: string; - interval: number; - intervalErrorMultiplier: number; -} - -// GenericWorkerFn is a generic for ImmediateExecuteFn | ESQueueWorkerExecuteFn, -type GenericWorkerFn = ( - jobSource: JobSource, - ...workerRestArgs: any[] -) => void | Promise; - -export interface ESQueueInstance { - addJob: (type: string, payload: unknown, options: object) => Job; - registerWorker: ( - pluginId: string, - workerFn: GenericWorkerFn, - workerOptions: ESQueueWorkerOptions - ) => ESQueueWorker; -} - -export type CreateJobFactory = ( - reporting: ReportingCore, - logger: LevelLogger -) => CreateJobFnType; -export type ExecuteJobFactory = ( - reporting: ReportingCore, - logger: LevelLogger -) => Promise; // FIXME: does not "need" to be async - -export interface ExportTypeDefinition< - JobParamsType, - CreateJobFnType, - JobPayloadType, - ExecuteJobFnType -> { - id: string; - name: string; - jobType: string; - jobContentEncoding?: string; - jobContentExtension: string; - createJobFactory: CreateJobFactory; - executeJobFactory: ExecuteJobFactory; - validLicenses: string[]; -} - -export { CancellationToken } from './common/cancellation_token'; - -export { HeadlessChromiumDriver, HeadlessChromiumDriverFactory } from './server/browsers'; - -export { ExportTypesRegistry } from './server/lib/export_types_registry'; -// Prefer to import this type using: `import { LevelLogger } from 'relative/path/server/lib';` -export { LevelLogger as Logger }; - -export interface AbsoluteURLFactoryOptions { - defaultBasePath: string; - protocol: string; - hostname: string; - port: string | number; -} - -export interface InterceptedRequest { - requestId: string; - request: { - url: string; - method: string; - headers: { - [key: string]: string; - }; - initialPriority: string; - referrerPolicy: string; - }; - frameId: string; - resourceType: string; -} diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index 4f5763dcde582..2044053e049f1 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -84,7 +84,7 @@ Array [ }, Object { "key": "profiling_inferred_spans_min_duration", - "min": "1ms", + "min": "0ms", "type": "duration", "units": Array [ "ms", diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts index bc8f19becf053..49cb0ae9cfa81 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts @@ -197,7 +197,8 @@ export const javaSettings: RawSettingDefinition[] = [ 'The minimum duration of an inferred span. Note that the min duration is also implicitly set by the sampling interval. However, increasing the sampling interval also decreases the accuracy of the duration of inferred spans.' } ), - includeAgents: ['java'] + includeAgents: ['java'], + min: '0ms' }, { key: 'profiling_inferred_spans_included_classes', diff --git a/x-pack/plugins/apm/common/agent_name.ts b/x-pack/plugins/apm/common/agent_name.ts index 085828b729ea5..dac29a4f50682 100644 --- a/x-pack/plugins/apm/common/agent_name.ts +++ b/x-pack/plugins/apm/common/agent_name.ts @@ -41,3 +41,16 @@ export function isJavaAgentName( ): agentName is 'java' { return agentName === 'java'; } + +/** + * "Normalizes" and agent name by: + * + * * Converting to lowercase + * * Converting "rum-js" to "js-base" + * + * This helps dealing with some older agent versions + */ +export function getNormalizedAgentName(agentName?: string) { + const lowercased = agentName && agentName.toLowerCase(); + return isRumAgentName(lowercased) ? 'js-base' : lowercased; +} diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx index 340c299f52c0b..2d1e99096a44f 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx @@ -186,6 +186,13 @@ storiesOf('app/ServiceMap/Cytoscape', module) 'agent.name': 'dotnet' } }, + { + data: { + id: 'dotNet', + 'service.name': 'dotNet service', + 'agent.name': 'dotNet' + } + }, { data: { id: 'go', diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts index 9fe5cbd23b07c..1b4bf1b77791c 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts @@ -5,7 +5,7 @@ */ import cytoscape from 'cytoscape'; -import { isRumAgentName } from '../../../../common/agent_name'; +import { getNormalizedAgentName } from '../../../../common/agent_name'; import { AGENT_NAME, SPAN_SUBTYPE, @@ -87,8 +87,7 @@ const agentIcons: { [key: string]: string } = { }; function getAgentIcon(agentName?: string) { - // RUM can have multiple names. Normalize it - const normalizedAgentName = isRumAgentName(agentName) ? 'js-base' : agentName; + const normalizedAgentName = getNormalizedAgentName(agentName); return normalizedAgentName && agentIcons[normalizedAgentName]; } diff --git a/x-pack/plugins/endpoint/common/alert_constants.ts b/x-pack/plugins/endpoint/common/alert_constants.ts index 85e1643d684f2..66de2b85ef3a7 100644 --- a/x-pack/plugins/endpoint/common/alert_constants.ts +++ b/x-pack/plugins/endpoint/common/alert_constants.ts @@ -13,10 +13,6 @@ export class AlertConstants { * The path for the Alert's Index Pattern API. */ static INDEX_PATTERN_ROUTE = `${AlertConstants.BASE_API_URL}/index_pattern`; - /** - * Alert's Index pattern - */ - static ALERT_INDEX_NAME = 'events-endpoint-1'; /** * A paramter passed to Alert's Index Pattern. */ diff --git a/x-pack/plugins/endpoint/common/models/event.ts b/x-pack/plugins/endpoint/common/models/event.ts index 47f39d2d11797..192daba4a717d 100644 --- a/x-pack/plugins/endpoint/common/models/event.ts +++ b/x-pack/plugins/endpoint/common/models/event.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - import { LegacyEndpointEvent, ResolverEvent } from '../types'; export function isLegacyEvent(event: ResolverEvent): event is LegacyEndpointEvent { @@ -46,3 +45,23 @@ export function parentEntityId(event: ResolverEvent): string | undefined { } return event.process.parent?.entity_id; } + +export function eventType(event: ResolverEvent): string { + // Returning "Process" as a catch-all here because it seems pretty general + let eventCategoryToReturn: string = 'Process'; + if (isLegacyEvent(event)) { + const legacyFullType = event.endgame.event_type_full; + if (legacyFullType) { + return legacyFullType; + } + } else { + const eventCategories = event.event.category; + const eventCategory = + typeof eventCategories === 'string' ? eventCategories : eventCategories[0] || ''; + + if (eventCategory) { + eventCategoryToReturn = eventCategory; + } + } + return eventCategoryToReturn; +} diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts index a26f43e1f8cc0..462f6e251d5d0 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts @@ -44,6 +44,15 @@ interface AppRequestedResolverData { readonly type: 'appRequestedResolverData'; } +/** + * The action dispatched when the app requests related event data for one or more + * subjects (whose ids should be included as an array @ `payload`) + */ +interface UserRequestedRelatedEventData { + readonly type: 'userRequestedRelatedEventData'; + readonly payload: ResolverEvent; +} + /** * When the user switches the "active descendant" of the Resolver. * The "active descendant" (from the point of view of the parent element) @@ -77,6 +86,28 @@ interface UserSelectedResolverNode { }; } +/** + * This action should dispatch to indicate that the user chose to + * focus on examining the related events of a particular ResolverEvent. + * Optionally, this can be bound by a category of related events (e.g. 'file' or 'dns') + */ +interface UserSelectedRelatedEventCategory { + readonly type: 'userSelectedRelatedEventCategory'; + readonly payload: { + subject: ResolverEvent; + category?: string; + }; +} + +/** + * This action should dispatch to indicate that the user chose to focus + * on examining alerts related to a particular ResolverEvent + */ +interface UserSelectedRelatedAlerts { + readonly type: 'userSelectedRelatedAlerts'; + readonly payload: ResolverEvent; +} + export type ResolverAction = | CameraAction | DataAction @@ -84,4 +115,7 @@ export type ResolverAction = | UserChangedSelectedEvent | AppRequestedResolverData | UserFocusedOnResolverNode - | UserSelectedResolverNode; + | UserSelectedResolverNode + | UserRequestedRelatedEventData + | UserSelectedRelatedEventCategory + | UserSelectedRelatedAlerts; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts index 3ec15f2f1985d..8c84d8f82b874 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts @@ -5,6 +5,7 @@ */ import { ResolverEvent } from '../../../../../common/types'; +import { RelatedEventDataEntry } from '../../types'; interface ServerReturnedResolverData { readonly type: 'serverReturnedResolverData'; @@ -15,4 +16,24 @@ interface ServerFailedToReturnResolverData { readonly type: 'serverFailedToReturnResolverData'; } -export type DataAction = ServerReturnedResolverData | ServerFailedToReturnResolverData; +/** + * Will occur when a request for related event data is fulfilled by the API. + */ +interface ServerReturnedRelatedEventData { + readonly type: 'serverReturnedRelatedEventData'; + readonly payload: Map; +} + +/** + * Will occur when a request for related event data is unsuccessful. + */ +interface ServerFailedToReturnRelatedEventData { + readonly type: 'serverFailedToReturnRelatedEventData'; + readonly payload: ResolverEvent; +} + +export type DataAction = + | ServerReturnedResolverData + | ServerFailedToReturnResolverData + | ServerReturnedRelatedEventData + | ServerFailedToReturnRelatedEventData; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts index fc307002819a9..9dd6bcdf385ae 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts @@ -12,6 +12,7 @@ function initialState(): DataState { results: [], isLoading: false, hasError: false, + resultsEnrichedWithRelatedEventInfo: new Map(), }; } @@ -23,6 +24,26 @@ export const dataReducer: Reducer = (state = initialS isLoading: false, hasError: false, }; + } else if (action.type === 'userRequestedRelatedEventData') { + const resolverEvent = action.payload; + const currentStatsMap = new Map(state.resultsEnrichedWithRelatedEventInfo); + /** + * Set the waiting indicator for this event to indicate that related event results are pending. + * It will be replaced by the actual results from the API when they are returned. + */ + currentStatsMap.set(resolverEvent, 'waitingForRelatedEventData'); + return { ...state, resultsEnrichedWithRelatedEventInfo: currentStatsMap }; + } else if (action.type === 'serverFailedToReturnRelatedEventData') { + const currentStatsMap = new Map(state.resultsEnrichedWithRelatedEventInfo); + const resolverEvent = action.payload; + currentStatsMap.set(resolverEvent, 'error'); + return { ...state, resultsEnrichedWithRelatedEventInfo: currentStatsMap }; + } else if (action.type === 'serverReturnedRelatedEventData') { + const relatedDataEntries = new Map([ + ...state.resultsEnrichedWithRelatedEventInfo, + ...action.payload, + ]); + return { ...state, resultsEnrichedWithRelatedEventInfo: relatedDataEntries }; } else if (action.type === 'appRequestedResolverData') { return { ...state, diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.test.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.test.ts new file mode 100644 index 0000000000000..561b0da12bcb1 --- /dev/null +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Store, createStore } from 'redux'; +import { DataAction } from './action'; +import { dataReducer } from './reducer'; +import { + DataState, + RelatedEventDataEntry, + RelatedEventDataEntryWithStats, + RelatedEventData, +} from '../../types'; +import { ResolverEvent } from '../../../../../common/types'; +import { relatedEventStats, relatedEvents } from './selectors'; + +describe('resolver data selectors', () => { + const store: Store = createStore(dataReducer, undefined); + describe('when related event data is reduced into state with no results', () => { + let relatedEventInfoBeforeAction: RelatedEventData; + beforeEach(() => { + relatedEventInfoBeforeAction = new Map(relatedEvents(store.getState()) || []); + const payload: Map = new Map(); + const action: DataAction = { type: 'serverReturnedRelatedEventData', payload }; + store.dispatch(action); + }); + it('should have the same related info as before the action', () => { + const relatedInfoAfterAction = relatedEvents(store.getState()); + expect(relatedInfoAfterAction).toEqual(relatedEventInfoBeforeAction); + }); + }); + describe('when related event data is reduced into state with 2 dns results', () => { + let mockBaseEvent: ResolverEvent; + beforeEach(() => { + mockBaseEvent = {} as ResolverEvent; + function dnsRelatedEventEntry() { + const fakeEvent = {} as ResolverEvent; + return { relatedEvent: fakeEvent, relatedEventType: 'dns' }; + } + const payload: Map = new Map([ + [ + mockBaseEvent, + { + relatedEvents: [dnsRelatedEventEntry(), dnsRelatedEventEntry()], + }, + ], + ]); + const action: DataAction = { type: 'serverReturnedRelatedEventData', payload }; + store.dispatch(action); + }); + it('should compile stats reflecting a count of 2 for dns', () => { + const actualStats = relatedEventStats(store.getState()); + const statsForFakeEvent = actualStats.get(mockBaseEvent)! as RelatedEventDataEntryWithStats; + expect(statsForFakeEvent.stats).toEqual({ dns: 2 }); + }); + }); +}); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.ts index 59ee4b3b87505..413f4db1cc99e 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/selectors.ts @@ -14,6 +14,8 @@ import { ProcessWithWidthMetadata, Matrix3, AdjacentProcessMap, + RelatedEventData, + RelatedEventDataEntryWithStats, } from '../../types'; import { ResolverEvent } from '../../../../../common/types'; import { Vector2 } from '../../types'; @@ -405,6 +407,86 @@ export const indexedProcessTree = createSelector(graphableProcesses, function in return indexedProcessTreeFactory(graphableProcesses); }); +/** + * Process events that will be graphed. + */ +export const relatedEventResults = function(data: DataState) { + return data.resultsEnrichedWithRelatedEventInfo; +}; + +/** + * This selector compiles the related event data attached in `relatedEventResults` + * into a `RelatedEventData` map of ResolverEvents to statistics about their related events + */ +export const relatedEventStats = createSelector(relatedEventResults, function getRelatedEvents( + /* eslint-disable no-shadow */ + relatedEventResults + /* eslint-enable no-shadow */ +) { + /* eslint-disable no-shadow */ + const relatedEventStats: RelatedEventData = new Map(); + /* eslint-enable no-shadow */ + if (!relatedEventResults) { + return relatedEventStats; + } + + for (const updatedEvent of relatedEventResults.keys()) { + const newStatsEntry = relatedEventResults.get(updatedEvent); + if (newStatsEntry === 'error') { + // If the entry is an error, return it as is + relatedEventStats.set(updatedEvent, newStatsEntry); + continue; + } + if (typeof newStatsEntry === 'object') { + /** + * Otherwise, it should be a valid stats entry. + * Do the work to compile the stats. + * Folowing reduction, this will be a record like + * {DNS: 10, File: 2} etc. + */ + const statsForEntry = newStatsEntry?.relatedEvents.reduce( + (compiledStats: Record, relatedEvent: { relatedEventType: string }) => { + compiledStats[relatedEvent.relatedEventType] = + (compiledStats[relatedEvent.relatedEventType] || 0) + 1; + return compiledStats; + }, + {} + ); + + const newRelatedEventStats: RelatedEventDataEntryWithStats = Object.assign(newStatsEntry, { + stats: statsForEntry, + }); + relatedEventStats.set(updatedEvent, newRelatedEventStats); + } + } + return relatedEventStats; +}); + +/** + * This selects `RelatedEventData` maps specifically for graphable processes + */ +export const relatedEvents = createSelector( + graphableProcesses, + relatedEventStats, + function getRelatedEvents( + /* eslint-disable no-shadow */ + graphableProcesses, + relatedEventStats + /* eslint-enable no-shadow */ + ) { + const eventsRelatedByProcess: RelatedEventData = new Map(); + /* eslint-disable no-shadow */ + return graphableProcesses.reduce((relatedEvents, graphableProcess) => { + /* eslint-enable no-shadow */ + const relatedEventDataEntry = relatedEventStats?.get(graphableProcess); + if (relatedEventDataEntry) { + relatedEvents.set(graphableProcess, relatedEventDataEntry); + } + return relatedEvents; + }, eventsRelatedByProcess); + } +); + export const processAdjacencies = createSelector( indexedProcessTree, graphableProcesses, diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts index c7177c6387e7a..06758022b05c5 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts @@ -5,9 +5,10 @@ */ import { Dispatch, MiddlewareAPI } from 'redux'; +import { HttpHandler } from 'kibana/public'; import { KibanaReactContextValue } from '../../../../../../../src/plugins/kibana_react/public'; import { EndpointPluginServices } from '../../../plugin'; -import { ResolverState, ResolverAction } from '../types'; +import { ResolverState, ResolverAction, RelatedEventDataEntry } from '../types'; import { ResolverEvent, ResolverNode } from '../../../../common/types'; import * as event from '../../../../common/models/event'; @@ -30,6 +31,33 @@ function flattenEvents(children: ResolverNode[], events: ResolverEvent[] = []): }, events); } +type RelatedEventAPIResponse = 'error' | { events: ResolverEvent[] }; +/** + * As the design goal of this stopgap was to prevent saturating the server with /events + * requests, this generator intentionally processes events in serial rather than in parallel. + * @param eventsToFetch + * events to run against the /id/events API + * @param httpGetter + * the HttpHandler to use + */ +async function* getEachRelatedEventsResult( + eventsToFetch: ResolverEvent[], + httpGetter: HttpHandler +): AsyncGenerator<[ResolverEvent, RelatedEventAPIResponse]> { + for (const eventToQueryForRelateds of eventsToFetch) { + const id = event.entityId(eventToQueryForRelateds); + let result: RelatedEventAPIResponse; + try { + result = await httpGetter(`/api/endpoint/resolver/${id}/events`, { + query: { events: 100 }, + }); + } catch (e) { + result = 'error'; + } + yield [eventToQueryForRelateds, result]; + } +} + export const resolverMiddlewareFactory: MiddlewareFactory = context => { return api => next => async (action: ResolverAction) => { next(action); @@ -78,5 +106,44 @@ export const resolverMiddlewareFactory: MiddlewareFactory = context => { } } } + + if (action.type === 'userRequestedRelatedEventData') { + if (typeof context !== 'undefined') { + const response: Map = new Map(); + for await (const results of getEachRelatedEventsResult( + [action.payload], + context.services.http.get + )) { + /** + * results here will take the shape of + * [event requested , response of event against the /related api] + */ + const [baseEvent, apiResults] = results; + if (apiResults === 'error') { + api.dispatch({ + type: 'serverFailedToReturnRelatedEventData', + payload: results[0], + }); + continue; + } + + const fetchedResults = apiResults.events; + // pack up the results into response + const relatedEventEntry = fetchedResults.map(relatedEvent => { + return { + relatedEvent, + relatedEventType: event.eventType(relatedEvent), + }; + }); + + response.set(baseEvent, { relatedEvents: relatedEventEntry }); + } + + api.dispatch({ + type: 'serverReturnedRelatedEventData', + payload: response, + }); + } + } }; }; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts index 7d09d90881da9..493c23621a6cf 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts @@ -60,6 +60,11 @@ export const processAdjacencies = composeSelectors( dataSelectors.processAdjacencies ); +/** + * Returns a map of `ResolverEvent`s to their related `ResolverEvent`s + */ +export const relatedEvents = composeSelectors(dataStateSelector, dataSelectors.relatedEvents); + /** * Returns the id of the "current" tree node (fake-focused) */ diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts index 17aa598720c59..32fefba8f0f20 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts @@ -9,6 +9,7 @@ import { Store } from 'redux'; import { ResolverAction } from './store/actions'; export { ResolverAction } from './store/actions'; import { ResolverEvent } from '../../../common/types'; +import { eventType } from '../../../common/models/event'; /** * Redux state for the Resolver feature. Properties on this interface are populated via multiple reducers using redux's `combineReducers`. @@ -130,6 +131,52 @@ export type CameraState = { } ); +/** + * This represents all the raw data (sans statistics, metadata, etc.) + * about a particular subject's related events + */ +export interface RelatedEventDataEntry { + relatedEvents: Array<{ + relatedEvent: ResolverEvent; + relatedEventType: ReturnType; + }>; +} + +/** + * Represents the status of the request for related event data, which will be either the data, + * a value indicating that it's still waiting for the data or an Error indicating the data can't be retrieved as expected + */ +export type RelatedEventDataResults = + | RelatedEventDataEntry + | 'waitingForRelatedEventData' + | 'error'; + +/** + * This represents the raw related events data enhanced with statistics + * (e.g. counts of items grouped by their related event types) + */ +export type RelatedEventDataEntryWithStats = RelatedEventDataEntry & { + stats: Record; +}; + +/** + * The status or value of any particular event's related events w.r.t. their valence to the current view. + * One of: + * `RelatedEventDataEntryWithStats` when results have been received and processed and are ready to display + * `waitingForRelatedEventData` when related events have been requested but have not yet matriculated + * `Error` when the request for any event encounters an error during service + */ +export type RelatedEventEntryWithStatsOrWaiting = + | RelatedEventDataEntryWithStats + | `waitingForRelatedEventData` + | 'error'; + +/** + * This represents a Map that will return either a `RelatedEventDataEntryWithStats` + * or a `waitingForRelatedEventData` symbol when referenced with a unique event. + */ +export type RelatedEventData = Map; + /** * State for `data` reducer which handles receiving Resolver data from the backend. */ @@ -137,6 +184,7 @@ export interface DataState { readonly results: readonly ResolverEvent[]; isLoading: boolean; hasError: boolean; + resultsEnrichedWithRelatedEventInfo: Map; } export type Vector2 = readonly [number, number]; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx index 2e7ca65c92dc1..5275ba3ec5b4c 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx @@ -57,7 +57,7 @@ export const Resolver = styled( const dispatch: (action: ResolverAction) => unknown = useDispatch(); const { processToAdjacencyMap } = useSelector(selectors.processAdjacencies); - + const relatedEvents = useSelector(selectors.relatedEvents); const { projectionMatrix, ref, onMouseDown } = useCamera(); const isLoading = useSelector(selectors.isLoading); const hasError = useSelector(selectors.hasError); @@ -116,6 +116,7 @@ export const Resolver = styled( projectionMatrix={projectionMatrix} event={processEvent} adjacentNodeMap={adjacentNodeMap} + relatedEvents={relatedEvents.get(processEvent)} /> ); })} diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 27844f09e2272..32928d511a1f9 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -9,14 +9,21 @@ import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { htmlIdGenerator, + EuiI18nNumber, EuiKeyboardAccessible, - EuiButton, EuiFlexGroup, EuiFlexItem, } from '@elastic/eui'; import { useSelector } from 'react-redux'; +import { NodeSubMenu, subMenuAssets } from './submenu'; import { applyMatrix3 } from '../lib/vector2'; -import { Vector2, Matrix3, AdjacentProcessMap, ResolverProcessType } from '../types'; +import { + Vector2, + Matrix3, + AdjacentProcessMap, + ResolverProcessType, + RelatedEventEntryWithStatsOrWaiting, +} from '../types'; import { SymbolIds, NamedColors } from './defs'; import { ResolverEvent } from '../../../../common/types'; import { useResolverDispatch } from './use_resolver_dispatch'; @@ -59,46 +66,129 @@ const nodeAssets = { }, }; -const ChildEventsButton = React.memo(() => { - return ( - ) => { - clickEvent.preventDefault(); - clickEvent.stopPropagation(); - }, [])} - color="ghost" - size="s" - iconType="arrowDown" - iconSide="right" - tabIndex={-1} - > - {i18n.translate('xpack.endpoint.resolver.relatedEvents', { - defaultMessage: 'Events', - })} - - ); -}); - -const RelatedAlertsButton = React.memo(() => { +/** + * Take a gross `schemaName` and return a beautiful translated one. + */ +const getDisplayName: (schemaName: string) => string = function nameInSchemaToDisplayName( + schemaName: string +) { + const displayNameRecord: Record = { + application: i18n.translate('xpack.endpoint.resolver.applicationEventTypeDisplayName', { + defaultMessage: 'Application', + }), + apm: i18n.translate('xpack.endpoint.resolver.apmEventTypeDisplayName', { + defaultMessage: 'APM', + }), + audit: i18n.translate('xpack.endpoint.resolver.auditEventTypeDisplayName', { + defaultMessage: 'Audit', + }), + authentication: i18n.translate('xpack.endpoint.resolver.authenticationEventTypeDisplayName', { + defaultMessage: 'Authentication', + }), + certificate: i18n.translate('xpack.endpoint.resolver.certificateEventTypeDisplayName', { + defaultMessage: 'Certificate', + }), + cloud: i18n.translate('xpack.endpoint.resolver.cloudEventTypeDisplayName', { + defaultMessage: 'Cloud', + }), + database: i18n.translate('xpack.endpoint.resolver.databaseEventTypeDisplayName', { + defaultMessage: 'Database', + }), + driver: i18n.translate('xpack.endpoint.resolver.driverEventTypeDisplayName', { + defaultMessage: 'Driver', + }), + email: i18n.translate('xpack.endpoint.resolver.emailEventTypeDisplayName', { + defaultMessage: 'Email', + }), + file: i18n.translate('xpack.endpoint.resolver.fileEventTypeDisplayName', { + defaultMessage: 'File', + }), + host: i18n.translate('xpack.endpoint.resolver.hostEventTypeDisplayName', { + defaultMessage: 'Host', + }), + iam: i18n.translate('xpack.endpoint.resolver.iamEventTypeDisplayName', { + defaultMessage: 'IAM', + }), + iam_group: i18n.translate('xpack.endpoint.resolver.iam_groupEventTypeDisplayName', { + defaultMessage: 'IAM Group', + }), + intrusion_detection: i18n.translate( + 'xpack.endpoint.resolver.intrusion_detectionEventTypeDisplayName', + { + defaultMessage: 'Intrusion Detection', + } + ), + malware: i18n.translate('xpack.endpoint.resolver.malwareEventTypeDisplayName', { + defaultMessage: 'Malware', + }), + network_flow: i18n.translate('xpack.endpoint.resolver.network_flowEventTypeDisplayName', { + defaultMessage: 'Network Flow', + }), + network: i18n.translate('xpack.endpoint.resolver.networkEventTypeDisplayName', { + defaultMessage: 'Network', + }), + package: i18n.translate('xpack.endpoint.resolver.packageEventTypeDisplayName', { + defaultMessage: 'Package', + }), + process: i18n.translate('xpack.endpoint.resolver.processEventTypeDisplayName', { + defaultMessage: 'Process', + }), + registry: i18n.translate('xpack.endpoint.resolver.registryEventTypeDisplayName', { + defaultMessage: 'Registry', + }), + session: i18n.translate('xpack.endpoint.resolver.sessionEventTypeDisplayName', { + defaultMessage: 'Session', + }), + service: i18n.translate('xpack.endpoint.resolver.serviceEventTypeDisplayName', { + defaultMessage: 'Service', + }), + socket: i18n.translate('xpack.endpoint.resolver.socketEventTypeDisplayName', { + defaultMessage: 'Socket', + }), + vulnerability: i18n.translate('xpack.endpoint.resolver.vulnerabilityEventTypeDisplayName', { + defaultMessage: 'Vulnerability', + }), + web: i18n.translate('xpack.endpoint.resolver.webEventTypeDisplayName', { + defaultMessage: 'Web', + }), + alert: i18n.translate('xpack.endpoint.resolver.alertEventTypeDisplayName', { + defaultMessage: 'Alert', + }), + security: i18n.translate('xpack.endpoint.resolver.securityEventTypeDisplayName', { + defaultMessage: 'Security', + }), + dns: i18n.translate('xpack.endpoint.resolver.dnsEventTypeDisplayName', { + defaultMessage: 'DNS', + }), + clr: i18n.translate('xpack.endpoint.resolver.clrEventTypeDisplayName', { + defaultMessage: 'CLR', + }), + image_load: i18n.translate('xpack.endpoint.resolver.image_loadEventTypeDisplayName', { + defaultMessage: 'Image Load', + }), + powershell: i18n.translate('xpack.endpoint.resolver.powershellEventTypeDisplayName', { + defaultMessage: 'Powershell', + }), + wmi: i18n.translate('xpack.endpoint.resolver.wmiEventTypeDisplayName', { + defaultMessage: 'WMI', + }), + api: i18n.translate('xpack.endpoint.resolver.apiEventTypeDisplayName', { + defaultMessage: 'API', + }), + user: i18n.translate('xpack.endpoint.resolver.userEventTypeDisplayName', { + defaultMessage: 'User', + }), + }; return ( - ) => { - clickEvent.preventDefault(); - clickEvent.stopPropagation(); - }, [])} - color="ghost" - size="s" - tabIndex={-1} - > - {i18n.translate('xpack.endpoint.resolver.relatedAlerts', { - defaultMessage: 'Related Alerts', - })} - + displayNameRecord[schemaName] || + i18n.translate('xpack.endpoint.resolver.userEventTypeDisplayUnknown', { + defaultMessage: 'Unknown', + }) ); -}); +}; /** - * An artefact that represents a process node. + * An artifact that represents a process node and the things associated with it in the Resolver */ export const ProcessEventDot = styled( React.memo( @@ -108,6 +198,7 @@ export const ProcessEventDot = styled( event, projectionMatrix, adjacentNodeMap, + relatedEvents, }: { /** * A `className` string provided by `styled` @@ -129,6 +220,11 @@ export const ProcessEventDot = styled( * map of what nodes are "adjacent" to this one in "up, down, previous, next" directions */ adjacentNodeMap: AdjacentProcessMap; + /** + * A collection of events related to the current node and statistics (e.g. counts indexed by event type) + * to provide the user some visibility regarding the contents thereof. + */ + relatedEvents?: RelatedEventEntryWithStatsOrWaiting; }) => { /** * Convert the position, which is in 'world' coordinates, to screen coordinates. @@ -203,7 +299,6 @@ export const ProcessEventDot = styled( ]); const labelId = useMemo(() => resolverNodeIdGenerator(), [resolverNodeIdGenerator]); const descriptionId = useMemo(() => resolverNodeIdGenerator(), [resolverNodeIdGenerator]); - const isActiveDescendant = nodeId === activeDescendantId; const isSelectedDescendant = nodeId === selectedDescendantId; @@ -230,6 +325,70 @@ export const ProcessEventDot = styled( }); }, [animationTarget, dispatch, nodeId]); + const handleRelatedEventRequest = useCallback(() => { + dispatch({ + type: 'userRequestedRelatedEventData', + payload: event, + }); + }, [dispatch, event]); + + const handleRelatedAlertsRequest = useCallback(() => { + dispatch({ + type: 'userSelectedRelatedAlerts', + payload: event, + }); + }, [dispatch, event]); + /** + * Enumerates the stats for related events to display with the node as options, + * generally in the form `number of related events in category` `category title` + * e.g. "10 DNS", "230 File" + */ + const relatedEventOptions = useMemo(() => { + if (relatedEvents === 'error') { + // Return an empty set of options if there was an error requesting them + return []; + } + const relatedStats = typeof relatedEvents === 'object' && relatedEvents.stats; + if (!relatedStats) { + // Return an empty set of options if there are no stats to report + return []; + } + // If we have entries to show, map them into options to display in the selectable list + return Object.entries(relatedStats).map(statsEntry => { + const displayName = getDisplayName(statsEntry[0]); + return { + prefix: , + optionTitle: `${displayName}`, + action: () => { + dispatch({ + type: 'userSelectedRelatedEventCategory', + payload: { + subject: event, + category: statsEntry[0], + }, + }); + }, + }; + }); + }, [relatedEvents, dispatch, event]); + + const relatedEventStatusOrOptions = (() => { + if (!relatedEvents) { + // If related events have not yet been requested + return subMenuAssets.initialMenuStatus; + } + if (relatedEvents === 'error') { + // If there was an error when we tried to request the events + return subMenuAssets.menuError; + } + if (relatedEvents === 'waitingForRelatedEventData') { + // If we're waiting for events to be returned + // Pass on the waiting symbol + return relatedEvents; + } + return relatedEventOptions; + })(); + /* eslint-disable jsx-a11y/click-events-have-key-events */ /** * Key event handling (e.g. 'Enter'/'Space') is provisioned by the `EuiKeyboardAccessible` component @@ -359,11 +518,18 @@ export const ProcessEventDot = styled(

    {magFactorX >= 2 && ( - - + + - + )} @@ -383,9 +549,10 @@ export const ProcessEventDot = styled( border-radius: 10%; white-space: nowrap; will-change: left, top, width, height; - contain: strict; + contain: layout; min-width: 280px; min-height: 90px; + overflow-y: visible; //dasharray & dashoffset should be equal to "pull" the stroke back //when it is transitioned. @@ -400,10 +567,27 @@ export const ProcessEventDot = styled( transition-duration: 1s; stroke-dashoffset: 0; } + + & .related-dropdown { + width: 4.5em; + } + & .euiSelectableList-bordered { + border-top-right-radius: 0px; + border-top-left-radius: 0px; + } + & .euiSelectableListItem { + background-color: black; + } + & .euiSelectableListItem path { + fill: white; + } + & .euiSelectableListItem__text { + color: white; + } `; const processTypeToCube: Record = { - processCreated: 'terminatedProcessCube', + processCreated: 'runningProcessCube', processRan: 'runningProcessCube', processTerminated: 'terminatedProcessCube', unknownProcessEvent: 'runningProcessCube', diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/submenu.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/submenu.tsx new file mode 100644 index 0000000000000..9f6427d801ce4 --- /dev/null +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/submenu.tsx @@ -0,0 +1,178 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import React, { ReactNode, useState, useMemo, useCallback } from 'react'; +import { EuiSelectable, EuiButton } from '@elastic/eui'; +import styled from 'styled-components'; + +/** + * i18n-translated titles for submenus and identifiers for display of states: + * initialMenuStatus: submenu before it has been opened / requested data + * menuError: if the submenu requested data, but received an error + */ +export const subMenuAssets = { + initialMenuStatus: i18n.translate('xpack.endpoint.resolver.relatedNotRetrieved', { + defaultMessage: 'Related Events have not yet been retrieved.', + }), + menuError: i18n.translate('xpack.endpoint.resolver.relatedRetrievalError', { + defaultMessage: 'There was an error retrieving related events.', + }), + relatedAlerts: { + title: i18n.translate('xpack.endpoint.resolver.relatedAlerts', { + defaultMessage: 'Related Alerts', + }), + }, + relatedEvents: { + title: i18n.translate('xpack.endpoint.resolver.relatedEvents', { + defaultMessage: 'Events', + }), + }, +}; + +interface ResolverSubmenuOption { + optionTitle: string; + action: () => unknown; + prefix?: number | JSX.Element; +} + +export type ResolverSubmenuOptionList = ResolverSubmenuOption[] | string; + +const OptionList = React.memo( + ({ + subMenuOptions, + isLoading, + }: { + subMenuOptions: ResolverSubmenuOptionList; + isLoading: boolean; + }) => { + const [options, setOptions] = useState(() => + typeof subMenuOptions !== 'object' + ? [] + : subMenuOptions.map((opt: ResolverSubmenuOption): { + label: string; + prepend?: ReactNode; + } => { + return opt.prefix + ? { + label: opt.optionTitle, + prepend: {opt.prefix} , + } + : { + label: opt.optionTitle, + prepend: , + }; + }) + ); + return useMemo( + () => ( + { + setOptions(newOptions); + }} + listProps={{ showIcons: true, bordered: true }} + isLoading={isLoading} + > + {list => list} + + ), + [isLoading, options] + ); + } +); + +/** + * A Submenu to be displayed in one of two forms: + * 1) Provided a collection of `optionsWithActions`: it will call `menuAction` then - if and when menuData becomes available - display each item with an optional prefix and call the supplied action for the options when that option is clicked. + * 2) Provided `optionsWithActions` is undefined, it will call the supplied `menuAction` when its host button is clicked. + */ +export const NodeSubMenu = styled( + React.memo( + ({ + menuTitle, + menuAction, + optionsWithActions, + className, + }: { menuTitle: string; className?: string; menuAction: () => unknown } & { + optionsWithActions?: ResolverSubmenuOptionList | string | undefined; + }) => { + const [menuIsOpen, setMenuOpen] = useState(false); + const handleMenuOpenClick = useCallback( + (clickEvent: React.MouseEvent) => { + // stopping propagation/default to prevent other node animations from triggering + clickEvent.preventDefault(); + clickEvent.stopPropagation(); + setMenuOpen(!menuIsOpen); + }, + [menuIsOpen] + ); + const handleMenuActionClick = useCallback( + (clickEvent: React.MouseEvent) => { + // stopping propagation/default to prevent other node animations from triggering + clickEvent.preventDefault(); + clickEvent.stopPropagation(); + if (typeof menuAction === 'function') menuAction(); + setMenuOpen(true); + }, + [menuAction] + ); + + const isMenuLoading = optionsWithActions === 'waitingForRelatedEventData'; + + if (!optionsWithActions) { + /** + * When called with a `menuAction` + * Render without dropdown and call the supplied action when host button is clicked + */ + return ( +
    + + {menuTitle} + +
    + ); + } + /** + * When called with a set of `optionsWithActions`: + * Render with a panel of options that appear when the menu host button is clicked + */ + return ( +
    + + {menuTitle} + + {menuIsOpen && typeof optionsWithActions === 'object' && ( + + )} +
    + ); + } + ) +)` + margin: 0; + padding: 0; + border: none; + display: flex; + flex-flow: column; + &.is-open .euiButton { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + &.is-open .euiSelectableListItem__prepend { + color: white; + } +`; diff --git a/x-pack/plugins/endpoint/server/routes/alerts/details/handlers.ts b/x-pack/plugins/endpoint/server/routes/alerts/details/handlers.ts index 92f8aacbf26a2..ab6d1850e425d 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/details/handlers.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/details/handlers.ts @@ -6,11 +6,11 @@ import { GetResponse } from 'elasticsearch'; import { KibanaRequest, RequestHandler } from 'kibana/server'; import { AlertEvent } from '../../../../common/types'; -import { AlertConstants } from '../../../../common/alert_constants'; import { EndpointAppContext } from '../../../types'; import { AlertDetailsRequestParams } from '../types'; import { AlertDetailsPagination } from './lib'; import { getHostData } from '../../metadata'; +import { AlertId, AlertIdError } from '../lib'; export const alertDetailsHandlerWrapper = function( endpointAppContext: EndpointAppContext @@ -21,10 +21,10 @@ export const alertDetailsHandlerWrapper = function( res ) => { try { - const alertId = req.params.id; + const alertId = AlertId.fromEncoded(req.params.id); const response = (await ctx.core.elasticsearch.dataClient.callAsCurrentUser('get', { - index: AlertConstants.ALERT_INDEX_NAME, - id: alertId, + index: alertId.index, + id: alertId.id, })) as GetResponse; const indexPattern = await endpointAppContext.service @@ -50,7 +50,7 @@ export const alertDetailsHandlerWrapper = function( return res.ok({ body: { - id: response._id, + id: alertId.toString(), ...response._source, state: { host_metadata: currentHostInfo?.metadata, @@ -60,7 +60,13 @@ export const alertDetailsHandlerWrapper = function( }, }); } catch (err) { - if (err.status === 404) { + const logger = endpointAppContext.logFactory.get('alerts'); + logger.warn(err); + + // err will be an AlertIdError if the passed in alert id is not valid + if (err instanceof AlertIdError) { + return res.badRequest({ body: err }); + } else if (err.status === 404) { return res.notFound({ body: err }); } return res.internalError({ body: err }); diff --git a/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts b/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts index 0f69e1bb60c44..5c95b1217d829 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts @@ -8,7 +8,7 @@ import { GetResponse, SearchResponse } from 'elasticsearch'; import { AlertEvent, AlertHits, AlertAPIOrdering } from '../../../../../common/types'; import { AlertConstants } from '../../../../../common/alert_constants'; import { EndpointConfigType } from '../../../../config'; -import { searchESForAlerts, Pagination } from '../../lib'; +import { searchESForAlerts, Pagination, AlertId } from '../../lib'; import { AlertSearchQuery, SearchCursor, AlertDetailsRequestParams } from '../../types'; import { BASE_ALERTS_ROUTE } from '../..'; import { RequestHandlerContext } from '../../../../../../../../src/core/server'; @@ -59,7 +59,8 @@ export class AlertDetailsPagination extends Pagination< protected getUrlFromHits(hits: AlertHits): string | null { if (hits.length > 0) { - return `${BASE_ALERTS_ROUTE}/${hits[0]._id}`; + const id = new AlertId(hits[0]._index, hits[0]._id); + return `${BASE_ALERTS_ROUTE}/${id.toString()}`; } return null; } diff --git a/x-pack/plugins/endpoint/server/routes/alerts/lib/alert_id.ts b/x-pack/plugins/endpoint/server/routes/alerts/lib/alert_id.ts new file mode 100644 index 0000000000000..797bf69f5991a --- /dev/null +++ b/x-pack/plugins/endpoint/server/routes/alerts/lib/alert_id.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { AlertIdError } from './error'; + +/** + * Abstraction over alert IDs. + */ +export class AlertId { + protected readonly _index: string; + protected readonly _id: string; + + constructor(index: string, id: string) { + this._index = index; + this._id = id; + } + + public get index() { + return this._index; + } + + public get id() { + return this._id; + } + + static fromEncoded(encoded: string): AlertId { + try { + const value = encoded.replace(/\-/g, '+').replace(/_/g, '/'); + const data = Buffer.from(value, 'base64').toString('utf8'); + const { index, id } = JSON.parse(data); + return new AlertId(index, id); + } catch (error) { + throw new AlertIdError(`Unable to decode alert id: ${encoded}`); + } + } + + toString(): string { + const value = JSON.stringify({ index: this.index, id: this.id }); + // replace invalid URL characters with valid ones + return Buffer.from(value, 'utf8') + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/g, ''); + } +} diff --git a/x-pack/plugins/reporting/common/types.d.ts b/x-pack/plugins/endpoint/server/routes/alerts/lib/error.ts similarity index 69% rename from x-pack/plugins/reporting/common/types.d.ts rename to x-pack/plugins/endpoint/server/routes/alerts/lib/error.ts index 7ab9a15e1773a..7b00634b25c9c 100644 --- a/x-pack/plugins/reporting/common/types.d.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/lib/error.ts @@ -4,5 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -export { ConfigType } from '../server/config'; +export class AlertIdError extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts index 7bc1c0c306ae2..1c98e3c615669 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts @@ -17,7 +17,9 @@ import { UndefinedResultPosition, } from '../types'; +export { AlertIdError } from './error'; export { Pagination } from './pagination'; +export { AlertId } from './alert_id'; function reverseSortDirection(order: AlertAPIOrdering): AlertAPIOrdering { if (order === 'asc') { diff --git a/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts index 114251820ce4b..0af8f6cf792dd 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts @@ -20,6 +20,7 @@ import { AlertConstants } from '../../../../../common/alert_constants'; import { EndpointAppContext } from '../../../../types'; import { AlertSearchQuery } from '../../types'; import { AlertListPagination } from './pagination'; +import { AlertId } from '../../lib'; export const getRequestData = async ( request: KibanaRequest, @@ -105,8 +106,9 @@ export async function mapToAlertResultList( const pagination: AlertListPagination = new AlertListPagination(config, reqCtx, reqData, hits); function mapHit(entry: AlertHits[0]): AlertData { + const alertId = new AlertId(entry._index, entry._id); return { - id: entry._id, + id: alertId.toString(), ...entry._source, prev: null, next: null, diff --git a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 7f57a3c207ccd..4404ea494b288 100644 --- a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -147,7 +147,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { if (noIndexPatterns) { const managementUrl = chrome.navLinks.get('kibana:stack_management')!.url; - const indexPatternUrl = `${managementUrl}/kibana/index_patterns`; + const indexPatternUrl = `${managementUrl}/kibana/indexPatterns`; const sampleDataUrl = `${application.getUrlForApp('home')}#/tutorial_directory/sampleData`; content = ( diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts index 12781f2f77d17..8bc80c69ce9b2 100644 --- a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts @@ -74,12 +74,22 @@ export const createFleetSetupHandler: RequestHandler< export const ingestManagerSetupHandler: RequestHandler = async (context, request, response) => { const soClient = context.core.savedObjects.client; const callCluster = context.core.elasticsearch.adminClient.callAsCurrentUser; + const logger = appContextService.getLogger(); try { await setupIngestManager(soClient, callCluster); return response.ok({ body: { isInitialized: true }, }); } catch (e) { + if (e.isBoom) { + logger.error(e.output.payload.message); + return response.customError({ + statusCode: e.output.statusCode, + body: { message: e.output.payload.message }, + }); + } + logger.error(e.message); + logger.error(e.stack); return response.customError({ statusCode: 500, body: { message: e.message }, diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts index 6ef6f863753b5..2c452f16cc104 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import Boom from 'boom'; import { Dataset, RegistryPackage, ElasticsearchAssetType, TemplateRef } from '../../../../types'; import { CallESAsCurrentUser } from '../../../../types'; import { Field, loadFieldsFromYaml, processFields } from '../../fields/field'; @@ -20,8 +21,8 @@ export const installTemplates = async ( // install any pre-built index template assets, // atm, this is only the base package's global index templates // Install component templates first, as they are used by the index templates - installPreBuiltComponentTemplates(pkgName, pkgVersion, callCluster); - installPreBuiltTemplates(pkgName, pkgVersion, callCluster); + await installPreBuiltComponentTemplates(pkgName, pkgVersion, callCluster); + await installPreBuiltTemplates(pkgName, pkgVersion, callCluster); // build templates per dataset from yml files const datasets = registryPackage.datasets; @@ -53,16 +54,7 @@ const installPreBuiltTemplates = async ( pkgVersion, (entry: Registry.ArchiveEntry) => isTemplate(entry) ); - // templatePaths.forEach(async path => { - // const { file } = Registry.pathParts(path); - // const templateName = file.substr(0, file.lastIndexOf('.')); - // const content = JSON.parse(Registry.getAsset(path).toString('utf8')); - // await callCluster('indices.putTemplate', { - // name: templateName, - // body: content, - // }); - // }); - templatePaths.forEach(async path => { + const templateInstallPromises = templatePaths.map(async path => { const { file } = Registry.pathParts(path); const templateName = file.substr(0, file.lastIndexOf('.')); const content = JSON.parse(Registry.getAsset(path).toString('utf8')); @@ -91,8 +83,15 @@ const installPreBuiltTemplates = async ( // The existing convenience endpoint `indices.putTemplate` only sends to _template, // which does not support v2 templates. // See src/core/server/elasticsearch/api_types.ts for available endpoints. - await callCluster('transport.request', callClusterParams); + return callCluster('transport.request', callClusterParams); }); + try { + return await Promise.all(templateInstallPromises); + } catch (e) { + throw new Boom(`Error installing prebuilt index templates ${e.message}`, { + statusCode: 400, + }); + } }; const installPreBuiltComponentTemplates = async ( @@ -105,7 +104,7 @@ const installPreBuiltComponentTemplates = async ( pkgVersion, (entry: Registry.ArchiveEntry) => isComponentTemplate(entry) ); - templatePaths.forEach(async path => { + const templateInstallPromises = templatePaths.map(async path => { const { file } = Registry.pathParts(path); const templateName = file.substr(0, file.lastIndexOf('.')); const content = JSON.parse(Registry.getAsset(path).toString('utf8')); @@ -124,8 +123,15 @@ const installPreBuiltComponentTemplates = async ( // This uses the catch-all endpoint 'transport.request' because there is no // convenience endpoint for component templates yet. // See src/core/server/elasticsearch/api_types.ts for available endpoints. - await callCluster('transport.request', callClusterParams); + return callCluster('transport.request', callClusterParams); }); + try { + return await Promise.all(templateInstallPromises); + } catch (e) { + throw new Boom(`Error installing prebuilt component templates ${e.message}`, { + statusCode: 400, + }); + } }; const isTemplate = ({ path }: Registry.ArchiveEntry) => { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 632bc3ac9b69f..79a5e98b9507d 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -73,17 +73,13 @@ export async function ensureInstalledPackage(options: { if (installedPackage) { return installedPackage; } - // if the requested packaged was not found to be installed, try installing - try { - await installLatestPackage({ - savedObjectsClient, - pkgName, - callCluster, - }); - return await getInstallation({ savedObjectsClient, pkgName }); - } catch (err) { - throw new Error(err.message); - } + // if the requested packaged was not found to be installed, install + await installLatestPackage({ + savedObjectsClient, + pkgName, + callCluster, + }); + return await getInstallation({ savedObjectsClient, pkgName }); } export async function installPackage(options: { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts index 654aa8aae1355..93e475cbc5956 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts @@ -17,7 +17,7 @@ export async function getResponse(url: string): Promise { throw new Boom(response.statusText, { statusCode: response.status }); } } catch (e) { - throw Boom.boomify(e); + throw new Boom(`Error connecting to package registry: ${e.message}`, { statusCode: 502 }); } } diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 4a3ac6390c5a7..60d437d2321b5 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -87,7 +87,7 @@ export class ESAggField implements IESAggField { return this._esDocField ? this._esDocField.getName() : ''; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const indexPattern = await this._source.getIndexPattern(); const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value); return new ESAggTooltipProperty(tooltipProperty, indexPattern, this, this.getAggType()); diff --git a/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts b/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts index 670b3ba32888b..9faa33fae5a43 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts @@ -45,7 +45,7 @@ export class ESDocField extends AbstractField implements IField { : indexPatternField; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const indexPattern = await this._source.getIndexPattern(); const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value); return new ESTooltipProperty(tooltipProperty, indexPattern, this as IField); diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 04daedc59c032..dfd5dc05f7b83 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -14,7 +14,7 @@ export interface IField { canValueBeFormatted(): boolean; getLabel(): Promise; getDataType(): Promise; - createTooltipProperty(value: string | undefined): Promise; + createTooltipProperty(value: string | string[] | undefined): Promise; getSource(): IVectorSource; getOrigin(): FIELD_ORIGIN; isValid(): boolean; @@ -60,7 +60,7 @@ export class AbstractField implements IField { return this._fieldName; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const label = await this.getLabel(); return new TooltipProperty(this.getName(), label, value); } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 84bade4d94490..6c504daf3e192 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -48,7 +48,7 @@ export class TopTermPercentageField implements IESAggField { return 'number'; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { return new TooltipProperty(this.getName(), await this.getLabel(), value); } diff --git a/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts index d2fdcfaab476c..516ad25f933f6 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts @@ -33,7 +33,7 @@ export class ESTooltipProperty implements ITooltipProperty { return this._tooltipProperty.getPropertyName(); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._tooltipProperty.getRawValue(); } @@ -48,7 +48,12 @@ export class ESTooltipProperty implements ITooltipProperty { const indexPatternField = this._getIndexPatternField(); if (!indexPatternField || !this._field.canValueBeFormatted()) { - return _.escape(this.getRawValue()); + const rawValue = this.getRawValue(); + if (Array.isArray(rawValue)) { + return _.escape(rawValue.join()); + } else { + return _.escape(rawValue); + } } const htmlConverter = indexPatternField.format.getConverterFor('html'); diff --git a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts index cc95c12ef630f..fad6d6b84f77f 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts @@ -29,7 +29,7 @@ export class JoinTooltipProperty implements ITooltipProperty { return this._tooltipProperty.getPropertyName(); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._tooltipProperty.getRawValue(); } diff --git a/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts index 8da2ed795943b..7149fe29f90ec 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts @@ -12,7 +12,7 @@ export interface ITooltipProperty { getPropertyKey(): string; getPropertyName(): string; getHtmlDisplayValue(): string; - getRawValue(): string | undefined; + getRawValue(): string | string[] | undefined; isFilterable(): boolean; getESFilters(): Promise; } @@ -41,10 +41,10 @@ export type RenderToolTipContent = (params: RenderTooltipContentParams) => JSX.E export class TooltipProperty implements ITooltipProperty { private readonly _propertyKey: string; - private readonly _rawValue: string | undefined; + private readonly _rawValue: string | string[] | undefined; private readonly _propertyName: string; - constructor(propertyKey: string, propertyName: string, rawValue: string | undefined) { + constructor(propertyKey: string, propertyName: string, rawValue: string | string[] | undefined) { this._propertyKey = propertyKey; this._propertyName = propertyName; this._rawValue = rawValue; @@ -59,10 +59,10 @@ export class TooltipProperty implements ITooltipProperty { } getHtmlDisplayValue(): string { - return _.escape(this._rawValue); + return _.escape(Array.isArray(this._rawValue) ? this._rawValue.join() : this._rawValue); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._rawValue; } diff --git a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js b/x-pack/plugins/maps/public/components/no_index_pattern_callout.js index f6c8b7ebba63b..89cd884a6dd32 100644 --- a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js +++ b/x-pack/plugins/maps/public/components/no_index_pattern_callout.js @@ -24,7 +24,7 @@ export function NoIndexPatternCallout() { id="xpack.maps.noIndexPattern.doThisPrefixDescription" defaultMessage="You'll need to " /> - + = () => }; export { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; +export { ITooltipProperty } from './classes/tooltips/tooltip_property'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx index 998cb4a75bf3c..88d437d7b8b3f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx @@ -153,8 +153,8 @@ export const ResultsLinks: FC = ({ /> } description="" - href={`${basePath.get()}/app/kibana#/management/kibana/index_patterns/${ - createIndexPattern ? indexPatternId : '' + href={`${basePath.get()}/app/kibana#/management/kibana/indexPatterns${ + createIndexPattern ? `/patterns/${indexPatternId}` : '' }`} /> diff --git a/x-pack/plugins/ml/server/routes/apidoc_scripts/schema_worker.ts b/x-pack/plugins/ml/server/routes/apidoc_scripts/schema_worker.ts index 7514e482783b3..0eaf3143eaac0 100644 --- a/x-pack/plugins/ml/server/routes/apidoc_scripts/schema_worker.ts +++ b/x-pack/plugins/ml/server/routes/apidoc_scripts/schema_worker.ts @@ -44,9 +44,10 @@ export function postProcess(parsedFiles: any[]): void { */ function updateBlockParameters(docEntries: DocEntry[], block: Block, paramsGroup: string): void { if (!block.local.parameter) { - block.local.parameter = { - fields: {}, - }; + block.local.parameter = {}; + } + if (!block.local.parameter.fields) { + block.local.parameter.fields = {}; } if (!block.local.parameter.fields![paramsGroup]) { diff --git a/x-pack/plugins/ml/server/routes/modules.ts b/x-pack/plugins/ml/server/routes/modules.ts index 622ae66ede426..ade3d3eca90ea 100644 --- a/x-pack/plugins/ml/server/routes/modules.ts +++ b/x-pack/plugins/ml/server/routes/modules.ts @@ -4,13 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { schema, TypeOf } from '@kbn/config-schema'; +import { TypeOf } from '@kbn/config-schema'; import { RequestHandlerContext } from 'kibana/server'; import { DatafeedOverride, JobOverride } from '../../common/types/modules'; import { wrapError } from '../client/error_wrapper'; import { DataRecognizer } from '../models/data_recognizer'; -import { getModuleIdParamSchema, setupModuleBodySchema } from './schemas/modules'; +import { + moduleIdParamSchema, + optionalModuleIdParamSchema, + modulesIndexPatternTitleSchema, + setupModuleBodySchema, +} from './schemas/modules'; import { RouteInitialization } from '../types'; function recognize(context: RequestHandlerContext, indexPatternTitle: string) { @@ -85,17 +90,33 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { * * @api {get} /api/ml/modules/recognize/:indexPatternTitle Recognize index pattern * @apiName RecognizeIndex - * @apiDescription Returns the list of modules that matching the index pattern. - * - * @apiParam {String} indexPatternTitle Index pattern title. + * @apiDescription By supplying an index pattern, discover if any of the modules are a match for data in that index. + * @apiSchema (params) modulesIndexPatternTitleSchema + * @apiSuccess {object[]} modules Array of objects describing the modules which match the index pattern. + * @apiSuccessExample {json} Success-Response: + * [{ + * "id": "nginx_ecs", + * "query": { + * "bool": { + * "filter": [ + * { "term": { "event.dataset": "nginx.access" } }, + * { "exists": { "field": "source.address" } }, + * { "exists": { "field": "url.original" } }, + * { "exists": { "field": "http.response.status_code" } } + * ] + * } + * }, + * "description": "Find unusual activity in HTTP access logs from filebeat (ECS)", + * "logo": { + * "icon": "logoNginx" + * } + * }] */ router.get( { path: '/api/ml/modules/recognize/{indexPatternTitle}', validate: { - params: schema.object({ - indexPatternTitle: schema.string(), - }), + params: modulesIndexPatternTitleSchema, }, options: { tags: ['access:ml:canCreateJob'], @@ -118,17 +139,114 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { * * @api {get} /api/ml/modules/get_module/:moduleId Get module * @apiName GetModule - * @apiDescription Returns module by id. - * - * @apiParam {String} [moduleId] Module id + * @apiDescription Retrieve a whole ML module, containing jobs, datafeeds and saved objects. If + * no module ID is supplied, returns all modules. + * @apiSchema (params) moduleIdParamSchema + * @apiSuccess {object} module When a module ID is specified, returns a module object containing + * all of the jobs, datafeeds and saved objects which will be created when the module is setup. + * @apiSuccess {object[]} modules If no module ID is supplied, an array of all modules will be returned. + * @apiSuccessExample {json} Success-Response: + * { + * "id":"sample_data_ecommerce", + * "title":"Kibana sample data eCommerce", + * "description":"Find anomalies in eCommerce total sales data", + * "type":"Sample Dataset", + * "logoFile":"logo.json", + * "defaultIndexPattern":"kibana_sample_data_ecommerce", + * "query":{ + * "bool":{ + * "filter":[ + * { + * "term":{ + * "_index":"kibana_sample_data_ecommerce" + * } + * } + * ] + * } + * }, + * "jobs":[ + * { + * "id":"high_sum_total_sales", + * "config":{ + * "groups":[ + * "kibana_sample_data", + * "kibana_sample_ecommerce" + * ], + * "description":"Find customers spending an unusually high amount in an hour", + * "analysis_config":{ + * "bucket_span":"1h", + * "detectors":[ + * { + * "detector_description":"High total sales", + * "function":"high_sum", + * "field_name":"taxful_total_price", + * "over_field_name":"customer_full_name.keyword" + * } + * ], + * "influencers":[ + * "customer_full_name.keyword", + * "category.keyword" + * ] + * }, + * "analysis_limits":{ + * "model_memory_limit":"10mb" + * }, + * "data_description":{ + * "time_field":"order_date" + * }, + * "model_plot_config":{ + * "enabled":true + * }, + * "custom_settings":{ + * "created_by":"ml-module-sample", + * "custom_urls":[ + * { + * "url_name":"Raw data", + * "url_value":"kibana#/discover?_g=(time:(from:'$earliest$',mode:absolute,to:'$latest$'))&_a + * (index:ff959d40-b880-11e8-a6d9-e546fe2bba5f,query:(language:kuery,query:'customer_full_name + * keyword:\"$customer_full_name.keyword$\"'),sort:!('@timestamp',desc))" + * }, + * { + * "url_name":"Data dashboard", + * "url_value":"kibana#/dashboard/722b74f0-b882-11e8-a6d9-e546fe2bba5f?_g=(filters:!(),time:(from:'$earliest$', + * mode:absolute,to:'$latest$'))&_a=(filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f + * index:'INDEX_PATTERN_ID', key:customer_full_name.keyword,negate:!f,params:(query:'$customer_full_name.keyword$') + * type:phrase,value:'$customer_full_name.keyword$'),query:(match:(customer_full_name.keyword: + * (query:'$customer_full_name.keyword$',type:phrase))))),query:(language:kuery, query:''))" + * } + * ] + * } + * } + * } + * ], + * "datafeeds":[ + * { + * "id":"datafeed-high_sum_total_sales", + * "config":{ + * "job_id":"high_sum_total_sales", + * "indexes":[ + * "INDEX_PATTERN_NAME" + * ], + * "query":{ + * "bool":{ + * "filter":[ + * { + * "term":{ "_index":"kibana_sample_data_ecommerce" } + * } + * ] + * } + * } + * } + * } + * ], + * "kibana":{} + * } */ router.get( { path: '/api/ml/modules/get_module/{moduleId?}', validate: { - params: schema.object({ - ...getModuleIdParamSchema(true), - }), + params: optionalModuleIdParamSchema, }, options: { tags: ['access:ml:canGetJobs'], @@ -154,17 +272,148 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { /** * @apiGroup Modules * - * @api {post} /api/ml/modules/setup/:moduleId Setup module + * @api {post} /api/ml/modules/setup/:moduleId Set up module * @apiName SetupModule - * @apiDescription Created module items. - * + * @apiDescription Runs the module setup process. + * This creates jobs, datafeeds and kibana saved objects. It allows for customization of the module, + * overriding the default configuration. It also allows the user to start the datafeed. + * @apiSchema (params) moduleIdParamSchema * @apiSchema (body) setupModuleBodySchema + * @apiParamExample {json} jobOverrides-no-job-ID: + * "jobOverrides": { + * "analysis_limits": { + * "model_memory_limit": "13mb" + * } + * } + * @apiParamExample {json} jobOverrides-with-job-ID: + * "jobOverrides": [ + * { + * "analysis_limits": { + * "job_id": "foo" + * "model_memory_limit": "13mb" + * } + * } + * ] + * @apiParamExample {json} datafeedOverrides: + * "datafeedOverrides": [ + * { + * "scroll_size": 1001 + * }, + * { + * "job_id": "visitor_rate_ecs", + * "frequency": "30m" + * } + * ] + * @apiParamExample {json} query-overrrides-datafeedOverrides-query: + * { + * "query": {"bool":{"must":[{"match_all":{}}]}} + * "datafeedOverrides": { + * "query": {} + * } + * } + * @apiSuccess {object} results An object containing the results of creating the items in a module, + * i.e. the jobs, datafeeds and saved objects. Each item is listed by id with a success flag + * signifying whether the creation was successful. If the item creation failed, an error object + * with also be supplied containing the error. + * @apiSuccessExample {json} Success-Response: + * { + * "jobs": [{ + * "id": "test-visitor_rate_ecs", + * "success": true + * }, { + * "id": "test-status_code_rate_ecs", + * "success": true + * }, { + * "id": "test-source_ip_url_count_ecs", + * "success": true + * }, { + * "id": "test-source_ip_request_rate_ecs", + * "success": true + * }, { + * "id": "test-low_request_rate_ecs", + * "success": true + * }], + * "datafeeds": [{ + * "id": "datafeed-test-visitor_rate_ecs", + * "success": true, + * "started": false + * }, { + * "id": "datafeed-test-status_code_rate_ecs", + * "success": true, + * "started": false + * }, { + * "id": "datafeed-test-source_ip_url_count_ecs", + * "success": true, + * "started": false + * }, { + * "id": "datafeed-test-low_request_rate_ecs", + * "success": true, + * "started": false + * }, { + * "id": "datafeed-test-source_ip_request_rate_ecs", + * "success": true, + * "started": false + * }], + * "kibana": { + * "dashboard": [{ + * "id": "ml_http_access_explorer_ecs", + * "success": true + * }], + * "search": [{ + * "id": "ml_http_access_filebeat_ecs", + * "success": true + * }], + * "visualization": [{ + * "id": "ml_http_access_map_ecs", + * "success": true + * }, { + * "id": "ml_http_access_source_ip_timechart_ecs", + * "success": true + * }, { + * "id": "ml_http_access_status_code_timechart_ecs", + * "success": true + * }, { + * "id": "ml_http_access_top_source_ips_table_ecs", + * "success": true + * }, { + * "id": "ml_http_access_top_urls_table_ecs", + * "success": true + * }, { + * "id": "ml_http_access_events_timechart_ecs", + * "success": true + * }, { + * "id": "ml_http_access_unique_count_url_timechart_ecs", + * "success": true + * }] + * } + * } + * @apiSuccessExample {json} Error-Response: + * { + * "jobs": [{ + * "id": "test-status_code_rate_ecs", + * "success": false, + * "error": { + * "msg": "[resource_already_exists_exception] The job cannot be created with the Id 'test-status_code_rate_ecs'. The Id is + * already used.", + * "path": "/_ml/anomaly_detectors/test-status_code_rate_ecs", + * "query": {}, + * "body": "{...}", + * "statusCode": 400, + * "response": "{\"error\":{\"root_cause\":[{\"type\":\"resource_already_exists_exception\",\"reason\":\"The job cannot be created + * with the Id 'test-status_code_rate_ecs'. The Id is already used.\"}],\"type\":\"resource_already_exists_exception\", + * \"reason\":\"The job cannot be created with the Id 'test-status_code_rate_ecs'. The Id is already used.\"},\"status\":400}" + * } + * }, + * }, + * ... + * }] + * } */ router.post( { path: '/api/ml/modules/setup/{moduleId}', validate: { - params: schema.object(getModuleIdParamSchema()), + params: moduleIdParamSchema, body: setupModuleBodySchema, }, options: { @@ -217,15 +466,58 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { * * @api {post} /api/ml/modules/jobs_exist/:moduleId Check if module jobs exist * @apiName CheckExistingModuleJobs - * @apiDescription Checks if the jobs in the module have been created. - * - * @apiParam {String} moduleId Module id + * @apiDescription Check whether the jobs in the module with the specified ID exist in the + * current list of jobs. The check runs a test to see if any of the jobs in existence + * have an ID which ends with the ID of each job in the module. This is done as a prefix + * may be supplied in the setup endpoint which is added to the start of the ID of every job in the module. + * @apiSchema (params) moduleIdParamSchema + * @apiSuccess {boolean} jobsExist true if all the jobs in the module have a matching job with an + * ID which ends with the job ID specified in the module, false otherwise. + * @apiSuccess {Object[]} jobs present if the jobs do all exist, with each object having keys of id, + * and optionally earliestTimestampMs, latestTimestampMs, latestResultsTimestampMs + * properties if the job has processed any data. + * @apiSuccessExample {json} Success-Response: + * { + * "jobsExist":true, + * "jobs":[ + * { + * "id":"nginx_low_request_rate_ecs", + * "earliestTimestampMs":1547016291000, + * "latestTimestampMs":1548256497000 + * "latestResultsTimestampMs":1548255600000 + * }, + * { + * "id":"nginx_source_ip_request_rate_ecs", + * "earliestTimestampMs":1547015109000, + * "latestTimestampMs":1548257222000 + * "latestResultsTimestampMs":1548255600000 + * }, + * { + * "id":"nginx_source_ip_url_count_ecs", + * "earliestTimestampMs":1547015109000, + * "latestTimestampMs":1548257222000 + * "latestResultsTimestampMs":1548255600000 + * }, + * { + * "id":"nginx_status_code_rate_ecs", + * "earliestTimestampMs":1547015109000, + * "latestTimestampMs":1548257222000 + * "latestResultsTimestampMs":1548255600000 + * }, + * { + * "id":"nginx_visitor_rate_ecs", + * "earliestTimestampMs":1547016291000, + * "latestTimestampMs":1548256497000 + * "latestResultsTimestampMs":1548255600000 + * } + * ] + * } */ router.get( { path: '/api/ml/modules/jobs_exist/{moduleId}', validate: { - params: schema.object(getModuleIdParamSchema()), + params: moduleIdParamSchema, }, options: { tags: ['access:ml:canGetJobs'], diff --git a/x-pack/plugins/ml/server/routes/schemas/modules.ts b/x-pack/plugins/ml/server/routes/schemas/modules.ts index 98e3d80f0ff84..23148c14c734e 100644 --- a/x-pack/plugins/ml/server/routes/schemas/modules.ts +++ b/x-pack/plugins/ml/server/routes/schemas/modules.ts @@ -7,24 +7,89 @@ import { schema } from '@kbn/config-schema'; export const setupModuleBodySchema = schema.object({ + /** + * Job ID prefix. This will be added to the start of the ID every job created by the module (optional). + */ prefix: schema.maybe(schema.string()), + /** + * List of group IDs. This will override the groups assigned to each job created by the module (optional). + */ groups: schema.maybe(schema.arrayOf(schema.string())), + /** + * Name of kibana index pattern. Overrides the index used in each datafeed and each index pattern + * used in the custom urls and saved objects created by the module. A matching index pattern must + * exist in kibana if the module contains custom urls or saved objects which rely on an index pattern ID. + * If the module does not contain custom urls or saved objects which require an index pattern ID, the + * indexPatternName can be any index name or pattern that will match an ES index. It can also be a comma + * separated list of names. If no indexPatternName is supplied, the default index pattern specified in + * the manifest.json will be used (optional). + */ indexPatternName: schema.maybe(schema.string()), + /** + * ES Query DSL object. Overrides the query object for each datafeed created by the module (optional). + */ query: schema.maybe(schema.any()), + /** + * Flag to specify that each job created by the module uses a dedicated index (optional). + */ useDedicatedIndex: schema.maybe(schema.boolean()), + /** + * Flag to specify that each datafeed created by the module is started once saved. Defaults to false (optional). + */ startDatafeed: schema.maybe(schema.boolean()), + /** + * Start date for datafeed. Specified in epoch seconds. Only used if startDatafeed is true. + * If not specified, a value of 0 is used i.e. start at the beginning of the data (optional). + */ start: schema.maybe(schema.number()), + /** + * End date for datafeed. Specified in epoch seconds. Only used if startDatafeed is true. + * If not specified, the datafeed will continue to run in real time (optional). + */ end: schema.maybe(schema.number()), + /** + * Partial job configuration which will override jobs contained in the module. Can be an array of objects. + * If a job_id is specified, only that job in the module will be overridden. + * Applied before any of the existing + * overridable options (e.g. useDedicatedIndex, groups, indexPatternName etc) + * and so can be overridden themselves (optional). + */ jobOverrides: schema.maybe(schema.any()), + /** + * Partial datafeed configuration which will override datafeeds contained in the module. + * Can be an array of objects. + * If a datafeed_id or a job_id is specified, + * only that datafeed in the module will be overridden. Applied before any of the existing + * overridable options (e.g. useDedicatedIndex, groups, indexPatternName etc) + * and so can be overridden themselves (optional). + */ datafeedOverrides: schema.maybe(schema.any()), /** * Indicates whether an estimate of the model memory limit - * should be made by checking the cardinality of fields in the job configurations. + * should be made by checking the cardinality of fields in the job configurations (optional). */ estimateModelMemory: schema.maybe(schema.boolean()), }); export const getModuleIdParamSchema = (optional = false) => { const stringType = schema.string(); - return { moduleId: optional ? schema.maybe(stringType) : stringType }; + return schema.object({ + /** + * ID of the module. + */ + moduleId: optional ? schema.maybe(stringType) : stringType, + }); }; + +export const optionalModuleIdParamSchema = getModuleIdParamSchema(true); + +export const moduleIdParamSchema = getModuleIdParamSchema(false); + +export const modulesIndexPatternTitleSchema = schema.object({ + /** + * Index pattern to recognize. Note that this does not need to be a Kibana + * index pattern, and can be the name of a single Elasticsearch index, + * or include a wildcard (*) to match multiple indices. + */ + indexPatternTitle: schema.string(), +}); diff --git a/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts b/x-pack/plugins/reporting/common/cancellation_token.test.ts similarity index 100% rename from x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts rename to x-pack/plugins/reporting/common/cancellation_token.test.ts diff --git a/x-pack/legacy/plugins/reporting/common/cancellation_token.ts b/x-pack/plugins/reporting/common/cancellation_token.ts similarity index 100% rename from x-pack/legacy/plugins/reporting/common/cancellation_token.ts rename to x-pack/plugins/reporting/common/cancellation_token.ts diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts b/x-pack/plugins/reporting/common/index.ts similarity index 80% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts rename to x-pack/plugins/reporting/common/index.ts index b4dc743664995..36c896fb4f7b8 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts +++ b/x-pack/plugins/reporting/common/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export type RawValue = string | object | null | undefined; +export { CancellationToken } from './cancellation_token'; diff --git a/x-pack/plugins/reporting/common/poller.ts b/x-pack/plugins/reporting/common/poller.ts index 919d7273062a8..1aeaca001cf1e 100644 --- a/x-pack/plugins/reporting/common/poller.ts +++ b/x-pack/plugins/reporting/common/poller.ts @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { PollerOptions } from '..'; +import { PollerOptions } from './types'; // @TODO Maybe move to observables someday export class Poller { diff --git a/x-pack/plugins/reporting/index.d.ts b/x-pack/plugins/reporting/common/types.ts similarity index 93% rename from x-pack/plugins/reporting/index.d.ts rename to x-pack/plugins/reporting/common/types.ts index 77faf837e6505..5b9ddfb1bbdea 100644 --- a/x-pack/plugins/reporting/index.d.ts +++ b/x-pack/plugins/reporting/common/types.ts @@ -4,6 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { ConfigType } from '../server/config'; + export type JobId = string; export type JobStatus = | 'completed' diff --git a/x-pack/plugins/reporting/public/components/job_download_button.tsx b/x-pack/plugins/reporting/public/components/job_download_button.tsx index 911a19c0176c2..7dff2cafa047b 100644 --- a/x-pack/plugins/reporting/public/components/job_download_button.tsx +++ b/x-pack/plugins/reporting/public/components/job_download_button.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { JobId, JobSummary } from '../../index.d'; +import React from 'react'; +import { JobId, JobSummary } from '../../common/types'; interface Props { getUrl: (jobId: JobId) => string; diff --git a/x-pack/plugins/reporting/public/components/job_failure.tsx b/x-pack/plugins/reporting/public/components/job_failure.tsx index 628ecb56b9c21..0da67ea367437 100644 --- a/x-pack/plugins/reporting/public/components/job_failure.tsx +++ b/x-pack/plugins/reporting/public/components/job_failure.tsx @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import React, { Fragment } from 'react'; import { ToastInput } from 'src/core/public'; import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; -import { JobSummary, ManagementLinkFn } from '../../index.d'; +import { JobSummary, ManagementLinkFn } from '../../common/types'; export const getFailureToast = ( errorText: string, diff --git a/x-pack/plugins/reporting/public/components/job_success.tsx b/x-pack/plugins/reporting/public/components/job_success.tsx index ad16a506aeb70..7f33321ee3645 100644 --- a/x-pack/plugins/reporting/public/components/job_success.tsx +++ b/x-pack/plugins/reporting/public/components/job_success.tsx @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import React, { Fragment } from 'react'; import { ToastInput } from 'src/core/public'; import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; -import { JobId, JobSummary } from '../../index.d'; +import { JobId, JobSummary } from '../../common/types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/components/job_warning_formulas.tsx b/x-pack/plugins/reporting/public/components/job_warning_formulas.tsx index 8717ae16d1ba1..e2afae1feaa01 100644 --- a/x-pack/plugins/reporting/public/components/job_warning_formulas.tsx +++ b/x-pack/plugins/reporting/public/components/job_warning_formulas.tsx @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import React, { Fragment } from 'react'; import { ToastInput } from 'src/core/public'; import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; -import { JobId, JobSummary } from '../../index.d'; +import { JobId, JobSummary } from '../../common/types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/components/job_warning_max_size.tsx b/x-pack/plugins/reporting/public/components/job_warning_max_size.tsx index 83fa129f0715a..6c0d6118dfff2 100644 --- a/x-pack/plugins/reporting/public/components/job_warning_max_size.tsx +++ b/x-pack/plugins/reporting/public/components/job_warning_max_size.tsx @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import React, { Fragment } from 'react'; import { ToastInput } from 'src/core/public'; import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; -import { JobId, JobSummary } from '../../index.d'; +import { JobId, JobSummary } from '../../common/types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/lib/license_check.ts b/x-pack/plugins/reporting/public/lib/license_check.ts index 0c16ead0b116d..bf4dfeeb8fe31 100644 --- a/x-pack/plugins/reporting/public/lib/license_check.ts +++ b/x-pack/plugins/reporting/public/lib/license_check.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { LicenseCheckResults } from '../..'; + import { LicenseCheck } from '../../../licensing/public'; +import { LicenseCheckResults } from '../../common/types'; export const checkLicense = (checkResults: LicenseCheck): LicenseCheckResults => { switch (checkResults.state) { diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client.ts index b6c33860752d6..54bdc99532320 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client.ts @@ -6,11 +6,10 @@ import { stringify } from 'query-string'; import rison from 'rison-node'; - import { HttpSetup } from 'src/core/public'; +import { JobId, SourceJob } from '../../common/types'; +import { API_BASE_GENERATE, API_LIST_URL, REPORTING_MANAGEMENT_HOME } from '../../constants'; import { add } from './job_completion_notifications'; -import { API_LIST_URL, API_BASE_GENERATE, REPORTING_MANAGEMENT_HOME } from '../../constants'; -import { JobId, SourceJob } from '../..'; export interface JobQueueEntry { _id: string; diff --git a/x-pack/plugins/reporting/public/lib/stream_handler.test.ts b/x-pack/plugins/reporting/public/lib/stream_handler.test.ts index 3a2c7de9ad0f0..96f284ae282b9 100644 --- a/x-pack/plugins/reporting/public/lib/stream_handler.test.ts +++ b/x-pack/plugins/reporting/public/lib/stream_handler.test.ts @@ -6,7 +6,7 @@ import sinon, { stub } from 'sinon'; import { NotificationsStart } from 'src/core/public'; -import { SourceJob, JobSummary } from '../../index.d'; +import { JobSummary, SourceJob } from '../../common/types'; import { ReportingAPIClient } from './reporting_api_client'; import { ReportingNotifierStreamHandler } from './stream_handler'; diff --git a/x-pack/plugins/reporting/public/lib/stream_handler.ts b/x-pack/plugins/reporting/public/lib/stream_handler.ts index eed6d5dd141e7..41e5353badfe5 100644 --- a/x-pack/plugins/reporting/public/lib/stream_handler.ts +++ b/x-pack/plugins/reporting/public/lib/stream_handler.ts @@ -8,13 +8,13 @@ import { i18n } from '@kbn/i18n'; import * as Rx from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { NotificationsSetup } from 'src/core/public'; +import { JobId, JobStatusBuckets, JobSummary, SourceJob } from '../../common/types'; import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JOB_STATUS_COMPLETED, JOB_STATUS_FAILED, JOB_STATUS_WARNINGS, } from '../../constants'; -import { JobId, JobStatusBuckets, JobSummary, SourceJob } from '../../index.d'; import { getFailureToast, getGeneralErrorToast, diff --git a/x-pack/plugins/reporting/public/plugin.tsx b/x-pack/plugins/reporting/public/plugin.tsx index f600b1ebbb96c..ac8ea661a21ab 100644 --- a/x-pack/plugins/reporting/public/plugin.tsx +++ b/x-pack/plugins/reporting/public/plugin.tsx @@ -18,16 +18,15 @@ import { PluginInitializerContext, } from 'src/core/public'; import { UiActionsSetup } from 'src/plugins/ui_actions/public'; -import { JobId, JobStatusBuckets } from '../'; -import { ManagementSetup, ManagementSectionId } from '../../../../src/plugins/management/public'; import { CONTEXT_MENU_TRIGGER } from '../../../../src/plugins/embeddable/public'; import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; +import { ManagementSectionId, ManagementSetup } from '../../../../src/plugins/management/public'; import { SharePluginSetup } from '../../../../src/plugins/share/public'; import { LicensingPluginSetup } from '../../licensing/public'; -import { ConfigType } from '../common/types'; +import { ConfigType, JobId, JobStatusBuckets } from '../common/types'; import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '../constants'; import { getGeneralErrorToast } from './components'; import { ReportListing } from './components/report_listing'; diff --git a/x-pack/plugins/reporting/server/index.ts b/x-pack/plugins/reporting/server/index.ts index 2b1844cf2e10e..9d34eba70d0f4 100644 --- a/x-pack/plugins/reporting/server/index.ts +++ b/x-pack/plugins/reporting/server/index.ts @@ -7,8 +7,8 @@ import { PluginInitializerContext } from 'src/core/server'; import { ReportingPlugin } from './plugin'; -export { config, ConfigSchema } from './config'; -export { ConfigType, PluginsSetup } from './plugin'; +export { config, ConfigSchema, ConfigType } from './config'; +export { PluginsSetup } from './plugin'; export const plugin = (initializerContext: PluginInitializerContext) => new ReportingPlugin(initializerContext); diff --git a/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js index c29fba44285be..a1c1fb4c7b388 100644 --- a/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js +++ b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js @@ -84,7 +84,7 @@ export class RollupIndexPatternCreationConfig extends IndexPatternCreationConfig testSubj: `createRollupIndexPatternButton`, isBeta: this.isBeta, onClick: () => { - urlHandler('/management/kibana/index_pattern?type=rollup'); + urlHandler('/create?type=rollup'); }, } : null; diff --git a/x-pack/plugins/siem/cypress/integration/cases.spec.ts b/x-pack/plugins/siem/cypress/integration/cases.spec.ts index e11d76d8f608a..8f35a3209c69d 100644 --- a/x-pack/plugins/siem/cypress/integration/cases.spec.ts +++ b/x-pack/plugins/siem/cypress/integration/cases.spec.ts @@ -30,7 +30,6 @@ import { CASE_DETAILS_PUSH_TO_EXTERNAL_SERVICE_BTN, CASE_DETAILS_STATUS, CASE_DETAILS_TAGS, - CASE_DETAILS_TIMELINE_MARKDOWN, CASE_DETAILS_USER_ACTION, CASE_DETAILS_USERNAMES, PARTICIPANTS, @@ -103,13 +102,11 @@ describe('Cases', () => { .should('have.text', case1.reporter); cy.get(CASE_DETAILS_TAGS).should('have.text', expectedTags); cy.get(CASE_DETAILS_PUSH_TO_EXTERNAL_SERVICE_BTN).should('have.attr', 'disabled'); - cy.get(CASE_DETAILS_TIMELINE_MARKDOWN).then($element => { - const timelineLink = $element.prop('href').match(/http(s?):\/\/\w*:\w*(\S*)/)[0]; - openCaseTimeline(timelineLink); - cy.get(TIMELINE_TITLE).should('have.attr', 'value', case1.timeline.title); - cy.get(TIMELINE_DESCRIPTION).should('have.attr', 'value', case1.timeline.description); - cy.get(TIMELINE_QUERY).should('have.attr', 'value', case1.timeline.query); - }); + openCaseTimeline(); + + cy.get(TIMELINE_TITLE).should('have.attr', 'value', case1.timeline.title); + cy.get(TIMELINE_DESCRIPTION).should('have.attr', 'value', case1.timeline.description); + cy.get(TIMELINE_QUERY).should('have.attr', 'value', case1.timeline.query); }); }); diff --git a/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts b/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts index 2d650b1bbd9d1..6beb936d15ee6 100644 --- a/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts +++ b/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts @@ -11,7 +11,6 @@ import { goToEditExternalConnection } from '../tasks/all_cases'; import { addServiceNowConnector, openAddNewConnectorOption, - saveChanges, selectLastConnectorCreated, } from '../tasks/configure_cases'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -37,7 +36,6 @@ describe('Cases connectors', () => { cy.get(TOASTER).should('have.text', "Created 'New connector'"); selectLastConnectorCreated(); - saveChanges(); cy.wait('@saveConnector', { timeout: 10000 }) .its('status') diff --git a/x-pack/plugins/siem/cypress/screens/case_details.ts b/x-pack/plugins/siem/cypress/screens/case_details.ts index 32bb64e93b05f..f2cdaa6994356 100644 --- a/x-pack/plugins/siem/cypress/screens/case_details.ts +++ b/x-pack/plugins/siem/cypress/screens/case_details.ts @@ -17,7 +17,7 @@ export const CASE_DETAILS_STATUS = '[data-test-subj="case-view-status"]'; export const CASE_DETAILS_TAGS = '[data-test-subj="case-tags"]'; -export const CASE_DETAILS_TIMELINE_MARKDOWN = '[data-test-subj="markdown-link"]'; +export const CASE_DETAILS_TIMELINE_LINK_MARKDOWN = '[data-test-subj="markdown-timeline-link"]'; export const CASE_DETAILS_USER_ACTION = '[data-test-subj="user-action-title"] .euiFlexItem'; diff --git a/x-pack/plugins/siem/cypress/screens/configure_cases.ts b/x-pack/plugins/siem/cypress/screens/configure_cases.ts index 5a1e897c43e27..006c524a38acb 100644 --- a/x-pack/plugins/siem/cypress/screens/configure_cases.ts +++ b/x-pack/plugins/siem/cypress/screens/configure_cases.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export const ADD_NEW_CONNECTOR_OPTION_LINK = - '[data-test-subj="case-configure-add-connector-button"]'; +export const ADD_NEW_CONNECTOR_DROPDOWN_BUTTON = + '[data-test-subj="dropdown-connector-add-connector"]'; export const CONNECTOR = (id: string) => { return `[data-test-subj='dropdown-connector-${id}']`; diff --git a/x-pack/plugins/siem/cypress/tasks/case_details.ts b/x-pack/plugins/siem/cypress/tasks/case_details.ts index a28f8b8010adb..976d568ab3a91 100644 --- a/x-pack/plugins/siem/cypress/tasks/case_details.ts +++ b/x-pack/plugins/siem/cypress/tasks/case_details.ts @@ -5,10 +5,9 @@ */ import { TIMELINE_TITLE } from '../screens/timeline'; +import { CASE_DETAILS_TIMELINE_LINK_MARKDOWN } from '../screens/case_details'; -export const openCaseTimeline = (link: string) => { - cy.visit('/app/kibana'); - cy.visit(link); - cy.contains('a', 'SIEM'); +export const openCaseTimeline = () => { + cy.get(CASE_DETAILS_TIMELINE_LINK_MARKDOWN).click(); cy.get(TIMELINE_TITLE).should('exist'); }; diff --git a/x-pack/plugins/siem/cypress/tasks/configure_cases.ts b/x-pack/plugins/siem/cypress/tasks/configure_cases.ts index 9172e02708ae7..6ba9e875c7cb0 100644 --- a/x-pack/plugins/siem/cypress/tasks/configure_cases.ts +++ b/x-pack/plugins/siem/cypress/tasks/configure_cases.ts @@ -5,13 +5,12 @@ */ import { - ADD_NEW_CONNECTOR_OPTION_LINK, + ADD_NEW_CONNECTOR_DROPDOWN_BUTTON, CONNECTOR, CONNECTOR_NAME, CONNECTORS_DROPDOWN, PASSWORD, SAVE_BTN, - SAVE_CHANGES_BTN, SERVICE_NOW_CONNECTOR_CARD, URL, USERNAME, @@ -33,15 +32,12 @@ export const openAddNewConnectorOption = () => { cy.get(MAIN_PAGE).then($page => { if ($page.find(SERVICE_NOW_CONNECTOR_CARD).length !== 1) { cy.wait(1000); - cy.get(ADD_NEW_CONNECTOR_OPTION_LINK).click({ force: true }); + cy.get(CONNECTORS_DROPDOWN).click({ force: true }); + cy.get(ADD_NEW_CONNECTOR_DROPDOWN_BUTTON).click(); } }); }; -export const saveChanges = () => { - cy.get(SAVE_CHANGES_BTN).click(); -}; - export const selectLastConnectorCreated = () => { cy.get(CONNECTORS_DROPDOWN).click({ force: true }); cy.get('@createConnector') diff --git a/x-pack/plugins/siem/public/cases/components/callout/index.test.tsx b/x-pack/plugins/siem/public/cases/components/callout/index.test.tsx index 0ab90d8a73126..f157f654d5617 100644 --- a/x-pack/plugins/siem/public/cases/components/callout/index.test.tsx +++ b/x-pack/plugins/siem/public/cases/components/callout/index.test.tsx @@ -19,53 +19,79 @@ describe('CaseCallOut ', () => { ...defaultProps, message: 'we have one message', }; + const wrapper = mount(); + expect( wrapper - .find(`[data-test-subj="callout-message"]`) + .find(`[data-test-subj="callout-message-primary"]`) .last() .exists() ).toBeTruthy(); + }); + + it('Renders multi message callout', () => { + const props = { + ...defaultProps, + messages: [ + { ...defaultProps, description:

    {'we have two messages'}

    }, + { ...defaultProps, description:

    {'for real'}

    }, + ], + }; + const wrapper = mount(); expect( wrapper - .find(`[data-test-subj="callout-messages"]`) + .find(`[data-test-subj="callout-message-primary"]`) .last() .exists() ).toBeFalsy(); + expect( + wrapper + .find(`[data-test-subj="callout-messages-primary"]`) + .last() + .exists() + ).toBeTruthy(); }); - it('Renders multi message callout', () => { + + it('it shows the correct type of callouts', () => { const props = { ...defaultProps, messages: [ - { ...defaultProps, description:

    {'we have two messages'}

    }, + { + ...defaultProps, + description:

    {'we have two messages'}

    , + errorType: 'danger' as 'primary' | 'success' | 'warning' | 'danger', + }, { ...defaultProps, description:

    {'for real'}

    }, ], }; const wrapper = mount(); expect( wrapper - .find(`[data-test-subj="callout-message"]`) + .find(`[data-test-subj="callout-messages-danger"]`) .last() .exists() - ).toBeFalsy(); + ).toBeTruthy(); + expect( wrapper - .find(`[data-test-subj="callout-messages"]`) + .find(`[data-test-subj="callout-messages-primary"]`) .last() .exists() ).toBeTruthy(); }); + it('Dismisses callout', () => { const props = { ...defaultProps, message: 'we have one message', }; const wrapper = mount(); - expect(wrapper.find(`[data-test-subj="case-call-out"]`).exists()).toBeTruthy(); + expect(wrapper.find(`[data-test-subj="case-call-out-primary"]`).exists()).toBeTruthy(); wrapper - .find(`[data-test-subj="callout-dismiss"]`) + .find(`[data-test-subj="callout-dismiss-primary"]`) .last() .simulate('click'); - expect(wrapper.find(`[data-test-subj="case-call-out"]`).exists()).toBeFalsy(); + expect(wrapper.find(`[data-test-subj="case-call-out-primary"]`).exists()).toBeFalsy(); }); }); diff --git a/x-pack/plugins/siem/public/cases/components/callout/index.tsx b/x-pack/plugins/siem/public/cases/components/callout/index.tsx index 0fc93af7f318d..5266c9aec9705 100644 --- a/x-pack/plugins/siem/public/cases/components/callout/index.tsx +++ b/x-pack/plugins/siem/public/cases/components/callout/index.tsx @@ -12,28 +12,69 @@ import * as i18n from './translations'; export * from './helpers'; +interface ErrorMessage { + title: string; + description: JSX.Element; + errorType?: 'primary' | 'success' | 'warning' | 'danger'; +} + interface CaseCallOutProps { title: string; message?: string; - messages?: Array<{ title: string; description: JSX.Element }>; + messages?: ErrorMessage[]; } const CaseCallOutComponent = ({ title, message, messages }: CaseCallOutProps) => { const [showCallOut, setShowCallOut] = useState(true); const handleCallOut = useCallback(() => setShowCallOut(false), [setShowCallOut]); + let callOutMessages = messages ?? []; + + if (message) { + callOutMessages = [ + ...callOutMessages, + { + title: '', + description:

    {message}

    , + errorType: 'primary', + }, + ]; + } + + const groupedErrorMessages = callOutMessages.reduce((acc, currentMessage: ErrorMessage) => { + const key = currentMessage.errorType == null ? 'primary' : currentMessage.errorType; + return { + ...acc, + [key]: [...(acc[key] || []), currentMessage], + }; + }, {} as { [key in NonNullable]: ErrorMessage[] }); return showCallOut ? ( <> - - {!isEmpty(messages) && ( - - )} - {!isEmpty(message) &&

    {message}

    } - - {i18n.DISMISS_CALLOUT} - -
    - + {(Object.keys(groupedErrorMessages) as Array).map(key => ( + + + {!isEmpty(groupedErrorMessages[key]) && ( + + )} + + {i18n.DISMISS_CALLOUT} + + + + + ))} ) : null; }; diff --git a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.test.tsx b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.test.tsx index 41cd3e549415d..4f6fad8491206 100644 --- a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.test.tsx +++ b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.test.tsx @@ -15,7 +15,6 @@ import { connectors } from './__mock__'; describe('Connectors', () => { let wrapper: ReactWrapper; const onChangeConnector = jest.fn(); - const handleShowAddFlyout = jest.fn(); const handleShowEditFlyout = jest.fn(); const props: Props = { @@ -25,7 +24,6 @@ describe('Connectors', () => { selectedConnector: 'none', isLoading: false, onChangeConnector, - handleShowAddFlyout, handleShowEditFlyout, }; @@ -92,6 +90,15 @@ describe('Connectors', () => { expect(onChangeConnector).toHaveBeenCalledWith('none'); }); + test('it shows the add connector button', () => { + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + + expect( + wrapper.find('button[data-test-subj="dropdown-connector-add-connector"]').exists() + ).toBeTruthy(); + }); + test('the text of the update button is shown correctly', () => { const newWrapper = mount(, { wrappingComponent: TestProviders, diff --git a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.tsx b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.tsx index 3916ce297a0a4..76e816a2909ab 100644 --- a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.tsx +++ b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors.tsx @@ -11,7 +11,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, - EuiButton, } from '@elastic/eui'; import styled from 'styled-components'; @@ -29,12 +28,6 @@ const EuiFormRowExtended = styled(EuiFormRow)` } `; -const AddConnectorEuiFormRow = styled(EuiFormRow)` - width: 100%; - max-width: 100%; - text-align: right; -`; - export interface Props { connectors: Connector[]; disabled: boolean; @@ -42,7 +35,6 @@ export interface Props { updateConnectorDisabled: boolean; onChangeConnector: (id: string) => void; selectedConnector: string; - handleShowAddFlyout: () => void; handleShowEditFlyout: () => void; } const ConnectorsComponent: React.FC = ({ @@ -52,7 +44,6 @@ const ConnectorsComponent: React.FC = ({ updateConnectorDisabled, onChangeConnector, selectedConnector, - handleShowAddFlyout, handleShowEditFlyout, }) => { const connectorsName = useMemo( @@ -77,7 +68,7 @@ const ConnectorsComponent: React.FC = ({ ), - [connectorsName] + [connectorsName, updateConnectorDisabled] ); return ( @@ -100,18 +91,9 @@ const ConnectorsComponent: React.FC = ({ isLoading={isLoading} onChange={onChangeConnector} data-test-subj="case-connectors-dropdown" + appendAddConnectorButton={true} /> - - - {i18n.ADD_NEW_CONNECTOR} - - ); diff --git a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors_dropdown.tsx b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors_dropdown.tsx index b2b2edb04bd29..c5481f592e750 100644 --- a/x-pack/plugins/siem/public/cases/components/configure_cases/connectors_dropdown.tsx +++ b/x-pack/plugins/siem/public/cases/components/configure_cases/connectors_dropdown.tsx @@ -18,6 +18,7 @@ export interface Props { isLoading: boolean; onChange: (id: string) => void; selectedConnector: string; + appendAddConnectorButton?: boolean; } const ICON_SIZE = 'm'; @@ -42,40 +43,55 @@ const noConnectorOption = { 'data-test-subj': 'dropdown-connector-no-connector', }; +const addNewConnector = { + value: 'add-connector', + inputDisplay: ( + + {i18n.ADD_NEW_CONNECTOR} + + ), + 'data-test-subj': 'dropdown-connector-add-connector', +}; + const ConnectorsDropdownComponent: React.FC = ({ connectors, disabled, isLoading, onChange, selectedConnector, + appendAddConnectorButton = false, }) => { - const connectorsAsOptions = useMemo( - () => - connectors.reduce( - (acc, connector) => [ - ...acc, - { - value: connector.id, - inputDisplay: ( - - - - - - {connector.name} - - - ), - 'data-test-subj': `dropdown-connector-${connector.id}`, - }, - ], - [noConnectorOption] - ), - [connectors] - ); + const connectorsAsOptions = useMemo(() => { + const connectorsFormatted = connectors.reduce( + (acc, connector) => [ + ...acc, + { + value: connector.id, + inputDisplay: ( + + + + + + {connector.name} + + + ), + 'data-test-subj': `dropdown-connector-${connector.id}`, + }, + ], + [noConnectorOption] + ); + + if (appendAddConnectorButton) { + return [...connectorsFormatted, addNewConnector]; + } + + return connectorsFormatted; + }, [connectors]); return ( { wrapper.find('[data-test-subj="configure-cases-warning-callout"]').exists() ).toBeFalsy(); }); - - test('it does NOT render the EuiBottomBar', () => { - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - }); - - test('it disables correctly ClosureOptions when the connector is set to none', () => { - expect(wrapper.find(ClosureOptions).prop('disabled')).toBe(true); - }); }); describe('Unhappy path', () => { @@ -182,12 +172,6 @@ describe('ConfigureCases', () => { expect(wrapper.find(ConnectorEditFlyout).prop('initialConnector')).toEqual(connectors[0]); }); - test('it does not shows the action bar when there is no change', () => { - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - }); - test('it disables correctly when the user cannot crud', () => { const newWrapper = mount(, { wrappingComponent: TestProviders, @@ -197,12 +181,6 @@ describe('ConfigureCases', () => { true ); - expect( - newWrapper - .find('button[data-test-subj="case-configure-add-connector-button"]') - .prop('disabled') - ).toBe(true); - expect( newWrapper .find('button[data-test-subj="case-configure-update-selected-connector-button"]') @@ -275,26 +253,6 @@ describe('ConfigureCases', () => { .prop('disabled') ).toBe(true); }); - - test('it disables the buttons of action bar when loading connectors', () => { - const newWrapper = mount(, { - wrappingComponent: TestProviders, - }); - - expect( - newWrapper - .find('button[data-test-subj="case-configure-action-bottom-bar-cancel-button"]') - .first() - .prop('disabled') - ).toBe(true); - - expect( - newWrapper - .find('button[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .prop('disabled') - ).toBe(true); - }); }); describe('saving configuration', () => { @@ -341,74 +299,6 @@ describe('ConfigureCases', () => { .prop('disabled') ).toBe(true); }); - - test('it disables the buttons of action bar when saving configuration', () => { - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', - currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-1', - closureType: 'close-by-user', - }, - persistLoading: true, - })); - - const newWrapper = mount(, { - wrappingComponent: TestProviders, - }); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-cancel-button"]') - .first() - .prop('isDisabled') - ).toBe(true); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .prop('isDisabled') - ).toBe(true); - }); - - test('it shows the loading spinner when saving configuration', () => { - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', - currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-1', - closureType: 'close-by-user', - }, - persistLoading: true, - })); - - const newWrapper = mount(, { - wrappingComponent: TestProviders, - }); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-cancel-button"]') - .first() - .prop('isLoading') - ).toBe(true); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .prop('isLoading') - ).toBe(true); - }); }); describe('loading configuration', () => { @@ -437,7 +327,7 @@ describe('ConfigureCases', () => { }); }); - describe('update connector', () => { + describe('connectors', () => { let wrapper: ReactWrapper; const persistCaseConfigure = jest.fn(); @@ -445,13 +335,13 @@ describe('ConfigureCases', () => { jest.resetAllMocks(); useCaseConfigureMock.mockImplementation(() => ({ ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, + mapping: connectors[0].config.casesConfiguration.mapping, closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', + connectorId: 'servicenow-1', + connectorName: 'My connector', currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-1', + connectorName: 'My connector', + connectorId: 'My connector', closureType: 'close-by-user', }, persistCaseConfigure, @@ -463,12 +353,10 @@ describe('ConfigureCases', () => { wrapper = mount(, { wrappingComponent: TestProviders }); }); - test('it submits the configuration correctly', () => { - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .simulate('click'); - + test('it submits the configuration correctly when changing connector', () => { + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); wrapper.update(); expect(persistCaseConfigure).toHaveBeenCalled(); @@ -479,382 +367,112 @@ describe('ConfigureCases', () => { }); }); - test('it has the correct url on cancel button', () => { - expect( - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-cancel-button"]') - .first() - .prop('href') - ).toBe(`#/link-to/case${searchURL}`); - }); - - test('it disables the buttons of action bar when loading configuration', () => { - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', - currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-1', - closureType: 'close-by-user', - }, - loading: true, - })); - const newWrapper = mount(, { - wrappingComponent: TestProviders, - }); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-cancel-button"]') - .first() - .prop('isDisabled') - ).toBe(true); - - expect( - newWrapper - .find('[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .prop('isDisabled') - ).toBe(true); - }); - }); - - describe('user interactions', () => { - beforeEach(() => { - jest.resetAllMocks(); - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', - currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-2', - closureType: 'close-by-user', - }, - })); - useConnectorsMock.mockImplementation(() => useConnectorsResponse); - useKibanaMock.mockImplementation(() => kibanaMockImplementationArgs); - useGetUrlSearchMock.mockImplementation(() => searchURL); - }); - - test('it show the add flyout when pressing the add connector button', () => { - const wrapper = mount(, { wrappingComponent: TestProviders }); - wrapper - .find('button[data-test-subj="case-configure-add-connector-button"]') - .simulate('click'); - wrapper.update(); - - expect(wrapper.find(ConnectorAddFlyout).prop('addFlyoutVisible')).toBe(true); - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - }); - - test('it show the edit flyout when pressing the update connector button', () => { - const wrapper = mount(, { wrappingComponent: TestProviders }); - wrapper - .find('button[data-test-subj="case-configure-update-selected-connector-button"]') - .simulate('click'); - wrapper.update(); - - expect(wrapper.find(ConnectorEditFlyout).prop('editFlyoutVisible')).toBe(true); - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - }); - - test('it tracks the changes successfully', () => { - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'unchanged', - currentConfiguration: { - connectorName: 'unchanged', - connectorId: 'servicenow-1', - closureType: 'close-by-pushing', - }, - })); - const wrapper = mount(, { wrappingComponent: TestProviders }); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); - wrapper.update(); - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-total-changes"]') - .first() - .text() - ).toBe('2 unsaved changes'); - }); - - test('it tracks the changes successfully when name changes', () => { - useCaseConfigureMock.mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - connectorName: 'nameChange', - currentConfiguration: { - connectorId: 'servicenow-1', - closureType: 'close-by-pushing', - connectorName: 'before', - }, - })); - - const wrapper = mount(, { wrappingComponent: TestProviders }); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); - wrapper.update(); - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-total-changes"]') - .first() - .text() - ).toBe('2 unsaved changes'); - }); - - test('it tracks and reverts the changes successfully ', () => { - const wrapper = mount(, { wrappingComponent: TestProviders }); - // change settings - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); - wrapper.update(); - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - // revert back to initial settings - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connector-servicenow-1"]').simulate('click'); - wrapper.update(); - wrapper.find('input[id="close-by-user"]').simulate('change'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - }); - - test('it close and restores the action bar when the add connector button is pressed', () => { - useCaseConfigureMock - .mockImplementationOnce(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, - })) - .mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-pushing', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, - })); - const wrapper = mount(, { wrappingComponent: TestProviders }); - // Change closure type - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - - // Press add connector button - wrapper - .find('button[data-test-subj="case-configure-add-connector-button"]') - .simulate('click'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - - expect(wrapper.find(ConnectorAddFlyout).prop('addFlyoutVisible')).toBe(true); - - // Close the add flyout - wrapper.find('button[data-test-subj="euiFlyoutCloseButton"]').simulate('click'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - - expect(wrapper.find(ConnectorAddFlyout).prop('addFlyoutVisible')).toBe(false); - - expect( - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-total-changes"]') - .first() - .text() - ).toBe('1 unsaved changes'); - }); - - test('it close and restores the action bar when the update connector button is pressed', () => { + test('the text of the update button is changed successfully', () => { useCaseConfigureMock .mockImplementationOnce(() => ({ ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, + connectorId: 'servicenow-1', })) .mockImplementation(() => ({ ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-pushing', connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, })); - const wrapper = mount(, { wrappingComponent: TestProviders }); - - // Change closure type - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - // Press update connector button - wrapper - .find('button[data-test-subj="case-configure-update-selected-connector-button"]') - .simulate('click'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); - - expect(wrapper.find(ConnectorEditFlyout).prop('editFlyoutVisible')).toBe(true); - - // Close the edit flyout - wrapper.find('button[data-test-subj="euiFlyoutCloseButton"]').simulate('click'); - wrapper.update(); - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - - expect(wrapper.find(ConnectorEditFlyout).prop('editFlyoutVisible')).toBe(false); - - expect( - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-total-changes"]') - .first() - .text() - ).toBe('1 unsaved changes'); - }); + wrapper = mount(, { wrappingComponent: TestProviders }); - test('it shows the action bar when the connector is changed', () => { - useCaseConfigureMock - .mockImplementationOnce(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[0].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-1', - currentConfiguration: { connectorId: 'servicenow-1', closureType: 'close-by-user' }, - })) - .mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-1', closureType: 'close-by-user' }, - })); - const wrapper = mount(, { wrappingComponent: TestProviders }); wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); wrapper.update(); wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); wrapper.update(); - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); expect( wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-total-changes"]') - .first() + .find('button[data-test-subj="case-configure-update-selected-connector-button"]') .text() - ).toBe('1 unsaved changes'); + ).toBe('Update My Connector 2'); }); + }); +}); - test('it closes the action bar when pressing save', () => { - useCaseConfigureMock - .mockImplementationOnce(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-user', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, - })) - .mockImplementation(() => ({ - ...useCaseConfigureResponse, - mapping: connectors[1].config.casesConfiguration.mapping, - closureType: 'close-by-pushing', - connectorId: 'servicenow-2', - currentConfiguration: { connectorId: 'servicenow-2', closureType: 'close-by-user' }, - })); - const wrapper = mount(, { wrappingComponent: TestProviders }); - wrapper.find('input[id="close-by-pushing"]').simulate('change'); - wrapper.update(); - - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeTruthy(); - - wrapper - .find('[data-test-subj="case-configure-action-bottom-bar-save-button"]') - .first() - .simulate('click'); +describe('closure options', () => { + let wrapper: ReactWrapper; + const persistCaseConfigure = jest.fn(); + + beforeEach(() => { + jest.resetAllMocks(); + useCaseConfigureMock.mockImplementation(() => ({ + ...useCaseConfigureResponse, + mapping: connectors[0].config.casesConfiguration.mapping, + closureType: 'close-by-user', + connectorId: 'servicenow-1', + connectorName: 'My connector', + currentConfiguration: { + connectorName: 'My connector', + connectorId: 'My connector', + closureType: 'close-by-user', + }, + persistCaseConfigure, + })); + useConnectorsMock.mockImplementation(() => useConnectorsResponse); + useKibanaMock.mockImplementation(() => kibanaMockImplementationArgs); + useGetUrlSearchMock.mockImplementation(() => searchURL); + + wrapper = mount(, { wrappingComponent: TestProviders }); + }); - wrapper.update(); + test('it submits the configuration correctly when changing closure type', () => { + wrapper.find('input[id="close-by-pushing"]').simulate('change'); + wrapper.update(); - expect( - wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() - ).toBeFalsy(); + expect(persistCaseConfigure).toHaveBeenCalled(); + expect(persistCaseConfigure).toHaveBeenCalledWith({ + connectorId: 'servicenow-1', + connectorName: 'My Connector', + closureType: 'close-by-pushing', }); + }); +}); - test('the text of the update button is changed successfully', () => { - useCaseConfigureMock - .mockImplementationOnce(() => ({ - ...useCaseConfigureResponse, - connectorId: 'servicenow-1', - })) - .mockImplementation(() => ({ - ...useCaseConfigureResponse, - connectorId: 'servicenow-2', - })); +describe('user interactions', () => { + beforeEach(() => { + jest.resetAllMocks(); + useCaseConfigureMock.mockImplementation(() => ({ + ...useCaseConfigureResponse, + mapping: connectors[1].config.casesConfiguration.mapping, + closureType: 'close-by-user', + connectorId: 'servicenow-2', + connectorName: 'unchanged', + currentConfiguration: { + connectorName: 'unchanged', + connectorId: 'servicenow-2', + closureType: 'close-by-user', + }, + })); + useConnectorsMock.mockImplementation(() => useConnectorsResponse); + useKibanaMock.mockImplementation(() => kibanaMockImplementationArgs); + useGetUrlSearchMock.mockImplementation(() => searchURL); + }); - const wrapper = mount(, { wrappingComponent: TestProviders }); + test('it show the add flyout when pressing the add connector button', () => { + const wrapper = mount(, { wrappingComponent: TestProviders }); + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + wrapper.find('button[data-test-subj="dropdown-connector-add-connector"]').simulate('click'); + wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.update(); - wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); - wrapper.update(); + expect(wrapper.find(ConnectorAddFlyout).prop('addFlyoutVisible')).toBe(true); + }); - expect( - wrapper - .find('button[data-test-subj="case-configure-update-selected-connector-button"]') - .text() - ).toBe('Update My Connector 2'); - }); + test('it show the edit flyout when pressing the update connector button', () => { + const wrapper = mount(, { wrappingComponent: TestProviders }); + wrapper + .find('button[data-test-subj="case-configure-update-selected-connector-button"]') + .simulate('click'); + wrapper.update(); + + expect(wrapper.find(ConnectorEditFlyout).prop('editFlyoutVisible')).toBe(true); + expect( + wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists() + ).toBeFalsy(); }); }); diff --git a/x-pack/plugins/siem/public/cases/components/configure_cases/index.tsx b/x-pack/plugins/siem/public/cases/components/configure_cases/index.tsx index d5c6cc671433b..e6fbc7cd3e4db 100644 --- a/x-pack/plugins/siem/public/cases/components/configure_cases/index.tsx +++ b/x-pack/plugins/siem/public/cases/components/configure_cases/index.tsx @@ -7,16 +7,8 @@ import React, { useCallback, useEffect, useState, Dispatch, SetStateAction } from 'react'; import styled, { css } from 'styled-components'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiButton, - EuiCallOut, - EuiBottomBar, - EuiButtonEmpty, - EuiText, -} from '@elastic/eui'; -import { difference } from 'lodash/fp'; +import { EuiCallOut } from '@elastic/eui'; + import { useKibana } from '../../../common/lib/kibana'; import { useConnectors } from '../../containers/configure/use_connectors'; import { useCaseConfigure } from '../../containers/configure/use_configure'; @@ -27,16 +19,15 @@ import { ConnectorEditFlyout, } from '../../../../../triggers_actions_ui/public'; +import { ClosureType } from '../../containers/configure/types'; + // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ActionConnectorTableItem } from '../../../../../triggers_actions_ui/public/types'; -import { getCaseUrl } from '../../../common/components/link_to'; -import { useGetUrlSearch } from '../../../common/components/navigation/use_get_url_search'; import { connectorsConfiguration } from '../../../common/lib/connectors/config'; import { Connectors } from './connectors'; import { ClosureOptions } from './closure_options'; import { SectionWrapper } from '../wrappers'; -import { navTabs } from '../../../app/home/home_navigations'; import * as i18n from './translations'; const FormWrapper = styled.div` @@ -61,7 +52,6 @@ interface ConfigureCasesComponentProps { } const ConfigureCasesComponent: React.FC = ({ userCanCrud }) => { - const search = useGetUrlSearch(navTabs.case); const { http, triggers_actions_ui, notifications, application, docLinks } = useKibana().services; const [connectorIsValid, setConnectorIsValid] = useState(true); @@ -71,15 +61,13 @@ const ConfigureCasesComponent: React.FC = ({ userC null ); - const [actionBarVisible, setActionBarVisible] = useState(false); - const [totalConfigurationChanges, setTotalConfigurationChanges] = useState(0); - const { connectorId, closureType, currentConfiguration, loading: loadingCaseConfigure, persistLoading, + version, persistCaseConfigure, setConnector, setClosureType, @@ -93,45 +81,12 @@ const ConfigureCasesComponent: React.FC = ({ userC const isLoadingAny = isLoadingConnectors || persistLoading || loadingCaseConfigure; const updateConnectorDisabled = isLoadingAny || !connectorIsValid || connectorId === 'none'; - const handleSubmit = useCallback( - // TO DO give a warning/error to user when field are not mapped so they have chance to do it - () => { - setActionBarVisible(false); - persistCaseConfigure({ - connectorId, - connectorName: connectors.find(c => c.id === connectorId)?.name ?? '', - closureType, - }); - }, - [connectorId, connectors, closureType] - ); - - const onClickAddConnector = useCallback(() => { - setActionBarVisible(false); - setAddFlyoutVisibility(true); - }, []); - const onClickUpdateConnector = useCallback(() => { - setActionBarVisible(false); setEditFlyoutVisibility(true); }, []); - const handleActionBar = useCallback(() => { - const currentConfigurationMinusName = { - connectorId: currentConfiguration.connectorId, - closureType: currentConfiguration.closureType, - }; - const unsavedChanges = difference(Object.values(currentConfigurationMinusName), [ - connectorId, - closureType, - ]).length; - setActionBarVisible(!(unsavedChanges === 0)); - setTotalConfigurationChanges(unsavedChanges); - }, [currentConfiguration, connectorId, closureType]); - const handleSetAddFlyoutVisibility = useCallback( (isVisible: boolean) => { - handleActionBar(); setAddFlyoutVisibility(isVisible); }, [currentConfiguration, connectorId, closureType] @@ -139,12 +94,40 @@ const ConfigureCasesComponent: React.FC = ({ userC const handleSetEditFlyoutVisibility = useCallback( (isVisible: boolean) => { - handleActionBar(); setEditFlyoutVisibility(isVisible); }, [currentConfiguration, connectorId, closureType] ); + const onChangeConnector = useCallback( + (id: string) => { + if (id === 'add-connector') { + setAddFlyoutVisibility(true); + return; + } + + setConnector(id); + persistCaseConfigure({ + connectorId: id, + connectorName: connectors.find(c => c.id === id)?.name ?? '', + closureType, + }); + }, + [connectorId, closureType, version] + ); + + const onChangeClosureType = useCallback( + (type: ClosureType) => { + setClosureType(type); + persistCaseConfigure({ + connectorId, + connectorName: connectors.find(c => c.id === connectorId)?.name ?? '', + closureType: type, + }); + }, + [connectorId, closureType, version] + ); + useEffect(() => { if ( !isLoadingConnectors && @@ -168,16 +151,6 @@ const ConfigureCasesComponent: React.FC = ({ userC } }, [connectors, connectorId]); - useEffect(() => { - handleActionBar(); - }, [ - connectors, - connectorId, - closureType, - currentConfiguration.connectorId, - currentConfiguration.closureType, - ]); - return ( {!connectorIsValid && ( @@ -195,8 +168,8 @@ const ConfigureCasesComponent: React.FC = ({ userC @@ -204,57 +177,12 @@ const ConfigureCasesComponent: React.FC = ({ userC connectors={connectors ?? []} disabled={persistLoading || isLoadingConnectors || !userCanCrud} isLoading={isLoadingConnectors} - onChangeConnector={setConnector} + onChangeConnector={onChangeConnector} updateConnectorDisabled={updateConnectorDisabled || !userCanCrud} - handleShowAddFlyout={onClickAddConnector} handleShowEditFlyout={onClickUpdateConnector} selectedConnector={connectorId} /> - {actionBarVisible && ( - - - - - - {i18n.UNSAVED_CHANGES(totalConfigurationChanges)} - - - - - - - - {i18n.CANCEL} - - - - - {i18n.SAVE_CHANGES} - - - - - - - )} { defaultMessage: 'Update { connectorName }', }); }; - -export const UNSAVED_CHANGES = (unsavedChanges: number): string => { - return i18n.translate('xpack.siem.case.configureCases.unsavedChanges', { - values: { unsavedChanges }, - defaultMessage: '{unsavedChanges} unsaved changes', - }); -}; diff --git a/x-pack/plugins/siem/public/cases/components/edit_connector/index.test.tsx b/x-pack/plugins/siem/public/cases/components/edit_connector/index.test.tsx index 5dfed80baa8ed..8fada565b3463 100644 --- a/x-pack/plugins/siem/public/cases/components/edit_connector/index.test.tsx +++ b/x-pack/plugins/siem/public/cases/components/edit_connector/index.test.tsx @@ -40,23 +40,17 @@ describe('EditConnector ', () => { ); - expect( - wrapper - .find(`[data-test-subj="dropdown-connectors"]`) - .last() - .prop('disabled') - ).toBeTruthy(); - expect( wrapper .find(`span[data-test-subj="dropdown-connector-no-connector"]`) .last() .exists() ).toBeTruthy(); - wrapper - .find(`[data-test-subj="connector-edit-button"]`) - .last() - .simulate('click'); + + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); + wrapper.update(); expect( wrapper @@ -64,30 +58,27 @@ describe('EditConnector ', () => { .last() .exists() ).toBeTruthy(); - - expect( - wrapper - .find(`[data-test-subj="dropdown-connectors"]`) - .last() - .prop('disabled') - ).toBeFalsy(); }); + it('Edit external service on submit', async () => { const wrapper = mount( ); - wrapper - .find(`[data-test-subj="connector-edit-button"]`) - .last() - .simulate('click'); + + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); + wrapper.update(); + expect( wrapper .find(`[data-test-subj="edit-connectors-submit"]`) .last() .exists() ).toBeTruthy(); + await act(async () => { wrapper .find(`[data-test-subj="edit-connectors-submit"]`) @@ -97,6 +88,7 @@ describe('EditConnector ', () => { expect(onSubmit).toBeCalledWith(sampleConnector); }); }); + it('Resets selector on cancel', async () => { const props = { ...defaultProps, @@ -106,10 +98,12 @@ describe('EditConnector ', () => { ); - wrapper - .find(`[data-test-subj="connector-edit-button"]`) - .last() - .simulate('click'); + + wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); + wrapper.update(); + wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click'); + wrapper.update(); + await act(async () => { wrapper .find(`[data-test-subj="edit-connectors-cancel"]`) @@ -123,20 +117,7 @@ describe('EditConnector ', () => { ); }); }); - it('Renders disabled button', () => { - const props = { ...defaultProps, disabled: true }; - const wrapper = mount( - - - - ); - expect( - wrapper - .find(`[data-test-subj="connector-edit-button"]`) - .last() - .prop('disabled') - ).toBeTruthy(); - }); + it('Renders loading spinner', () => { const props = { ...defaultProps, isLoading: true }; const wrapper = mount( diff --git a/x-pack/plugins/siem/public/cases/components/edit_connector/index.tsx b/x-pack/plugins/siem/public/cases/components/edit_connector/index.tsx index 29f06532a4ab4..38062b8837054 100644 --- a/x-pack/plugins/siem/public/cases/components/edit_connector/index.tsx +++ b/x-pack/plugins/siem/public/cases/components/edit_connector/index.tsx @@ -12,7 +12,6 @@ import { EuiFlexItem, EuiButton, EuiButtonEmpty, - EuiButtonIcon, EuiLoadingSpinner, } from '@elastic/eui'; import styled, { css } from 'styled-components'; @@ -52,21 +51,24 @@ export const EditConnector = React.memo( options: { stripEmptyFields: false }, schema, }); - const [isEditConnector, setIsEditConnector] = useState(false); - const handleOnClick = useCallback(() => { - setIsEditConnector(true); - }, []); + const [connectorHasChanged, setConnectorHasChanged] = useState(false); + const onChangeConnector = useCallback( + connectorId => { + setConnectorHasChanged(selectedConnector !== connectorId); + }, + [selectedConnector] + ); const onCancelConnector = useCallback(() => { form.setFieldValue('connector', selectedConnector); - setIsEditConnector(false); + setConnectorHasChanged(false); }, [form, selectedConnector]); const onSubmitConnector = useCallback(async () => { const { isValid, data: newData } = await form.submit(); if (isValid && newData.connector) { onSubmit(newData.connector); - setIsEditConnector(false); + setConnectorHasChanged(false); } }, [form, onSubmit]); return ( @@ -76,17 +78,6 @@ export const EditConnector = React.memo(

    {i18n.CONNECTORS}

    {isLoading && } - {!isLoading && ( - - - - )} @@ -103,15 +94,16 @@ export const EditConnector = React.memo( dataTestSubj: 'caseConnectors', idAria: 'caseConnectors', isLoading, - disabled: !isEditConnector, + disabled, defaultValue: selectedConnector, }} + onChange={onChangeConnector} /> - {isEditConnector && ( + {connectorHasChanged && ( diff --git a/x-pack/plugins/siem/public/cases/components/use_push_to_service/index.tsx b/x-pack/plugins/siem/public/cases/components/use_push_to_service/index.tsx index ae8a67b75d36c..5d238b623eb4a 100644 --- a/x-pack/plugins/siem/public/cases/components/use_push_to_service/index.tsx +++ b/x-pack/plugins/siem/public/cases/components/use_push_to_service/index.tsx @@ -67,7 +67,11 @@ export const usePushToService = ({ }, [caseId, caseServices, caseConnectorId, caseConnectorName, postPushToService, updateCase]); const errorsMsg = useMemo(() => { - let errors: Array<{ title: string; description: JSX.Element }> = []; + let errors: Array<{ + title: string; + description: JSX.Element; + errorType?: 'primary' | 'success' | 'warning' | 'danger'; + }> = []; if (actionLicense != null && !actionLicense.enabledInLicense) { errors = [...errors, getLicenseError()]; } @@ -115,6 +119,7 @@ export const usePushToService = ({ id="xpack.siem.case.caseView.pushToServiceDisableByInvalidConnector" /> ), + errorType: 'danger', }, ]; } diff --git a/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.test.tsx b/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.test.tsx new file mode 100644 index 0000000000000..27438207bed97 --- /dev/null +++ b/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.test.tsx @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { Router, mockHistory } from '../__mock__/router'; +import { UserActionMarkdown } from './user_action_markdown'; +import { TestProviders } from '../../../common/mock'; +import * as timelineHelpers from '../../../timelines/components/open_timeline/helpers'; +import { useApolloClient } from '../../../common/utils/apollo_context'; +const mockUseApolloClient = useApolloClient as jest.Mock; +jest.mock('../../../common/utils/apollo_context'); +const onChangeEditable = jest.fn(); +const onSaveContent = jest.fn(); + +const timelineId = '1e10f150-949b-11ea-b63c-2bc51864784c'; +const defaultProps = { + content: `A link to a timeline [timeline](http://localhost:5601/app/siem#/timelines?timeline=(id:'${timelineId}',isOpen:!t))`, + id: 'markdown-id', + isEditable: false, + onChangeEditable, + onSaveContent, +}; + +describe('UserActionMarkdown ', () => { + const queryTimelineByIdSpy = jest.spyOn(timelineHelpers, 'queryTimelineById'); + beforeEach(() => { + mockUseApolloClient.mockClear(); + jest.resetAllMocks(); + }); + + it('Opens timeline when timeline link clicked - isEditable: false', async () => { + const wrapper = mount( + + + + + + ); + wrapper + .find(`[data-test-subj="markdown-timeline-link"]`) + .first() + .simulate('click'); + + expect(queryTimelineByIdSpy).toBeCalledWith({ + apolloClient: mockUseApolloClient(), + timelineId, + updateIsLoading: expect.any(Function), + updateTimeline: expect.any(Function), + }); + }); + + it('Opens timeline when timeline link clicked - isEditable: true ', async () => { + const wrapper = mount( + + + + + + ); + wrapper + .find(`[data-test-subj="preview-tab"]`) + .first() + .simulate('click'); + wrapper + .find(`[data-test-subj="markdown-timeline-link"]`) + .first() + .simulate('click'); + expect(queryTimelineByIdSpy).toBeCalledWith({ + apolloClient: mockUseApolloClient(), + timelineId, + updateIsLoading: expect.any(Function), + updateTimeline: expect.any(Function), + }); + }); +}); diff --git a/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.tsx b/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.tsx index 23d8d8f1a7e68..03dd599da88e5 100644 --- a/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.tsx +++ b/x-pack/plugins/siem/public/cases/components/user_action_tree/user_action_markdown.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/e import React, { useCallback } from 'react'; import styled, { css } from 'styled-components'; +import { useDispatch } from 'react-redux'; import * as i18n from '../case_view/translations'; import { Markdown } from '../../../common/components/markdown'; import { Form, useForm, UseField } from '../../../shared_imports'; @@ -15,6 +16,13 @@ import { schema, Content } from './schema'; import { InsertTimelinePopover } from '../../../timelines/components/timeline/insert_timeline_popover'; import { useInsertTimeline } from '../../../timelines/components/timeline/insert_timeline_popover/use_insert_timeline'; import { MarkdownEditorForm } from '../../../common/components//markdown_editor/form'; +import { + dispatchUpdateTimeline, + queryTimelineById, +} from '../../../timelines/components/open_timeline/helpers'; + +import { updateIsLoading as dispatchUpdateIsLoading } from '../../../timelines/store/timeline/actions'; +import { useApolloClient } from '../../../common/utils/apollo_context'; const ContentWrapper = styled.div` ${({ theme }) => css` @@ -36,6 +44,8 @@ export const UserActionMarkdown = ({ onChangeEditable, onSaveContent, }: UserActionMarkdownProps) => { + const dispatch = useDispatch(); + const apolloClient = useApolloClient(); const { form } = useForm({ defaultValue: { content }, options: { stripEmptyFields: false }, @@ -49,6 +59,24 @@ export const UserActionMarkdown = ({ onChangeEditable(id); }, [id, onChangeEditable]); + const handleTimelineClick = useCallback( + (timelineId: string) => { + queryTimelineById({ + apolloClient, + timelineId, + updateIsLoading: ({ + id: currentTimelineId, + isLoading, + }: { + id: string; + isLoading: boolean; + }) => dispatch(dispatchUpdateIsLoading({ id: currentTimelineId, isLoading })), + updateTimeline: dispatchUpdateTimeline(dispatch), + }); + }, + [apolloClient] + ); + const handleSaveAction = useCallback(async () => { const { isValid, data } = await form.submit(); if (isValid) { @@ -98,6 +126,7 @@ export const UserActionMarkdown = ({ cancelAction: handleCancelAction, saveAction: handleSaveAction, }), + onClickTimeline: handleTimelineClick, onCursorPositionUpdate: handleCursorChange, topRightContent: ( ) : ( - + ); }; diff --git a/x-pack/plugins/siem/public/common/components/markdown/index.test.tsx b/x-pack/plugins/siem/public/common/components/markdown/index.test.tsx index 89af9202a597e..bbf59177bcf04 100644 --- a/x-pack/plugins/siem/public/common/components/markdown/index.test.tsx +++ b/x-pack/plugins/siem/public/common/components/markdown/index.test.tsx @@ -164,5 +164,37 @@ describe('Markdown', () => { expect(wrapper).toMatchSnapshot(); }); + + describe('markdown timeline links', () => { + const timelineId = '1e10f150-949b-11ea-b63c-2bc51864784c'; + const markdownWithTimelineLink = `A link to a timeline [timeline](http://localhost:5601/app/siem#/timelines?timeline=(id:'${timelineId}',isOpen:!t))`; + const onClickTimeline = jest.fn(); + beforeEach(() => { + jest.resetAllMocks(); + }); + test('it renders a timeline link without href when provided the onClickTimeline argument', () => { + const wrapper = mount( + + ); + + expect( + wrapper + .find('[data-test-subj="markdown-timeline-link"]') + .first() + .getDOMNode() + ).not.toHaveProperty('href'); + }); + test('timeline link onClick calls onClickTimeline with timelineId', () => { + const wrapper = mount( + + ); + wrapper + .find('[data-test-subj="markdown-timeline-link"]') + .first() + .simulate('click'); + + expect(onClickTimeline).toHaveBeenCalledWith(timelineId); + }); + }); }); }); diff --git a/x-pack/plugins/siem/public/common/components/markdown/index.tsx b/x-pack/plugins/siem/public/common/components/markdown/index.tsx index 8e051685af56d..1a4c9cb71a77e 100644 --- a/x-pack/plugins/siem/public/common/components/markdown/index.tsx +++ b/x-pack/plugins/siem/public/common/components/markdown/index.tsx @@ -10,6 +10,7 @@ import { EuiLink, EuiTableRow, EuiTableRowCell, EuiText, EuiToolTip } from '@ela import React from 'react'; import ReactMarkdown from 'react-markdown'; import styled, { css } from 'styled-components'; +import * as i18n from './translations'; const TableHeader = styled.thead` font-weight: bold; @@ -37,8 +38,9 @@ const REL_NOREFERRER = 'noreferrer'; export const Markdown = React.memo<{ disableLinks?: boolean; raw?: string; + onClickTimeline?: (timelineId: string) => void; size?: 'xs' | 's' | 'm'; -}>(({ disableLinks = false, raw, size = 's' }) => { +}>(({ disableLinks = false, onClickTimeline, raw, size = 's' }) => { const markdownRenderers = { root: ({ children }: { children: React.ReactNode[] }) => ( @@ -59,18 +61,33 @@ export const Markdown = React.memo<{ tableCell: ({ children }: { children: React.ReactNode[] }) => ( {children} ), - link: ({ children, href }: { children: React.ReactNode[]; href?: string }) => ( - - - {children} - - - ), + link: ({ children, href }: { children: React.ReactNode[]; href?: string }) => { + if (onClickTimeline != null && href != null && href.indexOf(`timelines?timeline=(id:`) > -1) { + const timelineId = href.split('timelines?timeline=(id:')[1].split("'")[1] ?? ''; + return ( + + onClickTimeline(timelineId)} + data-test-subj="markdown-timeline-link" + > + {children} + + + ); + } + return ( + + + {children} + + + ); + }, blockquote: ({ children }: { children: React.ReactNode[] }) => ( {children} ), diff --git a/x-pack/plugins/siem/public/common/components/markdown/translations.ts b/x-pack/plugins/siem/public/common/components/markdown/translations.ts index cfd9e9ef1b106..4524d27739ea8 100644 --- a/x-pack/plugins/siem/public/common/components/markdown/translations.ts +++ b/x-pack/plugins/siem/public/common/components/markdown/translations.ts @@ -51,3 +51,11 @@ export const MARKDOWN_HINT_STRIKETHROUGH = i18n.translate( export const MARKDOWN_HINT_IMAGE_URL = i18n.translate('xpack.siem.markdown.hint.imageUrlLabel', { defaultMessage: '![image](url)', }); + +export const TIMELINE_ID = (timelineId: string) => + i18n.translate('xpack.siem.markdown.toolTip.timelineId', { + defaultMessage: 'Timeline id: { timelineId }', + values: { + timelineId, + }, + }); diff --git a/x-pack/plugins/siem/public/common/components/markdown_editor/form.tsx b/x-pack/plugins/siem/public/common/components/markdown_editor/form.tsx index 2ed85b04fe3f6..f9efbc5705b92 100644 --- a/x-pack/plugins/siem/public/common/components/markdown_editor/form.tsx +++ b/x-pack/plugins/siem/public/common/components/markdown_editor/form.tsx @@ -16,6 +16,7 @@ interface IMarkdownEditorForm { field: FieldHook; idAria: string; isDisabled: boolean; + onClickTimeline?: (timelineId: string) => void; onCursorPositionUpdate?: (cursorPosition: CursorPosition) => void; placeholder?: string; topRightContent?: React.ReactNode; @@ -26,6 +27,7 @@ export const MarkdownEditorForm = ({ field, idAria, isDisabled = false, + onClickTimeline, onCursorPositionUpdate, placeholder, topRightContent, @@ -55,6 +57,7 @@ export const MarkdownEditorForm = ({ content={field.value as string} isDisabled={isDisabled} onChange={handleContentChange} + onClickTimeline={onClickTimeline} onCursorPositionUpdate={onCursorPositionUpdate} placeholder={placeholder} topRightContent={topRightContent} diff --git a/x-pack/plugins/siem/public/common/components/markdown_editor/index.tsx b/x-pack/plugins/siem/public/common/components/markdown_editor/index.tsx index 4fb7086e82b28..b0df2b6b5b60f 100644 --- a/x-pack/plugins/siem/public/common/components/markdown_editor/index.tsx +++ b/x-pack/plugins/siem/public/common/components/markdown_editor/index.tsx @@ -74,6 +74,7 @@ export const MarkdownEditor = React.memo<{ content: string; isDisabled?: boolean; onChange: (description: string) => void; + onClickTimeline?: (timelineId: string) => void; onCursorPositionUpdate?: (cursorPosition: CursorPosition) => void; placeholder?: string; }>( @@ -83,6 +84,7 @@ export const MarkdownEditor = React.memo<{ content, isDisabled = false, onChange, + onClickTimeline, placeholder, onCursorPositionUpdate, }) => { @@ -125,9 +127,10 @@ export const MarkdownEditor = React.memo<{ { id: 'preview', name: i18n.PREVIEW, + 'data-test-subj': 'preview-tab', content: ( - + ), }, diff --git a/x-pack/plugins/siem/public/network/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap b/x-pack/plugins/siem/public/network/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap index 171926b53e5b9..2f063bfbea288 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap +++ b/x-pack/plugins/siem/public/network/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap @@ -6,7 +6,7 @@ exports[`IndexPatternsMissingPrompt renders correctly against snapshot 1`] = ` Configure index patterns diff --git a/x-pack/plugins/siem/public/network/components/embeddables/index_patterns_missing_prompt.tsx b/x-pack/plugins/siem/public/network/components/embeddables/index_patterns_missing_prompt.tsx index aeed6fb2fe20e..f972acc142d25 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/index_patterns_missing_prompt.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/index_patterns_missing_prompt.tsx @@ -61,7 +61,7 @@ export const IndexPatternsMissingPromptComponent = () => { } actions={ { - const mockFeatureProps: FeatureProperty[] = [ - { - _propertyKey: SUM_OF_DESTINATION_BYTES, - _rawValue: 'testPropValue', - }, - { - _propertyKey: SUM_OF_SOURCE_BYTES, - _rawValue: 'testPropValue', - }, + const mockFeatureProps: ITooltipProperty[] = [ + new TooltipProperty(SUM_OF_DESTINATION_BYTES, SUM_OF_DESTINATION_BYTES, 'testPropValue'), + new TooltipProperty(SUM_OF_SOURCE_BYTES, SUM_OF_SOURCE_BYTES, 'testPropValue'), ]; - const mockClientServerFeatureProps: FeatureProperty[] = [ - { - _propertyKey: SUM_OF_SERVER_BYTES, - _rawValue: 'testPropValue', - }, - { - _propertyKey: SUM_OF_CLIENT_BYTES, - _rawValue: 'testPropValue', - }, + const mockClientServerFeatureProps: ITooltipProperty[] = [ + new TooltipProperty(SUM_OF_SERVER_BYTES, SUM_OF_SERVER_BYTES, 'testPropValue'), + new TooltipProperty(SUM_OF_CLIENT_BYTES, SUM_OF_CLIENT_BYTES, 'testPropValue'), ]; test('renders correctly against snapshot', () => { diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx index 7c2d5e51d813f..9238f7ec65a20 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx @@ -14,8 +14,9 @@ import { SUM_OF_SERVER_BYTES, SUM_OF_SOURCE_BYTES, } from '../map_config'; -import { FeatureProperty } from '../types'; + import * as i18n from '../translations'; +import { ITooltipProperty } from '../../../../../../maps/public'; const FlowBadge = (styled(EuiBadge)` height: 45px; @@ -28,20 +29,22 @@ const EuiFlexGroupStyled = styled(EuiFlexGroup)` interface LineToolTipContentProps { contextId: string; - featureProps: FeatureProperty[]; + featureProps: ITooltipProperty[]; } export const LineToolTipContentComponent = ({ contextId, featureProps, }: LineToolTipContentProps) => { - const lineProps = featureProps.reduce>( - (acc, f) => ({ + const lineProps = featureProps.reduce>((acc, f) => { + const rawValue = f.getRawValue() ?? []; + return { ...acc, - ...{ [f._propertyKey]: Array.isArray(f._rawValue) ? f._rawValue : [f._rawValue] }, - }), - {} - ); + ...{ + [f.getPropertyKey()]: Array.isArray(rawValue) ? rawValue : [rawValue], + }, + }; + }, {}); const isSrcDest = Object.keys(lineProps).includes(SUM_OF_SOURCE_BYTES); diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx index 0f38c350986b4..10267d398848e 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -11,12 +11,13 @@ import { EuiLoadingSpinner, EuiOutsideClickDetector, } from '@elastic/eui'; -import { FeatureGeometry, FeatureProperty, MapToolTipProps } from '../types'; +import { FeatureGeometry, MapToolTipProps } from '../types'; import { ToolTipFooter } from './tooltip_footer'; import { LineToolTipContent } from './line_tool_tip_content'; import { PointToolTipContent } from './point_tool_tip_content'; import { Loader } from '../../../../common/components/loader'; import * as i18n from '../translations'; +import { ITooltipProperty } from '../../../../../../maps/public'; export const MapToolTipComponent = ({ addFilters, @@ -31,7 +32,7 @@ export const MapToolTipComponent = ({ const [isLoadingNextFeature, setIsLoadingNextFeature] = useState(false); const [isError, setIsError] = useState(false); const [featureIndex, setFeatureIndex] = useState(0); - const [featureProps, setFeatureProps] = useState([]); + const [featureProps, setFeatureProps] = useState([]); const [featureGeometry, setFeatureGeometry] = useState(null); const [, setLayerName] = useState(''); @@ -64,7 +65,7 @@ export const MapToolTipComponent = ({ getLayerName(layerId), ]); - setFeatureProps((featureProperties as unknown) as FeatureProperty[]); + setFeatureProps(featureProperties); setFeatureGeometry(featureGeo); setLayerName(layerNameString); } catch (e) { diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx index d5a7c51ccdeb8..36b9f44e19630 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx @@ -6,29 +6,17 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { FeatureProperty } from '../types'; import { getRenderedFieldValue, PointToolTipContentComponent } from './point_tool_tip_content'; import { TestProviders } from '../../../../common/mock'; import { getEmptyStringTag } from '../../../../common/components/empty_value'; import { HostDetailsLink, IPDetailsLink } from '../../../../common/components/links'; -import { useMountAppended } from '../../../../common/utils/use_mount_appended'; import { FlowTarget } from '../../../../graphql/types'; +import { ITooltipProperty } from '../../../../../../maps/public'; +import { TooltipProperty } from '../../../../../../maps/public/classes/tooltips/tooltip_property'; describe('PointToolTipContent', () => { - const mount = useMountAppended(); - - const mockFeatureProps: FeatureProperty[] = [ - { - _propertyKey: 'host.name', - _rawValue: 'testPropValue', - }, - ]; - - const mockFeaturePropsArrayValue: FeatureProperty[] = [ - { - _propertyKey: 'host.name', - _rawValue: ['testPropValue1', 'testPropValue2'], - }, + const mockFeatureProps: ITooltipProperty[] = [ + new TooltipProperty('host.name', 'host.name', 'testPropValue'), ]; test('renders correctly against snapshot', () => { @@ -46,32 +34,6 @@ describe('PointToolTipContent', () => { expect(wrapper.find('PointToolTipContentComponent')).toMatchSnapshot(); }); - test('renders array filter correctly', () => { - const closeTooltip = jest.fn(); - - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="add-to-kql-host.name"]').prop('filter')).toEqual({ - meta: { - alias: null, - disabled: false, - key: 'host.name', - negate: false, - params: { query: 'testPropValue1' }, - type: 'phrase', - value: 'testPropValue1', - }, - query: { match: { 'host.name': { query: 'testPropValue1', type: 'phrase' } } }, - }); - }); - describe('#getRenderedFieldValue', () => { test('it returns empty tag if value is empty', () => { expect(getRenderedFieldValue('host.name', '')).toStrictEqual(getEmptyStringTag()); diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx index c691407f6166e..16494c01ac280 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx @@ -6,23 +6,19 @@ import React from 'react'; import { sourceDestinationFieldMappings } from '../map_config'; -import { - AddFilterToGlobalSearchBar, - createFilter, -} from '../../../../common/components/add_filter_to_global_search_bar'; import { getEmptyTagValue, getOrEmptyTagFromValue, } from '../../../../common/components/empty_value'; import { DescriptionListStyled } from '../../../../common/components/page'; -import { FeatureProperty } from '../types'; import { HostDetailsLink, IPDetailsLink } from '../../../../common/components/links'; import { DefaultFieldRenderer } from '../../../../timelines/components/field_renderers/field_renderers'; import { FlowTarget } from '../../../../graphql/types'; +import { ITooltipProperty } from '../../../../../../maps/public'; interface PointToolTipContentProps { contextId: string; - featureProps: FeatureProperty[]; + featureProps: ITooltipProperty[]; closeTooltip?(): void; } @@ -31,15 +27,14 @@ export const PointToolTipContentComponent = ({ featureProps, closeTooltip, }: PointToolTipContentProps) => { - const featureDescriptionListItems = featureProps.map( - ({ _propertyKey: key, _rawValue: value }) => ({ + const featureDescriptionListItems = featureProps.map(featureProp => { + const key = featureProp.getPropertyKey(); + const value = featureProp.getRawValue() ?? []; + + return { title: sourceDestinationFieldMappings[key], description: ( - + <> {value != null ? ( + ), - }) - ); + }; + }); return ; }; diff --git a/x-pack/plugins/siem/public/network/components/embeddables/types.ts b/x-pack/plugins/siem/public/network/components/embeddables/types.ts index e111c2728ba7e..9a49046634c3b 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/types.ts +++ b/x-pack/plugins/siem/public/network/components/embeddables/types.ts @@ -40,16 +40,6 @@ export interface MapFeature { layerId: string; } -export interface LoadFeatureProps { - layerId: string; - featureId: number; -} - -export interface FeatureProperty { - _propertyKey: string; - _rawValue: string | string[]; -} - export interface FeatureGeometry { coordinates: [number]; type: string; diff --git a/x-pack/plugins/siem/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/siem/public/timelines/components/open_timeline/helpers.ts index df433f147490e..30a88c58afff8 100644 --- a/x-pack/plugins/siem/public/timelines/components/open_timeline/helpers.ts +++ b/x-pack/plugins/siem/public/timelines/components/open_timeline/helpers.ts @@ -189,7 +189,7 @@ export const formatTimelineResultToModel = ( export interface QueryTimelineById { apolloClient: ApolloClient | ApolloClient<{}> | undefined; - duplicate: boolean; + duplicate?: boolean; timelineId: string; onOpenTimeline?: (timeline: TimelineModel) => void; openTimeline?: boolean; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 219e922a0158c..1295c775d00b5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -150,139 +150,139 @@ "common.ui.errorUrlOverflow.howTofixError.removeStuffFromDashboardText": "ダッシュボードからいくつか項目を取り除きましょう。これにより URL が短くなり、IE の動作が改善されます。", "common.ui.errorUrlOverflow.howTofixErrorDescription": "これは大抵大規模で複雑なダッシュボードで起こるため、いくつかのオプションがあります。", "common.ui.errorUrlOverflow.howTofixErrorTitle": "どうすれば良いのでしょう?", - "common.ui.fieldEditor.actions.cancelButton": "キャンセル", - "common.ui.fieldEditor.actions.createButton": "フィールドを作成", - "common.ui.fieldEditor.actions.deleteButton": "削除", - "common.ui.fieldEditor.actions.saveButton": "フィールドを保存", - "common.ui.fieldEditor.color.addColorButton": "色を追加", - "common.ui.fieldEditor.color.backgroundLabel": "背景色", - "common.ui.fieldEditor.color.deleteAria": "削除", - "common.ui.fieldEditor.color.deleteTitle": "色のフォーマットを削除", - "common.ui.fieldEditor.color.exampleLabel": "例", - "common.ui.fieldEditor.color.patternLabel": "パターン (正規表現)", - "common.ui.fieldEditor.color.rangeLabel": "範囲 (min:max)", - "common.ui.fieldEditor.color.textColorLabel": "文字の色", - "common.ui.fieldEditor.createHeader": "スクリプトフィールドを作成", - "common.ui.fieldEditor.date.documentationLabel": "ドキュメント", - "common.ui.fieldEditor.date.momentLabel": "Moment.js のフォーマットパターン (デフォルト: {defaultPattern})", - "common.ui.fieldEditor.defaultErrorMessage": "このフォーマット構成の使用を試みた際にエラーが発生しました: {message}", - "common.ui.fieldEditor.defaultFormatDropDown": "- デフォルト -", - "common.ui.fieldEditor.defaultFormatHeader": "フォーマット (デフォルト: {defaultFormat})", - "common.ui.fieldEditor.deleteField.cancelButton": "キャンセル", - "common.ui.fieldEditor.deleteField.deleteButton": "削除", - "common.ui.fieldEditor.deleteField.deletedHeader": "「{fieldName}」が削除されました", - "common.ui.fieldEditor.deleteField.savedHeader": "「{fieldName}」が保存されました", - "common.ui.fieldEditor.deleteFieldHeader": "フィールド「{fieldName}」を削除", - "common.ui.fieldEditor.deleteFieldLabel": "削除されたフィールドは復元できません。{separator}続行してよろしいですか?", - "common.ui.fieldEditor.disabledCallOutHeader": "スクリプティングが無効です", - "common.ui.fieldEditor.disabledCallOutLabel": "Elasticsearch でのすべてのインラインスクリプティングが無効になっています。Kibana でスクリプトフィールドを使用するには、インラインスクリプティングを有効にする必要があります。", - "common.ui.fieldEditor.duration.decimalPlacesLabel": "小数部分の桁数", - "common.ui.fieldEditor.duration.inputFormatLabel": "インプット形式", - "common.ui.fieldEditor.duration.outputFormatLabel": "アウトプット形式", - "common.ui.fieldEditor.durationErrorMessage": "小数部分の桁数は 0 から 20 までの間で指定する必要があります", - "common.ui.fieldEditor.editHeader": "{fieldName} を編集", - "common.ui.fieldEditor.fieldTypeConflict": "フィールドタイプの矛盾", - "common.ui.fieldEditor.formatHeader": "フォーマット", - "common.ui.fieldEditor.formatLabel": "フォーマットは、特定の値の表示形式を管理できます。また、値を完全に変更したり、ディスカバリでのハイライト機能を無効にしたりすることも可能です。", - "common.ui.fieldEditor.indexNameLabel": "インデックス名", - "common.ui.fieldEditor.labelTemplate.example.idLabel": "ユーザー #{value}", - "common.ui.fieldEditor.labelTemplate.example.output.idLabel": "ユーザー", - "common.ui.fieldEditor.labelTemplate.example.output.pathLabel": "アセットを表示", - "common.ui.fieldEditor.labelTemplate.example.pathLabel": "アセットを表示", - "common.ui.fieldEditor.labelTemplate.examplesHeader": "例", - "common.ui.fieldEditor.labelTemplate.inputHeader": "インプット", - "common.ui.fieldEditor.labelTemplate.labelHeader": "ラベルテンプレート", - "common.ui.fieldEditor.labelTemplate.outputHeader": "アウトプット", - "common.ui.fieldEditor.labelTemplate.urlHeader": "URL テンプレート", - "common.ui.fieldEditor.labelTemplate.urlLabel": "フォーマット済み URL", - "common.ui.fieldEditor.labelTemplate.valueLabel": "フィールド値", - "common.ui.fieldEditor.labelTemplateHeader": "ラベルテンプレート", - "common.ui.fieldEditor.labelTemplateLabel": "このフィールドの URL が長い場合、URL のテキストバージョン用の代替テンプレートを使用すると良いかもしれません。URL の代わりに表示されますが、URL にリンクされます。このフォーマットは、値の投入に二重中括弧の表記 {doubleCurlyBraces} を使用する文字列です。次の値にアクセスできます。", - "common.ui.fieldEditor.languageLabel": "言語", - "common.ui.fieldEditor.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} 既に「{fieldName}」という名前のフィールドが存在します。スクリプトフィールドに同じ名前を付けると、同時に両方のフィールドにクエリが実行できなくなります。", - "common.ui.fieldEditor.mappingConflictLabel.mappingConflictLabel": "マッピングの矛盾:", - "common.ui.fieldEditor.multiTypeLabelDesc": "フィールドのタイプがインデックスごとに変わります。多くの分析機能には使用できません。タイプごとのインデックスは次の通りです:", - "common.ui.fieldEditor.nameErrorMessage": "名前が必要です", - "common.ui.fieldEditor.nameLabel": "名前", - "common.ui.fieldEditor.namePlaceholder": "新規スクリプトフィールド", - "common.ui.fieldEditor.number.documentationLabel": "ドキュメント", - "common.ui.fieldEditor.number.numeralLabel": "Numeral.js のフォーマットパターン (デフォルト: {defaultPattern})", - "common.ui.fieldEditor.popularityLabel": "利用頻度", - "common.ui.fieldEditor.samples.inputHeader": "インプット", - "common.ui.fieldEditor.samples.outputHeader": "アウトプット", - "common.ui.fieldEditor.samplesHeader": "サンプル", - "common.ui.fieldEditor.script.accessWithLabel": "{code} でフィールドにアクセスします。", - "common.ui.fieldEditor.script.getHelpLabel": "構文のヒントを得たり、スクリプトの結果をプレビューしたりできます。", - "common.ui.fieldEditor.scriptInvalidErrorMessage": "スクリプトが無効です。スクリプトのプレビューで詳細を確認", - "common.ui.fieldEditor.scriptLabel": "スクリプト", - "common.ui.fieldEditor.scriptRequiredErrorMessage": "スクリプトが必要です", - "common.ui.fieldEditor.staticLookup.addEntryButton": "エントリーを追加", - "common.ui.fieldEditor.staticLookup.deleteAria": "削除", - "common.ui.fieldEditor.staticLookup.deleteTitle": "エントリーの削除", - "common.ui.fieldEditor.staticLookup.keyLabel": "キー", - "common.ui.fieldEditor.staticLookup.leaveBlankPlaceholder": "値をそのままにするには空欄にします", - "common.ui.fieldEditor.staticLookup.unknownKeyLabel": "不明なキーの値", - "common.ui.fieldEditor.staticLookup.valueLabel": "値", - "common.ui.fieldEditor.string.transformLabel": "変換", - "common.ui.fieldEditor.syntax.default.formatLabel": "doc['some_field'].値", - "common.ui.fieldEditor.syntax.defaultLabel.defaultDetail": "デフォルトで、Kibana のスクリプトフィールドは Elasticsearch での使用を目的に特別に開発されたシンプルでセキュアなスクリプト言語の {painless} を使用します。ドキュメントの値にアクセスするには次のフォーマットを使用します。", - "common.ui.fieldEditor.syntax.defaultLabel.painlessLink": "Painless", - "common.ui.fieldEditor.syntax.kibanaLabel": "Kibana は現在 Painless スクリプトに特別な制限が 1 つあります。Named 関数を含めることができません。", - "common.ui.fieldEditor.syntax.lucene.commonLabel.commonDetail": "Kibana の旧バージョンからのアップグレードですか?お馴染みの {lucene} は引き続きご利用いただけます。Lucene 表現は JavaScript と非常に似ていますが、基本的な計算、ビット処理、比較オペレーション用に開発されたものです。", - "common.ui.fieldEditor.syntax.lucene.commonLabel.luceneLink": "Lucene 表現", - "common.ui.fieldEditor.syntax.lucene.limits.fieldsLabel": "格納されたフィールドは利用できません", - "common.ui.fieldEditor.syntax.lucene.limits.sparseLabel": "フィールドがまばらな (ドキュメントの一部にしか値がない) 場合、値がないドキュメントには 0 の値が入力されます", - "common.ui.fieldEditor.syntax.lucene.limits.typesLabel": "数字、ブール、日付、、geo_point フィールドのみアクセスできます", - "common.ui.fieldEditor.syntax.lucene.limitsLabel": "Lucene 表現には次のいくつかの制限があります。", - "common.ui.fieldEditor.syntax.lucene.operations.arithmeticLabel": "算術演算子: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.bitwiseLabel": "ビット処理演算子: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.booleanLabel": "ブール演算子 (三項演算子を含む): {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.comparisonLabel": "比較演算子: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.distanceLabel": "距離関数: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.mathLabel": "一般的な関数: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.miscellaneousLabel": "その他関数: {operators}", - "common.ui.fieldEditor.syntax.lucene.operations.trigLabel": "三角ライブラリ関数: {operators}", - "common.ui.fieldEditor.syntax.lucene.operationsLabel": "Lucene 表現で利用可能なオペレーションは次の通りです。", - "common.ui.fieldEditor.syntax.painlessLabel.javaAPIsLink": "ネイティブ Java API", - "common.ui.fieldEditor.syntax.painlessLabel.painlessDetail": "Painless は非常に強力かつ使いやすい言語です。多くの {javaAPIs} にアクセスすることができます。{syntax} について読めば、すぐに習得することができます!", - "common.ui.fieldEditor.syntax.painlessLabel.syntaxLink": "構文", - "common.ui.fieldEditor.syntaxHeader": "構文", - "common.ui.fieldEditor.testScript.errorMessage": "スクリプト内にエラーがあります", - "common.ui.fieldEditor.testScript.fieldsLabel": "追加フィールド", - "common.ui.fieldEditor.testScript.fieldsPlaceholder": "選択してください…", - "common.ui.fieldEditor.testScript.instructions": "スクリプトを実行すると、最初の検索結果10件をプレビューできます。追加フィールドを選択して結果に含み、コンテクストをさらに加えたり、特定の文書上でフィルタにクエリを追加したりすることもできます。", - "common.ui.fieldEditor.testScript.resultsLabel": "最初の10件", - "common.ui.fieldEditor.testScript.resultsTitle": "結果を表示", - "common.ui.fieldEditor.testScript.submitButtonLabel": "スクリプトを実行", - "common.ui.fieldEditor.truncate.lengthLabel": "フィールドの長さ", - "common.ui.fieldEditor.typeLabel": "タイプ", - "common.ui.fieldEditor.url.heightLabel": "高さ", - "common.ui.fieldEditor.url.labelTemplateHelpText": "ラベルテンプレートのヘルプ", - "common.ui.fieldEditor.url.labelTemplateLabel": "ラベルテンプレート", - "common.ui.fieldEditor.url.offLabel": "オフ", - "common.ui.fieldEditor.url.onLabel": "オン", - "common.ui.fieldEditor.url.openTabLabel": "新規タブで開く", - "common.ui.fieldEditor.url.template.helpLinkText": "URL テンプレートのヘルプ", - "common.ui.fieldEditor.url.typeLabel": "タイプ", - "common.ui.fieldEditor.url.urlTemplateLabel": "URL テンプレート", - "common.ui.fieldEditor.url.widthLabel": "幅", - "common.ui.fieldEditor.urlTemplate.examplesHeader": "例", - "common.ui.fieldEditor.urlTemplate.inputHeader": "インプット", - "common.ui.fieldEditor.urlTemplate.outputHeader": "アウトプット", - "common.ui.fieldEditor.urlTemplate.rawValueLabel": "非エスケープ値", - "common.ui.fieldEditor.urlTemplate.templateHeader": "テンプレート", - "common.ui.fieldEditor.urlTemplate.valueLabel": "URL エスケープ値", - "common.ui.fieldEditor.urlTemplateHeader": "URL テンプレート", - "common.ui.fieldEditor.urlTemplateLabel.fieldDetail": "フィールドに URL の一部のみが含まれている場合、{strongUrlTemplate} でその値を完全な URL としてフォーマットできます。このフォーマットは、値の投入に二重中括弧の表記 {doubleCurlyBraces} を使用する文字列です。次の値にアクセスできます。", - "common.ui.fieldEditor.urlTemplateLabel.strongUrlTemplateLabel": "URL テンプレート", - "common.ui.fieldEditor.warningCallOut.descriptionLabel": "計算値の表示と集約にスクリプトフィールドが使用できます。そのため非常に遅い場合があり、適切に行わないと Kibana が使用できなくなる可能性もあります。この場合安全策はありません。入力ミスがあると、あちこちに予期せぬ例外が起こります!", - "common.ui.fieldEditor.warningCallOutHeader": "十分ご注意ください", - "common.ui.fieldEditor.warningCallOutLabel.callOutDetail": "スクリプトフィールドを使う前に、{scripFields} と {scriptsInAggregation} についてよく理解するようにしてください。", - "common.ui.fieldEditor.warningCallOutLabel.scripFieldsLink": "スクリプトフィールド", - "common.ui.fieldEditor.warningCallOutLabel.scriptsInAggregationLink": "集約におけるスクリプト", - "common.ui.fieldEditor.warningHeader": "廃止警告:", - "common.ui.fieldEditor.warningLabel.painlessLinkLabel": "Painless", - "common.ui.fieldEditor.warningLabel.warningDetail": "{language} は廃止され、Kibana と Elasticsearch の次のメジャーなバージョンではサポートされなくなります。新規スクリプトフィールドには {painlessLink} を使うことをお勧めします。", + "indexPatternManagement.actions.cancelButton": "キャンセル", + "indexPatternManagement.actions.createButton": "フィールドを作成", + "indexPatternManagement.actions.deleteButton": "削除", + "indexPatternManagement.actions.saveButton": "フィールドを保存", + "indexPatternManagement.color.addColorButton": "色を追加", + "indexPatternManagement.color.backgroundLabel": "背景色", + "indexPatternManagement.color.deleteAria": "削除", + "indexPatternManagement.color.deleteTitle": "色のフォーマットを削除", + "indexPatternManagement.color.exampleLabel": "例", + "indexPatternManagement.color.patternLabel": "パターン (正規表現)", + "indexPatternManagement.color.rangeLabel": "範囲 (min:max)", + "indexPatternManagement.color.textColorLabel": "文字の色", + "indexPatternManagement.createHeader": "スクリプトフィールドを作成", + "indexPatternManagement.date.documentationLabel": "ドキュメント", + "indexPatternManagement.date.momentLabel": "Moment.js のフォーマットパターン (デフォルト: {defaultPattern})", + "indexPatternManagement.defaultErrorMessage": "このフォーマット構成の使用を試みた際にエラーが発生しました: {message}", + "indexPatternManagement.defaultFormatDropDown": "- デフォルト -", + "indexPatternManagement.defaultFormatHeader": "フォーマット (デフォルト: {defaultFormat})", + "indexPatternManagement.deleteField.cancelButton": "キャンセル", + "indexPatternManagement.deleteField.deleteButton": "削除", + "indexPatternManagement.deleteField.deletedHeader": "「{fieldName}」が削除されました", + "indexPatternManagement.deleteField.savedHeader": "「{fieldName}」が保存されました", + "indexPatternManagement.deleteFieldHeader": "フィールド「{fieldName}」を削除", + "indexPatternManagement.deleteFieldLabel": "削除されたフィールドは復元できません。{separator}続行してよろしいですか?", + "indexPatternManagement.disabledCallOutHeader": "スクリプティングが無効です", + "indexPatternManagement.disabledCallOutLabel": "Elasticsearch でのすべてのインラインスクリプティングが無効になっています。Kibana でスクリプトフィールドを使用するには、インラインスクリプティングを有効にする必要があります。", + "indexPatternManagement.duration.decimalPlacesLabel": "小数部分の桁数", + "indexPatternManagement.duration.inputFormatLabel": "インプット形式", + "indexPatternManagement.duration.outputFormatLabel": "アウトプット形式", + "indexPatternManagement.durationErrorMessage": "小数部分の桁数は 0 から 20 までの間で指定する必要があります", + "indexPatternManagement.editHeader": "{fieldName} を編集", + "indexPatternManagement.fieldTypeConflict": "フィールドタイプの矛盾", + "indexPatternManagement.formatHeader": "フォーマット", + "indexPatternManagement.formatLabel": "フォーマットは、特定の値の表示形式を管理できます。また、値を完全に変更したり、ディスカバリでのハイライト機能を無効にしたりすることも可能です。", + "indexPatternManagement.indexNameLabel": "インデックス名", + "indexPatternManagement.labelTemplate.example.idLabel": "ユーザー #{value}", + "indexPatternManagement.labelTemplate.example.output.idLabel": "ユーザー", + "indexPatternManagement.labelTemplate.example.output.pathLabel": "アセットを表示", + "indexPatternManagement.labelTemplate.example.pathLabel": "アセットを表示", + "indexPatternManagement.labelTemplate.examplesHeader": "例", + "indexPatternManagement.labelTemplate.inputHeader": "インプット", + "indexPatternManagement.labelTemplate.labelHeader": "ラベルテンプレート", + "indexPatternManagement.labelTemplate.outputHeader": "アウトプット", + "indexPatternManagement.labelTemplate.urlHeader": "URL テンプレート", + "indexPatternManagement.labelTemplate.urlLabel": "フォーマット済み URL", + "indexPatternManagement.labelTemplate.valueLabel": "フィールド値", + "indexPatternManagement.labelTemplateHeader": "ラベルテンプレート", + "indexPatternManagement.labelTemplateLabel": "このフィールドの URL が長い場合、URL のテキストバージョン用の代替テンプレートを使用すると良いかもしれません。URL の代わりに表示されますが、URL にリンクされます。このフォーマットは、値の投入に二重中括弧の表記 {doubleCurlyBraces} を使用する文字列です。次の値にアクセスできます。", + "indexPatternManagement.languageLabel": "言語", + "indexPatternManagement.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} 既に「{fieldName}」という名前のフィールドが存在します。スクリプトフィールドに同じ名前を付けると、同時に両方のフィールドにクエリが実行できなくなります。", + "indexPatternManagement.mappingConflictLabel.mappingConflictLabel": "マッピングの矛盾:", + "indexPatternManagement.multiTypeLabelDesc": "フィールドのタイプがインデックスごとに変わります。多くの分析機能には使用できません。タイプごとのインデックスは次の通りです:", + "indexPatternManagement.nameErrorMessage": "名前が必要です", + "indexPatternManagement.nameLabel": "名前", + "indexPatternManagement.namePlaceholder": "新規スクリプトフィールド", + "indexPatternManagement.number.documentationLabel": "ドキュメント", + "indexPatternManagement.number.numeralLabel": "Numeral.js のフォーマットパターン (デフォルト: {defaultPattern})", + "indexPatternManagement.popularityLabel": "利用頻度", + "indexPatternManagement.samples.inputHeader": "インプット", + "indexPatternManagement.samples.outputHeader": "アウトプット", + "indexPatternManagement.samplesHeader": "サンプル", + "indexPatternManagement.script.accessWithLabel": "{code} でフィールドにアクセスします。", + "indexPatternManagement.script.getHelpLabel": "構文のヒントを得たり、スクリプトの結果をプレビューしたりできます。", + "indexPatternManagement.scriptInvalidErrorMessage": "スクリプトが無効です。スクリプトのプレビューで詳細を確認", + "indexPatternManagement.scriptLabel": "スクリプト", + "indexPatternManagement.scriptRequiredErrorMessage": "スクリプトが必要です", + "indexPatternManagement.staticLookup.addEntryButton": "エントリーを追加", + "indexPatternManagement.staticLookup.deleteAria": "削除", + "indexPatternManagement.staticLookup.deleteTitle": "エントリーの削除", + "indexPatternManagement.staticLookup.keyLabel": "キー", + "indexPatternManagement.staticLookup.leaveBlankPlaceholder": "値をそのままにするには空欄にします", + "indexPatternManagement.staticLookup.unknownKeyLabel": "不明なキーの値", + "indexPatternManagement.staticLookup.valueLabel": "値", + "indexPatternManagement.string.transformLabel": "変換", + "indexPatternManagement.syntax.default.formatLabel": "doc['some_field'].値", + "indexPatternManagement.syntax.defaultLabel.defaultDetail": "デフォルトで、Kibana のスクリプトフィールドは Elasticsearch での使用を目的に特別に開発されたシンプルでセキュアなスクリプト言語の {painless} を使用します。ドキュメントの値にアクセスするには次のフォーマットを使用します。", + "indexPatternManagement.syntax.defaultLabel.painlessLink": "Painless", + "indexPatternManagement.syntax.kibanaLabel": "Kibana は現在 Painless スクリプトに特別な制限が 1 つあります。Named 関数を含めることができません。", + "indexPatternManagement.syntax.lucene.commonLabel.commonDetail": "Kibana の旧バージョンからのアップグレードですか?お馴染みの {lucene} は引き続きご利用いただけます。Lucene 表現は JavaScript と非常に似ていますが、基本的な計算、ビット処理、比較オペレーション用に開発されたものです。", + "indexPatternManagement.syntax.lucene.commonLabel.luceneLink": "Lucene 表現", + "indexPatternManagement.syntax.lucene.limits.fieldsLabel": "格納されたフィールドは利用できません", + "indexPatternManagement.syntax.lucene.limits.sparseLabel": "フィールドがまばらな (ドキュメントの一部にしか値がない) 場合、値がないドキュメントには 0 の値が入力されます", + "indexPatternManagement.syntax.lucene.limits.typesLabel": "数字、ブール、日付、、geo_point フィールドのみアクセスできます", + "indexPatternManagement.syntax.lucene.limitsLabel": "Lucene 表現には次のいくつかの制限があります。", + "indexPatternManagement.syntax.lucene.operations.arithmeticLabel": "算術演算子: {operators}", + "indexPatternManagement.syntax.lucene.operations.bitwiseLabel": "ビット処理演算子: {operators}", + "indexPatternManagement.syntax.lucene.operations.booleanLabel": "ブール演算子 (三項演算子を含む): {operators}", + "indexPatternManagement.syntax.lucene.operations.comparisonLabel": "比較演算子: {operators}", + "indexPatternManagement.syntax.lucene.operations.distanceLabel": "距離関数: {operators}", + "indexPatternManagement.syntax.lucene.operations.mathLabel": "一般的な関数: {operators}", + "indexPatternManagement.syntax.lucene.operations.miscellaneousLabel": "その他関数: {operators}", + "indexPatternManagement.syntax.lucene.operations.trigLabel": "三角ライブラリ関数: {operators}", + "indexPatternManagement.syntax.lucene.operationsLabel": "Lucene 表現で利用可能なオペレーションは次の通りです。", + "indexPatternManagement.syntax.painlessLabel.javaAPIsLink": "ネイティブ Java API", + "indexPatternManagement.syntax.painlessLabel.painlessDetail": "Painless は非常に強力かつ使いやすい言語です。多くの {javaAPIs} にアクセスすることができます。{syntax} について読めば、すぐに習得することができます!", + "indexPatternManagement.syntax.painlessLabel.syntaxLink": "構文", + "indexPatternManagement.syntaxHeader": "構文", + "indexPatternManagement.testScript.errorMessage": "スクリプト内にエラーがあります", + "indexPatternManagement.testScript.fieldsLabel": "追加フィールド", + "indexPatternManagement.testScript.fieldsPlaceholder": "選択してください…", + "indexPatternManagement.testScript.instructions": "スクリプトを実行すると、最初の検索結果10件をプレビューできます。追加フィールドを選択して結果に含み、コンテクストをさらに加えたり、特定の文書上でフィルタにクエリを追加したりすることもできます。", + "indexPatternManagement.testScript.resultsLabel": "最初の10件", + "indexPatternManagement.testScript.resultsTitle": "結果を表示", + "indexPatternManagement.testScript.submitButtonLabel": "スクリプトを実行", + "indexPatternManagement.truncate.lengthLabel": "フィールドの長さ", + "indexPatternManagement.typeLabel": "タイプ", + "indexPatternManagement.url.heightLabel": "高さ", + "indexPatternManagement.url.labelTemplateHelpText": "ラベルテンプレートのヘルプ", + "indexPatternManagement.url.labelTemplateLabel": "ラベルテンプレート", + "indexPatternManagement.url.offLabel": "オフ", + "indexPatternManagement.url.onLabel": "オン", + "indexPatternManagement.url.openTabLabel": "新規タブで開く", + "indexPatternManagement.url.template.helpLinkText": "URL テンプレートのヘルプ", + "indexPatternManagement.url.typeLabel": "タイプ", + "indexPatternManagement.url.urlTemplateLabel": "URL テンプレート", + "indexPatternManagement.url.widthLabel": "幅", + "indexPatternManagement.urlTemplate.examplesHeader": "例", + "indexPatternManagement.urlTemplate.inputHeader": "インプット", + "indexPatternManagement.urlTemplate.outputHeader": "アウトプット", + "indexPatternManagement.urlTemplate.rawValueLabel": "非エスケープ値", + "indexPatternManagement.urlTemplate.templateHeader": "テンプレート", + "indexPatternManagement.urlTemplate.valueLabel": "URL エスケープ値", + "indexPatternManagement.urlTemplateHeader": "URL テンプレート", + "indexPatternManagement.urlTemplateLabel.fieldDetail": "フィールドに URL の一部のみが含まれている場合、{strongUrlTemplate} でその値を完全な URL としてフォーマットできます。このフォーマットは、値の投入に二重中括弧の表記 {doubleCurlyBraces} を使用する文字列です。次の値にアクセスできます。", + "indexPatternManagement.urlTemplateLabel.strongUrlTemplateLabel": "URL テンプレート", + "indexPatternManagement.warningCallOut.descriptionLabel": "計算値の表示と集約にスクリプトフィールドが使用できます。そのため非常に遅い場合があり、適切に行わないと Kibana が使用できなくなる可能性もあります。この場合安全策はありません。入力ミスがあると、あちこちに予期せぬ例外が起こります!", + "indexPatternManagement.warningCallOutHeader": "十分ご注意ください", + "indexPatternManagement.warningCallOutLabel.callOutDetail": "スクリプトフィールドを使う前に、{scripFields} と {scriptsInAggregation} についてよく理解するようにしてください。", + "indexPatternManagement.warningCallOutLabel.scripFieldsLink": "スクリプトフィールド", + "indexPatternManagement.warningCallOutLabel.scriptsInAggregationLink": "集約におけるスクリプト", + "indexPatternManagement.warningHeader": "廃止警告:", + "indexPatternManagement.warningLabel.painlessLinkLabel": "Painless", + "indexPatternManagement.warningLabel.warningDetail": "{language} は廃止され、Kibana と Elasticsearch の次のメジャーなバージョンではサポートされなくなります。新規スクリプトフィールドには {painlessLink} を使うことをお勧めします。", "common.ui.flotCharts.aprLabel": "4 月", "common.ui.flotCharts.augLabel": "8 月", "common.ui.flotCharts.decLabel": "12 月", @@ -303,7 +303,7 @@ "common.ui.flotCharts.thuLabel": "木", "common.ui.flotCharts.tueLabel": "火", "common.ui.flotCharts.wedLabel": "水", - "common.ui.scriptingLanguages.errorFetchingToastDescription": "Elasticsearch から利用可能なスクリプト言語の取得中にエラーが発生しました", + "indexPatternManagement.scriptingLanguages.errorFetchingToastDescription": "Elasticsearch から利用可能なスクリプト言語の取得中にエラーが発生しました", "common.ui.stateManagement.unableToParseUrlErrorMessage": "URL をパースできません", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "URL を完全に復元できません。共有機能を使用していることを確認してください。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", @@ -2099,164 +2099,164 @@ "kbn.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "デフォルトの WMS プロパティ", "kbn.advancedSettings.visualizeEnableLabsText": "ユーザーが実験的なビジュアライゼーションを作成、表示、編集できるようになります。無効の場合、\n ユーザーは本番準備が整ったビジュアライゼーションのみを利用できます。", "kbn.advancedSettings.visualizeEnableLabsTitle": "実験的なビジュアライゼーションを有効にする", - "kbn.management.createIndexPattern.betaLabel": "ベータ", - "kbn.management.createIndexPattern.emptyState.checkDataButton": "新規データを確認", - "kbn.management.createIndexPattern.emptyStateHeader": "Elasticsearch データが見つかりませんでした", - "kbn.management.createIndexPattern.emptyStateLabel.emptyStateDetail": "{needToIndex} {learnHowLink} または {getStartedLink}", - "kbn.management.createIndexPattern.emptyStateLabel.getStartedLink": "サンプルデータで始めましょう。", - "kbn.management.createIndexPattern.emptyStateLabel.learnHowLink": "方法を学習", - "kbn.management.createIndexPattern.emptyStateLabel.needToIndexLabel": "インデックスパターンを作成する前に、Elasticsearch へのデータのインデックスが必要です。", - "kbn.management.createIndexPattern.includeSystemIndicesToggleSwitchLabel": "システムインデックスを含める", - "kbn.management.createIndexPattern.loadClustersFailMsg": "リモートクラスターの読み込みに失敗", - "kbn.management.createIndexPattern.loadIndicesFailMsg": "インデックスの読み込みに失敗", - "kbn.management.createIndexPattern.loadingState.checkingLabel": "Elasticsearch データを確認中", - "kbn.management.createIndexPattern.step.indexPattern.allowLabel": "インデックスパターンでワイルドカードとして {asterisk} を使用できます。", - "kbn.management.createIndexPattern.step.indexPattern.disallowLabel": "スペースや {characterList} は使用できません。", - "kbn.management.createIndexPattern.step.indexPatternLabel": "インデックスパターン", - "kbn.management.createIndexPattern.step.indexPatternPlaceholder": "index-name-*", - "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage": "{indexPatternName} にはスペースや {characterList} は使えません。", - "kbn.management.createIndexPattern.step.loadingHeader": "一致するインデックスを検索中…", - "kbn.management.createIndexPattern.step.loadingLabel": "お待ちください…", - "kbn.management.createIndexPattern.step.nextStepButton": "次のステップ", - "kbn.management.createIndexPattern.step.pagingLabel": "ページごとの行数: {perPage}", - "kbn.management.createIndexPattern.step.status.matchAnyLabel.matchAnyDetail": "インデックスパターンは下の{strongIndices} の いずれかに一致します。", - "kbn.management.createIndexPattern.step.status.noSystemIndicesLabel": "パターンに一致する Elasticsearch インデックスがありません。", - "kbn.management.createIndexPattern.step.status.noSystemIndicesWithPromptLabel": "パターンに一致する Elasticsearch インデックスがありません。一致するシステムインデックスを表示するには、右上のスイッチを切り替えます。", - "kbn.management.createIndexPattern.step.status.notMatchLabel.allIndicesLabel": "{indicesLength, plural, one {# インデックス} other {# インデックス}}", - "kbn.management.createIndexPattern.step.status.notMatchLabel.notMatchDetail": "入力されたインデックスパターンがどのインデックスにも一致しません。下の {indicesLength, plural, one {} other {}}{strongIndices} と一致させることができます。", - "kbn.management.createIndexPattern.step.status.partialMatchLabel.partialMatchDetail": "インデックスパターンがどのインデックスとも一致ませんが、似た {matchedIndicesLength, plural, one {} other {}}{strongIndices} があります。", - "kbn.management.createIndexPattern.step.status.partialMatchLabel.strongIndicesLabel": "{matchedIndicesLength, plural, one {# インデックス} other {# インデックス}}", - "kbn.management.createIndexPattern.step.status.successLabel.strongIndicesLabel": "{indicesLength, plural, one {# インデックス} other {# インデックス}}", - "kbn.management.createIndexPattern.step.status.successLabel.strongSuccessLabel": "成功!", - "kbn.management.createIndexPattern.step.status.successLabel.successDetail": "{strongSuccess} インデックスパターンが {strongIndices} と一致しています。", - "kbn.management.createIndexPattern.step.warningHeader": "既に {query} という名前のインデックスパターンがあります。", - "kbn.management.createIndexPattern.stepHeader": "ステップ 1/2:インデックスパターンの定義", - "kbn.management.createIndexPattern.stepTime.backButton": "戻る", - "kbn.management.createIndexPattern.stepTime.createPatternButton": "インデックスパターンを作成", - "kbn.management.createIndexPattern.stepTime.creatingLabel": "インデックスパターンを作成中…", - "kbn.management.createIndexPattern.stepTime.error": "エラー", - "kbn.management.createIndexPattern.stepTime.field.loadingDropDown": "読み込み中…", - "kbn.management.createIndexPattern.stepTime.field.noTimeFieldsLabel": "このインデックスパターンに一致するインデックスには時間フィールドがありません。", - "kbn.management.createIndexPattern.stepTime.fieldHeader": "時間フィルターのフィールド名", - "kbn.management.createIndexPattern.stepTime.fieldLabel": "時間フィルターはこのフィールドを使って時間でフィールドを絞ります。", - "kbn.management.createIndexPattern.stepTime.fieldWarningLabel": "時間フィールドを使わないこともできますが、その場合データを時間範囲で絞ることができません。", - "kbn.management.createIndexPattern.stepTime.noTimeFieldOptionLabel": "時間フィルターを使用しない", - "kbn.management.createIndexPattern.stepTime.noTimeFieldsLabel": "このインデックスパターンに一致するインデックスには時間フィールドがありません。", - "kbn.management.createIndexPattern.stepTime.options.hideButton": "高度なオプションを非表示", - "kbn.management.createIndexPattern.stepTime.options.patternHeader": "カスタムインデックスパターン ID", - "kbn.management.createIndexPattern.stepTime.options.patternLabel": "Kibana はそれぞれのインデックスパターンに固有の識別子を割り当てます。固有 ID を使用しない場合は、カスタム ID を入力してください。", - "kbn.management.createIndexPattern.stepTime.options.patternPlaceholder": "custom-index-pattern-id", - "kbn.management.createIndexPattern.stepTime.options.showButton": "高度なオプションを表示", - "kbn.management.createIndexPattern.stepTime.patterAlreadyExists": "カスタムインデックスパターン ID が既に存在します。", - "kbn.management.createIndexPattern.stepTime.refreshButton": "更新", - "kbn.management.createIndexPattern.stepTimeHeader": "ステップ 2/2:設定の変更", - "kbn.management.createIndexPattern.stepTimeLabel": "{indexPattern} を {indexPatternName} に定義しました。次に、作成前に他の設定を行うことができます。", - "kbn.management.createIndexPatternHeader": "{indexPatternName} の作成", - "kbn.management.createIndexPatternLabel": "Kibana は、可視化などを目的に Elasticsearch インデックスからデータを取得するために、インデックスパターンを使用します。", - "kbn.management.editIndexPattern.deleteButton": "削除", - "kbn.management.editIndexPattern.deleteHeader": "インデックスパターンを削除しますか?", - "kbn.management.editIndexPattern.detailsAria": "インデックスパターンの詳細", - "kbn.management.editIndexPattern.fields.allLangsDropDown": "すべての言語", - "kbn.management.editIndexPattern.fields.allTypesDropDown": "すべてのフィールドタイプ", - "kbn.management.editIndexPattern.fields.filterAria": "フィルター", - "kbn.management.editIndexPattern.fields.filterPlaceholder": "フィルター", - "kbn.management.editIndexPattern.fields.table.additionalInfoAriaLabel": "追加フィールド情報", - "kbn.management.editIndexPattern.fields.table.aggregatableDescription": "これらのフィールドはビジュアライゼーションの集約に使用できます", - "kbn.management.editIndexPattern.fields.table.aggregatableLabel": "集約可能", - "kbn.management.editIndexPattern.fields.table.editDescription": "編集", - "kbn.management.editIndexPattern.fields.table.editLabel": "編集", - "kbn.management.editIndexPattern.fields.table.excludedDescription": "取得の際に _source から除外されるフィールドです", - "kbn.management.editIndexPattern.fields.table.excludedLabel": "除外", - "kbn.management.editIndexPattern.fields.table.formatHeader": "フォーマット", - "kbn.management.editIndexPattern.fields.table.isAggregatableAria": "は集約可能です", - "kbn.management.editIndexPattern.fields.table.isExcludedAria": "は除外されています", - "kbn.management.editIndexPattern.fields.table.isSearchableAria": "は検索可能です", - "kbn.management.editIndexPattern.fields.table.multiTypeAria": "複数タイプのフィールド", - "kbn.management.editIndexPattern.fields.table.multiTypeTooltip": "フィールドのタイプがインデックスごとに変わります。多くの分析機能には使用できません。", - "kbn.management.editIndexPattern.fields.table.nameHeader": "名前", - "kbn.management.editIndexPattern.fields.table.primaryTimeAriaLabel": "プライマリ時間フィールド", - "kbn.management.editIndexPattern.fields.table.primaryTimeTooltip": "このフィールドはイベントの発生時刻を表します。", - "kbn.management.editIndexPattern.fields.table.searchableDescription": "これらのフィールドはフィルターバーで使用できます", - "kbn.management.editIndexPattern.fields.table.searchableHeader": "検索可能", - "kbn.management.editIndexPattern.fields.table.typeHeader": "タイプ", - "kbn.management.editIndexPattern.mappingConflictHeader": "マッピングの矛盾", - "kbn.management.editIndexPattern.mappingConflictLabel": "{conflictFieldsLength, plural, one {フィールドが} other {# フィールドが}}このパターンと一致するインデックスの間で異なるタイプ (文字列、整数など) に定義されています。これらの矛盾したフィールドは Kibana の一部で使用できますが、Kibana がタイプを把握しなければならない機能には使用できません。この問題を修正するにはデータのレンダリングが必要です。", - "kbn.management.editIndexPattern.refreshAria": "フィールドリストを再度読み込みます", - "kbn.management.editIndexPattern.refreshButton": "更新", - "kbn.management.editIndexPattern.refreshHeader": "フィールドリストを更新しますか?", - "kbn.management.editIndexPattern.refreshLabel": "この操作は各フィールドの使用頻度をリセットします。", - "kbn.management.editIndexPattern.refreshTooltip": "フィールドリストを更新", - "kbn.management.editIndexPattern.removeAria": "インデックスパターンを削除", - "kbn.management.editIndexPattern.removeTooltip": "インデックスパターンを削除います", - "kbn.management.editIndexPattern.scripted.addFieldButton": "スクリプトフィールドを追加", - "kbn.management.editIndexPattern.scripted.deleteField.cancelButton": "キャンセル", - "kbn.management.editIndexPattern.scripted.deleteField.deleteButton": "削除", - "kbn.management.editIndexPattern.scripted.deleteFieldLabel": "スクリプトフィールド「{fieldName}」を削除しますか?", - "kbn.management.editIndexPattern.scripted.deprecationLangHeader": "廃止された言語が使用されています", - "kbn.management.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "次の廃止された言語が使用されています: {deprecatedLangsInUse}これらの言語は、Kibana と Elasticsearch の次のメジャーなバージョンでサポートされなくなります。問題を避けるため、スクリプトフィールドを {link} に変換してください。", - "kbn.management.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "パターン", - "kbn.management.editIndexPattern.scripted.newFieldPlaceholder": "新規スクリプトフィールド", - "kbn.management.editIndexPattern.scripted.noFieldLabel": "「{indexPatternTitle}」インデックスパターンには「{fieldName}」というスクリプトフィールドがありません", - "kbn.management.editIndexPattern.scripted.table.deleteDescription": "このフィールドを削除します", - "kbn.management.editIndexPattern.scripted.table.deleteHeader": "削除", - "kbn.management.editIndexPattern.scripted.table.editDescription": "このフィールドを編集します", - "kbn.management.editIndexPattern.scripted.table.editHeader": "編集", - "kbn.management.editIndexPattern.scripted.table.formatDescription": "フィールドに使用されているフォーマットです", - "kbn.management.editIndexPattern.scripted.table.formatHeader": "フォーマット", - "kbn.management.editIndexPattern.scripted.table.langDescription": "フィールドに使用されている言語です", - "kbn.management.editIndexPattern.scripted.table.langHeader": "言語", - "kbn.management.editIndexPattern.scripted.table.nameDescription": "フィールドの名前です", - "kbn.management.editIndexPattern.scripted.table.nameHeader": "名前", - "kbn.management.editIndexPattern.scripted.table.scriptDescription": "フィールドのスクリプトです", - "kbn.management.editIndexPattern.scripted.table.scriptHeader": "スクリプト", - "kbn.management.editIndexPattern.scriptedHeader": "スクリプトフィールド", - "kbn.management.editIndexPattern.scriptedLabel": "ビジュアライゼーションにスクリプトフィールドを使用し、ドキュメントに表示させることができます。但し、スクリプトフィールドは検索できません。", - "kbn.management.editIndexPattern.setDefaultAria": "デフォルトのインデックスに設定", - "kbn.management.editIndexPattern.setDefaultTooltip": "デフォルトのインデックスに設定します", - "kbn.management.editIndexPattern.source.addButtonLabel": "追加", - "kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel": "キャンセル", - "kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel": "削除", - "kbn.management.editIndexPattern.source.deleteSourceFilterLabel": "ソースフィルター「{value}」を削除しますか?", - "kbn.management.editIndexPattern.source.noteLabel": "下の表で、マルチフィールドが一致として誤って表示されます。これらのフィルターは、オリジナルのソースドキュメントの\\フィールドのみに適用されるため、一致するマルチフィールドはフィルタリングされません。", - "kbn.management.editIndexPattern.source.table.cancelAria": "キャンセル", - "kbn.management.editIndexPattern.source.table.deleteAria": "削除", - "kbn.management.editIndexPattern.source.table.editAria": "編集", - "kbn.management.editIndexPattern.source.table.filterDescription": "フィルター名", - "kbn.management.editIndexPattern.source.table.filterHeader": "フィルター", - "kbn.management.editIndexPattern.source.table.matchesDescription": "フィールドに使用されている言語です", - "kbn.management.editIndexPattern.source.table.matchesHeader": "一致", - "kbn.management.editIndexPattern.source.table.notMatchedLabel": "ソースフィルターが既知のフィールドと一致しません。", - "kbn.management.editIndexPattern.source.table.saveAria": "保存", - "kbn.management.editIndexPattern.sourceHeader": "ソースフィルター", - "kbn.management.editIndexPattern.sourceLabel": "ソースフィルターは、ドキュメントソースの取得時に 1 つまたは複数のフィールドを除外するのに使用される場合もあります。これはディスカバリアプリでのドキュメントの表示中、またはダッシュボードアプリの保存された検索の結果を表示する表で起こります。それぞれの行は 1 つのドキュメントのソースで作成されており、ドキュメントに大きなフィールドや重要ではないフィールドが含まれている場合、このレベルでフィルターで除外すると良いかもしれません。", - "kbn.management.editIndexPattern.sourcePlaceholder": "ソースフィルター、ワイルドカード使用可 (例: 「user」と入力して「user」で始まるフィールドをフィルタリング)", - "kbn.management.editIndexPattern.tabs.fieldsHeader": "フィールド", - "kbn.management.editIndexPattern.tabs.scriptedHeader": "スクリプトフィールド", - "kbn.management.editIndexPattern.tabs.sourceHeader": "ソースフィルター", - "kbn.management.editIndexPattern.timeFilterHeader": "時間フィルターフィールド名: {timeFieldName}", - "kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink": "マッピング API", - "kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail": "このページは {indexPatternTitle} インデックス内のすべてのフィールドと、Elasticsearch に記録された各フィールドのコアタイプを一覧表示します。フィールドタイプを変更するには Elasticsearch を使用します", - "kbn.management.editIndexPatternLiveRegionAriaLabel": "インデックスパターン", - "kbn.management.indexPattern.goToPatternButtonLabel": "既存のパターンに移動", - "kbn.management.indexPattern.sectionsHeader": "インデックスパターン", - "kbn.management.indexPattern.titleExistsLabel": "「{title}」というタイトルのインデックスパターンが既に存在します。", - "kbn.management.indexPatternList.createButton.betaLabel": "ベータ", - "kbn.management.indexPatternPrompt.exampleOne": "チャートを作成したりコンテンツを素早くクエリできるように log-west-001 という名前の単一のデータソースをインデックスします。", - "kbn.management.indexPatternPrompt.exampleOneTitle": "単一のデータソース", - "kbn.management.indexPatternPrompt.examplesTitle": "インデックスパターンの例", - "kbn.management.indexPatternPrompt.exampleThree": "比較目的に履歴の動向を集約できるよう、これらのログのアーカイブされた月々のロールアップメトリックスを指定通りに別々のインデックスパターンにグループ分けします。", - "kbn.management.indexPatternPrompt.exampleThreeTitle": "カスタムグルーピング", - "kbn.management.indexPatternPrompt.exampleTwo": "すべての西海岸のサーバーログに対してクエリを実行できるように、頭に「log-west」の付いたすべての受信データソースをグループ化します。", - "kbn.management.indexPatternPrompt.exampleTwoTitle": "複数データソース", - "kbn.management.indexPatternPrompt.subtitle": "インデックスパターンは、Kibana で共有フィールドにクエリを実行できるよう、種類の異なるデータソースをバケットにまとめることができます。", - "kbn.management.indexPatternPrompt.title": "インデックスパターンについて", - "kbn.management.indexPatterns.badge.readOnly.text": "読み込み専用", - "kbn.management.indexPatterns.badge.readOnly.tooltip": "インデックスパターンを保存できません", - "kbn.management.indexPatterns.createBreadcrumb": "インデックスパターンを作成", - "kbn.management.indexPatterns.createFieldBreadcrumb": "フィールドを作成", - "kbn.management.indexPatterns.listBreadcrumb": "インデックスパターン", - "kbn.management.indexPatternTable.createBtn": "インデックスパターンの作成", - "kbn.management.indexPatternTable.title": "インデックスパターン", + "indexPatternManagement.createIndexPattern.betaLabel": "ベータ", + "indexPatternManagement.createIndexPattern.emptyState.checkDataButton": "新規データを確認", + "indexPatternManagement.createIndexPattern.emptyStateHeader": "Elasticsearch データが見つかりませんでした", + "indexPatternManagement.createIndexPattern.emptyStateLabel.emptyStateDetail": "{needToIndex} {learnHowLink} または {getStartedLink}", + "indexPatternManagement.createIndexPattern.emptyStateLabel.getStartedLink": "サンプルデータで始めましょう。", + "indexPatternManagement.createIndexPattern.emptyStateLabel.learnHowLink": "方法を学習", + "indexPatternManagement.createIndexPattern.emptyStateLabel.needToIndexLabel": "インデックスパターンを作成する前に、Elasticsearch へのデータのインデックスが必要です。", + "indexPatternManagement.createIndexPattern.includeSystemIndicesToggleSwitchLabel": "システムインデックスを含める", + "indexPatternManagement.createIndexPattern.loadClustersFailMsg": "リモートクラスターの読み込みに失敗", + "indexPatternManagement.createIndexPattern.loadIndicesFailMsg": "インデックスの読み込みに失敗", + "indexPatternManagement.createIndexPattern.loadingState.checkingLabel": "Elasticsearch データを確認中", + "indexPatternManagement.createIndexPattern.step.indexPattern.allowLabel": "インデックスパターンでワイルドカードとして {asterisk} を使用できます。", + "indexPatternManagement.createIndexPattern.step.indexPattern.disallowLabel": "スペースや {characterList} は使用できません。", + "indexPatternManagement.createIndexPattern.step.indexPatternLabel": "インデックスパターン", + "indexPatternManagement.createIndexPattern.step.indexPatternPlaceholder": "index-name-*", + "indexPatternManagement.createIndexPattern.step.invalidCharactersErrorMessage": "{indexPatternName} にはスペースや {characterList} は使えません。", + "indexPatternManagement.createIndexPattern.step.loadingHeader": "一致するインデックスを検索中…", + "indexPatternManagement.createIndexPattern.step.loadingLabel": "お待ちください…", + "indexPatternManagement.createIndexPattern.step.nextStepButton": "次のステップ", + "indexPatternManagement.createIndexPattern.step.pagingLabel": "ページごとの行数: {perPage}", + "indexPatternManagement.createIndexPattern.step.status.matchAnyLabel.matchAnyDetail": "インデックスパターンは下の{strongIndices} の いずれかに一致します。", + "indexPatternManagement.createIndexPattern.step.status.noSystemIndicesLabel": "パターンに一致する Elasticsearch インデックスがありません。", + "indexPatternManagement.createIndexPattern.step.status.noSystemIndicesWithPromptLabel": "パターンに一致する Elasticsearch インデックスがありません。一致するシステムインデックスを表示するには、右上のスイッチを切り替えます。", + "indexPatternManagement.createIndexPattern.step.status.notMatchLabel.allIndicesLabel": "{indicesLength, plural, one {# インデックス} other {# インデックス}}", + "indexPatternManagement.createIndexPattern.step.status.notMatchLabel.notMatchDetail": "入力されたインデックスパターンがどのインデックスにも一致しません。下の {indicesLength, plural, one {} other {}}{strongIndices} と一致させることができます。", + "indexPatternManagement.createIndexPattern.step.status.partialMatchLabel.partialMatchDetail": "インデックスパターンがどのインデックスとも一致ませんが、似た {matchedIndicesLength, plural, one {} other {}}{strongIndices} があります。", + "indexPatternManagement.createIndexPattern.step.status.partialMatchLabel.strongIndicesLabel": "{matchedIndicesLength, plural, one {# インデックス} other {# インデックス}}", + "indexPatternManagement.createIndexPattern.step.status.successLabel.strongIndicesLabel": "{indicesLength, plural, one {# インデックス} other {# インデックス}}", + "indexPatternManagement.createIndexPattern.step.status.successLabel.strongSuccessLabel": "成功!", + "indexPatternManagement.createIndexPattern.step.status.successLabel.successDetail": "{strongSuccess} インデックスパターンが {strongIndices} と一致しています。", + "indexPatternManagement.createIndexPattern.step.warningHeader": "既に {query} という名前のインデックスパターンがあります。", + "indexPatternManagement.createIndexPattern.stepHeader": "ステップ 1/2:インデックスパターンの定義", + "indexPatternManagement.createIndexPattern.stepTime.backButton": "戻る", + "indexPatternManagement.createIndexPattern.stepTime.createPatternButton": "インデックスパターンを作成", + "indexPatternManagement.createIndexPattern.stepTime.creatingLabel": "インデックスパターンを作成中…", + "indexPatternManagement.createIndexPattern.stepTime.error": "エラー", + "indexPatternManagement.createIndexPattern.stepTime.field.loadingDropDown": "読み込み中…", + "indexPatternManagement.createIndexPattern.stepTime.field.noTimeFieldsLabel": "このインデックスパターンに一致するインデックスには時間フィールドがありません。", + "indexPatternManagement.createIndexPattern.stepTime.fieldHeader": "時間フィルターのフィールド名", + "indexPatternManagement.createIndexPattern.stepTime.fieldLabel": "時間フィルターはこのフィールドを使って時間でフィールドを絞ります。", + "indexPatternManagement.createIndexPattern.stepTime.fieldWarningLabel": "時間フィールドを使わないこともできますが、その場合データを時間範囲で絞ることができません。", + "indexPatternManagement.createIndexPattern.stepTime.noTimeFieldOptionLabel": "時間フィルターを使用しない", + "indexPatternManagement.createIndexPattern.stepTime.noTimeFieldsLabel": "このインデックスパターンに一致するインデックスには時間フィールドがありません。", + "indexPatternManagement.createIndexPattern.stepTime.options.hideButton": "高度なオプションを非表示", + "indexPatternManagement.createIndexPattern.stepTime.options.patternHeader": "カスタムインデックスパターン ID", + "indexPatternManagement.createIndexPattern.stepTime.options.patternLabel": "Kibana はそれぞれのインデックスパターンに固有の識別子を割り当てます。固有 ID を使用しない場合は、カスタム ID を入力してください。", + "indexPatternManagement.createIndexPattern.stepTime.options.patternPlaceholder": "custom-index-pattern-id", + "indexPatternManagement.createIndexPattern.stepTime.options.showButton": "高度なオプションを表示", + "indexPatternManagement.createIndexPattern.stepTime.patterAlreadyExists": "カスタムインデックスパターン ID が既に存在します。", + "indexPatternManagement.createIndexPattern.stepTime.refreshButton": "更新", + "indexPatternManagement.createIndexPattern.stepTimeHeader": "ステップ 2/2:設定の変更", + "indexPatternManagement.createIndexPattern.stepTimeLabel": "{indexPattern} を {indexPatternName} に定義しました。次に、作成前に他の設定を行うことができます。", + "indexPatternManagement.createIndexPatternHeader": "{indexPatternName} の作成", + "indexPatternManagement.createIndexPatternLabel": "Kibana は、可視化などを目的に Elasticsearch インデックスからデータを取得するために、インデックスパターンを使用します。", + "indexPatternManagement.editIndexPattern.deleteButton": "削除", + "indexPatternManagement.editIndexPattern.deleteHeader": "インデックスパターンを削除しますか?", + "indexPatternManagement.editIndexPattern.detailsAria": "インデックスパターンの詳細", + "indexPatternManagement.editIndexPattern.fields.allLangsDropDown": "すべての言語", + "indexPatternManagement.editIndexPattern.fields.allTypesDropDown": "すべてのフィールドタイプ", + "indexPatternManagement.editIndexPattern.fields.filterAria": "フィルター", + "indexPatternManagement.editIndexPattern.fields.filterPlaceholder": "フィルター", + "indexPatternManagement.editIndexPattern.fields.table.additionalInfoAriaLabel": "追加フィールド情報", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableDescription": "これらのフィールドはビジュアライゼーションの集約に使用できます", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableLabel": "集約可能", + "indexPatternManagement.editIndexPattern.fields.table.editDescription": "編集", + "indexPatternManagement.editIndexPattern.fields.table.editLabel": "編集", + "indexPatternManagement.editIndexPattern.fields.table.excludedDescription": "取得の際に _source から除外されるフィールドです", + "indexPatternManagement.editIndexPattern.fields.table.excludedLabel": "除外", + "indexPatternManagement.editIndexPattern.fields.table.formatHeader": "フォーマット", + "indexPatternManagement.editIndexPattern.fields.table.isAggregatableAria": "は集約可能です", + "indexPatternManagement.editIndexPattern.fields.table.isExcludedAria": "は除外されています", + "indexPatternManagement.editIndexPattern.fields.table.isSearchableAria": "は検索可能です", + "indexPatternManagement.editIndexPattern.fields.table.multiTypeAria": "複数タイプのフィールド", + "indexPatternManagement.editIndexPattern.fields.table.multiTypeTooltip": "フィールドのタイプがインデックスごとに変わります。多くの分析機能には使用できません。", + "indexPatternManagement.editIndexPattern.fields.table.nameHeader": "名前", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeAriaLabel": "プライマリ時間フィールド", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeTooltip": "このフィールドはイベントの発生時刻を表します。", + "indexPatternManagement.editIndexPattern.fields.table.searchableDescription": "これらのフィールドはフィルターバーで使用できます", + "indexPatternManagement.editIndexPattern.fields.table.searchableHeader": "検索可能", + "indexPatternManagement.editIndexPattern.fields.table.typeHeader": "タイプ", + "indexPatternManagement.editIndexPattern.mappingConflictHeader": "マッピングの矛盾", + "indexPatternManagement.editIndexPattern.mappingConflictLabel": "{conflictFieldsLength, plural, one {フィールドが} other {# フィールドが}}このパターンと一致するインデックスの間で異なるタイプ (文字列、整数など) に定義されています。これらの矛盾したフィールドは Kibana の一部で使用できますが、Kibana がタイプを把握しなければならない機能には使用できません。この問題を修正するにはデータのレンダリングが必要です。", + "indexPatternManagement.editIndexPattern.refreshAria": "フィールドリストを再度読み込みます", + "indexPatternManagement.editIndexPattern.refreshButton": "更新", + "indexPatternManagement.editIndexPattern.refreshHeader": "フィールドリストを更新しますか?", + "indexPatternManagement.editIndexPattern.refreshLabel": "この操作は各フィールドの使用頻度をリセットします。", + "indexPatternManagement.editIndexPattern.refreshTooltip": "フィールドリストを更新", + "indexPatternManagement.editIndexPattern.removeAria": "インデックスパターンを削除", + "indexPatternManagement.editIndexPattern.removeTooltip": "インデックスパターンを削除います", + "indexPatternManagement.editIndexPattern.scripted.addFieldButton": "スクリプトフィールドを追加", + "indexPatternManagement.editIndexPattern.scripted.deleteField.cancelButton": "キャンセル", + "indexPatternManagement.editIndexPattern.scripted.deleteField.deleteButton": "削除", + "indexPatternManagement.editIndexPattern.scripted.deleteFieldLabel": "スクリプトフィールド「{fieldName}」を削除しますか?", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangHeader": "廃止された言語が使用されています", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "次の廃止された言語が使用されています: {deprecatedLangsInUse}これらの言語は、Kibana と Elasticsearch の次のメジャーなバージョンでサポートされなくなります。問題を避けるため、スクリプトフィールドを {link} に変換してください。", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "パターン", + "indexPatternManagement.editIndexPattern.scripted.newFieldPlaceholder": "新規スクリプトフィールド", + "indexPatternManagement.editIndexPattern.scripted.noFieldLabel": "「{indexPatternTitle}」インデックスパターンには「{fieldName}」というスクリプトフィールドがありません", + "indexPatternManagement.editIndexPattern.scripted.table.deleteDescription": "このフィールドを削除します", + "indexPatternManagement.editIndexPattern.scripted.table.deleteHeader": "削除", + "indexPatternManagement.editIndexPattern.scripted.table.editDescription": "このフィールドを編集します", + "indexPatternManagement.editIndexPattern.scripted.table.editHeader": "編集", + "indexPatternManagement.editIndexPattern.scripted.table.formatDescription": "フィールドに使用されているフォーマットです", + "indexPatternManagement.editIndexPattern.scripted.table.formatHeader": "フォーマット", + "indexPatternManagement.editIndexPattern.scripted.table.langDescription": "フィールドに使用されている言語です", + "indexPatternManagement.editIndexPattern.scripted.table.langHeader": "言語", + "indexPatternManagement.editIndexPattern.scripted.table.nameDescription": "フィールドの名前です", + "indexPatternManagement.editIndexPattern.scripted.table.nameHeader": "名前", + "indexPatternManagement.editIndexPattern.scripted.table.scriptDescription": "フィールドのスクリプトです", + "indexPatternManagement.editIndexPattern.scripted.table.scriptHeader": "スクリプト", + "indexPatternManagement.editIndexPattern.scriptedHeader": "スクリプトフィールド", + "indexPatternManagement.editIndexPattern.scriptedLabel": "ビジュアライゼーションにスクリプトフィールドを使用し、ドキュメントに表示させることができます。但し、スクリプトフィールドは検索できません。", + "indexPatternManagement.editIndexPattern.setDefaultAria": "デフォルトのインデックスに設定", + "indexPatternManagement.editIndexPattern.setDefaultTooltip": "デフォルトのインデックスに設定します", + "indexPatternManagement.editIndexPattern.source.addButtonLabel": "追加", + "indexPatternManagement.editIndexPattern.source.deleteFilter.cancelButtonLabel": "キャンセル", + "indexPatternManagement.editIndexPattern.source.deleteFilter.deleteButtonLabel": "削除", + "indexPatternManagement.editIndexPattern.source.deleteSourceFilterLabel": "ソースフィルター「{value}」を削除しますか?", + "indexPatternManagement.editIndexPattern.source.noteLabel": "下の表で、マルチフィールドが一致として誤って表示されます。これらのフィルターは、オリジナルのソースドキュメントの\\フィールドのみに適用されるため、一致するマルチフィールドはフィルタリングされません。", + "indexPatternManagement.editIndexPattern.source.table.cancelAria": "キャンセル", + "indexPatternManagement.editIndexPattern.source.table.deleteAria": "削除", + "indexPatternManagement.editIndexPattern.source.table.editAria": "編集", + "indexPatternManagement.editIndexPattern.source.table.filterDescription": "フィルター名", + "indexPatternManagement.editIndexPattern.source.table.filterHeader": "フィルター", + "indexPatternManagement.editIndexPattern.source.table.matchesDescription": "フィールドに使用されている言語です", + "indexPatternManagement.editIndexPattern.source.table.matchesHeader": "一致", + "indexPatternManagement.editIndexPattern.source.table.notMatchedLabel": "ソースフィルターが既知のフィールドと一致しません。", + "indexPatternManagement.editIndexPattern.source.table.saveAria": "保存", + "indexPatternManagement.editIndexPattern.sourceHeader": "ソースフィルター", + "indexPatternManagement.editIndexPattern.sourceLabel": "ソースフィルターは、ドキュメントソースの取得時に 1 つまたは複数のフィールドを除外するのに使用される場合もあります。これはディスカバリアプリでのドキュメントの表示中、またはダッシュボードアプリの保存された検索の結果を表示する表で起こります。それぞれの行は 1 つのドキュメントのソースで作成されており、ドキュメントに大きなフィールドや重要ではないフィールドが含まれている場合、このレベルでフィルターで除外すると良いかもしれません。", + "indexPatternManagement.editIndexPattern.sourcePlaceholder": "ソースフィルター、ワイルドカード使用可 (例: 「user」と入力して「user」で始まるフィールドをフィルタリング)", + "indexPatternManagement.editIndexPattern.tabs.fieldsHeader": "フィールド", + "indexPatternManagement.editIndexPattern.tabs.scriptedHeader": "スクリプトフィールド", + "indexPatternManagement.editIndexPattern.tabs.sourceHeader": "ソースフィルター", + "indexPatternManagement.editIndexPattern.timeFilterHeader": "時間フィルターフィールド名: {timeFieldName}", + "indexPatternManagement.editIndexPattern.timeFilterLabel.mappingAPILink": "マッピング API", + "indexPatternManagement.editIndexPattern.timeFilterLabel.timeFilterDetail": "このページは {indexPatternTitle} インデックス内のすべてのフィールドと、Elasticsearch に記録された各フィールドのコアタイプを一覧表示します。フィールドタイプを変更するには Elasticsearch を使用します", + "indexPatternManagement.editIndexPatternLiveRegionAriaLabel": "インデックスパターン", + "indexPatternManagement.indexPattern.goToPatternButtonLabel": "既存のパターンに移動", + "indexPatternManagement.indexPattern.sectionsHeader": "インデックスパターン", + "indexPatternManagement.indexPattern.titleExistsLabel": "「{title}」というタイトルのインデックスパターンが既に存在します。", + "indexPatternManagement.indexPatternList.createButton.betaLabel": "ベータ", + "indexPatternManagement.indexPatternPrompt.exampleOne": "チャートを作成したりコンテンツを素早くクエリできるように log-west-001 という名前の単一のデータソースをインデックスします。", + "indexPatternManagement.indexPatternPrompt.exampleOneTitle": "単一のデータソース", + "indexPatternManagement.indexPatternPrompt.examplesTitle": "インデックスパターンの例", + "indexPatternManagement.indexPatternPrompt.exampleThree": "比較目的に履歴の動向を集約できるよう、これらのログのアーカイブされた月々のロールアップメトリックスを指定通りに別々のインデックスパターンにグループ分けします。", + "indexPatternManagement.indexPatternPrompt.exampleThreeTitle": "カスタムグルーピング", + "indexPatternManagement.indexPatternPrompt.exampleTwo": "すべての西海岸のサーバーログに対してクエリを実行できるように、頭に「log-west」の付いたすべての受信データソースをグループ化します。", + "indexPatternManagement.indexPatternPrompt.exampleTwoTitle": "複数データソース", + "indexPatternManagement.indexPatternPrompt.subtitle": "インデックスパターンは、Kibana で共有フィールドにクエリを実行できるよう、種類の異なるデータソースをバケットにまとめることができます。", + "indexPatternManagement.indexPatternPrompt.title": "インデックスパターンについて", + "indexPatternManagement.indexPatterns.badge.readOnly.text": "読み込み専用", + "indexPatternManagement.indexPatterns.badge.readOnly.tooltip": "インデックスパターンを保存できません", + "indexPatternManagement.indexPatterns.createBreadcrumb": "インデックスパターンを作成", + "indexPatternManagement.indexPatterns.createFieldBreadcrumb": "フィールドを作成", + "indexPatternManagement.indexPatterns.listBreadcrumb": "インデックスパターン", + "indexPatternManagement.indexPatternTable.createBtn": "インデックスパターンの作成", + "indexPatternManagement.indexPatternTable.title": "インデックスパターン", "kbn.management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。", "kbn.management.landing.text": "すべてのツールの一覧は、左のメニューにあります。", "kbn.managementTitle": "管理", @@ -13152,7 +13152,6 @@ "xpack.siem.case.configureCases.incidentManagementSystemLabel": "インシデント管理システム", "xpack.siem.case.configureCases.incidentManagementSystemTitle": "サードパーティのインシデント管理システムに接続", "xpack.siem.case.configureCases.noConnector": "コネクターを選択していません", - "xpack.siem.case.configureCases.saveChangesButton": "変更を保存", "xpack.siem.case.configureCases.updateConnector": "コネクターを更新", "xpack.siem.case.configureCases.warningMessage": "構成が無効のようです。選択したコネクターが見つかりませんコネクターを削除しましたか?", "xpack.siem.case.configureCases.warningTitle": "警告", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 954162647bf83..ed94278db6035 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -150,139 +150,139 @@ "common.ui.errorUrlOverflow.howTofixError.removeStuffFromDashboardText": "从您的仪表板中删除一些内容。这回减小 URL 的长度,使 IE 能够处理它。", "common.ui.errorUrlOverflow.howTofixErrorDescription": "通常只有较大的、复杂的仪表板会发生此问题,因此您会有一些选项:", "common.ui.errorUrlOverflow.howTofixErrorTitle": "那么,我如何解决此问题?", - "common.ui.fieldEditor.actions.cancelButton": "取消", - "common.ui.fieldEditor.actions.createButton": "创建字段", - "common.ui.fieldEditor.actions.deleteButton": "删除", - "common.ui.fieldEditor.actions.saveButton": "保存字段", - "common.ui.fieldEditor.color.addColorButton": "添加颜色", - "common.ui.fieldEditor.color.backgroundLabel": "背景色", - "common.ui.fieldEditor.color.deleteAria": "删除", - "common.ui.fieldEditor.color.deleteTitle": "删除颜色格式", - "common.ui.fieldEditor.color.exampleLabel": "示例", - "common.ui.fieldEditor.color.patternLabel": "模式(正则表达式)", - "common.ui.fieldEditor.color.rangeLabel": "范围(最小值:最大值)", - "common.ui.fieldEditor.color.textColorLabel": "文本颜色", - "common.ui.fieldEditor.createHeader": "创建脚本字段", - "common.ui.fieldEditor.date.documentationLabel": "文档", - "common.ui.fieldEditor.date.momentLabel": "Moment.js 格式模式(默认值:{defaultPattern})", - "common.ui.fieldEditor.defaultErrorMessage": "尝试使用此格式配置时发生错误:{message}", - "common.ui.fieldEditor.defaultFormatDropDown": "- 默认值 -", - "common.ui.fieldEditor.defaultFormatHeader": "格式(默认值:{defaultFormat})", - "common.ui.fieldEditor.deleteField.cancelButton": "取消", - "common.ui.fieldEditor.deleteField.deleteButton": "删除", - "common.ui.fieldEditor.deleteField.deletedHeader": "已删除 “{fieldName}”", - "common.ui.fieldEditor.deleteField.savedHeader": "已保存 “{fieldName}”", - "common.ui.fieldEditor.deleteFieldHeader": "删除字段 “{fieldName}”", - "common.ui.fieldEditor.deleteFieldLabel": "您无法恢复已删除字段。{separator}确定要执行此操作?", - "common.ui.fieldEditor.disabledCallOutHeader": "脚本已禁用", - "common.ui.fieldEditor.disabledCallOutLabel": "所有内联脚本在 Elasticsearch 中已禁用。必须至少为一种语言启用内联脚本,才能在 Kibana 中使用脚本字段。", - "common.ui.fieldEditor.duration.decimalPlacesLabel": "小数位数", - "common.ui.fieldEditor.duration.inputFormatLabel": "输入格式", - "common.ui.fieldEditor.duration.outputFormatLabel": "输出格式", - "common.ui.fieldEditor.durationErrorMessage": "小数位数必须介于 0 和 20 之间", - "common.ui.fieldEditor.editHeader": "编辑“{fieldName}", - "common.ui.fieldEditor.fieldTypeConflict": "字段类型冲突", - "common.ui.fieldEditor.formatHeader": "格式", - "common.ui.fieldEditor.formatLabel": "设置格式允许您控制特定值的显示方式。其还会导致值完全更改, 并阻止 Discover 中的突出显示起作用。", - "common.ui.fieldEditor.indexNameLabel": "索引名称", - "common.ui.fieldEditor.labelTemplate.example.idLabel": "用户 #{value}", - "common.ui.fieldEditor.labelTemplate.example.output.idLabel": "用户", - "common.ui.fieldEditor.labelTemplate.example.output.pathLabel": "查看资产", - "common.ui.fieldEditor.labelTemplate.example.pathLabel": "查看资产", - "common.ui.fieldEditor.labelTemplate.examplesHeader": "示例", - "common.ui.fieldEditor.labelTemplate.inputHeader": "输入", - "common.ui.fieldEditor.labelTemplate.labelHeader": "标签模板", - "common.ui.fieldEditor.labelTemplate.outputHeader": "输出", - "common.ui.fieldEditor.labelTemplate.urlHeader": "URL 模板", - "common.ui.fieldEditor.labelTemplate.urlLabel": "格式化 URL", - "common.ui.fieldEditor.labelTemplate.valueLabel": "字段值", - "common.ui.fieldEditor.labelTemplateHeader": "标签模板", - "common.ui.fieldEditor.labelTemplateLabel": "如果此字段中的 URL 很长,为 URL 的文本版提供备选模板可能会很有用。该文本将会显示,而非显示该 url,但仍会链接到该 URL。该格式是使用双大括号表示法 {doubleCurlyBraces} 来注入值的字符串。可以访问以下值:", - "common.ui.fieldEditor.languageLabel": "语言", - "common.ui.fieldEditor.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} 您已有名称为 “{fieldName}” 的字段。使用相同的名称命名您的脚本字段意味着您将无法同时查找两个字段。", - "common.ui.fieldEditor.mappingConflictLabel.mappingConflictLabel": "映射冲突:", - "common.ui.fieldEditor.multiTypeLabelDesc": "此字段的类型在不同的索引中会有所不同。其不可用于许多分析功能。每个类型的索引如下所示:", - "common.ui.fieldEditor.nameErrorMessage": "“名称”必填", - "common.ui.fieldEditor.nameLabel": "名称", - "common.ui.fieldEditor.namePlaceholder": "新建脚本字段", - "common.ui.fieldEditor.number.documentationLabel": "文档", - "common.ui.fieldEditor.number.numeralLabel": "Numeral.js 格式模式(默认值:{defaultPattern})", - "common.ui.fieldEditor.popularityLabel": "常用度", - "common.ui.fieldEditor.samples.inputHeader": "输入", - "common.ui.fieldEditor.samples.outputHeader": "输出", - "common.ui.fieldEditor.samplesHeader": "样例", - "common.ui.fieldEditor.script.accessWithLabel": "使用 {code} 访问字段。", - "common.ui.fieldEditor.script.getHelpLabel": "获取该语法的帮助,预览脚本的结果。", - "common.ui.fieldEditor.scriptInvalidErrorMessage": "脚本无效。查看脚本预览以了解详情", - "common.ui.fieldEditor.scriptLabel": "脚本", - "common.ui.fieldEditor.scriptRequiredErrorMessage": "“脚本”必填", - "common.ui.fieldEditor.staticLookup.addEntryButton": "添加条目", - "common.ui.fieldEditor.staticLookup.deleteAria": "删除", - "common.ui.fieldEditor.staticLookup.deleteTitle": "删除条目", - "common.ui.fieldEditor.staticLookup.keyLabel": "键", - "common.ui.fieldEditor.staticLookup.leaveBlankPlaceholder": "留空可使值保持原样", - "common.ui.fieldEditor.staticLookup.unknownKeyLabel": "未知键的值", - "common.ui.fieldEditor.staticLookup.valueLabel": "值", - "common.ui.fieldEditor.string.transformLabel": "转换", - "common.ui.fieldEditor.syntax.default.formatLabel": "doc['some_field'].value", - "common.ui.fieldEditor.syntax.defaultLabel.defaultDetail": "默认情况下,Kibana 脚本字段使用 {painless}(一种简单且安全的脚本语言,专用于 Elasticsearch)通过以下格式访问文档中的值:", - "common.ui.fieldEditor.syntax.defaultLabel.painlessLink": "Painless", - "common.ui.fieldEditor.syntax.kibanaLabel": "Kibana 当前对您编写的 Painless 脚本强加一个特殊限制。它们不能包含命名函数。", - "common.ui.fieldEditor.syntax.lucene.commonLabel.commonDetail": "来自较旧的 Kibana 版本?您了解并喜爱的 {lucene} 仍可用。Lucene 表达式很像 JavaScript,但仅限于基本的算术、位和比较运算。", - "common.ui.fieldEditor.syntax.lucene.commonLabel.luceneLink": "Lucene 表达式", - "common.ui.fieldEditor.syntax.lucene.limits.fieldsLabel": "存储字段不可用", - "common.ui.fieldEditor.syntax.lucene.limits.sparseLabel": "如果字段为稀疏字段(仅某些文档包含值),则缺失该字段的文档将具有 0 值", - "common.ui.fieldEditor.syntax.lucene.limits.typesLabel": "仅数值、布尔值、日期和 geo_point 字段可以访问", - "common.ui.fieldEditor.syntax.lucene.limitsLabel": "使用 Lucene 表达式时有一些限制:", - "common.ui.fieldEditor.syntax.lucene.operations.arithmeticLabel": "算术运算符:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.bitwiseLabel": "位运算符:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.booleanLabel": "布尔运算符(包括三元运算符):{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.comparisonLabel": "比较运算符:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.distanceLabel": "距离函数:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.mathLabel": "常用数学函数:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.miscellaneousLabel": "其他函数:{operators}", - "common.ui.fieldEditor.syntax.lucene.operations.trigLabel": "三角库函数:{operators}", - "common.ui.fieldEditor.syntax.lucene.operationsLabel": "以下是可用于 lucene 表达式的所有运算:", - "common.ui.fieldEditor.syntax.painlessLabel.javaAPIsLink": "原生 Java API", - "common.ui.fieldEditor.syntax.painlessLabel.painlessDetail": "Painless 功能强大但却易于使用。通过它,可访问很多 {javaAPIs}。研读其 {syntax},您将很快上手!", - "common.ui.fieldEditor.syntax.painlessLabel.syntaxLink": "语法", - "common.ui.fieldEditor.syntaxHeader": "语法", - "common.ui.fieldEditor.testScript.errorMessage": "您的脚本中有错误", - "common.ui.fieldEditor.testScript.fieldsLabel": "其他字段", - "common.ui.fieldEditor.testScript.fieldsPlaceholder": "选择......", - "common.ui.fieldEditor.testScript.instructions": "运行您的脚本以预览前 10 个结果。还可以选择其他字段包括在您的结果中,以获取更多上下文,或添加查询以在特定文档上进行筛选。", - "common.ui.fieldEditor.testScript.resultsLabel": "前 10 个结果", - "common.ui.fieldEditor.testScript.resultsTitle": "预览结果", - "common.ui.fieldEditor.testScript.submitButtonLabel": "运行脚本", - "common.ui.fieldEditor.truncate.lengthLabel": "字段长度", - "common.ui.fieldEditor.typeLabel": "类型", - "common.ui.fieldEditor.url.heightLabel": "高", - "common.ui.fieldEditor.url.labelTemplateHelpText": "标签模板帮助", - "common.ui.fieldEditor.url.labelTemplateLabel": "标签模板", - "common.ui.fieldEditor.url.offLabel": "关闭", - "common.ui.fieldEditor.url.onLabel": "开启", - "common.ui.fieldEditor.url.openTabLabel": "在新选项卡中打开", - "common.ui.fieldEditor.url.template.helpLinkText": "URL 模板帮助", - "common.ui.fieldEditor.url.typeLabel": "类型", - "common.ui.fieldEditor.url.urlTemplateLabel": "URL 模板", - "common.ui.fieldEditor.url.widthLabel": "宽", - "common.ui.fieldEditor.urlTemplate.examplesHeader": "示例", - "common.ui.fieldEditor.urlTemplate.inputHeader": "输入", - "common.ui.fieldEditor.urlTemplate.outputHeader": "输出", - "common.ui.fieldEditor.urlTemplate.rawValueLabel": "非转义值", - "common.ui.fieldEditor.urlTemplate.templateHeader": "模板", - "common.ui.fieldEditor.urlTemplate.valueLabel": "URI 转义值", - "common.ui.fieldEditor.urlTemplateHeader": "Url 模板", - "common.ui.fieldEditor.urlTemplateLabel.fieldDetail": "如果字段仅包含 URL 的一部分,则 {strongUrlTemplate} 可用于将该值格式化为完整的 URL。该格式是使用双大括号表示法 {doubleCurlyBraces} 来注入值的字符串。可以访问以下值:", - "common.ui.fieldEditor.urlTemplateLabel.strongUrlTemplateLabel": "Url 模板", - "common.ui.fieldEditor.warningCallOut.descriptionLabel": "脚本字段可用于显示并聚合计算值。他们本身会很慢,如果操作不当,会导致 Kibana 不可用。此处没有安全网。如果拼写错误,任何地方都会引发意外异常!", - "common.ui.fieldEditor.warningCallOutHeader": "谨慎操作", - "common.ui.fieldEditor.warningCallOutLabel.callOutDetail": "请先熟悉{scripFields}以及{scriptsInAggregation},然后再使用脚本字段。", - "common.ui.fieldEditor.warningCallOutLabel.scripFieldsLink": "脚本字段", - "common.ui.fieldEditor.warningCallOutLabel.scriptsInAggregationLink": "聚合中的脚本", - "common.ui.fieldEditor.warningHeader": "弃用警告:", - "common.ui.fieldEditor.warningLabel.painlessLinkLabel": "Painless", - "common.ui.fieldEditor.warningLabel.warningDetail": "{language} 已弃用,Kibana 和 Elasticsearch 下一主要版本将移除对其的支持。建议将 {painlessLink} 用于新的脚本字段。", + "indexPatternManagement.actions.cancelButton": "取消", + "indexPatternManagement.actions.createButton": "创建字段", + "indexPatternManagement.actions.deleteButton": "删除", + "indexPatternManagement.actions.saveButton": "保存字段", + "indexPatternManagement.color.addColorButton": "添加颜色", + "indexPatternManagement.color.backgroundLabel": "背景色", + "indexPatternManagement.color.deleteAria": "删除", + "indexPatternManagement.color.deleteTitle": "删除颜色格式", + "indexPatternManagement.color.exampleLabel": "示例", + "indexPatternManagement.color.patternLabel": "模式(正则表达式)", + "indexPatternManagement.color.rangeLabel": "范围(最小值:最大值)", + "indexPatternManagement.color.textColorLabel": "文本颜色", + "indexPatternManagement.createHeader": "创建脚本字段", + "indexPatternManagement.date.documentationLabel": "文档", + "indexPatternManagement.date.momentLabel": "Moment.js 格式模式(默认值:{defaultPattern})", + "indexPatternManagement.defaultErrorMessage": "尝试使用此格式配置时发生错误:{message}", + "indexPatternManagement.defaultFormatDropDown": "- 默认值 -", + "indexPatternManagement.defaultFormatHeader": "格式(默认值:{defaultFormat})", + "indexPatternManagement.deleteField.cancelButton": "取消", + "indexPatternManagement.deleteField.deleteButton": "删除", + "indexPatternManagement.deleteField.deletedHeader": "已删除 “{fieldName}”", + "indexPatternManagement.deleteField.savedHeader": "已保存 “{fieldName}”", + "indexPatternManagement.deleteFieldHeader": "删除字段 “{fieldName}”", + "indexPatternManagement.deleteFieldLabel": "您无法恢复已删除字段。{separator}确定要执行此操作?", + "indexPatternManagement.disabledCallOutHeader": "脚本已禁用", + "indexPatternManagement.disabledCallOutLabel": "所有内联脚本在 Elasticsearch 中已禁用。必须至少为一种语言启用内联脚本,才能在 Kibana 中使用脚本字段。", + "indexPatternManagement.duration.decimalPlacesLabel": "小数位数", + "indexPatternManagement.duration.inputFormatLabel": "输入格式", + "indexPatternManagement.duration.outputFormatLabel": "输出格式", + "indexPatternManagement.durationErrorMessage": "小数位数必须介于 0 和 20 之间", + "indexPatternManagement.editHeader": "编辑“{fieldName}", + "indexPatternManagement.fieldTypeConflict": "字段类型冲突", + "indexPatternManagement.formatHeader": "格式", + "indexPatternManagement.formatLabel": "设置格式允许您控制特定值的显示方式。其还会导致值完全更改, 并阻止 Discover 中的突出显示起作用。", + "indexPatternManagement.indexNameLabel": "索引名称", + "indexPatternManagement.labelTemplate.example.idLabel": "用户 #{value}", + "indexPatternManagement.labelTemplate.example.output.idLabel": "用户", + "indexPatternManagement.labelTemplate.example.output.pathLabel": "查看资产", + "indexPatternManagement.labelTemplate.example.pathLabel": "查看资产", + "indexPatternManagement.labelTemplate.examplesHeader": "示例", + "indexPatternManagement.labelTemplate.inputHeader": "输入", + "indexPatternManagement.labelTemplate.labelHeader": "标签模板", + "indexPatternManagement.labelTemplate.outputHeader": "输出", + "indexPatternManagement.labelTemplate.urlHeader": "URL 模板", + "indexPatternManagement.labelTemplate.urlLabel": "格式化 URL", + "indexPatternManagement.labelTemplate.valueLabel": "字段值", + "indexPatternManagement.labelTemplateHeader": "标签模板", + "indexPatternManagement.labelTemplateLabel": "如果此字段中的 URL 很长,为 URL 的文本版提供备选模板可能会很有用。该文本将会显示,而非显示该 url,但仍会链接到该 URL。该格式是使用双大括号表示法 {doubleCurlyBraces} 来注入值的字符串。可以访问以下值:", + "indexPatternManagement.languageLabel": "语言", + "indexPatternManagement.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} 您已有名称为 “{fieldName}” 的字段。使用相同的名称命名您的脚本字段意味着您将无法同时查找两个字段。", + "indexPatternManagement.mappingConflictLabel.mappingConflictLabel": "映射冲突:", + "indexPatternManagement.multiTypeLabelDesc": "此字段的类型在不同的索引中会有所不同。其不可用于许多分析功能。每个类型的索引如下所示:", + "indexPatternManagement.nameErrorMessage": "“名称”必填", + "indexPatternManagement.nameLabel": "名称", + "indexPatternManagement.namePlaceholder": "新建脚本字段", + "indexPatternManagement.number.documentationLabel": "文档", + "indexPatternManagement.number.numeralLabel": "Numeral.js 格式模式(默认值:{defaultPattern})", + "indexPatternManagement.popularityLabel": "常用度", + "indexPatternManagement.samples.inputHeader": "输入", + "indexPatternManagement.samples.outputHeader": "输出", + "indexPatternManagement.samplesHeader": "样例", + "indexPatternManagement.script.accessWithLabel": "使用 {code} 访问字段。", + "indexPatternManagement.script.getHelpLabel": "获取该语法的帮助,预览脚本的结果。", + "indexPatternManagement.scriptInvalidErrorMessage": "脚本无效。查看脚本预览以了解详情", + "indexPatternManagement.scriptLabel": "脚本", + "indexPatternManagement.scriptRequiredErrorMessage": "“脚本”必填", + "indexPatternManagement.staticLookup.addEntryButton": "添加条目", + "indexPatternManagement.staticLookup.deleteAria": "删除", + "indexPatternManagement.staticLookup.deleteTitle": "删除条目", + "indexPatternManagement.staticLookup.keyLabel": "键", + "indexPatternManagement.staticLookup.leaveBlankPlaceholder": "留空可使值保持原样", + "indexPatternManagement.staticLookup.unknownKeyLabel": "未知键的值", + "indexPatternManagement.staticLookup.valueLabel": "值", + "indexPatternManagement.string.transformLabel": "转换", + "indexPatternManagement.syntax.default.formatLabel": "doc['some_field'].value", + "indexPatternManagement.syntax.defaultLabel.defaultDetail": "默认情况下,Kibana 脚本字段使用 {painless}(一种简单且安全的脚本语言,专用于 Elasticsearch)通过以下格式访问文档中的值:", + "indexPatternManagement.syntax.defaultLabel.painlessLink": "Painless", + "indexPatternManagement.syntax.kibanaLabel": "Kibana 当前对您编写的 Painless 脚本强加一个特殊限制。它们不能包含命名函数。", + "indexPatternManagement.syntax.lucene.commonLabel.commonDetail": "来自较旧的 Kibana 版本?您了解并喜爱的 {lucene} 仍可用。Lucene 表达式很像 JavaScript,但仅限于基本的算术、位和比较运算。", + "indexPatternManagement.syntax.lucene.commonLabel.luceneLink": "Lucene 表达式", + "indexPatternManagement.syntax.lucene.limits.fieldsLabel": "存储字段不可用", + "indexPatternManagement.syntax.lucene.limits.sparseLabel": "如果字段为稀疏字段(仅某些文档包含值),则缺失该字段的文档将具有 0 值", + "indexPatternManagement.syntax.lucene.limits.typesLabel": "仅数值、布尔值、日期和 geo_point 字段可以访问", + "indexPatternManagement.syntax.lucene.limitsLabel": "使用 Lucene 表达式时有一些限制:", + "indexPatternManagement.syntax.lucene.operations.arithmeticLabel": "算术运算符:{operators}", + "indexPatternManagement.syntax.lucene.operations.bitwiseLabel": "位运算符:{operators}", + "indexPatternManagement.syntax.lucene.operations.booleanLabel": "布尔运算符(包括三元运算符):{operators}", + "indexPatternManagement.syntax.lucene.operations.comparisonLabel": "比较运算符:{operators}", + "indexPatternManagement.syntax.lucene.operations.distanceLabel": "距离函数:{operators}", + "indexPatternManagement.syntax.lucene.operations.mathLabel": "常用数学函数:{operators}", + "indexPatternManagement.syntax.lucene.operations.miscellaneousLabel": "其他函数:{operators}", + "indexPatternManagement.syntax.lucene.operations.trigLabel": "三角库函数:{operators}", + "indexPatternManagement.syntax.lucene.operationsLabel": "以下是可用于 lucene 表达式的所有运算:", + "indexPatternManagement.syntax.painlessLabel.javaAPIsLink": "原生 Java API", + "indexPatternManagement.syntax.painlessLabel.painlessDetail": "Painless 功能强大但却易于使用。通过它,可访问很多 {javaAPIs}。研读其 {syntax},您将很快上手!", + "indexPatternManagement.syntax.painlessLabel.syntaxLink": "语法", + "indexPatternManagement.syntaxHeader": "语法", + "indexPatternManagement.testScript.errorMessage": "您的脚本中有错误", + "indexPatternManagement.testScript.fieldsLabel": "其他字段", + "indexPatternManagement.testScript.fieldsPlaceholder": "选择......", + "indexPatternManagement.testScript.instructions": "运行您的脚本以预览前 10 个结果。还可以选择其他字段包括在您的结果中,以获取更多上下文,或添加查询以在特定文档上进行筛选。", + "indexPatternManagement.testScript.resultsLabel": "前 10 个结果", + "indexPatternManagement.testScript.resultsTitle": "预览结果", + "indexPatternManagement.testScript.submitButtonLabel": "运行脚本", + "indexPatternManagement.truncate.lengthLabel": "字段长度", + "indexPatternManagement.typeLabel": "类型", + "indexPatternManagement.url.heightLabel": "高", + "indexPatternManagement.url.labelTemplateHelpText": "标签模板帮助", + "indexPatternManagement.url.labelTemplateLabel": "标签模板", + "indexPatternManagement.url.offLabel": "关闭", + "indexPatternManagement.url.onLabel": "开启", + "indexPatternManagement.url.openTabLabel": "在新选项卡中打开", + "indexPatternManagement.url.template.helpLinkText": "URL 模板帮助", + "indexPatternManagement.url.typeLabel": "类型", + "indexPatternManagement.url.urlTemplateLabel": "URL 模板", + "indexPatternManagement.url.widthLabel": "宽", + "indexPatternManagement.urlTemplate.examplesHeader": "示例", + "indexPatternManagement.urlTemplate.inputHeader": "输入", + "indexPatternManagement.urlTemplate.outputHeader": "输出", + "indexPatternManagement.urlTemplate.rawValueLabel": "非转义值", + "indexPatternManagement.urlTemplate.templateHeader": "模板", + "indexPatternManagement.urlTemplate.valueLabel": "URI 转义值", + "indexPatternManagement.urlTemplateHeader": "Url 模板", + "indexPatternManagement.urlTemplateLabel.fieldDetail": "如果字段仅包含 URL 的一部分,则 {strongUrlTemplate} 可用于将该值格式化为完整的 URL。该格式是使用双大括号表示法 {doubleCurlyBraces} 来注入值的字符串。可以访问以下值:", + "indexPatternManagement.urlTemplateLabel.strongUrlTemplateLabel": "Url 模板", + "indexPatternManagement.warningCallOut.descriptionLabel": "脚本字段可用于显示并聚合计算值。他们本身会很慢,如果操作不当,会导致 Kibana 不可用。此处没有安全网。如果拼写错误,任何地方都会引发意外异常!", + "indexPatternManagement.warningCallOutHeader": "谨慎操作", + "indexPatternManagement.warningCallOutLabel.callOutDetail": "请先熟悉{scripFields}以及{scriptsInAggregation},然后再使用脚本字段。", + "indexPatternManagement.warningCallOutLabel.scripFieldsLink": "脚本字段", + "indexPatternManagement.warningCallOutLabel.scriptsInAggregationLink": "聚合中的脚本", + "indexPatternManagement.warningHeader": "弃用警告:", + "indexPatternManagement.warningLabel.painlessLinkLabel": "Painless", + "indexPatternManagement.warningLabel.warningDetail": "{language} 已弃用,Kibana 和 Elasticsearch 下一主要版本将移除对其的支持。建议将 {painlessLink} 用于新的脚本字段。", "common.ui.flotCharts.aprLabel": "四月", "common.ui.flotCharts.augLabel": "八月", "common.ui.flotCharts.decLabel": "十二月", @@ -303,7 +303,7 @@ "common.ui.flotCharts.thuLabel": "周四", "common.ui.flotCharts.tueLabel": "周二", "common.ui.flotCharts.wedLabel": "周三", - "common.ui.scriptingLanguages.errorFetchingToastDescription": "从 Elasticsearch 获取可用的脚本语言时出错", + "indexPatternManagement.scriptingLanguages.errorFetchingToastDescription": "从 Elasticsearch 获取可用的脚本语言时出错", "common.ui.stateManagement.unableToParseUrlErrorMessage": "无法解析 URL", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "无法完整还原 URL,确保使用共享功能。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。", @@ -2100,164 +2100,164 @@ "kbn.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "默认 WMS 属性", "kbn.advancedSettings.visualizeEnableLabsText": "允许用户创建、查看和编辑实验性可视化。如果禁用,\n 仅被视为生产就绪的可视化可供用户使用。", "kbn.advancedSettings.visualizeEnableLabsTitle": "启用实验性可视化", - "kbn.management.createIndexPattern.betaLabel": "公测版", - "kbn.management.createIndexPattern.emptyState.checkDataButton": "检查新数据", - "kbn.management.createIndexPattern.emptyStateHeader": "找不到任何 Elasticsearch 数据", - "kbn.management.createIndexPattern.emptyStateLabel.emptyStateDetail": "{needToIndex}{learnHowLink}或{getStartedLink}", - "kbn.management.createIndexPattern.emptyStateLabel.getStartedLink": "开始使用一些样例数据集。", - "kbn.management.createIndexPattern.emptyStateLabel.learnHowLink": "了解操作方法", - "kbn.management.createIndexPattern.emptyStateLabel.needToIndexLabel": "您需要在 Elasticsearch 中索引一些数据后,才能创建索引模式。", - "kbn.management.createIndexPattern.includeSystemIndicesToggleSwitchLabel": "包括系统索引", - "kbn.management.createIndexPattern.loadClustersFailMsg": "无法加载远程集群", - "kbn.management.createIndexPattern.loadIndicesFailMsg": "无法加载索引", - "kbn.management.createIndexPattern.loadingState.checkingLabel": "正在检查 Elasticsearch 数据", - "kbn.management.createIndexPattern.step.indexPattern.allowLabel": "可以在索引模式中将 {asterisk} 用作通配符。", - "kbn.management.createIndexPattern.step.indexPattern.disallowLabel": "不能使用空格或字符 {characterList}。", - "kbn.management.createIndexPattern.step.indexPatternLabel": "索引模式", - "kbn.management.createIndexPattern.step.indexPatternPlaceholder": "index-name-*", - "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage": "“{indexPatternName} 不能包含空格或字符:{characterList}", - "kbn.management.createIndexPattern.step.loadingHeader": "正在寻找匹配的索引......", - "kbn.management.createIndexPattern.step.loadingLabel": "请稍候......", - "kbn.management.createIndexPattern.step.nextStepButton": "下一步", - "kbn.management.createIndexPattern.step.pagingLabel": "每页行数:{perPage}", - "kbn.management.createIndexPattern.step.status.matchAnyLabel.matchAnyDetail": "您的索引模式可以匹配以下 {strongIndices}中的任意一个。", - "kbn.management.createIndexPattern.step.status.noSystemIndicesLabel": "没有 Elasticsearch 索引匹配您的模式。", - "kbn.management.createIndexPattern.step.status.noSystemIndicesWithPromptLabel": "没有 Elasticsearch 索引匹配您的模式。要查看匹配的系统索引,请切换右上角的开关。", - "kbn.management.createIndexPattern.step.status.notMatchLabel.allIndicesLabel": "{indicesLength, plural, one {# 个索引} other {# 个索引}}", - "kbn.management.createIndexPattern.step.status.notMatchLabel.notMatchDetail": "输入的索引模式不匹配任何索引。可以匹配您的以下{indicesLength, plural, one {} other {任何}} {strongIndices}。", - "kbn.management.createIndexPattern.step.status.partialMatchLabel.partialMatchDetail": "您的索引模式不匹配任何索引,但您有 {strongIndices}{matchedIndicesLength, plural, one {看起来} other {看起来}}类似。", - "kbn.management.createIndexPattern.step.status.partialMatchLabel.strongIndicesLabel": "{matchedIndicesLength, plural, one {# 个索引} other {# 个索引}}", - "kbn.management.createIndexPattern.step.status.successLabel.strongIndicesLabel": "{indicesLength, plural, one {# 个索引} other {# 个索引}}", - "kbn.management.createIndexPattern.step.status.successLabel.strongSuccessLabel": "成功!", - "kbn.management.createIndexPattern.step.status.successLabel.successDetail": "{strongSuccess}您的索引模式匹配 {strongIndices}。", - "kbn.management.createIndexPattern.step.warningHeader": "已有索引模式称作“{query}”", - "kbn.management.createIndexPattern.stepHeader": "第 1 步(共 2 步):定义索引模式", - "kbn.management.createIndexPattern.stepTime.backButton": "上一步", - "kbn.management.createIndexPattern.stepTime.createPatternButton": "创建索引模式", - "kbn.management.createIndexPattern.stepTime.creatingLabel": "正在创建索引模式……", - "kbn.management.createIndexPattern.stepTime.error": "错误", - "kbn.management.createIndexPattern.stepTime.field.loadingDropDown": "正在加载……", - "kbn.management.createIndexPattern.stepTime.field.noTimeFieldsLabel": "匹配此索引模式的索引不包含任何时间字段。", - "kbn.management.createIndexPattern.stepTime.fieldHeader": "时间筛选字段名称", - "kbn.management.createIndexPattern.stepTime.fieldLabel": "时间筛选将使用此字段按时间筛选您的数据。", - "kbn.management.createIndexPattern.stepTime.fieldWarningLabel": "您可以选择不使用时间字段,但将无法通过时间范围缩小您的数据范围。", - "kbn.management.createIndexPattern.stepTime.noTimeFieldOptionLabel": "我不想使用时间筛选", - "kbn.management.createIndexPattern.stepTime.noTimeFieldsLabel": "匹配此索引模式的索引不包含任何时间字段。", - "kbn.management.createIndexPattern.stepTime.options.hideButton": "隐藏高级选项", - "kbn.management.createIndexPattern.stepTime.options.patternHeader": "定制索引模式 ID", - "kbn.management.createIndexPattern.stepTime.options.patternLabel": "Kibana 将为每个索引模式提供唯一的标识符。如果不想使用此唯一 ID,请输入定制 ID。", - "kbn.management.createIndexPattern.stepTime.options.patternPlaceholder": "custom-index-pattern-id", - "kbn.management.createIndexPattern.stepTime.options.showButton": "显示高级选项", - "kbn.management.createIndexPattern.stepTime.patterAlreadyExists": "自定义索引模式 ID 已存在。", - "kbn.management.createIndexPattern.stepTime.refreshButton": "刷新", - "kbn.management.createIndexPattern.stepTimeHeader": "第 2 步(共 2 步):配置设置", - "kbn.management.createIndexPattern.stepTimeLabel": "您已将 “{indexPattern}” 定义为 “{indexPatternName}”。现在,在我们创建之前,您可以指定一些设置。", - "kbn.management.createIndexPatternHeader": "创建 {indexPatternName}", - "kbn.management.createIndexPatternLabel": "Kibana 使用索引模式从 Elasticsearch 索引中检索数据,以实现诸如可视化等功能。", - "kbn.management.editIndexPattern.deleteButton": "删除", - "kbn.management.editIndexPattern.deleteHeader": "删除索引模式?", - "kbn.management.editIndexPattern.detailsAria": "索引模式详细信息", - "kbn.management.editIndexPattern.fields.allLangsDropDown": "所有语言", - "kbn.management.editIndexPattern.fields.allTypesDropDown": "所有字段类型", - "kbn.management.editIndexPattern.fields.filterAria": "筛选", - "kbn.management.editIndexPattern.fields.filterPlaceholder": "筛选", - "kbn.management.editIndexPattern.fields.table.additionalInfoAriaLabel": "其他字段信息", - "kbn.management.editIndexPattern.fields.table.aggregatableDescription": "这些字段可用在可视化聚合中", - "kbn.management.editIndexPattern.fields.table.aggregatableLabel": "可聚合", - "kbn.management.editIndexPattern.fields.table.editDescription": "编辑", - "kbn.management.editIndexPattern.fields.table.editLabel": "编辑", - "kbn.management.editIndexPattern.fields.table.excludedDescription": "提取 _source 时从其中排除的字段", - "kbn.management.editIndexPattern.fields.table.excludedLabel": "已排除", - "kbn.management.editIndexPattern.fields.table.formatHeader": "格式", - "kbn.management.editIndexPattern.fields.table.isAggregatableAria": "可聚合", - "kbn.management.editIndexPattern.fields.table.isExcludedAria": "已排除", - "kbn.management.editIndexPattern.fields.table.isSearchableAria": "可搜索", - "kbn.management.editIndexPattern.fields.table.multiTypeAria": "多类型字段", - "kbn.management.editIndexPattern.fields.table.multiTypeTooltip": "此字段的类型在不同的索引中会有所不同。其不可用于许多分析功能。", - "kbn.management.editIndexPattern.fields.table.nameHeader": "名称", - "kbn.management.editIndexPattern.fields.table.primaryTimeAriaLabel": "主要时间字段", - "kbn.management.editIndexPattern.fields.table.primaryTimeTooltip": "此字段表示事件发生的时间。", - "kbn.management.editIndexPattern.fields.table.searchableDescription": "这些字段可用于筛选栏", - "kbn.management.editIndexPattern.fields.table.searchableHeader": "可搜索", - "kbn.management.editIndexPattern.fields.table.typeHeader": "类型", - "kbn.management.editIndexPattern.mappingConflictHeader": "映射冲突", - "kbn.management.editIndexPattern.mappingConflictLabel": "匹配此模式的各个索引中{conflictFieldsLength, plural, one {一个字段已} other {# 个字段已}}定义为若干类型(字符串、整数等)。您仍能够在 Kibana 的各个部分中使用这些冲突类型,但它们将无法用于需要 Kibana 知道其类型的函数。要解决此问题,需要重新索引您的数据。", - "kbn.management.editIndexPattern.refreshAria": "重新加载字段列表", - "kbn.management.editIndexPattern.refreshButton": "刷新", - "kbn.management.editIndexPattern.refreshHeader": "刷新字段列表?", - "kbn.management.editIndexPattern.refreshLabel": "此操作重置每个字段的常用度计数器。", - "kbn.management.editIndexPattern.refreshTooltip": "重新刷新字段列表", - "kbn.management.editIndexPattern.removeAria": "删除索引模式", - "kbn.management.editIndexPattern.removeTooltip": "删除索引模式", - "kbn.management.editIndexPattern.scripted.addFieldButton": "添加脚本字段", - "kbn.management.editIndexPattern.scripted.deleteField.cancelButton": "取消", - "kbn.management.editIndexPattern.scripted.deleteField.deleteButton": "删除", - "kbn.management.editIndexPattern.scripted.deleteFieldLabel": "删除脚本字段 “{fieldName}”?", - "kbn.management.editIndexPattern.scripted.deprecationLangHeader": "在用的弃用语言", - "kbn.management.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "以下已弃用语言正被使用:{deprecatedLangsInUse}。Kibana 和 Elasticsearch 下一主要版本将移除对这些语言的支持。将您的脚本字段转换成 {link} 以避免问题。", - "kbn.management.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "Painless", - "kbn.management.editIndexPattern.scripted.newFieldPlaceholder": "新建脚本字段", - "kbn.management.editIndexPattern.scripted.noFieldLabel": "“{indexPatternTitle}” 索引模式没有称作 “{fieldName}” 的脚本字段", - "kbn.management.editIndexPattern.scripted.table.deleteDescription": "删除此字段", - "kbn.management.editIndexPattern.scripted.table.deleteHeader": "删除", - "kbn.management.editIndexPattern.scripted.table.editDescription": "编辑此字段", - "kbn.management.editIndexPattern.scripted.table.editHeader": "编辑", - "kbn.management.editIndexPattern.scripted.table.formatDescription": "用于该字段的格式", - "kbn.management.editIndexPattern.scripted.table.formatHeader": "格式", - "kbn.management.editIndexPattern.scripted.table.langDescription": "用于该字段的语言", - "kbn.management.editIndexPattern.scripted.table.langHeader": "语言", - "kbn.management.editIndexPattern.scripted.table.nameDescription": "字段的名称", - "kbn.management.editIndexPattern.scripted.table.nameHeader": "名称", - "kbn.management.editIndexPattern.scripted.table.scriptDescription": "字段的脚本", - "kbn.management.editIndexPattern.scripted.table.scriptHeader": "脚本", - "kbn.management.editIndexPattern.scriptedHeader": "脚本字段", - "kbn.management.editIndexPattern.scriptedLabel": "可以在可视化中使用脚本字段,并在您的文档中显示它们。但是,您不能搜索脚本字段。", - "kbn.management.editIndexPattern.setDefaultAria": "设置为默认索引", - "kbn.management.editIndexPattern.setDefaultTooltip": "设置为默认索引", - "kbn.management.editIndexPattern.source.addButtonLabel": "添加", - "kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel": "取消", - "kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel": "删除", - "kbn.management.editIndexPattern.source.deleteSourceFilterLabel": "删除源筛选 “{value}”?", - "kbn.management.editIndexPattern.source.noteLabel": "请注意,多字段将错误地显示为下表中的匹配。这些筛选仅应用于原始源文档中的字段,因此实际未筛选匹配的多字段。", - "kbn.management.editIndexPattern.source.table.cancelAria": "取消", - "kbn.management.editIndexPattern.source.table.deleteAria": "删除", - "kbn.management.editIndexPattern.source.table.editAria": "编辑", - "kbn.management.editIndexPattern.source.table.filterDescription": "筛选名称", - "kbn.management.editIndexPattern.source.table.filterHeader": "筛选", - "kbn.management.editIndexPattern.source.table.matchesDescription": "用于该字段的语言", - "kbn.management.editIndexPattern.source.table.matchesHeader": "匹配", - "kbn.management.editIndexPattern.source.table.notMatchedLabel": "源筛选不匹配任何已知字段。", - "kbn.management.editIndexPattern.source.table.saveAria": "保存", - "kbn.management.editIndexPattern.sourceHeader": "源筛选", - "kbn.management.editIndexPattern.sourceLabel": "提取文档源时,源筛选可用于排除一个或多个字段。在 Discover 应用中查看文档时会发生此问题,表在 Dashboard 应用中显示已保存搜索的结果时也会发生此问题。每行使用单个文档的源进行生成,如果您具有含有较大或不重要字段的文档,则通过在此较低层级筛除这些字段会更好。", - "kbn.management.editIndexPattern.sourcePlaceholder": "源筛选,接受通配符(例如“user*”用于筛选以“user”开头的字段)", - "kbn.management.editIndexPattern.tabs.fieldsHeader": "字段", - "kbn.management.editIndexPattern.tabs.scriptedHeader": "脚本字段", - "kbn.management.editIndexPattern.tabs.sourceHeader": "源筛选", - "kbn.management.editIndexPattern.timeFilterHeader": "时间筛选字段名称:{timeFieldName}", - "kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink": "映射 API", - "kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail": "此页根据 Elasticsearch 的记录列出“{indexPatternTitle}”索引中的每个字段以及字段的关联核心类型。要更改字段类型,请使用 Elasticsearch", - "kbn.management.editIndexPatternLiveRegionAriaLabel": "索引模式", - "kbn.management.indexPattern.goToPatternButtonLabel": "前往现有模式", - "kbn.management.indexPattern.sectionsHeader": "索引模式", - "kbn.management.indexPattern.titleExistsLabel": "具有标题 “{title}” 的索引模式已存在。", - "kbn.management.indexPatternList.createButton.betaLabel": "公测版", - "kbn.management.indexPatternPrompt.exampleOne": "索引单个称作 log-west-001 的数据源,以便可以快速地构建图表或查询其内容。", - "kbn.management.indexPatternPrompt.exampleOneTitle": "单数据源", - "kbn.management.indexPatternPrompt.examplesTitle": "索引模式示例", - "kbn.management.indexPatternPrompt.exampleThree": "具体而言,将这些日志每月存档的汇总/打包指标分组成不同的索引模式,从而可以聚合历史趋势以进行比较。", - "kbn.management.indexPatternPrompt.exampleThreeTitle": "定制分组", - "kbn.management.indexPatternPrompt.exampleTwo": "分组以 log-west* 开头的所有传入数据源,以便可以查询所有所有西海岸服务器日志。", - "kbn.management.indexPatternPrompt.exampleTwoTitle": "多数据源", - "kbn.management.indexPatternPrompt.subtitle": "索引模式允许您将异类的数据源一起装入存储桶,从而可以在 Kibana 中查询它们共享的字段。", - "kbn.management.indexPatternPrompt.title": "关于索引模式", - "kbn.management.indexPatterns.badge.readOnly.text": "只读", - "kbn.management.indexPatterns.badge.readOnly.tooltip": "无法保存索引模式", - "kbn.management.indexPatterns.createBreadcrumb": "创建索引模式", - "kbn.management.indexPatterns.createFieldBreadcrumb": "创建字段", - "kbn.management.indexPatterns.listBreadcrumb": "索引模式", - "kbn.management.indexPatternTable.createBtn": "创建索引模式", - "kbn.management.indexPatternTable.title": "索引模式", + "indexPatternManagement.createIndexPattern.betaLabel": "公测版", + "indexPatternManagement.createIndexPattern.emptyState.checkDataButton": "检查新数据", + "indexPatternManagement.createIndexPattern.emptyStateHeader": "找不到任何 Elasticsearch 数据", + "indexPatternManagement.createIndexPattern.emptyStateLabel.emptyStateDetail": "{needToIndex}{learnHowLink}或{getStartedLink}", + "indexPatternManagement.createIndexPattern.emptyStateLabel.getStartedLink": "开始使用一些样例数据集。", + "indexPatternManagement.createIndexPattern.emptyStateLabel.learnHowLink": "了解操作方法", + "indexPatternManagement.createIndexPattern.emptyStateLabel.needToIndexLabel": "您需要在 Elasticsearch 中索引一些数据后,才能创建索引模式。", + "indexPatternManagement.createIndexPattern.includeSystemIndicesToggleSwitchLabel": "包括系统索引", + "indexPatternManagement.createIndexPattern.loadClustersFailMsg": "无法加载远程集群", + "indexPatternManagement.createIndexPattern.loadIndicesFailMsg": "无法加载索引", + "indexPatternManagement.createIndexPattern.loadingState.checkingLabel": "正在检查 Elasticsearch 数据", + "indexPatternManagement.createIndexPattern.step.indexPattern.allowLabel": "可以在索引模式中将 {asterisk} 用作通配符。", + "indexPatternManagement.createIndexPattern.step.indexPattern.disallowLabel": "不能使用空格或字符 {characterList}。", + "indexPatternManagement.createIndexPattern.step.indexPatternLabel": "索引模式", + "indexPatternManagement.createIndexPattern.step.indexPatternPlaceholder": "index-name-*", + "indexPatternManagement.createIndexPattern.step.invalidCharactersErrorMessage": "“{indexPatternName} 不能包含空格或字符:{characterList}", + "indexPatternManagement.createIndexPattern.step.loadingHeader": "正在寻找匹配的索引......", + "indexPatternManagement.createIndexPattern.step.loadingLabel": "请稍候......", + "indexPatternManagement.createIndexPattern.step.nextStepButton": "下一步", + "indexPatternManagement.createIndexPattern.step.pagingLabel": "每页行数:{perPage}", + "indexPatternManagement.createIndexPattern.step.status.matchAnyLabel.matchAnyDetail": "您的索引模式可以匹配以下 {strongIndices}中的任意一个。", + "indexPatternManagement.createIndexPattern.step.status.noSystemIndicesLabel": "没有 Elasticsearch 索引匹配您的模式。", + "indexPatternManagement.createIndexPattern.step.status.noSystemIndicesWithPromptLabel": "没有 Elasticsearch 索引匹配您的模式。要查看匹配的系统索引,请切换右上角的开关。", + "indexPatternManagement.createIndexPattern.step.status.notMatchLabel.allIndicesLabel": "{indicesLength, plural, one {# 个索引} other {# 个索引}}", + "indexPatternManagement.createIndexPattern.step.status.notMatchLabel.notMatchDetail": "输入的索引模式不匹配任何索引。可以匹配您的以下{indicesLength, plural, one {} other {任何}} {strongIndices}。", + "indexPatternManagement.createIndexPattern.step.status.partialMatchLabel.partialMatchDetail": "您的索引模式不匹配任何索引,但您有 {strongIndices}{matchedIndicesLength, plural, one {看起来} other {看起来}}类似。", + "indexPatternManagement.createIndexPattern.step.status.partialMatchLabel.strongIndicesLabel": "{matchedIndicesLength, plural, one {# 个索引} other {# 个索引}}", + "indexPatternManagement.createIndexPattern.step.status.successLabel.strongIndicesLabel": "{indicesLength, plural, one {# 个索引} other {# 个索引}}", + "indexPatternManagement.createIndexPattern.step.status.successLabel.strongSuccessLabel": "成功!", + "indexPatternManagement.createIndexPattern.step.status.successLabel.successDetail": "{strongSuccess}您的索引模式匹配 {strongIndices}。", + "indexPatternManagement.createIndexPattern.step.warningHeader": "已有索引模式称作“{query}”", + "indexPatternManagement.createIndexPattern.stepHeader": "第 1 步(共 2 步):定义索引模式", + "indexPatternManagement.createIndexPattern.stepTime.backButton": "上一步", + "indexPatternManagement.createIndexPattern.stepTime.createPatternButton": "创建索引模式", + "indexPatternManagement.createIndexPattern.stepTime.creatingLabel": "正在创建索引模式……", + "indexPatternManagement.createIndexPattern.stepTime.error": "错误", + "indexPatternManagement.createIndexPattern.stepTime.field.loadingDropDown": "正在加载……", + "indexPatternManagement.createIndexPattern.stepTime.field.noTimeFieldsLabel": "匹配此索引模式的索引不包含任何时间字段。", + "indexPatternManagement.createIndexPattern.stepTime.fieldHeader": "时间筛选字段名称", + "indexPatternManagement.createIndexPattern.stepTime.fieldLabel": "时间筛选将使用此字段按时间筛选您的数据。", + "indexPatternManagement.createIndexPattern.stepTime.fieldWarningLabel": "您可以选择不使用时间字段,但将无法通过时间范围缩小您的数据范围。", + "indexPatternManagement.createIndexPattern.stepTime.noTimeFieldOptionLabel": "我不想使用时间筛选", + "indexPatternManagement.createIndexPattern.stepTime.noTimeFieldsLabel": "匹配此索引模式的索引不包含任何时间字段。", + "indexPatternManagement.createIndexPattern.stepTime.options.hideButton": "隐藏高级选项", + "indexPatternManagement.createIndexPattern.stepTime.options.patternHeader": "定制索引模式 ID", + "indexPatternManagement.createIndexPattern.stepTime.options.patternLabel": "Kibana 将为每个索引模式提供唯一的标识符。如果不想使用此唯一 ID,请输入定制 ID。", + "indexPatternManagement.createIndexPattern.stepTime.options.patternPlaceholder": "custom-index-pattern-id", + "indexPatternManagement.createIndexPattern.stepTime.options.showButton": "显示高级选项", + "indexPatternManagement.createIndexPattern.stepTime.patterAlreadyExists": "自定义索引模式 ID 已存在。", + "indexPatternManagement.createIndexPattern.stepTime.refreshButton": "刷新", + "indexPatternManagement.createIndexPattern.stepTimeHeader": "第 2 步(共 2 步):配置设置", + "indexPatternManagement.createIndexPattern.stepTimeLabel": "您已将 “{indexPattern}” 定义为 “{indexPatternName}”。现在,在我们创建之前,您可以指定一些设置。", + "indexPatternManagement.createIndexPatternHeader": "创建 {indexPatternName}", + "indexPatternManagement.createIndexPatternLabel": "Kibana 使用索引模式从 Elasticsearch 索引中检索数据,以实现诸如可视化等功能。", + "indexPatternManagement.editIndexPattern.deleteButton": "删除", + "indexPatternManagement.editIndexPattern.deleteHeader": "删除索引模式?", + "indexPatternManagement.editIndexPattern.detailsAria": "索引模式详细信息", + "indexPatternManagement.editIndexPattern.fields.allLangsDropDown": "所有语言", + "indexPatternManagement.editIndexPattern.fields.allTypesDropDown": "所有字段类型", + "indexPatternManagement.editIndexPattern.fields.filterAria": "筛选", + "indexPatternManagement.editIndexPattern.fields.filterPlaceholder": "筛选", + "indexPatternManagement.editIndexPattern.fields.table.additionalInfoAriaLabel": "其他字段信息", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableDescription": "这些字段可用在可视化聚合中", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableLabel": "可聚合", + "indexPatternManagement.editIndexPattern.fields.table.editDescription": "编辑", + "indexPatternManagement.editIndexPattern.fields.table.editLabel": "编辑", + "indexPatternManagement.editIndexPattern.fields.table.excludedDescription": "提取 _source 时从其中排除的字段", + "indexPatternManagement.editIndexPattern.fields.table.excludedLabel": "已排除", + "indexPatternManagement.editIndexPattern.fields.table.formatHeader": "格式", + "indexPatternManagement.editIndexPattern.fields.table.isAggregatableAria": "可聚合", + "indexPatternManagement.editIndexPattern.fields.table.isExcludedAria": "已排除", + "indexPatternManagement.editIndexPattern.fields.table.isSearchableAria": "可搜索", + "indexPatternManagement.editIndexPattern.fields.table.multiTypeAria": "多类型字段", + "indexPatternManagement.editIndexPattern.fields.table.multiTypeTooltip": "此字段的类型在不同的索引中会有所不同。其不可用于许多分析功能。", + "indexPatternManagement.editIndexPattern.fields.table.nameHeader": "名称", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeAriaLabel": "主要时间字段", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeTooltip": "此字段表示事件发生的时间。", + "indexPatternManagement.editIndexPattern.fields.table.searchableDescription": "这些字段可用于筛选栏", + "indexPatternManagement.editIndexPattern.fields.table.searchableHeader": "可搜索", + "indexPatternManagement.editIndexPattern.fields.table.typeHeader": "类型", + "indexPatternManagement.editIndexPattern.mappingConflictHeader": "映射冲突", + "indexPatternManagement.editIndexPattern.mappingConflictLabel": "匹配此模式的各个索引中{conflictFieldsLength, plural, one {一个字段已} other {# 个字段已}}定义为若干类型(字符串、整数等)。您仍能够在 Kibana 的各个部分中使用这些冲突类型,但它们将无法用于需要 Kibana 知道其类型的函数。要解决此问题,需要重新索引您的数据。", + "indexPatternManagement.editIndexPattern.refreshAria": "重新加载字段列表", + "indexPatternManagement.editIndexPattern.refreshButton": "刷新", + "indexPatternManagement.editIndexPattern.refreshHeader": "刷新字段列表?", + "indexPatternManagement.editIndexPattern.refreshLabel": "此操作重置每个字段的常用度计数器。", + "indexPatternManagement.editIndexPattern.refreshTooltip": "重新刷新字段列表", + "indexPatternManagement.editIndexPattern.removeAria": "删除索引模式", + "indexPatternManagement.editIndexPattern.removeTooltip": "删除索引模式", + "indexPatternManagement.editIndexPattern.scripted.addFieldButton": "添加脚本字段", + "indexPatternManagement.editIndexPattern.scripted.deleteField.cancelButton": "取消", + "indexPatternManagement.editIndexPattern.scripted.deleteField.deleteButton": "删除", + "indexPatternManagement.editIndexPattern.scripted.deleteFieldLabel": "删除脚本字段 “{fieldName}”?", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangHeader": "在用的弃用语言", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "以下已弃用语言正被使用:{deprecatedLangsInUse}。Kibana 和 Elasticsearch 下一主要版本将移除对这些语言的支持。将您的脚本字段转换成 {link} 以避免问题。", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "Painless", + "indexPatternManagement.editIndexPattern.scripted.newFieldPlaceholder": "新建脚本字段", + "indexPatternManagement.editIndexPattern.scripted.noFieldLabel": "“{indexPatternTitle}” 索引模式没有称作 “{fieldName}” 的脚本字段", + "indexPatternManagement.editIndexPattern.scripted.table.deleteDescription": "删除此字段", + "indexPatternManagement.editIndexPattern.scripted.table.deleteHeader": "删除", + "indexPatternManagement.editIndexPattern.scripted.table.editDescription": "编辑此字段", + "indexPatternManagement.editIndexPattern.scripted.table.editHeader": "编辑", + "indexPatternManagement.editIndexPattern.scripted.table.formatDescription": "用于该字段的格式", + "indexPatternManagement.editIndexPattern.scripted.table.formatHeader": "格式", + "indexPatternManagement.editIndexPattern.scripted.table.langDescription": "用于该字段的语言", + "indexPatternManagement.editIndexPattern.scripted.table.langHeader": "语言", + "indexPatternManagement.editIndexPattern.scripted.table.nameDescription": "字段的名称", + "indexPatternManagement.editIndexPattern.scripted.table.nameHeader": "名称", + "indexPatternManagement.editIndexPattern.scripted.table.scriptDescription": "字段的脚本", + "indexPatternManagement.editIndexPattern.scripted.table.scriptHeader": "脚本", + "indexPatternManagement.editIndexPattern.scriptedHeader": "脚本字段", + "indexPatternManagement.editIndexPattern.scriptedLabel": "可以在可视化中使用脚本字段,并在您的文档中显示它们。但是,您不能搜索脚本字段。", + "indexPatternManagement.editIndexPattern.setDefaultAria": "设置为默认索引", + "indexPatternManagement.editIndexPattern.setDefaultTooltip": "设置为默认索引", + "indexPatternManagement.editIndexPattern.source.addButtonLabel": "添加", + "indexPatternManagement.editIndexPattern.source.deleteFilter.cancelButtonLabel": "取消", + "indexPatternManagement.editIndexPattern.source.deleteFilter.deleteButtonLabel": "删除", + "indexPatternManagement.editIndexPattern.source.deleteSourceFilterLabel": "删除源筛选 “{value}”?", + "indexPatternManagement.editIndexPattern.source.noteLabel": "请注意,多字段将错误地显示为下表中的匹配。这些筛选仅应用于原始源文档中的字段,因此实际未筛选匹配的多字段。", + "indexPatternManagement.editIndexPattern.source.table.cancelAria": "取消", + "indexPatternManagement.editIndexPattern.source.table.deleteAria": "删除", + "indexPatternManagement.editIndexPattern.source.table.editAria": "编辑", + "indexPatternManagement.editIndexPattern.source.table.filterDescription": "筛选名称", + "indexPatternManagement.editIndexPattern.source.table.filterHeader": "筛选", + "indexPatternManagement.editIndexPattern.source.table.matchesDescription": "用于该字段的语言", + "indexPatternManagement.editIndexPattern.source.table.matchesHeader": "匹配", + "indexPatternManagement.editIndexPattern.source.table.notMatchedLabel": "源筛选不匹配任何已知字段。", + "indexPatternManagement.editIndexPattern.source.table.saveAria": "保存", + "indexPatternManagement.editIndexPattern.sourceHeader": "源筛选", + "indexPatternManagement.editIndexPattern.sourceLabel": "提取文档源时,源筛选可用于排除一个或多个字段。在 Discover 应用中查看文档时会发生此问题,表在 Dashboard 应用中显示已保存搜索的结果时也会发生此问题。每行使用单个文档的源进行生成,如果您具有含有较大或不重要字段的文档,则通过在此较低层级筛除这些字段会更好。", + "indexPatternManagement.editIndexPattern.sourcePlaceholder": "源筛选,接受通配符(例如“user*”用于筛选以“user”开头的字段)", + "indexPatternManagement.editIndexPattern.tabs.fieldsHeader": "字段", + "indexPatternManagement.editIndexPattern.tabs.scriptedHeader": "脚本字段", + "indexPatternManagement.editIndexPattern.tabs.sourceHeader": "源筛选", + "indexPatternManagement.editIndexPattern.timeFilterHeader": "时间筛选字段名称:{timeFieldName}", + "indexPatternManagement.editIndexPattern.timeFilterLabel.mappingAPILink": "映射 API", + "indexPatternManagement.editIndexPattern.timeFilterLabel.timeFilterDetail": "此页根据 Elasticsearch 的记录列出“{indexPatternTitle}”索引中的每个字段以及字段的关联核心类型。要更改字段类型,请使用 Elasticsearch", + "indexPatternManagement.editIndexPatternLiveRegionAriaLabel": "索引模式", + "indexPatternManagement.indexPattern.goToPatternButtonLabel": "前往现有模式", + "indexPatternManagement.indexPattern.sectionsHeader": "索引模式", + "indexPatternManagement.indexPattern.titleExistsLabel": "具有标题 “{title}” 的索引模式已存在。", + "indexPatternManagement.indexPatternList.createButton.betaLabel": "公测版", + "indexPatternManagement.indexPatternPrompt.exampleOne": "索引单个称作 log-west-001 的数据源,以便可以快速地构建图表或查询其内容。", + "indexPatternManagement.indexPatternPrompt.exampleOneTitle": "单数据源", + "indexPatternManagement.indexPatternPrompt.examplesTitle": "索引模式示例", + "indexPatternManagement.indexPatternPrompt.exampleThree": "具体而言,将这些日志每月存档的汇总/打包指标分组成不同的索引模式,从而可以聚合历史趋势以进行比较。", + "indexPatternManagement.indexPatternPrompt.exampleThreeTitle": "定制分组", + "indexPatternManagement.indexPatternPrompt.exampleTwo": "分组以 log-west* 开头的所有传入数据源,以便可以查询所有所有西海岸服务器日志。", + "indexPatternManagement.indexPatternPrompt.exampleTwoTitle": "多数据源", + "indexPatternManagement.indexPatternPrompt.subtitle": "索引模式允许您将异类的数据源一起装入存储桶,从而可以在 Kibana 中查询它们共享的字段。", + "indexPatternManagement.indexPatternPrompt.title": "关于索引模式", + "indexPatternManagement.indexPatterns.badge.readOnly.text": "只读", + "indexPatternManagement.indexPatterns.badge.readOnly.tooltip": "无法保存索引模式", + "indexPatternManagement.indexPatterns.createBreadcrumb": "创建索引模式", + "indexPatternManagement.indexPatterns.createFieldBreadcrumb": "创建字段", + "indexPatternManagement.indexPatterns.listBreadcrumb": "索引模式", + "indexPatternManagement.indexPatternTable.createBtn": "创建索引模式", + "indexPatternManagement.indexPatternTable.title": "索引模式", "kbn.management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", "kbn.management.landing.text": "应用的完整列表位于左侧菜单中。", "kbn.managementTitle": "管理", @@ -13159,7 +13159,6 @@ "xpack.siem.case.configureCases.incidentManagementSystemLabel": "事件管理系统", "xpack.siem.case.configureCases.incidentManagementSystemTitle": "连接到第三方事件管理系统", "xpack.siem.case.configureCases.noConnector": "未选择连接器", - "xpack.siem.case.configureCases.saveChangesButton": "保存更改", "xpack.siem.case.configureCases.updateConnector": "更新连接器", "xpack.siem.case.configureCases.warningMessage": "配置似乎无效。选择的连接器缺失。您是否已删除该连接器?", "xpack.siem.case.configureCases.warningTitle": "警告", diff --git a/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx b/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx index 1ff823750a346..bd6fb4cf54b2b 100644 --- a/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx +++ b/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx @@ -134,7 +134,7 @@ export function KueryBarComponent({ queryExample="" /> - {indexPatternMissing && ( + {indexPatternMissing && !loading && ( { - const documentID = 'zbNm0HABdD75WLjLYgcB'; - const prevDocumentID = '2rNm0HABdD75WLjLYgcU'; + const documentID = new AlertId(alertIndex, 'zbNm0HABdD75WLjLYgcB'); + const prevDocumentID = new AlertId(alertIndex, '2rNm0HABdD75WLjLYgcU'); const { body } = await supertest - .get(`/api/endpoint/alerts/${documentID}`) + .get(`/api/endpoint/alerts/${documentID.toString()}`) .set('kbn-xsrf', 'xxx') .expect(200); - expect(body.id).to.eql(documentID); - expect(body.prev).to.eql(`/api/endpoint/alerts/${prevDocumentID}`); + expect(body.id).to.eql(documentID.toString()); + expect(body.prev).to.eql(`/api/endpoint/alerts/${prevDocumentID.toString()}`); expect(body.next).to.eql(null); // last alert, no more beyond this expect(body.state.host_metadata.host.id).to.eql(body.host.id); }); it('should return alert details by id, getting first alert', async () => { - const documentID = 'p7Nm0HABdD75WLjLYghv'; - const nextDocumentID = 'mbNm0HABdD75WLjLYgho'; + const documentID = new AlertId(alertIndex, 'p7Nm0HABdD75WLjLYghv'); + const nextDocumentID = new AlertId(alertIndex, 'mbNm0HABdD75WLjLYgho'); const { body } = await supertest - .get(`/api/endpoint/alerts/${documentID}`) + .get(`/api/endpoint/alerts/${documentID.toString()}`) .set('kbn-xsrf', 'xxx') .expect(200); - expect(body.id).to.eql(documentID); - expect(body.next).to.eql(`/api/endpoint/alerts/${nextDocumentID}`); + expect(body.id).to.eql(documentID.toString()); + expect(body.next).to.eql(`/api/endpoint/alerts/${nextDocumentID.toString()}`); expect(body.prev).to.eql(null); // first alert, no more before this }); it('should return 404 when alert is not found', async () => { + const documentID = new AlertId(alertIndex, 'does-not-exit'); + await supertest - .get('/api/endpoint/alerts/does-not-exist') + .get(`/api/endpoint/alerts/${documentID.toString()}`) .set('kbn-xsrf', 'xxx') .expect(404); }); + + it('should return 400 when alert id is not valid', async () => { + await supertest + .get('/api/endpoint/alerts/does-not-exist') + .set('kbn-xsrf', 'xxx') + .expect(400); + }); }); }); } diff --git a/x-pack/test/api_integration/apis/ml/modules/setup_module.ts b/x-pack/test/api_integration/apis/ml/modules/setup_module.ts index 39c87a91f0ccf..54ccbb5e0cbbd 100644 --- a/x-pack/test/api_integration/apis/ml/modules/setup_module.ts +++ b/x-pack/test/api_integration/apis/ml/modules/setup_module.ts @@ -236,6 +236,9 @@ export default ({ getService }: FtrProviderContext) => { const datafeedId = `datafeed-${job.jobId}`; await ml.api.waitForAnomalyDetectionJobToExist(job.jobId); await ml.api.waitForDatafeedToExist(datafeedId); + if (testData.requestBody.startDatafeed === true) { + await ml.api.waitForADJobRecordCountToBePositive(job.jobId); + } await ml.api.waitForJobState(job.jobId, job.jobState); await ml.api.waitForDatafeedState(datafeedId, job.datafeedState); } diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index 008590c9c8dc1..5f2e82d7e8d31 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -186,12 +186,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await testSubjects.missingOrFail('index_patterns'); }); - it(`does not allow navigation to Index Patterns; redirects to Kibana home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/index_patterns', { + it(`does not allow navigation to Index Patterns; redirects to management home`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/indexPatterns', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); - await testSubjects.existOrFail('homeApp', { timeout: config.get('timeouts.waitFor') }); + await testSubjects.existOrFail('managementHome', { + timeout: config.get('timeouts.waitFor'), + }); }); }); }); diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts index 6513c0be44683..69f315cff5c3f 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts @@ -69,13 +69,15 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('empty_kibana'); }); - it(`redirects to Kibana home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/index_patterns', { + it(`redirects to management home`, async () => { + await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/indexPatterns', { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); - await testSubjects.existOrFail('homeApp', { timeout: config.get('timeouts.waitFor') }); + await testSubjects.existOrFail('managementHome', { + timeout: config.get('timeouts.waitFor'), + }); }); }); }); diff --git a/x-pack/test/functional/page_objects/canvas_page.ts b/x-pack/test/functional/page_objects/canvas_page.ts index ce36385a2f9df..f08d1e6b7fef4 100644 --- a/x-pack/test/functional/page_objects/canvas_page.ts +++ b/x-pack/test/functional/page_objects/canvas_page.ts @@ -33,8 +33,12 @@ export function CanvasPageProvider({ getService }: FtrProviderContext) { async fillOutCustomElementForm(name: string, description: string) { // Fill out the custom element form and submit it - await testSubjects.setValue('canvasCustomElementForm-name', name); - await testSubjects.setValue('canvasCustomElementForm-description', description); + await testSubjects.setValue('canvasCustomElementForm-name', name, { + clearWithKeyboard: true, + }); + await testSubjects.setValue('canvasCustomElementForm-description', description, { + clearWithKeyboard: true, + }); await testSubjects.click('canvasCustomElementForm-submit'); }, diff --git a/x-pack/test/functional/services/machine_learning/api.ts b/x-pack/test/functional/services/machine_learning/api.ts index afc2567f3cce9..6fdc268810036 100644 --- a/x-pack/test/functional/services/machine_learning/api.ts +++ b/x-pack/test/functional/services/machine_learning/api.ts @@ -138,11 +138,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { }, async getJobState(jobId: string): Promise { - log.debug(`Fetching job state for job ${jobId}`); - const jobStats = await esSupertest - .get(`/_ml/anomaly_detectors/${jobId}/_stats`) - .expect(200) - .then((res: any) => res.body); + const jobStats = await this.getADJobStats(jobId); expect(jobStats.jobs).to.have.length(1); const state: JOB_STATE = jobStats.jobs[0].state; @@ -150,6 +146,16 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { return state; }, + async getADJobStats(jobId: string): Promise { + log.debug(`Fetching anomaly detection job stats for job ${jobId}...`); + const jobStats = await esSupertest + .get(`/_ml/anomaly_detectors/${jobId}/_stats`) + .expect(200) + .then((res: any) => res.body); + + return jobStats; + }, + async waitForJobState(jobId: string, expectedJobState: JOB_STATE) { await retry.waitForWithTimeout( `job state to be ${expectedJobState}`, @@ -390,5 +396,31 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { await this.waitForDataFrameAnalyticsJobToExist(analyticsId); }, + + async getADJobRecordCount(jobId: string): Promise { + const jobStats = await this.getADJobStats(jobId); + + expect(jobStats.jobs).to.have.length(1); + const processedRecordCount: number = jobStats.jobs[0].data_counts.processed_record_count; + + return processedRecordCount; + }, + + async waitForADJobRecordCountToBePositive(jobId: string) { + await retry.waitForWithTimeout( + `'${jobId}' to have processed_record_count > 0`, + 10 * 1000, + async () => { + const processedRecordCount = await this.getADJobRecordCount(jobId); + if (processedRecordCount > 0) { + return true; + } else { + throw new Error( + `expected anomaly detection job '${jobId}' to have processed_record_count > 0 (got ${processedRecordCount})` + ); + } + } + ); + }, }; } diff --git a/x-pack/test/functional/services/machine_learning/job_management.ts b/x-pack/test/functional/services/machine_learning/job_management.ts index 8b85f85d46cf4..085bb31258012 100644 --- a/x-pack/test/functional/services/machine_learning/job_management.ts +++ b/x-pack/test/functional/services/machine_learning/job_management.ts @@ -43,6 +43,7 @@ export function MachineLearningJobManagementProvider( }, async waitForJobCompletion(jobId: string) { + await mlApi.waitForADJobRecordCountToBePositive(jobId); await mlApi.waitForDatafeedState(`datafeed-${jobId}`, DATAFEED_STATE.STOPPED); await mlApi.waitForJobState(jobId, JOB_STATE.CLOSED); },