diff --git a/.bazelrc.common b/.bazelrc.common
index 20a41c4cde9a0d..115c0214b1a533 100644
--- a/.bazelrc.common
+++ b/.bazelrc.common
@@ -10,12 +10,13 @@
build --experimental_guard_against_concurrent_changes
run --experimental_guard_against_concurrent_changes
test --experimental_guard_against_concurrent_changes
+query --experimental_guard_against_concurrent_changes
## Cache action outputs on disk so they persist across output_base and bazel shutdown (eg. changing branches)
-build --disk_cache=~/.bazel-cache/disk-cache
+common --disk_cache=~/.bazel-cache/disk-cache
## Bazel repo cache settings
-build --repository_cache=~/.bazel-cache/repository-cache
+common --repository_cache=~/.bazel-cache/repository-cache
# Bazel will create symlinks from the workspace directory to output artifacts.
# Build results will be placed in a directory called "bazel-bin"
@@ -35,13 +36,16 @@ build --experimental_inprocess_symlink_creation
# Incompatible flags to run with
build --incompatible_no_implicit_file_export
build --incompatible_restrict_string_escapes
+query --incompatible_no_implicit_file_export
+query --incompatible_restrict_string_escapes
# Log configs
## different from default
common --color=yes
-build --show_task_finish
-build --noshow_progress
+common --noshow_progress
+common --show_task_finish
build --noshow_loading_progress
+query --noshow_loading_progress
build --show_result=0
# Specifies desired output mode for running tests.
@@ -82,7 +86,7 @@ test:debug --test_output=streamed --test_strategy=exclusive --test_timeout=9999
run:debug --define=VERBOSE_LOGS=1 -- --node_options=--inspect-brk
# The following option will change the build output of certain rules such as terser and may not be desirable in all cases
# It will also output both the repo cache and action cache to a folder inside the repo
-build:debug --compilation_mode=dbg --show_result=1
+build:debug --compilation_mode=dbg --show_result=0 --noshow_loading_progress --noshow_progress --show_task_finish
# Turn off legacy external runfiles
# This prevents accidentally depending on this feature, which Bazel will remove.
diff --git a/.editorconfig b/.editorconfig
index 7564b3596f0433..ec8a51f2314bea 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -12,6 +12,6 @@ insert_final_newline = true
[package.json]
insert_final_newline = false
-[*.{md,asciidoc}]
+[*.{md,mdx,asciidoc}]
trim_trailing_whitespace = false
insert_final_newline = false
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
index e74c646eedeaf8..bd4d8801b0d4e2 100644
--- a/WORKSPACE.bazel
+++ b/WORKSPACE.bazel
@@ -52,9 +52,6 @@ node_repositories(
# NOTE: FORCE_COLOR env var forces colors on non tty mode
yarn_install(
name = "npm",
- environment = {
- "FORCE_COLOR": "True",
- },
package_json = "//:package.json",
yarn_lock = "//:yarn.lock",
data = [
diff --git a/docs/concepts/images/add-filter-popup.png b/docs/concepts/images/add-filter-popup.png
new file mode 100644
index 00000000000000..f1b5b1ff3f6ca6
Binary files /dev/null and b/docs/concepts/images/add-filter-popup.png differ
diff --git a/docs/concepts/images/global-search.png b/docs/concepts/images/global-search.png
new file mode 100644
index 00000000000000..a867477938219a
Binary files /dev/null and b/docs/concepts/images/global-search.png differ
diff --git a/docs/concepts/images/refresh-every.png b/docs/concepts/images/refresh-every.png
new file mode 100644
index 00000000000000..a0930a6c56a653
Binary files /dev/null and b/docs/concepts/images/refresh-every.png differ
diff --git a/docs/concepts/images/save-icon.png b/docs/concepts/images/save-icon.png
new file mode 100644
index 00000000000000..959c7ef8e1bb97
Binary files /dev/null and b/docs/concepts/images/save-icon.png differ
diff --git a/docs/concepts/images/top-bar.png b/docs/concepts/images/top-bar.png
new file mode 100755
index 00000000000000..73c872c29e6ae9
Binary files /dev/null and b/docs/concepts/images/top-bar.png differ
diff --git a/docs/concepts/index.asciidoc b/docs/concepts/index.asciidoc
new file mode 100644
index 00000000000000..70b8a5265ce8ad
--- /dev/null
+++ b/docs/concepts/index.asciidoc
@@ -0,0 +1,149 @@
+[[kibana-concepts-analysts]]
+== {kib} concepts for analysts
+**_Learn the shared concepts for analyzing and visualizing your data_**
+
+As an analyst, you will use a combination of {kib} apps to analyze and
+visualize your data. {kib} contains both general-purpose apps and apps for the
+https://www.elastic.co/guide/en/enterprise-search/current/index.html[*Enterprise Search*],
+{observability-guide}/observability-introduction.html[*Elastic Observability*],
+and {security-guide}/es-overview.html[*Elastic Security*] solutions.
+These apps share a common set of concepts.
+
+[float]
+=== Three things to know about {es}
+
+You don't need to know everything about {es} to use {kib}, but the most important concepts follow:
+
+* *{es} makes JSON documents searchable and aggregatable.* The documents are
+stored in an {ref}/documents-indices.html[index] or {ref}/data-streams.html[data stream], which represent one type of data.
+
+* **_Searchable_ means that you can filter the documents for conditions.**
+For example, you can filter for data "within the last 7 days" or data that "contains the word {kib}".
+{kib} provides many ways for you to construct filters, which are also called queries or search terms.
+
+* **_Aggregatable_ means that you can extract summaries from matching documents.**
+The simplest aggregation is *count*, and it is frequently used in combination
+with the *date histogram*, to see count over time. The *terms* aggregation shows the most frequent values.
+
+[float]
+=== Finding your apps and objects
+
+{kib} offers a <> on every page that you can use to find any app or saved object.
+Open the search bar using the keyboard shortcut Ctrl+/ on Windows and Linux, Command+/ on MacOS.
+
+[role="screenshot"]
+image:concepts/images/global-search.png["Global search showing matches to apps and saved objects for the word visualize"]
+
+[float]
+=== Accessing data with index patterns
+
+{kib} requires an index pattern to tell it which {es} data you want to access,
+and whether the data is time-based. An index pattern can point to one or more {es}
+data streams, indices, or index aliases by name.
+For example, `logs-elasticsearch-prod-*` is an index pattern,
+and it is time-based with a time field of `@timestamp`. The time field is not editable.
+
+Index patterns are typically created by an administrator when sending data to {es}.
+You can <> in *Stack Management*, or by using a script
+that accesses the {kib} API.
+
+{kib} uses the index pattern to show you a list of fields, such as
+`event.duration`. You can customize the display name and format for each field.
+For example, you can tell Kibana to display `event.duration` in seconds.
+{kib} has <> for strings,
+dates, geopoints,
+and numbers.
+
+[float]
+=== Searching your data
+
+{kib} provides you several ways to build search queries,
+which will reduce the number of document matches that you get from {es}.
+Each app in {kib} provides a time filter, and most apps also include semi-structured search and extra filters.
+
+[role="screenshot"]
+image:concepts/images/top-bar.png["Time filter, semi-structured search, and filters in a {kib} app"]
+
+If you frequently use any of the search options, you can click the
+save icon
+image:concepts/images/save-icon.png["save icon"] next to the
+semi-structured search to save or load a previously saved query.
+The saved query will always contain the semi-structured search query,
+and can optionally contain the time filter and extra filters.
+
+[float]
+==== Time filter
+
+The <> limits the time range of data displayed.
+In most cases, the time filter applies to the time field in the index pattern,
+but some apps allow you to use a different time field.
+
+Using the time filter, you can configure a refresh rate to periodically
+resubmit your searches. You can also click *Refresh* to resubmit the search.
+This might be useful if you use {kib} to monitor the underlying data.
+
+[role="screenshot"]
+image:concepts/images/refresh-every.png["section of time filter where you can configure a refresh rate"]
+
+
+[float]
+==== Semi-structured search
+
+Combine free text search with field-based search using the Kibana Query Language (KQL).
+Type a search term to match across all fields, or start typing a field name to
+get suggestions for field names and operators that you can use to build a structured query.
+The semi-structured search will filter documents for matches, and only return matching documents.
+
+Following are some example KQL queries. For more detailed examples, refer to <>.
+
+[cols=2*]
+|===
+| Exact phrase query
+| `http.response.body.content.text:"quick brown fox"`
+
+| Terms query
+| http.response.status_code:400 401 404
+
+| Boolean query
+| `response:200 or extension:php`
+
+| Range query
+| `account_number >= 100 and items_sold <= 200`
+
+| Wildcard query
+| `machine.os:win*`
+|===
+
+[float]
+==== Additional filters with AND
+
+Structured filters are a more interactive way to create {es} queries,
+and are commonly used when building dashboards that are shared by multiple analysts.
+Each filter can be disabled, inverted, or pinned across all apps.
+The structured filters are the only way to use the {es} Query DSL in JSON form,
+or to target a specific index pattern for filtering. Each of the structured
+filters is combined with AND logic on the rest of the query.
+
+[role="screenshot"]
+image:concepts/images/add-filter-popup.png["Add filter popup"]
+
+[float]
+=== Saving objects
+{kib} lets you save objects for your own future use or for sharing with others.
+Each <> type has different abilities. For example, you can save
+your search queries made with *Discover*, which lets you:
+
+* Share a link to your search
+* Download the full search results in CSV form
+* Start an aggregated visualization using the same search query
+* Embed the *Discover* search results into a dashboard
+* Embed the *Discover* search results into a Canvas workpad
+
+For organization, every saved object can have a name, <>, and type.
+Use the global search to quickly open a saved object.
+
+[float]
+=== What's next?
+
+* Try the {kib} <>, which shows you how to put these concepts into action.
+* Go to <> for instructions on searching your data.
diff --git a/docs/concepts/save-query.asciidoc b/docs/concepts/save-query.asciidoc
new file mode 100644
index 00000000000000..4f049d121bbef5
--- /dev/null
+++ b/docs/concepts/save-query.asciidoc
@@ -0,0 +1,39 @@
+[[save-load-delete-query]]
+== Save a query
+A saved query is a collection of query text and filters that you can
+reuse in any app with a query bar, like <> and <>. Save a query when you want to:
+
+* Retrieve results from the same query at a later time without having to reenter the query text, add the filters or set the time filter
+* View the results of the same query in multiple apps
+* Share your query
+
+Saved queries don't include information specific to *Discover*,
+such as the currently selected columns in the document table, the sort order, and the index pattern.
+To save your current view of *Discover* for later retrieval and reuse,
+create a <> instead.
+
+NOTE::
+
+If you have insufficient privileges to save queries, the *Save current query*
+button isn't visible in the saved query management popover.
+For more information, see <>
+
+. Click *#* in the query bar.
+. In the popover, click *Save current query*.
++
+[role="screenshot"]
+image::discover/images/saved-query-management-component-all-privileges.png["Example of the saved query management popover with a list of saved queries with write access",width="80%"]
++
+. Enter a name, a description, and then select the filter options.
+By default, filters are automatically included, but the time filter is not.
++
+[role="screenshot"]
+image::discover/images/saved-query-save-form-default-filters.png["Example of the saved query management save form with the filters option included and the time filter option excluded",width="80%"]
+. Click *Save*.
+. To load a saved query into *Discover* or *Dashboard*, open the *Saved search* popover, and select the query.
+. To manage your saved queries, use these actions in the popover:
++
+* Save as new: Save changes to the current query.
+* Clear. Clear a query that is currently loaded in an app.
+* Delete. You can’t recover a deleted query.
+. To import and export saved queries, go to <>.
diff --git a/docs/developer/getting-started/index.asciidoc b/docs/developer/getting-started/index.asciidoc
index 5a16dac66c822d..d5fe7ebf470382 100644
--- a/docs/developer/getting-started/index.asciidoc
+++ b/docs/developer/getting-started/index.asciidoc
@@ -66,7 +66,8 @@ yarn kbn bootstrap --force-install
(You can also run `yarn kbn` to see the other available commands. For
more info about this tool, see
-{kib-repo}tree/{branch}/packages/kbn-pm[{kib-repo}tree/{branch}/packages/kbn-pm].)
+{kib-repo}tree/{branch}/packages/kbn-pm[{kib-repo}tree/{branch}/packages/kbn-pm]. If you want more
+information about how to actively develop over packages please read <>)
When switching branches which use different versions of npm packages you
may need to run:
@@ -169,3 +170,5 @@ include::debugging.asciidoc[leveloffset=+1]
include::building-kibana.asciidoc[leveloffset=+1]
include::development-plugin-resources.asciidoc[leveloffset=+1]
+
+include::monorepo-packages.asciidoc[leveloffset=+1]
diff --git a/docs/developer/getting-started/monorepo-packages.asciidoc b/docs/developer/getting-started/monorepo-packages.asciidoc
new file mode 100644
index 00000000000000..fc78729be5a692
--- /dev/null
+++ b/docs/developer/getting-started/monorepo-packages.asciidoc
@@ -0,0 +1,68 @@
+[[monorepo-packages]]
+== {kib} Monorepo Packages
+
+Currently {kib} works as a monorepo composed by a core, plugins and packages.
+The latest are located in a folder called `packages` and are pieces of software that
+composes a set of features that can be isolated and reused across the entire repository.
+They are also supposed to be able to imported just like any other `node_module`.
+
+Previously we relied solely on `@kbn/pm` to manage the development tools of those packages, but we are
+now in the middle of migrating those responsibilities into Bazel. Every package already migrated
+will contain in its root folder a `BUILD.bazel` file and other `build` and `watching` strategies should be used.
+
+Remember that any time you need to make sure the monorepo is ready to be used just run:
+
+[source,bash]
+----
+yarn kbn bootstrap
+----
+
+[discrete]
+=== Building Non Bazel Packages
+
+Non Bazel packages can be built independently with
+
+[source,bash]
+----
+yarn kbn run build -i PACKAGE_NAME
+----
+
+[discrete]
+=== Watching Non Bazel Packages
+
+Non Bazel packages can be watched independently with
+
+[source,bash]
+----
+yarn kbn watch -i PACKAGE_NAME
+----
+
+[discrete]
+=== Building Bazel Packages
+
+Bazel packages are built as a whole for now. You can use:
+
+[source,bash]
+----
+yarn kbn build-bazel
+----
+
+[discrete]
+=== Watching Bazel Packages
+
+Bazel packages are watched as a whole for now. You can use:
+
+[source,bash]
+----
+yarn kbn watch-bazel
+----
+
+
+[discrete]
+=== List of Already Migrated Packages to Bazel
+
+- @elastic/datemath
+- @kbn/apm-utils
+- @kbn/config-schema
+- @kbn/tinymath
+
diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc
index 0c40c2a8c4db94..353a77527d1d53 100644
--- a/docs/developer/plugin-list.asciidoc
+++ b/docs/developer/plugin-list.asciidoc
@@ -216,14 +216,27 @@ which also contains the timelion APIs and backend, look at the vis_type_timelion
|<>
-|An API for:
-
-- creating custom functionality (`actions`)
-- creating custom user interaction events (`triggers`)
-- attaching and detaching `actions` to `triggers`.
-- emitting `trigger` events
-- executing `actions` attached to a given `trigger`.
-- exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger.
+|UI Actions plugins provides API to manage *triggers* and *actions*.
+
+*Trigger* is an abstract description of user's intent to perform an action
+(like user clicking on a value inside chart). It allows us to do runtime
+binding between code from different plugins. For, example one such
+trigger is when somebody applies filters on dashboard; another one is when
+somebody opens a Dashboard panel context menu.
+
+*Actions* are pieces of code that execute in response to a trigger. For example,
+to the dashboard filtering trigger multiple actions can be attached. Once a user
+filters on the dashboard all possible actions are displayed to the user in a
+popup menu and the user has to chose one.
+
+In general this plugin provides:
+
+- Creating custom functionality (actions).
+- Creating custom user interaction events (triggers).
+- Attaching and detaching actions to triggers.
+- Emitting trigger events.
+- Executing actions attached to a given trigger.
+- Exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger.
|{kib-repo}blob/{branch}/src/plugins/url_forwarding/README.md[urlForwarding]
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
index 860f7c3c748924..535bd8f11236df 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
@@ -88,6 +88,7 @@ readonly links: {
readonly top_hits: string;
};
readonly runtimeFields: {
+ readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
@@ -107,6 +108,7 @@ readonly links: {
};
readonly addData: string;
readonly kibana: string;
+ readonly upgradeAssistant: string;
readonly elasticsearch: Record;
readonly siem: {
readonly guide: string;
@@ -114,9 +116,10 @@ readonly links: {
};
readonly query: {
readonly eql: string;
+ readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
+ readonly percolate: string;
readonly queryDsl: string;
- readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
@@ -127,6 +130,7 @@ readonly links: {
readonly transforms: Record;
readonly visualize: Record;
readonly apis: Readonly<{
+ bulkIndexAlias: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
@@ -143,6 +147,7 @@ readonly links: {
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
+ putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
updateTransform: string;
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
index a9cb6729b214e6..11814e7ca8b771 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
@@ -17,5 +17,5 @@ export interface DocLinksStart
| --- | --- | --- |
| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string
| |
| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string
| |
-| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
};
readonly addData: string;
readonly kibana: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putWatch: string;
simulatePipeline: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
}
| |
+| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
};
readonly addData: string;
readonly kibana: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
}
| |
diff --git a/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.domainid.md b/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.domainid.md
new file mode 100644
index 00000000000000..b6d1f9386be8fb
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.domainid.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DomainDeprecationDetails](./kibana-plugin-core-public.domaindeprecationdetails.md) > [domainId](./kibana-plugin-core-public.domaindeprecationdetails.domainid.md)
+
+## DomainDeprecationDetails.domainId property
+
+Signature:
+
+```typescript
+domainId: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.md b/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.md
new file mode 100644
index 00000000000000..93d715a11c5036
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.domaindeprecationdetails.md
@@ -0,0 +1,18 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DomainDeprecationDetails](./kibana-plugin-core-public.domaindeprecationdetails.md)
+
+## DomainDeprecationDetails interface
+
+Signature:
+
+```typescript
+export interface DomainDeprecationDetails extends DeprecationsDetails
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [domainId](./kibana-plugin-core-public.domaindeprecationdetails.domainid.md) | string
| |
+
diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md
index 32f17d5488f66c..39e554f5492ac2 100644
--- a/docs/development/core/public/kibana-plugin-core-public.md
+++ b/docs/development/core/public/kibana-plugin-core-public.md
@@ -61,6 +61,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin
start lifecycle |
| [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. |
| [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | |
+| [DomainDeprecationDetails](./kibana-plugin-core-public.domaindeprecationdetails.md) | |
| [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. |
| [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message
and stack
of a fatal Error |
| [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. |
diff --git a/docs/user/alerting/defining-rules.asciidoc b/docs/user/alerting/defining-rules.asciidoc
index 63839cf465e983..05885f1af13ba2 100644
--- a/docs/user/alerting/defining-rules.asciidoc
+++ b/docs/user/alerting/defining-rules.asciidoc
@@ -28,8 +28,8 @@ Name:: The name of the rule. While this name does not have to be unique, th
Tags:: A list of tag names that can be applied to a rule. Tags can help you organize and find rules, because tags appear in the rule listing in the management UI which is searchable by tag.
Check every:: This value determines how frequently the rule conditions below are checked. Note that the timing of background rule checks are not guaranteed, particularly for intervals of less than 10 seconds. See <> for more information.
Notify:: This value limits how often actions are repeated when an alert remains active across rule checks. See <> for more information. +
-- **Only on status change**: Actions are not repeated when an alert remains active across checks. Actions run only when the rule status changes.
-- **Every time rule is active**: Actions are repeated when an alert remains active across checks.
+- **Only on status change**: Actions are not repeated when an alert remains active across checks. Actions run only when the alert status changes.
+- **Every time alert is active**: Actions are repeated when an alert remains active across checks.
- **On a custom action interval**: Actions are suppressed for the throttle interval, but repeat when an alert remains active across checks for a duration longer than the throttle interval.
diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc
index d7e15258bf29bb..81ded1e54d8fdb 100644
--- a/docs/user/index.asciidoc
+++ b/docs/user/index.asciidoc
@@ -2,6 +2,8 @@ include::introduction.asciidoc[]
include::whats-new.asciidoc[]
+include::{kib-repo-dir}/concepts/index.asciidoc[]
+
include::{kib-repo-dir}/getting-started/quick-start-guide.asciidoc[]
include::setup.asciidoc[]
diff --git a/docs/user/monitoring/kibana-alerts.asciidoc b/docs/user/monitoring/kibana-alerts.asciidoc
index bbc9c41c6ca5a6..2944921edd2eea 100644
--- a/docs/user/monitoring/kibana-alerts.asciidoc
+++ b/docs/user/monitoring/kibana-alerts.asciidoc
@@ -81,8 +81,8 @@ by running checks on a schedule time of 1 minute with a re-notify interval of 6
[[kibana-alerts-large-shard-size]]
== Large shard size
-This alert is triggered if a large (primary) shard size is found on any of the
-specified index patterns. The trigger condition is met if an index's shard size is
+This alert is triggered if a large average shard size (across associated primaries) is found on any of the
+specified index patterns. The trigger condition is met if an index's average shard size is
55gb or higher in the last 5 minutes. The alert is grouped across all indices that match
the default pattern of `*` by running checks on a schedule time of 1 minute with a re-notify
interval of 12 hours.
diff --git a/docs/user/security/api-keys/images/api-key-invalidate.png b/docs/user/security/api-keys/images/api-key-invalidate.png
deleted file mode 100755
index c925679ab24bc6..00000000000000
Binary files a/docs/user/security/api-keys/images/api-key-invalidate.png and /dev/null differ
diff --git a/docs/user/security/api-keys/images/api-keys.png b/docs/user/security/api-keys/images/api-keys.png
old mode 100755
new mode 100644
index df74f245676d9c..ec4111a4432534
Binary files a/docs/user/security/api-keys/images/api-keys.png and b/docs/user/security/api-keys/images/api-keys.png differ
diff --git a/docs/user/security/api-keys/images/create-api-key.png b/docs/user/security/api-keys/images/create-api-key.png
new file mode 100644
index 00000000000000..c763dcbfa53f86
Binary files /dev/null and b/docs/user/security/api-keys/images/create-api-key.png differ
diff --git a/docs/user/security/api-keys/index.asciidoc b/docs/user/security/api-keys/index.asciidoc
index 3edd1f8f9c63d4..6b92ab3c6656a0 100644
--- a/docs/user/security/api-keys/index.asciidoc
+++ b/docs/user/security/api-keys/index.asciidoc
@@ -4,7 +4,7 @@
API keys enable you to create secondary credentials so that you can send
-requests on behalf of the user. Secondary credentials have
+requests on behalf of a user. Secondary credentials have
the same or lower access rights.
For example, if you extract data from an {es} cluster on a daily
@@ -14,8 +14,7 @@ and then put the API credentials into a cron job.
Or, you might create API keys to automate ingestion of new data from
remote sources, without a live user interaction.
-You can create API keys from the {kib} Console. To view and invalidate
-API keys, open the main menu, then click *Stack Management > API Keys*.
+To manage API keys, open the main menu, then click *Stack Management > API Keys*.
[role="screenshot"]
image:user/security/api-keys/images/api-keys.png["API Keys UI"]
@@ -46,37 +45,15 @@ cluster privileges to use API keys in {kib}. To manage roles, open the main menu
[float]
[[create-api-key]]
=== Create an API key
-You can {ref}/security-api-create-api-key.html[create an API key] from
-the {kib} Console. This example shows how to create an API key
-to authenticate to a <>.
-
-[source,js]
-POST /_security/api_key
-{
- "name": "kibana_api_key"
-}
-
-This creates an API key with the
-name `kibana_api_key`. API key
-names must be globally unique.
-An expiration date is optional and follows
-{ref}/common-options.html#time-units[{es} time unit format].
-When an expiration is not provided, the API key does not expire.
-
-The response should look something like this:
-
-[source,js]
-{
- "id" : "XFcbCnIBnbwqt2o79G4q",
- "name" : "kibana_api_key",
- "api_key" : "FD6P5UA4QCWlZZQhYF3YGw"
-}
-
-Now, you can use the API key to request {kib} roles. You'll need to send a request with a
-`Authorization` header with a value having the prefix `ApiKey` followed by the credentials,
-where credentials is the base64 encoding of `id` and `api_key` joined by a colon. For example:
-
-[source,js]
+
+To create an API key, open the main menu, then click *Stack Management > API Keys > Create API key*.
+
+[role="screenshot"]
+image:user/security/api-keys/images/create-api-key.png["Create API Key UI"]
+
+Once created, you can copy the API key (Base64 encoded) and use it to send requests to {es} on your behalf. For example:
+
+[source,bash]
curl --location --request GET 'http://localhost:5601/api/security/role' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'kbn-xsrf: true' \
@@ -84,20 +61,16 @@ curl --location --request GET 'http://localhost:5601/api/security/role' \
[float]
[[view-api-keys]]
-=== View and invalidate API keys
-The *API Keys* feature in Kibana lists your API keys, including the name, date created,
-and expiration date. If an API key expires, its status changes from `Active` to `Expired`.
+=== View and delete API keys
+
+The *API Keys* feature in Kibana lists your API keys, including the name, date created, and status. If an API key expires, its status changes from `Active` to `Expired`.
If you have `manage_security` or `manage_api_key` permissions,
you can view the API keys of all users, and see which API key was
created by which user in which realm.
If you have only the `manage_own_api_key` permission, you see only a list of your own keys.
-You can invalidate API keys individually or in bulk.
-Invalidated keys are deleted in batch after seven days.
-
-[role="screenshot"]
-image:user/security/api-keys/images/api-key-invalidate.png["API Keys invalidate"]
+You can delete API keys individually or in bulk.
You cannot modify an API key. If you need additional privileges,
you must create a new key with the desired configuration and invalidate the old key.
diff --git a/package.json b/package.json
index 9bddca46654674..ff7f76df4aee55 100644
--- a/package.json
+++ b/package.json
@@ -102,7 +102,7 @@
"@elastic/datemath": "link:bazel-bin/packages/elastic-datemath/npm_module",
"@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.4",
"@elastic/ems-client": "7.12.0",
- "@elastic/eui": "31.10.0",
+ "@elastic/eui": "32.0.4",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "^9.0.1-kibana3",
"@elastic/maki": "6.3.0",
@@ -125,9 +125,9 @@
"@kbn/ace": "link:packages/kbn-ace",
"@kbn/analytics": "link:packages/kbn-analytics",
"@kbn/apm-config-loader": "link:packages/kbn-apm-config-loader",
- "@kbn/apm-utils": "link:packages/kbn-apm-utils",
+ "@kbn/apm-utils": "link:bazel-bin/packages/kbn-apm-utils/npm_module",
"@kbn/config": "link:packages/kbn-config",
- "@kbn/config-schema": "link:packages/kbn-config-schema",
+ "@kbn/config-schema": "link:bazel-bin/packages/kbn-config-schema/npm_module",
"@kbn/crypto": "link:packages/kbn-crypto",
"@kbn/i18n": "link:packages/kbn-i18n",
"@kbn/interpreter": "link:packages/kbn-interpreter",
@@ -138,7 +138,7 @@
"@kbn/server-http-tools": "link:packages/kbn-server-http-tools",
"@kbn/server-route-repository": "link:packages/kbn-server-route-repository",
"@kbn/std": "link:packages/kbn-std",
- "@kbn/tinymath": "link:packages/kbn-tinymath",
+ "@kbn/tinymath": "link:bazel-bin/packages/kbn-tinymath/npm_module",
"@kbn/ui-framework": "link:packages/kbn-ui-framework",
"@kbn/ui-shared-deps": "link:packages/kbn-ui-shared-deps",
"@kbn/utility-types": "link:packages/kbn-utility-types",
diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel
index 31894fcb1bb5db..182013c356bb0b 100644
--- a/packages/BUILD.bazel
+++ b/packages/BUILD.bazel
@@ -3,6 +3,9 @@
filegroup(
name = "build",
srcs = [
- "//packages/elastic-datemath:build"
+ "//packages/elastic-datemath:build",
+ "//packages/kbn-apm-utils:build",
+ "//packages/kbn-config-schema:build",
+ "//packages/kbn-tinymath:build",
],
)
diff --git a/packages/elastic-datemath/BUILD.bazel b/packages/elastic-datemath/BUILD.bazel
index 6a80556d4eed51..bc0c1412ef5f15 100644
--- a/packages/elastic-datemath/BUILD.bazel
+++ b/packages/elastic-datemath/BUILD.bazel
@@ -4,15 +4,15 @@ load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm")
PKG_BASE_NAME = "elastic-datemath"
PKG_REQUIRE_NAME = "@elastic/datemath"
-SOURCE_FILES = [
+SOURCE_FILES = glob([
"src/index.ts",
-]
+])
SRCS = SOURCE_FILES
filegroup(
name = "srcs",
- srcs = glob(SOURCE_FILES),
+ srcs = SRCS,
)
NPM_MODULE_EXTRA_FILES = [
@@ -40,6 +40,7 @@ ts_config(
ts_project(
name = "tsc",
+ args = ['--pretty'],
srcs = SRCS,
deps = DEPS,
declaration = True,
diff --git a/packages/elastic-datemath/tsconfig.json b/packages/elastic-datemath/tsconfig.json
index d0fa806ed411b4..6e7219c7a82455 100644
--- a/packages/elastic-datemath/tsconfig.json
+++ b/packages/elastic-datemath/tsconfig.json
@@ -3,6 +3,7 @@
"compilerOptions": {
"declaration": true,
"declarationMap": true,
+ "incremental": true,
"outDir": "target",
"rootDir": "src",
"sourceMap": true,
diff --git a/packages/kbn-apm-utils/BUILD.bazel b/packages/kbn-apm-utils/BUILD.bazel
new file mode 100644
index 00000000000000..63adf2b77b5163
--- /dev/null
+++ b/packages/kbn-apm-utils/BUILD.bazel
@@ -0,0 +1,76 @@
+load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project")
+load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm")
+
+PKG_BASE_NAME = "kbn-apm-utils"
+PKG_REQUIRE_NAME = "@kbn/apm-utils"
+
+SOURCE_FILES = glob([
+ "src/index.ts",
+])
+
+SRCS = SOURCE_FILES
+
+filegroup(
+ name = "srcs",
+ srcs = SRCS,
+)
+
+NPM_MODULE_EXTRA_FILES = [
+ "package.json",
+]
+
+SRC_DEPS = [
+ "@npm//elastic-apm-node",
+]
+
+TYPES_DEPS = [
+ "@npm//@types/node",
+]
+
+DEPS = SRC_DEPS + TYPES_DEPS
+
+ts_config(
+ name = "tsconfig",
+ src = "tsconfig.json",
+ deps = [
+ "//:tsconfig.base.json",
+ ],
+)
+
+ts_project(
+ name = "tsc",
+ args = ['--pretty'],
+ srcs = SRCS,
+ deps = DEPS,
+ declaration = True,
+ declaration_map = True,
+ incremental = True,
+ out_dir = "target",
+ source_map = True,
+ root_dir = "src",
+ tsconfig = ":tsconfig",
+)
+
+js_library(
+ name = PKG_BASE_NAME,
+ srcs = [],
+ deps = [":tsc"] + DEPS,
+ package_name = PKG_REQUIRE_NAME,
+ visibility = ["//visibility:public"],
+)
+
+pkg_npm(
+ name = "npm_module",
+ srcs = NPM_MODULE_EXTRA_FILES,
+ deps = [
+ ":%s" % PKG_BASE_NAME,
+ ]
+)
+
+filegroup(
+ name = "build",
+ srcs = [
+ ":npm_module",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/packages/kbn-apm-utils/package.json b/packages/kbn-apm-utils/package.json
index d414b94cb39789..04b8e2ed831b39 100644
--- a/packages/kbn-apm-utils/package.json
+++ b/packages/kbn-apm-utils/package.json
@@ -4,10 +4,5 @@
"types": "./target/index.d.ts",
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0",
- "private": true,
- "scripts": {
- "build": "../../node_modules/.bin/tsc",
- "kbn:bootstrap": "yarn build",
- "kbn:watch": "yarn build --watch"
- }
+ "private": true
}
diff --git a/packages/kbn-apm-utils/tsconfig.json b/packages/kbn-apm-utils/tsconfig.json
index e08769aab65436..3ce240059486a7 100644
--- a/packages/kbn-apm-utils/tsconfig.json
+++ b/packages/kbn-apm-utils/tsconfig.json
@@ -1,11 +1,11 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
- "incremental": false,
- "outDir": "./target",
- "stripInternal": false,
"declaration": true,
"declarationMap": true,
+ "incremental": true,
+ "outDir": "target",
+ "rootDir": "src",
"sourceMap": true,
"sourceRoot": "../../../../packages/kbn-apm-utils/src",
"types": [
diff --git a/packages/kbn-cli-dev-mode/package.json b/packages/kbn-cli-dev-mode/package.json
index 2ee9831e960842..1ea319ef3601c9 100644
--- a/packages/kbn-cli-dev-mode/package.json
+++ b/packages/kbn-cli-dev-mode/package.json
@@ -15,7 +15,6 @@
},
"dependencies": {
"@kbn/config": "link:../kbn-config",
- "@kbn/config-schema": "link:../kbn-config-schema",
"@kbn/logging": "link:../kbn-logging",
"@kbn/server-http-tools": "link:../kbn-server-http-tools",
"@kbn/optimizer": "link:../kbn-optimizer",
diff --git a/packages/kbn-config-schema/BUILD.bazel b/packages/kbn-config-schema/BUILD.bazel
new file mode 100644
index 00000000000000..5dcbd9e5a802a2
--- /dev/null
+++ b/packages/kbn-config-schema/BUILD.bazel
@@ -0,0 +1,86 @@
+load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project")
+load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm")
+
+PKG_BASE_NAME = "kbn-config-schema"
+PKG_REQUIRE_NAME = "@kbn/config-schema"
+
+SOURCE_FILES = glob([
+ "src/**/*.ts",
+ "types/joi.d.ts"
+])
+
+SRCS = SOURCE_FILES
+
+filegroup(
+ name = "srcs",
+ srcs = SRCS,
+)
+
+NPM_MODULE_EXTRA_FILES = [
+ "package.json",
+ "README.md",
+]
+
+SRC_DEPS = [
+ "@npm//joi",
+ "@npm//lodash",
+ "@npm//moment",
+ "@npm//tsd",
+ "@npm//type-detect",
+]
+
+TYPES_DEPS = [
+ "@npm//@types/jest",
+ "@npm//@types/joi",
+ "@npm//@types/lodash",
+ "@npm//@types/node",
+ "@npm//@types/type-detect",
+]
+
+DEPS = SRC_DEPS + TYPES_DEPS
+
+ts_config(
+ name = "tsconfig",
+ src = "tsconfig.json",
+ deps = [
+ "//:tsconfig.base.json",
+ ],
+)
+
+ts_project(
+ name = "tsc",
+ args = ['--pretty'],
+ srcs = SRCS,
+ deps = DEPS,
+ declaration = True,
+ declaration_map = True,
+ incremental = True,
+ out_dir = "target",
+ source_map = True,
+ root_dir = "src",
+ tsconfig = ":tsconfig",
+)
+
+js_library(
+ name = PKG_BASE_NAME,
+ srcs = [],
+ deps = [":tsc"] + DEPS,
+ package_name = PKG_REQUIRE_NAME,
+ visibility = ["//visibility:public"],
+)
+
+pkg_npm(
+ name = "npm_module",
+ srcs = NPM_MODULE_EXTRA_FILES,
+ deps = [
+ ":%s" % PKG_BASE_NAME,
+ ]
+)
+
+filegroup(
+ name = "build",
+ srcs = [
+ ":npm_module",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/packages/kbn-config-schema/package.json b/packages/kbn-config-schema/package.json
index a47dee88db5887..85b52f5d75533d 100644
--- a/packages/kbn-config-schema/package.json
+++ b/packages/kbn-config-schema/package.json
@@ -1,12 +1,8 @@
{
"name": "@kbn/config-schema",
- "main": "./target/out/index.js",
- "types": "./target/types/index.d.ts",
+ "main": "./target/index.js",
+ "types": "./target/index.d.ts",
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0",
- "private": true,
- "scripts": {
- "build": "../../node_modules/.bin/tsc",
- "kbn:bootstrap": "yarn build"
- }
+ "private": true
}
\ No newline at end of file
diff --git a/packages/kbn-config-schema/tsconfig.json b/packages/kbn-config-schema/tsconfig.json
index d33683acded162..5490f37a943fc9 100644
--- a/packages/kbn-config-schema/tsconfig.json
+++ b/packages/kbn-config-schema/tsconfig.json
@@ -1,14 +1,14 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
- "incremental": false,
- "outDir": "./target/out",
- "declarationDir": "./target/types",
- "stripInternal": true,
"declaration": true,
"declarationMap": true,
+ "incremental": true,
+ "outDir": "target",
+ "rootDir": "src",
"sourceMap": true,
"sourceRoot": "../../../../../packages/kbn-config-schema/src",
+ "stripInternal": true,
"types": [
"jest",
"node"
diff --git a/packages/kbn-config/package.json b/packages/kbn-config/package.json
index e71175034787aa..8093b6ac0d211d 100644
--- a/packages/kbn-config/package.json
+++ b/packages/kbn-config/package.json
@@ -11,7 +11,6 @@
},
"dependencies": {
"@elastic/safer-lodash-set": "link:../elastic-safer-lodash-set",
- "@kbn/config-schema": "link:../kbn-config-schema",
"@kbn/logging": "link:../kbn-logging",
"@kbn/std": "link:../kbn-std"
},
diff --git a/packages/kbn-legacy-logging/package.json b/packages/kbn-legacy-logging/package.json
index 96edeccad6658a..9450fd39607ea9 100644
--- a/packages/kbn-legacy-logging/package.json
+++ b/packages/kbn-legacy-logging/package.json
@@ -11,7 +11,6 @@
"kbn:watch": "yarn build --watch"
},
"dependencies": {
- "@kbn/utils": "link:../kbn-utils",
- "@kbn/config-schema": "link:../kbn-config-schema"
+ "@kbn/utils": "link:../kbn-utils"
}
}
diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml
index 249183d4b1e316..e114e3e9300168 100644
--- a/packages/kbn-optimizer/limits.yml
+++ b/packages/kbn-optimizer/limits.yml
@@ -100,7 +100,7 @@ pageLoadAssetSize:
watcher: 43598
runtimeFields: 41752
stackAlerts: 29684
- presentationUtil: 28545
+ presentationUtil: 49767
spacesOss: 18817
indexPatternFieldEditor: 90489
osquery: 107090
diff --git a/packages/kbn-plugin-generator/src/render_template.ts b/packages/kbn-plugin-generator/src/render_template.ts
index 282a547318d288..1a9716f1f1ba5a 100644
--- a/packages/kbn-plugin-generator/src/render_template.ts
+++ b/packages/kbn-plugin-generator/src/render_template.ts
@@ -84,7 +84,7 @@ export async function renderTemplates({
answers.ui ? [] : 'public/**/*',
answers.ui && !answers.internal ? [] : ['translations/**/*', 'i18nrc.json'],
answers.server ? [] : 'server/**/*',
- !answers.internal ? [] : ['eslintrc.js', 'tsconfig.json', 'package.json', '.gitignore']
+ !answers.internal ? [] : ['.eslintrc.js', 'tsconfig.json', 'package.json', '.gitignore']
)
),
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index 7c5d0390d9fba2..e6cdd52686656a 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; });
-/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(563);
+/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(565);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildBazelProductionProjects"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; });
@@ -108,7 +108,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(251);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return _utils_package_json__WEBPACK_IMPORTED_MODULE_4__["transformDependencies"]; });
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(562);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(564);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; });
/*
@@ -141,7 +141,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
/* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(128);
-/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(514);
+/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(516);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(246);
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
@@ -8833,10 +8833,12 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter;
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; });
/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(129);
-/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(478);
-/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(510);
-/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(511);
-/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(512);
+/* harmony import */ var _build_bazel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(478);
+/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(479);
+/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(511);
+/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(512);
+/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(513);
+/* harmony import */ var _watch_bazel__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(515);
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
@@ -8849,12 +8851,16 @@ __webpack_require__.r(__webpack_exports__);
+
+
const commands = {
bootstrap: _bootstrap__WEBPACK_IMPORTED_MODULE_0__["BootstrapCommand"],
- clean: _clean__WEBPACK_IMPORTED_MODULE_1__["CleanCommand"],
- reset: _reset__WEBPACK_IMPORTED_MODULE_2__["ResetCommand"],
- run: _run__WEBPACK_IMPORTED_MODULE_3__["RunCommand"],
- watch: _watch__WEBPACK_IMPORTED_MODULE_4__["WatchCommand"]
+ 'build-bazel': _build_bazel__WEBPACK_IMPORTED_MODULE_1__["BuildBazelCommand"],
+ clean: _clean__WEBPACK_IMPORTED_MODULE_2__["CleanCommand"],
+ reset: _reset__WEBPACK_IMPORTED_MODULE_3__["ResetCommand"],
+ run: _run__WEBPACK_IMPORTED_MODULE_4__["RunCommand"],
+ watch: _watch__WEBPACK_IMPORTED_MODULE_5__["WatchCommand"],
+ 'watch-bazel': _watch_bazel__WEBPACK_IMPORTED_MODULE_6__["WatchBazelCommand"]
};
/***/ }),
@@ -8933,7 +8939,7 @@ const BootstrapCommand = {
await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['run', '@nodejs//:yarn'], runOffline);
}
- await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['build', '//packages:build'], runOffline); // Install monorepo npm dependencies outside of the Bazel managed ones
+ await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['build', '//packages:build', '--show_result=1'], runOffline); // Install monorepo npm dependencies outside of the Bazel managed ones
for (const batch of batchedNonBazelProjects) {
for (const project of batch) {
@@ -29748,15 +29754,14 @@ var gitHosts = __webpack_require__(284)
var GitHost = module.exports = __webpack_require__(285)
var protocolToRepresentationMap = {
- 'git+ssh': 'sshurl',
- 'git+https': 'https',
- 'ssh': 'sshurl',
- 'git': 'git'
+ 'git+ssh:': 'sshurl',
+ 'git+https:': 'https',
+ 'ssh:': 'sshurl',
+ 'git:': 'git'
}
function protocolToRepresentation (protocol) {
- if (protocol.substr(-1) === ':') protocol = protocol.slice(0, -1)
- return protocolToRepresentationMap[protocol] || protocol
+ return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}
var authProtocols = {
@@ -29770,6 +29775,7 @@ var authProtocols = {
var cache = {}
module.exports.fromUrl = function (giturl, opts) {
+ if (typeof giturl !== 'string') return
var key = giturl + JSON.stringify(opts || {})
if (!(key in cache)) {
@@ -29785,13 +29791,13 @@ function fromUrl (giturl, opts) {
isGitHubShorthand(giturl) ? 'github:' + giturl : giturl
)
var parsed = parseGitUrl(url)
- var shortcutMatch = url.match(new RegExp('^([^:]+):(?:(?:[^@:]+(?:[^@]+)?@)?([^/]*))[/](.+?)(?:[.]git)?($|#)'))
+ var shortcutMatch = url.match(/^([^:]+):(?:[^@]+@)?(?:([^/]*)\/)?([^#]+)/)
var matches = Object.keys(gitHosts).map(function (gitHostName) {
try {
var gitHostInfo = gitHosts[gitHostName]
var auth = null
if (parsed.auth && authProtocols[parsed.protocol]) {
- auth = decodeURIComponent(parsed.auth)
+ auth = parsed.auth
}
var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
var user = null
@@ -29799,22 +29805,27 @@ function fromUrl (giturl, opts) {
var defaultRepresentation = null
if (shortcutMatch && shortcutMatch[1] === gitHostName) {
user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2])
- project = decodeURIComponent(shortcutMatch[3])
+ project = decodeURIComponent(shortcutMatch[3].replace(/\.git$/, ''))
defaultRepresentation = 'shortcut'
} else {
- if (parsed.host !== gitHostInfo.domain) return
+ if (parsed.host && parsed.host !== gitHostInfo.domain && parsed.host.replace(/^www[.]/, '') !== gitHostInfo.domain) return
if (!gitHostInfo.protocols_re.test(parsed.protocol)) return
if (!parsed.path) return
var pathmatch = gitHostInfo.pathmatch
var matched = parsed.path.match(pathmatch)
if (!matched) return
- if (matched[1] != null) user = decodeURIComponent(matched[1].replace(/^:/, ''))
- if (matched[2] != null) project = decodeURIComponent(matched[2])
+ /* istanbul ignore else */
+ if (matched[1] !== null && matched[1] !== undefined) {
+ user = decodeURIComponent(matched[1].replace(/^:/, ''))
+ }
+ project = decodeURIComponent(matched[2])
defaultRepresentation = protocolToRepresentation(parsed.protocol)
}
return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
} catch (ex) {
- if (!(ex instanceof URIError)) throw ex
+ /* istanbul ignore else */
+ if (ex instanceof URIError) {
+ } else throw ex
}
}).filter(function (gitHostInfo) { return gitHostInfo })
if (matches.length !== 1) return
@@ -29844,9 +29855,31 @@ function fixupUnqualifiedGist (giturl) {
}
function parseGitUrl (giturl) {
- if (typeof giturl !== 'string') giturl = '' + giturl
var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
- if (!matched) return url.parse(giturl)
+ if (!matched) {
+ var legacy = url.parse(giturl)
+ // If we don't have url.URL, then sorry, this is just not fixable.
+ // This affects Node <= 6.12.
+ if (legacy.auth && typeof url.URL === 'function') {
+ // git urls can be in the form of scp-style/ssh-connect strings, like
+ // git+ssh://user@host.com:some/path, which the legacy url parser
+ // supports, but WhatWG url.URL class does not. However, the legacy
+ // parser de-urlencodes the username and password, so something like
+ // https://user%3An%40me:p%40ss%3Aword@x.com/ becomes
+ // https://user:n@me:p@ss:word@x.com/ which is all kinds of wrong.
+ // Pull off just the auth and host, so we dont' get the confusing
+ // scp-style URL, then pass that to the WhatWG parser to get the
+ // auth properly escaped.
+ var authmatch = giturl.match(/[^@]+@[^:/]+/)
+ /* istanbul ignore else - this should be impossible */
+ if (authmatch) {
+ var whatwg = new url.URL(authmatch[0])
+ legacy.auth = whatwg.username || ''
+ if (whatwg.password) legacy.auth += ':' + whatwg.password
+ }
+ }
+ return legacy
+ }
return {
protocol: 'git+ssh:',
slashes: true,
@@ -29888,7 +29921,7 @@ var gitHosts = module.exports = {
'filetemplate': 'https://{auth@}raw.githubusercontent.com/{user}/{project}/{committish}/{path}',
'bugstemplate': 'https://{domain}/{user}/{project}/issues',
'gittemplate': 'git://{auth@}{domain}/{user}/{project}.git{#committish}',
- 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz'
+ 'tarballtemplate': 'https://codeload.{domain}/{user}/{project}/tar.gz/{committish}'
},
bitbucket: {
'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ],
@@ -29900,25 +29933,30 @@ var gitHosts = module.exports = {
'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ],
'domain': 'gitlab.com',
'treepath': 'tree',
- 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#README',
'bugstemplate': 'https://{domain}/{user}/{project}/issues',
- 'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}'
+ 'httpstemplate': 'git+https://{auth@}{domain}/{user}/{projectPath}.git{#committish}',
+ 'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}',
+ 'pathmatch': /^[/]([^/]+)[/]((?!.*(\/-\/|\/repository\/archive\.tar\.gz\?=.*|\/repository\/[^/]+\/archive.tar.gz$)).*?)(?:[.]git|[/])?$/
},
gist: {
'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ],
'domain': 'gist.github.com',
- 'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]+)(?:[.]git)?$/,
+ 'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]{32,})(?:[.]git)?$/,
'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}',
'bugstemplate': 'https://{domain}/{project}',
'gittemplate': 'git://{domain}/{project}.git{#committish}',
'sshtemplate': 'git@{domain}:/{project}.git{#committish}',
'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}',
'browsetemplate': 'https://{domain}/{project}{/committish}',
+ 'browsefiletemplate': 'https://{domain}/{project}{/committish}{#path}',
'docstemplate': 'https://{domain}/{project}{/committish}',
'httpstemplate': 'git+https://{domain}/{project}.git{#committish}',
'shortcuttemplate': '{type}:{project}{#committish}',
'pathtemplate': '{project}{#committish}',
- 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz'
+ 'tarballtemplate': 'https://codeload.github.com/gist/{project}/tar.gz/{committish}',
+ 'hashformat': function (fragment) {
+ return 'file-' + formatHashFragment(fragment)
+ }
}
}
@@ -29926,12 +29964,14 @@ var gitHostDefaults = {
'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}',
'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}',
'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}',
+ 'browsefiletemplate': 'https://{domain}/{user}/{project}/{treepath}/{committish}/{path}{#fragment}',
'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme',
'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}',
'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}',
'shortcuttemplate': '{type}:{user}/{project}{#committish}',
'pathtemplate': '{user}/{project}{#committish}',
- 'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/
+ 'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/,
+ 'hashformat': formatHashFragment
}
Object.keys(gitHosts).forEach(function (name) {
@@ -29945,6 +29985,10 @@ Object.keys(gitHosts).forEach(function (name) {
}).join('|') + '):$')
})
+function formatHashFragment (fragment) {
+ return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
+}
+
/***/ }),
/* 285 */
@@ -29953,9 +29997,25 @@ Object.keys(gitHosts).forEach(function (name) {
"use strict";
var gitHosts = __webpack_require__(284)
-var extend = Object.assign || __webpack_require__(112)._extend
+/* eslint-disable node/no-deprecated-api */
-var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) {
+// copy-pasta util._extend from node's source, to avoid pulling
+// the whole util module into peoples' webpack bundles.
+/* istanbul ignore next */
+var extend = Object.assign || function _extend (target, source) {
+ // Don't do anything if source isn't an object
+ if (source === null || typeof source !== 'object') return target
+
+ var keys = Object.keys(source)
+ var i = keys.length
+ while (i--) {
+ target[keys[i]] = source[keys[i]]
+ }
+ return target
+}
+
+module.exports = GitHost
+function GitHost (type, user, auth, project, committish, defaultRepresentation, opts) {
var gitHostInfo = this
gitHostInfo.type = type
Object.keys(gitHosts[type]).forEach(function (key) {
@@ -29968,7 +30028,6 @@ var GitHost = module.exports = function (type, user, auth, project, committish,
gitHostInfo.default = defaultRepresentation
gitHostInfo.opts = opts || {}
}
-GitHost.prototype = {}
GitHost.prototype.hash = function () {
return this.committish ? '#' + this.committish : ''
@@ -29977,27 +30036,43 @@ GitHost.prototype.hash = function () {
GitHost.prototype._fill = function (template, opts) {
if (!template) return
var vars = extend({}, opts)
+ vars.path = vars.path ? vars.path.replace(/^[/]+/g, '') : ''
opts = extend(extend({}, this.opts), opts)
var self = this
Object.keys(this).forEach(function (key) {
if (self[key] != null && vars[key] == null) vars[key] = self[key]
})
var rawAuth = vars.auth
- var rawComittish = vars.committish
+ var rawcommittish = vars.committish
+ var rawFragment = vars.fragment
+ var rawPath = vars.path
+ var rawProject = vars.project
Object.keys(vars).forEach(function (key) {
- vars[key] = encodeURIComponent(vars[key])
+ var value = vars[key]
+ if ((key === 'path' || key === 'project') && typeof value === 'string') {
+ vars[key] = value.split('/').map(function (pathComponent) {
+ return encodeURIComponent(pathComponent)
+ }).join('/')
+ } else {
+ vars[key] = encodeURIComponent(value)
+ }
})
vars['auth@'] = rawAuth ? rawAuth + '@' : ''
+ vars['#fragment'] = rawFragment ? '#' + this.hashformat(rawFragment) : ''
+ vars.fragment = vars.fragment ? vars.fragment : ''
+ vars['#path'] = rawPath ? '#' + this.hashformat(rawPath) : ''
+ vars['/path'] = vars.path ? '/' + vars.path : ''
+ vars.projectPath = rawProject.split('/').map(encodeURIComponent).join('/')
if (opts.noCommittish) {
vars['#committish'] = ''
vars['/tree/committish'] = ''
- vars['/comittish'] = ''
- vars.comittish = ''
+ vars['/committish'] = ''
+ vars.committish = ''
} else {
- vars['#committish'] = rawComittish ? '#' + rawComittish : ''
+ vars['#committish'] = rawcommittish ? '#' + rawcommittish : ''
vars['/tree/committish'] = vars.committish
- ? '/' + vars.treepath + '/' + vars.committish
- : ''
+ ? '/' + vars.treepath + '/' + vars.committish
+ : ''
vars['/committish'] = vars.committish ? '/' + vars.committish : ''
vars.committish = vars.committish || 'master'
}
@@ -30020,8 +30095,19 @@ GitHost.prototype.sshurl = function (opts) {
return this._fill(this.sshurltemplate, opts)
}
-GitHost.prototype.browse = function (opts) {
- return this._fill(this.browsetemplate, opts)
+GitHost.prototype.browse = function (P, F, opts) {
+ if (typeof P === 'string') {
+ if (typeof F !== 'string') {
+ opts = F
+ F = null
+ }
+ return this._fill(this.browsefiletemplate, extend({
+ fragment: F,
+ path: P
+ }, opts))
+ } else {
+ return this._fill(this.browsetemplate, P)
+ }
}
GitHost.prototype.docs = function (opts) {
@@ -30048,14 +30134,13 @@ GitHost.prototype.path = function (opts) {
return this._fill(this.pathtemplate, opts)
}
-GitHost.prototype.tarball = function (opts) {
+GitHost.prototype.tarball = function (opts_) {
+ var opts = extend({}, opts_, { noCommittish: false })
return this._fill(this.tarballtemplate, opts)
}
GitHost.prototype.file = function (P, opts) {
- return this._fill(this.filetemplate, extend({
- path: P.replace(/^[/]+/g, '')
- }, opts))
+ return this._fill(this.filetemplate, extend({ path: P }, opts))
}
GitHost.prototype.getDefaultRepresentation = function () {
@@ -30063,7 +30148,8 @@ GitHost.prototype.getDefaultRepresentation = function () {
}
GitHost.prototype.toString = function (opts) {
- return (this[this.default] || this.sshurl).call(this, opts)
+ if (this.default && typeof this[this.default] === 'function') return this[this.default](opts)
+ return this.sshurl(opts)
}
@@ -48141,6 +48227,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(376);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runBazel"]; });
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runIBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runIBazel"]; });
+
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
@@ -48363,6 +48451,7 @@ async function installBazelTools(repoRootPath) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runBazel", function() { return runBazel; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runIBazel", function() { return runIBazel; });
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
@@ -48371,6 +48460,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(319);
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(246);
+/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(249);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -48390,7 +48480,9 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
-async function runBazel(bazelArgs, offline = false, runOpts = {}) {
+
+
+async function runBazelCommandWithRunner(bazelCommandRunner, bazelArgs, offline = false, runOpts = {}) {
// Force logs to pipe in order to control the output of them
const bazelOpts = _objectSpread(_objectSpread({}, runOpts), {}, {
stdio: 'pipe'
@@ -48400,17 +48492,29 @@ async function runBazel(bazelArgs, offline = false, runOpts = {}) {
bazelArgs.push('--config=offline');
}
- const bazelProc = Object(_child_process__WEBPACK_IMPORTED_MODULE_4__["spawn"])('bazel', bazelArgs, bazelOpts);
+ const bazelProc = Object(_child_process__WEBPACK_IMPORTED_MODULE_4__["spawn"])(bazelCommandRunner, bazelArgs, bazelOpts);
const bazelLogs$ = new rxjs__WEBPACK_IMPORTED_MODULE_1__["Subject"](); // Bazel outputs machine readable output into stdout and human readable output goes to stderr.
// Therefore we need to get both. In order to get errors we need to parse the actual text line
- const bazelLogSubscription = rxjs__WEBPACK_IMPORTED_MODULE_1__["merge"](Object(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__["observeLines"])(bazelProc.stdout).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["tap"])(line => _log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan('[bazel]')} ${line}`))), Object(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__["observeLines"])(bazelProc.stderr).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["tap"])(line => _log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan('[bazel]')} ${line}`)))).subscribe(bazelLogs$); // Wait for process and logs to finish, unsubscribing in the end
+ const bazelLogSubscription = rxjs__WEBPACK_IMPORTED_MODULE_1__["merge"](Object(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__["observeLines"])(bazelProc.stdout).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["tap"])(line => _log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan(`[${bazelCommandRunner}]`)} ${line}`))), Object(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__["observeLines"])(bazelProc.stderr).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["tap"])(line => _log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan(`[${bazelCommandRunner}]`)} ${line}`)))).subscribe(bazelLogs$); // Wait for process and logs to finish, unsubscribing in the end
+
+ try {
+ await bazelProc;
+ } catch {
+ throw new _errors__WEBPACK_IMPORTED_MODULE_6__["CliError"](`The bazel command that was running failed to complete.`);
+ }
- await bazelProc;
await bazelLogs$.toPromise();
await bazelLogSubscription.unsubscribe();
}
+async function runBazel(bazelArgs, offline = false, runOpts = {}) {
+ await runBazelCommandWithRunner('bazel', bazelArgs, offline, runOpts);
+}
+async function runIBazel(bazelArgs, offline = false, runOpts = {}) {
+ await runBazelCommandWithRunner('ibazel', bazelArgs, offline, runOpts);
+}
+
/***/ }),
/* 377 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -54550,6 +54654,36 @@ exports.observeReadable = observeReadable;
/* 478 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuildBazelCommand", function() { return BuildBazelCommand; });
+/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(372);
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+const BuildBazelCommand = {
+ description: 'Runs a build in the Bazel built packages',
+ name: 'build-bazel',
+
+ async run(projects, projectGraph, {
+ options
+ }) {
+ const runOffline = (options === null || options === void 0 ? void 0 : options.offline) === true; // Call bazel with the target to build all available packages
+
+ await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_0__["runBazel"])(['build', '//packages:build', '--show_result=1'], runOffline);
+ }
+
+};
+
+/***/ }),
+/* 479 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; });
@@ -54557,7 +54691,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(479);
+/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(480);
/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
@@ -54660,20 +54794,20 @@ const CleanCommand = {
};
/***/ }),
-/* 479 */
+/* 480 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const readline = __webpack_require__(480);
-const chalk = __webpack_require__(481);
-const cliCursor = __webpack_require__(488);
-const cliSpinners = __webpack_require__(490);
-const logSymbols = __webpack_require__(492);
-const stripAnsi = __webpack_require__(502);
-const wcwidth = __webpack_require__(504);
-const isInteractive = __webpack_require__(508);
-const MuteStream = __webpack_require__(509);
+const readline = __webpack_require__(481);
+const chalk = __webpack_require__(482);
+const cliCursor = __webpack_require__(489);
+const cliSpinners = __webpack_require__(491);
+const logSymbols = __webpack_require__(493);
+const stripAnsi = __webpack_require__(503);
+const wcwidth = __webpack_require__(505);
+const isInteractive = __webpack_require__(509);
+const MuteStream = __webpack_require__(510);
const TEXT = Symbol('text');
const PREFIX_TEXT = Symbol('prefixText');
@@ -55026,23 +55160,23 @@ module.exports.promise = (action, options) => {
/***/ }),
-/* 480 */
+/* 481 */
/***/ (function(module, exports) {
module.exports = require("readline");
/***/ }),
-/* 481 */
+/* 482 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiStyles = __webpack_require__(482);
+const ansiStyles = __webpack_require__(483);
const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(120);
const {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
-} = __webpack_require__(486);
+} = __webpack_require__(487);
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = [
@@ -55243,7 +55377,7 @@ const chalkTag = (chalk, ...strings) => {
}
if (template === undefined) {
- template = __webpack_require__(487);
+ template = __webpack_require__(488);
}
return template(chalk, parts.join(''));
@@ -55272,7 +55406,7 @@ module.exports = chalk;
/***/ }),
-/* 482 */
+/* 483 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55318,7 +55452,7 @@ const setLazyProperty = (object, property, get) => {
let colorConvert;
const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
if (colorConvert === undefined) {
- colorConvert = __webpack_require__(483);
+ colorConvert = __webpack_require__(484);
}
const offset = isBackground ? 10 : 0;
@@ -55443,11 +55577,11 @@ Object.defineProperty(module, 'exports', {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module)))
/***/ }),
-/* 483 */
+/* 484 */
/***/ (function(module, exports, __webpack_require__) {
-const conversions = __webpack_require__(484);
-const route = __webpack_require__(485);
+const conversions = __webpack_require__(485);
+const route = __webpack_require__(486);
const convert = {};
@@ -55530,7 +55664,7 @@ module.exports = convert;
/***/ }),
-/* 484 */
+/* 485 */
/***/ (function(module, exports, __webpack_require__) {
/* MIT license */
@@ -56375,10 +56509,10 @@ convert.rgb.gray = function (rgb) {
/***/ }),
-/* 485 */
+/* 486 */
/***/ (function(module, exports, __webpack_require__) {
-const conversions = __webpack_require__(484);
+const conversions = __webpack_require__(485);
/*
This function routes a model to all other models.
@@ -56478,7 +56612,7 @@ module.exports = function (fromModel) {
/***/ }),
-/* 486 */
+/* 487 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56524,7 +56658,7 @@ module.exports = {
/***/ }),
-/* 487 */
+/* 488 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56665,12 +56799,12 @@ module.exports = (chalk, temporary) => {
/***/ }),
-/* 488 */
+/* 489 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const restoreCursor = __webpack_require__(489);
+const restoreCursor = __webpack_require__(490);
let isHidden = false;
@@ -56707,7 +56841,7 @@ exports.toggle = (force, writableStream) => {
/***/ }),
-/* 489 */
+/* 490 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56723,13 +56857,13 @@ module.exports = onetime(() => {
/***/ }),
-/* 490 */
+/* 491 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const spinners = Object.assign({}, __webpack_require__(491));
+const spinners = Object.assign({}, __webpack_require__(492));
const spinnersList = Object.keys(spinners);
@@ -56747,18 +56881,18 @@ module.exports.default = spinners;
/***/ }),
-/* 491 */
+/* 492 */
/***/ (function(module) {
module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]},\"aesthetic\":{\"interval\":80,\"frames\":[\"▰▱▱▱▱▱▱\",\"▰▰▱▱▱▱▱\",\"▰▰▰▱▱▱▱\",\"▰▰▰▰▱▱▱\",\"▰▰▰▰▰▱▱\",\"▰▰▰▰▰▰▱\",\"▰▰▰▰▰▰▰\",\"▰▱▱▱▱▱▱\"]}}");
/***/ }),
-/* 492 */
+/* 493 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const chalk = __webpack_require__(493);
+const chalk = __webpack_require__(494);
const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color';
@@ -56780,16 +56914,16 @@ module.exports = isSupported ? main : fallbacks;
/***/ }),
-/* 493 */
+/* 494 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const escapeStringRegexp = __webpack_require__(265);
-const ansiStyles = __webpack_require__(494);
-const stdoutColor = __webpack_require__(499).stdout;
+const ansiStyles = __webpack_require__(495);
+const stdoutColor = __webpack_require__(500).stdout;
-const template = __webpack_require__(501);
+const template = __webpack_require__(502);
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
@@ -57015,12 +57149,12 @@ module.exports.default = module.exports; // For TypeScript
/***/ }),
-/* 494 */
+/* 495 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(module) {
-const colorConvert = __webpack_require__(495);
+const colorConvert = __webpack_require__(496);
const wrapAnsi16 = (fn, offset) => function () {
const code = fn.apply(colorConvert, arguments);
@@ -57188,11 +57322,11 @@ Object.defineProperty(module, 'exports', {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module)))
/***/ }),
-/* 495 */
+/* 496 */
/***/ (function(module, exports, __webpack_require__) {
-var conversions = __webpack_require__(496);
-var route = __webpack_require__(498);
+var conversions = __webpack_require__(497);
+var route = __webpack_require__(499);
var convert = {};
@@ -57272,11 +57406,11 @@ module.exports = convert;
/***/ }),
-/* 496 */
+/* 497 */
/***/ (function(module, exports, __webpack_require__) {
/* MIT license */
-var cssKeywords = __webpack_require__(497);
+var cssKeywords = __webpack_require__(498);
// NOTE: conversions should only return primitive values (i.e. arrays, or
// values that give correct `typeof` results).
@@ -58146,7 +58280,7 @@ convert.rgb.gray = function (rgb) {
/***/ }),
-/* 497 */
+/* 498 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -58305,10 +58439,10 @@ module.exports = {
/***/ }),
-/* 498 */
+/* 499 */
/***/ (function(module, exports, __webpack_require__) {
-var conversions = __webpack_require__(496);
+var conversions = __webpack_require__(497);
/*
this function routes a model to all other models.
@@ -58408,13 +58542,13 @@ module.exports = function (fromModel) {
/***/ }),
-/* 499 */
+/* 500 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const os = __webpack_require__(121);
-const hasFlag = __webpack_require__(500);
+const hasFlag = __webpack_require__(501);
const env = process.env;
@@ -58546,7 +58680,7 @@ module.exports = {
/***/ }),
-/* 500 */
+/* 501 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -58561,7 +58695,7 @@ module.exports = (flag, argv) => {
/***/ }),
-/* 501 */
+/* 502 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -58696,18 +58830,18 @@ module.exports = (chalk, tmp) => {
/***/ }),
-/* 502 */
+/* 503 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiRegex = __webpack_require__(503);
+const ansiRegex = __webpack_require__(504);
module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string;
/***/ }),
-/* 503 */
+/* 504 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -58724,14 +58858,14 @@ module.exports = ({onlyFirst = false} = {}) => {
/***/ }),
-/* 504 */
+/* 505 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var defaults = __webpack_require__(505)
-var combining = __webpack_require__(507)
+var defaults = __webpack_require__(506)
+var combining = __webpack_require__(508)
var DEFAULTS = {
nul: 0,
@@ -58830,10 +58964,10 @@ function bisearch(ucs) {
/***/ }),
-/* 505 */
+/* 506 */
/***/ (function(module, exports, __webpack_require__) {
-var clone = __webpack_require__(506);
+var clone = __webpack_require__(507);
module.exports = function(options, defaults) {
options = options || {};
@@ -58848,7 +58982,7 @@ module.exports = function(options, defaults) {
};
/***/ }),
-/* 506 */
+/* 507 */
/***/ (function(module, exports, __webpack_require__) {
var clone = (function() {
@@ -59020,7 +59154,7 @@ if ( true && module.exports) {
/***/ }),
-/* 507 */
+/* 508 */
/***/ (function(module, exports) {
module.exports = [
@@ -59076,7 +59210,7 @@ module.exports = [
/***/ }),
-/* 508 */
+/* 509 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -59092,7 +59226,7 @@ module.exports = ({stream = process.stdout} = {}) => {
/***/ }),
-/* 509 */
+/* 510 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(138)
@@ -59243,7 +59377,7 @@ MuteStream.prototype.close = proxy('close')
/***/ }),
-/* 510 */
+/* 511 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -59253,7 +59387,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(479);
+/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(480);
/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
@@ -59362,16 +59496,18 @@ const ResetCommand = {
};
/***/ }),
-/* 511 */
+/* 512 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; });
-/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(249);
-/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246);
-/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(248);
+/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
+/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(249);
+/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(246);
+/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(247);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(248);
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
@@ -59383,53 +59519,61 @@ __webpack_require__.r(__webpack_exports__);
+
const RunCommand = {
- description: 'Run script defined in package.json in each package that contains that script.',
+ description: 'Run script defined in package.json in each package that contains that script (only works on packages not using Bazel yet)',
name: 'run',
async run(projects, projectGraph, {
extraArgs,
options
}) {
- const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph);
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].warning(dedent__WEBPACK_IMPORTED_MODULE_0___default.a`
+ We are migrating packages into the Bazel build system and we will no longer support running npm scripts on
+ packages using 'yarn kbn run' on Bazel built packages. If the package you are trying to act on contains a
+ BUILD.bazel file please just use 'yarn kbn build-bazel' to build it or 'yarn kbn watch-bazel' to watch it
+ `);
+ const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph);
if (extraArgs.length === 0) {
- throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"]('No script specified');
+ throw new _utils_errors__WEBPACK_IMPORTED_MODULE_1__["CliError"]('No script specified');
}
const scriptName = extraArgs[0];
const scriptArgs = extraArgs.slice(1);
- await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async project => {
+ await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_3__["parallelizeBatches"])(batchedProjects, async project => {
if (!project.hasScript(scriptName)) {
if (!!options['skip-missing']) {
return;
}
- throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"](`[${project.name}] no "${scriptName}" script defined. To skip packages without the "${scriptName}" script pass --skip-missing`);
+ throw new _utils_errors__WEBPACK_IMPORTED_MODULE_1__["CliError"](`[${project.name}] no "${scriptName}" script defined. To skip packages without the "${scriptName}" script pass --skip-missing`);
}
- _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`[${project.name}] running "${scriptName}" script`);
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].info(`[${project.name}] running "${scriptName}" script`);
await project.runScriptStreaming(scriptName, {
args: scriptArgs
});
- _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${project.name}] complete`);
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].success(`[${project.name}] complete`);
});
}
};
/***/ }),
-/* 512 */
+/* 513 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; });
-/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(249);
-/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246);
-/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(248);
-/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(513);
+/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
+/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(249);
+/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(246);
+/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(247);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(248);
+/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(514);
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
@@ -59443,6 +59587,7 @@ __webpack_require__.r(__webpack_exports__);
+
/**
* Name of the script in the package/project package.json file to run during `kbn watch`.
*/
@@ -59464,10 +59609,14 @@ const kibanaProjectName = 'kibana';
*/
const WatchCommand = {
- description: 'Runs `kbn:watch` script for every project.',
+ description: 'Runs `kbn:watch` script for every project (only works on packages not using Bazel yet)',
name: 'watch',
async run(projects, projectGraph) {
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].warning(dedent__WEBPACK_IMPORTED_MODULE_0___default.a`
+ We are migrating packages into the Bazel build system. If the package you are trying to watch
+ contains a BUILD.bazel file please just use 'yarn kbn watch-bazel'
+ `);
const projectsToWatch = new Map();
for (const project of projects.values()) {
@@ -59478,33 +59627,33 @@ const WatchCommand = {
}
if (projectsToWatch.size === 0) {
- throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"](`There are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.`);
+ throw new _utils_errors__WEBPACK_IMPORTED_MODULE_1__["CliError"](`There are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.`);
}
const projectNames = Array.from(projectsToWatch.keys());
- _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`); // Kibana should always be run the last, so we don't rely on automatic
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].info(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`); // Kibana should always be run the last, so we don't rely on automatic
// topological batching and push it to the last one-entry batch manually.
const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName);
- const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projectsToWatch, projectGraph);
+ const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projectsToWatch, projectGraph);
if (shouldWatchKibanaProject) {
batchedProjects.push([projects.get(kibanaProjectName)]);
}
- await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => {
- const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_4__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName, {
+ await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_3__["parallelizeBatches"])(batchedProjects, async pkg => {
+ const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_5__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName, {
debug: false
}).stdout // TypeScript note: As long as the proc stdio[1] is 'pipe', then stdout will not be null
);
- _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${pkg.name}] Initial build completed (${completionHint}).`);
+ _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].success(`[${pkg.name}] Initial build completed (${completionHint}).`);
});
}
};
/***/ }),
-/* 513 */
+/* 514 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -59567,19 +59716,52 @@ function waitUntilWatchIsReady(stream, opts = {}) {
}
/***/ }),
-/* 514 */
+/* 515 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchBazelCommand", function() { return WatchBazelCommand; });
+/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(372);
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+const WatchBazelCommand = {
+ description: 'Runs a build in the Bazel built packages and keeps watching them for changes',
+ name: 'watch-bazel',
+
+ async run(projects, projectGraph, {
+ options
+ }) {
+ const runOffline = (options === null || options === void 0 ? void 0 : options.offline) === true; // Call bazel with the target to build all available packages and run it through iBazel to watch it for changes
+ //
+ // Note: --run_output=false arg will disable the iBazel notifications about gazelle and buildozer when running it
+ // Can also be solved by adding a root `.bazel_fix_commands.json` but its not needed at the moment
+
+ await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_0__["runIBazel"])(['--run_output=false', 'build', '//packages:build'], runOffline);
+ }
+
+};
+
+/***/ }),
+/* 516 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; });
-/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(515);
+/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(517);
/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(249);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(246);
/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(248);
/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(371);
-/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(558);
+/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(560);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -59697,7 +59879,7 @@ function toArray(value) {
}
/***/ }),
-/* 515 */
+/* 517 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -59716,8 +59898,8 @@ const util_1 = __webpack_require__(112);
const os_1 = tslib_1.__importDefault(__webpack_require__(121));
const fs_1 = tslib_1.__importDefault(__webpack_require__(134));
const path_1 = tslib_1.__importDefault(__webpack_require__(4));
-const axios_1 = tslib_1.__importDefault(__webpack_require__(516));
-const ci_stats_config_1 = __webpack_require__(556);
+const axios_1 = tslib_1.__importDefault(__webpack_require__(518));
+const ci_stats_config_1 = __webpack_require__(558);
const BASE_URL = 'https://ci-stats.kibana.dev';
class CiStatsReporter {
constructor(config, log) {
@@ -59805,7 +59987,7 @@ class CiStatsReporter {
// specify the module id in a way that will keep webpack from bundling extra code into @kbn/pm
const hideFromWebpack = ['@', 'kbn/utils'];
// eslint-disable-next-line @typescript-eslint/no-var-requires
- const { kibanaPackageJson } = __webpack_require__(557)(hideFromWebpack.join(''));
+ const { kibanaPackageJson } = __webpack_require__(559)(hideFromWebpack.join(''));
return kibanaPackageJson.branch;
}
/**
@@ -59817,7 +59999,7 @@ class CiStatsReporter {
// specify the module id in a way that will keep webpack from bundling extra code into @kbn/pm
const hideFromWebpack = ['@', 'kbn/utils'];
// eslint-disable-next-line @typescript-eslint/no-var-requires
- const { REPO_ROOT } = __webpack_require__(557)(hideFromWebpack.join(''));
+ const { REPO_ROOT } = __webpack_require__(559)(hideFromWebpack.join(''));
try {
return fs_1.default.readFileSync(path_1.default.resolve(REPO_ROOT, 'data/uuid'), 'utf-8').trim();
}
@@ -59880,23 +60062,23 @@ exports.CiStatsReporter = CiStatsReporter;
//# sourceMappingURL=ci_stats_reporter.js.map
/***/ }),
-/* 516 */
+/* 518 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = __webpack_require__(517);
+module.exports = __webpack_require__(519);
/***/ }),
-/* 517 */
+/* 519 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var bind = __webpack_require__(519);
-var Axios = __webpack_require__(520);
-var mergeConfig = __webpack_require__(551);
-var defaults = __webpack_require__(526);
+var utils = __webpack_require__(520);
+var bind = __webpack_require__(521);
+var Axios = __webpack_require__(522);
+var mergeConfig = __webpack_require__(553);
+var defaults = __webpack_require__(528);
/**
* Create an instance of Axios
@@ -59929,18 +60111,18 @@ axios.create = function create(instanceConfig) {
};
// Expose Cancel & CancelToken
-axios.Cancel = __webpack_require__(552);
-axios.CancelToken = __webpack_require__(553);
-axios.isCancel = __webpack_require__(525);
+axios.Cancel = __webpack_require__(554);
+axios.CancelToken = __webpack_require__(555);
+axios.isCancel = __webpack_require__(527);
// Expose all/spread
axios.all = function all(promises) {
return Promise.all(promises);
};
-axios.spread = __webpack_require__(554);
+axios.spread = __webpack_require__(556);
// Expose isAxiosError
-axios.isAxiosError = __webpack_require__(555);
+axios.isAxiosError = __webpack_require__(557);
module.exports = axios;
@@ -59949,13 +60131,13 @@ module.exports.default = axios;
/***/ }),
-/* 518 */
+/* 520 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var bind = __webpack_require__(519);
+var bind = __webpack_require__(521);
/*global toString:true*/
@@ -60307,7 +60489,7 @@ module.exports = {
/***/ }),
-/* 519 */
+/* 521 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -60325,17 +60507,17 @@ module.exports = function bind(fn, thisArg) {
/***/ }),
-/* 520 */
+/* 522 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var buildURL = __webpack_require__(521);
-var InterceptorManager = __webpack_require__(522);
-var dispatchRequest = __webpack_require__(523);
-var mergeConfig = __webpack_require__(551);
+var utils = __webpack_require__(520);
+var buildURL = __webpack_require__(523);
+var InterceptorManager = __webpack_require__(524);
+var dispatchRequest = __webpack_require__(525);
+var mergeConfig = __webpack_require__(553);
/**
* Create a new instance of Axios
@@ -60427,13 +60609,13 @@ module.exports = Axios;
/***/ }),
-/* 521 */
+/* 523 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
function encode(val) {
return encodeURIComponent(val).
@@ -60504,13 +60686,13 @@ module.exports = function buildURL(url, params, paramsSerializer) {
/***/ }),
-/* 522 */
+/* 524 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
function InterceptorManager() {
this.handlers = [];
@@ -60563,16 +60745,16 @@ module.exports = InterceptorManager;
/***/ }),
-/* 523 */
+/* 525 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var transformData = __webpack_require__(524);
-var isCancel = __webpack_require__(525);
-var defaults = __webpack_require__(526);
+var utils = __webpack_require__(520);
+var transformData = __webpack_require__(526);
+var isCancel = __webpack_require__(527);
+var defaults = __webpack_require__(528);
/**
* Throws a `Cancel` if cancellation has been requested.
@@ -60649,13 +60831,13 @@ module.exports = function dispatchRequest(config) {
/***/ }),
-/* 524 */
+/* 526 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
/**
* Transform the data for a request or a response
@@ -60676,7 +60858,7 @@ module.exports = function transformData(data, headers, fns) {
/***/ }),
-/* 525 */
+/* 527 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -60688,14 +60870,14 @@ module.exports = function isCancel(value) {
/***/ }),
-/* 526 */
+/* 528 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var normalizeHeaderName = __webpack_require__(527);
+var utils = __webpack_require__(520);
+var normalizeHeaderName = __webpack_require__(529);
var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded'
@@ -60711,10 +60893,10 @@ function getDefaultAdapter() {
var adapter;
if (typeof XMLHttpRequest !== 'undefined') {
// For browsers use XHR adapter
- adapter = __webpack_require__(528);
+ adapter = __webpack_require__(530);
} else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
// For node use HTTP adapter
- adapter = __webpack_require__(538);
+ adapter = __webpack_require__(540);
}
return adapter;
}
@@ -60793,13 +60975,13 @@ module.exports = defaults;
/***/ }),
-/* 527 */
+/* 529 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
module.exports = function normalizeHeaderName(headers, normalizedName) {
utils.forEach(headers, function processHeader(value, name) {
@@ -60812,20 +60994,20 @@ module.exports = function normalizeHeaderName(headers, normalizedName) {
/***/ }),
-/* 528 */
+/* 530 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var settle = __webpack_require__(529);
-var cookies = __webpack_require__(532);
-var buildURL = __webpack_require__(521);
-var buildFullPath = __webpack_require__(533);
-var parseHeaders = __webpack_require__(536);
-var isURLSameOrigin = __webpack_require__(537);
-var createError = __webpack_require__(530);
+var utils = __webpack_require__(520);
+var settle = __webpack_require__(531);
+var cookies = __webpack_require__(534);
+var buildURL = __webpack_require__(523);
+var buildFullPath = __webpack_require__(535);
+var parseHeaders = __webpack_require__(538);
+var isURLSameOrigin = __webpack_require__(539);
+var createError = __webpack_require__(532);
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
@@ -60998,13 +61180,13 @@ module.exports = function xhrAdapter(config) {
/***/ }),
-/* 529 */
+/* 531 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var createError = __webpack_require__(530);
+var createError = __webpack_require__(532);
/**
* Resolve or reject a Promise based on response status.
@@ -61030,13 +61212,13 @@ module.exports = function settle(resolve, reject, response) {
/***/ }),
-/* 530 */
+/* 532 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var enhanceError = __webpack_require__(531);
+var enhanceError = __webpack_require__(533);
/**
* Create an Error with the specified message, config, error code, request and response.
@@ -61055,7 +61237,7 @@ module.exports = function createError(message, config, code, request, response)
/***/ }),
-/* 531 */
+/* 533 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -61104,13 +61286,13 @@ module.exports = function enhanceError(error, config, code, request, response) {
/***/ }),
-/* 532 */
+/* 534 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
module.exports = (
utils.isStandardBrowserEnv() ?
@@ -61164,14 +61346,14 @@ module.exports = (
/***/ }),
-/* 533 */
+/* 535 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isAbsoluteURL = __webpack_require__(534);
-var combineURLs = __webpack_require__(535);
+var isAbsoluteURL = __webpack_require__(536);
+var combineURLs = __webpack_require__(537);
/**
* Creates a new URL by combining the baseURL with the requestedURL,
@@ -61191,7 +61373,7 @@ module.exports = function buildFullPath(baseURL, requestedURL) {
/***/ }),
-/* 534 */
+/* 536 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -61212,7 +61394,7 @@ module.exports = function isAbsoluteURL(url) {
/***/ }),
-/* 535 */
+/* 537 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -61233,13 +61415,13 @@ module.exports = function combineURLs(baseURL, relativeURL) {
/***/ }),
-/* 536 */
+/* 538 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
// Headers whose duplicates are ignored by node
// c.f. https://nodejs.org/api/http.html#http_message_headers
@@ -61293,13 +61475,13 @@ module.exports = function parseHeaders(headers) {
/***/ }),
-/* 537 */
+/* 539 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
module.exports = (
utils.isStandardBrowserEnv() ?
@@ -61368,25 +61550,25 @@ module.exports = (
/***/ }),
-/* 538 */
+/* 540 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
-var settle = __webpack_require__(529);
-var buildFullPath = __webpack_require__(533);
-var buildURL = __webpack_require__(521);
-var http = __webpack_require__(539);
-var https = __webpack_require__(540);
-var httpFollow = __webpack_require__(541).http;
-var httpsFollow = __webpack_require__(541).https;
+var utils = __webpack_require__(520);
+var settle = __webpack_require__(531);
+var buildFullPath = __webpack_require__(535);
+var buildURL = __webpack_require__(523);
+var http = __webpack_require__(541);
+var https = __webpack_require__(542);
+var httpFollow = __webpack_require__(543).http;
+var httpsFollow = __webpack_require__(543).https;
var url = __webpack_require__(283);
-var zlib = __webpack_require__(549);
-var pkg = __webpack_require__(550);
-var createError = __webpack_require__(530);
-var enhanceError = __webpack_require__(531);
+var zlib = __webpack_require__(551);
+var pkg = __webpack_require__(552);
+var createError = __webpack_require__(532);
+var enhanceError = __webpack_require__(533);
var isHttps = /https:?/;
@@ -61678,28 +61860,28 @@ module.exports = function httpAdapter(config) {
/***/ }),
-/* 539 */
+/* 541 */
/***/ (function(module, exports) {
module.exports = require("http");
/***/ }),
-/* 540 */
+/* 542 */
/***/ (function(module, exports) {
module.exports = require("https");
/***/ }),
-/* 541 */
+/* 543 */
/***/ (function(module, exports, __webpack_require__) {
var url = __webpack_require__(283);
var URL = url.URL;
-var http = __webpack_require__(539);
-var https = __webpack_require__(540);
+var http = __webpack_require__(541);
+var https = __webpack_require__(542);
var Writable = __webpack_require__(138).Writable;
var assert = __webpack_require__(140);
-var debug = __webpack_require__(542);
+var debug = __webpack_require__(544);
// Create handlers that pass events from native requests
var eventHandlers = Object.create(null);
@@ -62194,13 +62376,13 @@ module.exports.wrap = wrap;
/***/ }),
-/* 542 */
+/* 544 */
/***/ (function(module, exports, __webpack_require__) {
var debug;
try {
/* eslint global-require: off */
- debug = __webpack_require__(543)("follow-redirects");
+ debug = __webpack_require__(545)("follow-redirects");
}
catch (error) {
debug = function () { /* */ };
@@ -62209,7 +62391,7 @@ module.exports = debug;
/***/ }),
-/* 543 */
+/* 545 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -62218,14 +62400,14 @@ module.exports = debug;
*/
if (typeof process !== 'undefined' && process.type === 'renderer') {
- module.exports = __webpack_require__(544);
+ module.exports = __webpack_require__(546);
} else {
- module.exports = __webpack_require__(547);
+ module.exports = __webpack_require__(549);
}
/***/ }),
-/* 544 */
+/* 546 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -62234,7 +62416,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') {
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(545);
+exports = module.exports = __webpack_require__(547);
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
@@ -62416,7 +62598,7 @@ function localstorage() {
/***/ }),
-/* 545 */
+/* 547 */
/***/ (function(module, exports, __webpack_require__) {
@@ -62432,7 +62614,7 @@ exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
-exports.humanize = __webpack_require__(546);
+exports.humanize = __webpack_require__(548);
/**
* The currently active debug mode names, and names to skip.
@@ -62624,7 +62806,7 @@ function coerce(val) {
/***/ }),
-/* 546 */
+/* 548 */
/***/ (function(module, exports) {
/**
@@ -62782,7 +62964,7 @@ function plural(ms, n, name) {
/***/ }),
-/* 547 */
+/* 549 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -62798,7 +62980,7 @@ var util = __webpack_require__(112);
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(545);
+exports = module.exports = __webpack_require__(547);
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
@@ -62977,7 +63159,7 @@ function createWritableStdioStream (fd) {
case 'PIPE':
case 'TCP':
- var net = __webpack_require__(548);
+ var net = __webpack_require__(550);
stream = new net.Socket({
fd: fd,
readable: false,
@@ -63036,31 +63218,31 @@ exports.enable(load());
/***/ }),
-/* 548 */
+/* 550 */
/***/ (function(module, exports) {
module.exports = require("net");
/***/ }),
-/* 549 */
+/* 551 */
/***/ (function(module, exports) {
module.exports = require("zlib");
/***/ }),
-/* 550 */
+/* 552 */
/***/ (function(module) {
module.exports = JSON.parse("{\"name\":\"axios\",\"version\":\"0.21.1\",\"description\":\"Promise based HTTP client for the browser and node.js\",\"main\":\"index.js\",\"scripts\":{\"test\":\"grunt test && bundlesize\",\"start\":\"node ./sandbox/server.js\",\"build\":\"NODE_ENV=production grunt build\",\"preversion\":\"npm test\",\"version\":\"npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json\",\"postversion\":\"git push && git push --tags\",\"examples\":\"node ./examples/server.js\",\"coveralls\":\"cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\",\"fix\":\"eslint --fix lib/**/*.js\"},\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/axios/axios.git\"},\"keywords\":[\"xhr\",\"http\",\"ajax\",\"promise\",\"node\"],\"author\":\"Matt Zabriskie\",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/axios/axios/issues\"},\"homepage\":\"https://github.com/axios/axios\",\"devDependencies\":{\"bundlesize\":\"^0.17.0\",\"coveralls\":\"^3.0.0\",\"es6-promise\":\"^4.2.4\",\"grunt\":\"^1.0.2\",\"grunt-banner\":\"^0.6.0\",\"grunt-cli\":\"^1.2.0\",\"grunt-contrib-clean\":\"^1.1.0\",\"grunt-contrib-watch\":\"^1.0.0\",\"grunt-eslint\":\"^20.1.0\",\"grunt-karma\":\"^2.0.0\",\"grunt-mocha-test\":\"^0.13.3\",\"grunt-ts\":\"^6.0.0-beta.19\",\"grunt-webpack\":\"^1.0.18\",\"istanbul-instrumenter-loader\":\"^1.0.0\",\"jasmine-core\":\"^2.4.1\",\"karma\":\"^1.3.0\",\"karma-chrome-launcher\":\"^2.2.0\",\"karma-coverage\":\"^1.1.1\",\"karma-firefox-launcher\":\"^1.1.0\",\"karma-jasmine\":\"^1.1.1\",\"karma-jasmine-ajax\":\"^0.1.13\",\"karma-opera-launcher\":\"^1.0.0\",\"karma-safari-launcher\":\"^1.0.0\",\"karma-sauce-launcher\":\"^1.2.0\",\"karma-sinon\":\"^1.0.5\",\"karma-sourcemap-loader\":\"^0.3.7\",\"karma-webpack\":\"^1.7.0\",\"load-grunt-tasks\":\"^3.5.2\",\"minimist\":\"^1.2.0\",\"mocha\":\"^5.2.0\",\"sinon\":\"^4.5.0\",\"typescript\":\"^2.8.1\",\"url-search-params\":\"^0.10.0\",\"webpack\":\"^1.13.1\",\"webpack-dev-server\":\"^1.14.1\"},\"browser\":{\"./lib/adapters/http.js\":\"./lib/adapters/xhr.js\"},\"jsdelivr\":\"dist/axios.min.js\",\"unpkg\":\"dist/axios.min.js\",\"typings\":\"./index.d.ts\",\"dependencies\":{\"follow-redirects\":\"^1.10.0\"},\"bundlesize\":[{\"path\":\"./dist/axios.min.js\",\"threshold\":\"5kB\"}]}");
/***/ }),
-/* 551 */
+/* 553 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(518);
+var utils = __webpack_require__(520);
/**
* Config-specific merge-function which creates a new config-object
@@ -63148,7 +63330,7 @@ module.exports = function mergeConfig(config1, config2) {
/***/ }),
-/* 552 */
+/* 554 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63174,13 +63356,13 @@ module.exports = Cancel;
/***/ }),
-/* 553 */
+/* 555 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Cancel = __webpack_require__(552);
+var Cancel = __webpack_require__(554);
/**
* A `CancelToken` is an object that can be used to request cancellation of an operation.
@@ -63238,7 +63420,7 @@ module.exports = CancelToken;
/***/ }),
-/* 554 */
+/* 556 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63272,7 +63454,7 @@ module.exports = function spread(callback) {
/***/ }),
-/* 555 */
+/* 557 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63290,7 +63472,7 @@ module.exports = function isAxiosError(payload) {
/***/ }),
-/* 556 */
+/* 558 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63340,7 +63522,7 @@ exports.parseConfig = parseConfig;
//# sourceMappingURL=ci_stats_config.js.map
/***/ }),
-/* 557 */
+/* 559 */
/***/ (function(module, exports) {
function webpackEmptyContext(req) {
@@ -63351,10 +63533,10 @@ function webpackEmptyContext(req) {
webpackEmptyContext.keys = function() { return []; };
webpackEmptyContext.resolve = webpackEmptyContext;
module.exports = webpackEmptyContext;
-webpackEmptyContext.id = 557;
+webpackEmptyContext.id = 559;
/***/ }),
-/* 558 */
+/* 560 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -63364,13 +63546,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(559);
+/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(561);
/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239);
/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(366);
/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(248);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(562);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(564);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -63534,15 +63716,15 @@ class Kibana {
}
/***/ }),
-/* 559 */
+/* 561 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const minimatch = __webpack_require__(150);
const arrayUnion = __webpack_require__(145);
-const arrayDiffer = __webpack_require__(560);
-const arrify = __webpack_require__(561);
+const arrayDiffer = __webpack_require__(562);
+const arrify = __webpack_require__(563);
module.exports = (list, patterns, options = {}) => {
list = arrify(list);
@@ -63566,7 +63748,7 @@ module.exports = (list, patterns, options = {}) => {
/***/ }),
-/* 560 */
+/* 562 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63581,7 +63763,7 @@ module.exports = arrayDiffer;
/***/ }),
-/* 561 */
+/* 563 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63611,7 +63793,7 @@ module.exports = arrify;
/***/ }),
-/* 562 */
+/* 564 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -63670,15 +63852,15 @@ function getProjectPaths({
}
/***/ }),
-/* 563 */
+/* 565 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(564);
+/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(566);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildBazelProductionProjects"]; });
-/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(812);
+/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(814);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; });
/*
@@ -63692,19 +63874,19 @@ __webpack_require__.r(__webpack_exports__);
/***/ }),
-/* 564 */
+/* 566 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return buildBazelProductionProjects; });
-/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(565);
+/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(567);
/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(774);
+/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(776);
/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(globby__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(812);
+/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(814);
/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(372);
/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(131);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(246);
@@ -63799,7 +63981,7 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) {
}
/***/ }),
-/* 565 */
+/* 567 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63807,14 +63989,14 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) {
const EventEmitter = __webpack_require__(156);
const path = __webpack_require__(4);
const os = __webpack_require__(121);
-const pMap = __webpack_require__(566);
-const arrify = __webpack_require__(561);
-const globby = __webpack_require__(569);
-const hasGlob = __webpack_require__(758);
-const cpFile = __webpack_require__(760);
-const junk = __webpack_require__(770);
-const pFilter = __webpack_require__(771);
-const CpyError = __webpack_require__(773);
+const pMap = __webpack_require__(568);
+const arrify = __webpack_require__(563);
+const globby = __webpack_require__(571);
+const hasGlob = __webpack_require__(760);
+const cpFile = __webpack_require__(762);
+const junk = __webpack_require__(772);
+const pFilter = __webpack_require__(773);
+const CpyError = __webpack_require__(775);
const defaultOptions = {
ignoreJunk: true
@@ -63965,12 +64147,12 @@ module.exports = (source, destination, {
/***/ }),
-/* 566 */
+/* 568 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const AggregateError = __webpack_require__(567);
+const AggregateError = __webpack_require__(569);
module.exports = async (
iterable,
@@ -64053,12 +64235,12 @@ module.exports = async (
/***/ }),
-/* 567 */
+/* 569 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const indentString = __webpack_require__(568);
+const indentString = __webpack_require__(570);
const cleanStack = __webpack_require__(244);
const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, '');
@@ -64107,7 +64289,7 @@ module.exports = AggregateError;
/***/ }),
-/* 568 */
+/* 570 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64149,17 +64331,17 @@ module.exports = (string, count = 1, options) => {
/***/ }),
-/* 569 */
+/* 571 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(134);
-const arrayUnion = __webpack_require__(570);
+const arrayUnion = __webpack_require__(572);
const glob = __webpack_require__(147);
-const fastGlob = __webpack_require__(572);
-const dirGlob = __webpack_require__(751);
-const gitignore = __webpack_require__(754);
+const fastGlob = __webpack_require__(574);
+const dirGlob = __webpack_require__(753);
+const gitignore = __webpack_require__(756);
const DEFAULT_FILTER = () => false;
@@ -64304,12 +64486,12 @@ module.exports.gitignore = gitignore;
/***/ }),
-/* 570 */
+/* 572 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var arrayUniq = __webpack_require__(571);
+var arrayUniq = __webpack_require__(573);
module.exports = function () {
return arrayUniq([].concat.apply([], arguments));
@@ -64317,7 +64499,7 @@ module.exports = function () {
/***/ }),
-/* 571 */
+/* 573 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64386,10 +64568,10 @@ if ('Set' in global) {
/***/ }),
-/* 572 */
+/* 574 */
/***/ (function(module, exports, __webpack_require__) {
-const pkg = __webpack_require__(573);
+const pkg = __webpack_require__(575);
module.exports = pkg.async;
module.exports.default = pkg.async;
@@ -64402,19 +64584,19 @@ module.exports.generateTasks = pkg.generateTasks;
/***/ }),
-/* 573 */
+/* 575 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var optionsManager = __webpack_require__(574);
-var taskManager = __webpack_require__(575);
-var reader_async_1 = __webpack_require__(722);
-var reader_stream_1 = __webpack_require__(746);
-var reader_sync_1 = __webpack_require__(747);
-var arrayUtils = __webpack_require__(749);
-var streamUtils = __webpack_require__(750);
+var optionsManager = __webpack_require__(576);
+var taskManager = __webpack_require__(577);
+var reader_async_1 = __webpack_require__(724);
+var reader_stream_1 = __webpack_require__(748);
+var reader_sync_1 = __webpack_require__(749);
+var arrayUtils = __webpack_require__(751);
+var streamUtils = __webpack_require__(752);
/**
* Synchronous API.
*/
@@ -64480,7 +64662,7 @@ function isString(source) {
/***/ }),
-/* 574 */
+/* 576 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64518,13 +64700,13 @@ exports.prepare = prepare;
/***/ }),
-/* 575 */
+/* 577 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var patternUtils = __webpack_require__(576);
+var patternUtils = __webpack_require__(578);
/**
* Generate tasks based on parent directory of each pattern.
*/
@@ -64615,16 +64797,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask;
/***/ }),
-/* 576 */
+/* 578 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var path = __webpack_require__(4);
-var globParent = __webpack_require__(577);
+var globParent = __webpack_require__(579);
var isGlob = __webpack_require__(172);
-var micromatch = __webpack_require__(580);
+var micromatch = __webpack_require__(582);
var GLOBSTAR = '**';
/**
* Return true for static pattern.
@@ -64770,15 +64952,15 @@ exports.matchAny = matchAny;
/***/ }),
-/* 577 */
+/* 579 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var path = __webpack_require__(4);
-var isglob = __webpack_require__(578);
-var pathDirname = __webpack_require__(579);
+var isglob = __webpack_require__(580);
+var pathDirname = __webpack_require__(581);
var isWin32 = __webpack_require__(121).platform() === 'win32';
module.exports = function globParent(str) {
@@ -64801,7 +64983,7 @@ module.exports = function globParent(str) {
/***/ }),
-/* 578 */
+/* 580 */
/***/ (function(module, exports, __webpack_require__) {
/*!
@@ -64832,7 +65014,7 @@ module.exports = function isGlob(str) {
/***/ }),
-/* 579 */
+/* 581 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64982,7 +65164,7 @@ module.exports.win32 = win32;
/***/ }),
-/* 580 */
+/* 582 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64993,18 +65175,18 @@ module.exports.win32 = win32;
*/
var util = __webpack_require__(112);
-var braces = __webpack_require__(581);
-var toRegex = __webpack_require__(582);
-var extend = __webpack_require__(690);
+var braces = __webpack_require__(583);
+var toRegex = __webpack_require__(584);
+var extend = __webpack_require__(692);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(692);
-var parsers = __webpack_require__(718);
-var cache = __webpack_require__(719);
-var utils = __webpack_require__(720);
+var compilers = __webpack_require__(694);
+var parsers = __webpack_require__(720);
+var cache = __webpack_require__(721);
+var utils = __webpack_require__(722);
var MAX_LENGTH = 1024 * 64;
/**
@@ -65866,7 +66048,7 @@ module.exports = micromatch;
/***/ }),
-/* 581 */
+/* 583 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -65876,18 +66058,18 @@ module.exports = micromatch;
* Module dependencies
*/
-var toRegex = __webpack_require__(582);
-var unique = __webpack_require__(602);
-var extend = __webpack_require__(603);
+var toRegex = __webpack_require__(584);
+var unique = __webpack_require__(604);
+var extend = __webpack_require__(605);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(605);
-var parsers = __webpack_require__(618);
-var Braces = __webpack_require__(623);
-var utils = __webpack_require__(606);
+var compilers = __webpack_require__(607);
+var parsers = __webpack_require__(620);
+var Braces = __webpack_require__(625);
+var utils = __webpack_require__(608);
var MAX_LENGTH = 1024 * 64;
var cache = {};
@@ -66191,16 +66373,16 @@ module.exports = braces;
/***/ }),
-/* 582 */
+/* 584 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var safe = __webpack_require__(583);
-var define = __webpack_require__(589);
-var extend = __webpack_require__(595);
-var not = __webpack_require__(599);
+var safe = __webpack_require__(585);
+var define = __webpack_require__(591);
+var extend = __webpack_require__(597);
+var not = __webpack_require__(601);
var MAX_LENGTH = 1024 * 64;
/**
@@ -66353,10 +66535,10 @@ module.exports.makeRe = makeRe;
/***/ }),
-/* 583 */
+/* 585 */
/***/ (function(module, exports, __webpack_require__) {
-var parse = __webpack_require__(584);
+var parse = __webpack_require__(586);
var types = parse.types;
module.exports = function (re, opts) {
@@ -66402,13 +66584,13 @@ function isRegExp (x) {
/***/ }),
-/* 584 */
+/* 586 */
/***/ (function(module, exports, __webpack_require__) {
-var util = __webpack_require__(585);
-var types = __webpack_require__(586);
-var sets = __webpack_require__(587);
-var positions = __webpack_require__(588);
+var util = __webpack_require__(587);
+var types = __webpack_require__(588);
+var sets = __webpack_require__(589);
+var positions = __webpack_require__(590);
module.exports = function(regexpStr) {
@@ -66690,11 +66872,11 @@ module.exports.types = types;
/***/ }),
-/* 585 */
+/* 587 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(586);
-var sets = __webpack_require__(587);
+var types = __webpack_require__(588);
+var sets = __webpack_require__(589);
// All of these are private and only used by randexp.
@@ -66807,7 +66989,7 @@ exports.error = function(regexp, msg) {
/***/ }),
-/* 586 */
+/* 588 */
/***/ (function(module, exports) {
module.exports = {
@@ -66823,10 +67005,10 @@ module.exports = {
/***/ }),
-/* 587 */
+/* 589 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(586);
+var types = __webpack_require__(588);
var INTS = function() {
return [{ type: types.RANGE , from: 48, to: 57 }];
@@ -66911,10 +67093,10 @@ exports.anyChar = function() {
/***/ }),
-/* 588 */
+/* 590 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(586);
+var types = __webpack_require__(588);
exports.wordBoundary = function() {
return { type: types.POSITION, value: 'b' };
@@ -66934,7 +67116,7 @@ exports.end = function() {
/***/ }),
-/* 589 */
+/* 591 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66947,8 +67129,8 @@ exports.end = function() {
-var isobject = __webpack_require__(590);
-var isDescriptor = __webpack_require__(591);
+var isobject = __webpack_require__(592);
+var isDescriptor = __webpack_require__(593);
var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
? Reflect.defineProperty
: Object.defineProperty;
@@ -66979,7 +67161,7 @@ module.exports = function defineProperty(obj, key, val) {
/***/ }),
-/* 590 */
+/* 592 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66998,7 +67180,7 @@ module.exports = function isObject(val) {
/***/ }),
-/* 591 */
+/* 593 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67011,9 +67193,9 @@ module.exports = function isObject(val) {
-var typeOf = __webpack_require__(592);
-var isAccessor = __webpack_require__(593);
-var isData = __webpack_require__(594);
+var typeOf = __webpack_require__(594);
+var isAccessor = __webpack_require__(595);
+var isData = __webpack_require__(596);
module.exports = function isDescriptor(obj, key) {
if (typeOf(obj) !== 'object') {
@@ -67027,7 +67209,7 @@ module.exports = function isDescriptor(obj, key) {
/***/ }),
-/* 592 */
+/* 594 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -67162,7 +67344,7 @@ function isBuffer(val) {
/***/ }),
-/* 593 */
+/* 595 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67175,7 +67357,7 @@ function isBuffer(val) {
-var typeOf = __webpack_require__(592);
+var typeOf = __webpack_require__(594);
// accessor descriptor properties
var accessor = {
@@ -67238,7 +67420,7 @@ module.exports = isAccessorDescriptor;
/***/ }),
-/* 594 */
+/* 596 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67251,7 +67433,7 @@ module.exports = isAccessorDescriptor;
-var typeOf = __webpack_require__(592);
+var typeOf = __webpack_require__(594);
module.exports = function isDataDescriptor(obj, prop) {
// data descriptor properties
@@ -67294,14 +67476,14 @@ module.exports = function isDataDescriptor(obj, prop) {
/***/ }),
-/* 595 */
+/* 597 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(596);
-var assignSymbols = __webpack_require__(598);
+var isExtendable = __webpack_require__(598);
+var assignSymbols = __webpack_require__(600);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -67361,7 +67543,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 596 */
+/* 598 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67374,7 +67556,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -67382,7 +67564,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 597 */
+/* 599 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67395,7 +67577,7 @@ module.exports = function isExtendable(val) {
-var isObject = __webpack_require__(590);
+var isObject = __webpack_require__(592);
function isObjectObject(o) {
return isObject(o) === true
@@ -67426,7 +67608,7 @@ module.exports = function isPlainObject(o) {
/***/ }),
-/* 598 */
+/* 600 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67473,14 +67655,14 @@ module.exports = function(receiver, objects) {
/***/ }),
-/* 599 */
+/* 601 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extend = __webpack_require__(600);
-var safe = __webpack_require__(583);
+var extend = __webpack_require__(602);
+var safe = __webpack_require__(585);
/**
* The main export is a function that takes a `pattern` string and an `options` object.
@@ -67552,14 +67734,14 @@ module.exports = toRegex;
/***/ }),
-/* 600 */
+/* 602 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(601);
-var assignSymbols = __webpack_require__(598);
+var isExtendable = __webpack_require__(603);
+var assignSymbols = __webpack_require__(600);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -67619,7 +67801,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 601 */
+/* 603 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67632,7 +67814,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -67640,7 +67822,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 602 */
+/* 604 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67690,13 +67872,13 @@ module.exports.immutable = function uniqueImmutable(arr) {
/***/ }),
-/* 603 */
+/* 605 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(604);
+var isObject = __webpack_require__(606);
module.exports = function extend(o/*, objects*/) {
if (!isObject(o)) { o = {}; }
@@ -67730,7 +67912,7 @@ function hasOwn(obj, key) {
/***/ }),
-/* 604 */
+/* 606 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67750,13 +67932,13 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 605 */
+/* 607 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(606);
+var utils = __webpack_require__(608);
module.exports = function(braces, options) {
braces.compiler
@@ -68039,25 +68221,25 @@ function hasQueue(node) {
/***/ }),
-/* 606 */
+/* 608 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var splitString = __webpack_require__(607);
+var splitString = __webpack_require__(609);
var utils = module.exports;
/**
* Module dependencies
*/
-utils.extend = __webpack_require__(603);
-utils.flatten = __webpack_require__(610);
-utils.isObject = __webpack_require__(590);
-utils.fillRange = __webpack_require__(611);
-utils.repeat = __webpack_require__(617);
-utils.unique = __webpack_require__(602);
+utils.extend = __webpack_require__(605);
+utils.flatten = __webpack_require__(612);
+utils.isObject = __webpack_require__(592);
+utils.fillRange = __webpack_require__(613);
+utils.repeat = __webpack_require__(619);
+utils.unique = __webpack_require__(604);
utils.define = function(obj, key, val) {
Object.defineProperty(obj, key, {
@@ -68389,7 +68571,7 @@ utils.escapeRegex = function(str) {
/***/ }),
-/* 607 */
+/* 609 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68402,7 +68584,7 @@ utils.escapeRegex = function(str) {
-var extend = __webpack_require__(608);
+var extend = __webpack_require__(610);
module.exports = function(str, options, fn) {
if (typeof str !== 'string') {
@@ -68567,14 +68749,14 @@ function keepEscaping(opts, str, idx) {
/***/ }),
-/* 608 */
+/* 610 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(609);
-var assignSymbols = __webpack_require__(598);
+var isExtendable = __webpack_require__(611);
+var assignSymbols = __webpack_require__(600);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -68634,7 +68816,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 609 */
+/* 611 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68647,7 +68829,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -68655,7 +68837,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 610 */
+/* 612 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68684,7 +68866,7 @@ function flat(arr, res) {
/***/ }),
-/* 611 */
+/* 613 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68698,10 +68880,10 @@ function flat(arr, res) {
var util = __webpack_require__(112);
-var isNumber = __webpack_require__(612);
-var extend = __webpack_require__(603);
-var repeat = __webpack_require__(615);
-var toRegex = __webpack_require__(616);
+var isNumber = __webpack_require__(614);
+var extend = __webpack_require__(605);
+var repeat = __webpack_require__(617);
+var toRegex = __webpack_require__(618);
/**
* Return a range of numbers or letters.
@@ -68899,7 +69081,7 @@ module.exports = fillRange;
/***/ }),
-/* 612 */
+/* 614 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68912,7 +69094,7 @@ module.exports = fillRange;
-var typeOf = __webpack_require__(613);
+var typeOf = __webpack_require__(615);
module.exports = function isNumber(num) {
var type = typeOf(num);
@@ -68928,10 +69110,10 @@ module.exports = function isNumber(num) {
/***/ }),
-/* 613 */
+/* 615 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -69050,7 +69232,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 614 */
+/* 616 */
/***/ (function(module, exports) {
/*!
@@ -69077,7 +69259,7 @@ function isSlowBuffer (obj) {
/***/ }),
-/* 615 */
+/* 617 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69154,7 +69336,7 @@ function repeat(str, num) {
/***/ }),
-/* 616 */
+/* 618 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69167,8 +69349,8 @@ function repeat(str, num) {
-var repeat = __webpack_require__(615);
-var isNumber = __webpack_require__(612);
+var repeat = __webpack_require__(617);
+var isNumber = __webpack_require__(614);
var cache = {};
function toRegexRange(min, max, options) {
@@ -69455,7 +69637,7 @@ module.exports = toRegexRange;
/***/ }),
-/* 617 */
+/* 619 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69480,14 +69662,14 @@ module.exports = function repeat(ele, num) {
/***/ }),
-/* 618 */
+/* 620 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Node = __webpack_require__(619);
-var utils = __webpack_require__(606);
+var Node = __webpack_require__(621);
+var utils = __webpack_require__(608);
/**
* Braces parsers
@@ -69847,15 +70029,15 @@ function concatNodes(pos, node, parent, options) {
/***/ }),
-/* 619 */
+/* 621 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(590);
-var define = __webpack_require__(620);
-var utils = __webpack_require__(621);
+var isObject = __webpack_require__(592);
+var define = __webpack_require__(622);
+var utils = __webpack_require__(623);
var ownNames;
/**
@@ -70346,7 +70528,7 @@ exports = module.exports = Node;
/***/ }),
-/* 620 */
+/* 622 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70359,7 +70541,7 @@ exports = module.exports = Node;
-var isDescriptor = __webpack_require__(591);
+var isDescriptor = __webpack_require__(593);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -70384,13 +70566,13 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 621 */
+/* 623 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var typeOf = __webpack_require__(622);
+var typeOf = __webpack_require__(624);
var utils = module.exports;
/**
@@ -71410,10 +71592,10 @@ function assert(val, message) {
/***/ }),
-/* 622 */
+/* 624 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -71532,17 +71714,17 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 623 */
+/* 625 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extend = __webpack_require__(603);
-var Snapdragon = __webpack_require__(624);
-var compilers = __webpack_require__(605);
-var parsers = __webpack_require__(618);
-var utils = __webpack_require__(606);
+var extend = __webpack_require__(605);
+var Snapdragon = __webpack_require__(626);
+var compilers = __webpack_require__(607);
+var parsers = __webpack_require__(620);
+var utils = __webpack_require__(608);
/**
* Customize Snapdragon parser and renderer
@@ -71643,17 +71825,17 @@ module.exports = Braces;
/***/ }),
-/* 624 */
+/* 626 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Base = __webpack_require__(625);
-var define = __webpack_require__(653);
-var Compiler = __webpack_require__(664);
-var Parser = __webpack_require__(687);
-var utils = __webpack_require__(667);
+var Base = __webpack_require__(627);
+var define = __webpack_require__(655);
+var Compiler = __webpack_require__(666);
+var Parser = __webpack_require__(689);
+var utils = __webpack_require__(669);
var regexCache = {};
var cache = {};
@@ -71824,20 +72006,20 @@ module.exports.Parser = Parser;
/***/ }),
-/* 625 */
+/* 627 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(112);
-var define = __webpack_require__(626);
-var CacheBase = __webpack_require__(627);
-var Emitter = __webpack_require__(628);
-var isObject = __webpack_require__(590);
-var merge = __webpack_require__(647);
-var pascal = __webpack_require__(650);
-var cu = __webpack_require__(651);
+var define = __webpack_require__(628);
+var CacheBase = __webpack_require__(629);
+var Emitter = __webpack_require__(630);
+var isObject = __webpack_require__(592);
+var merge = __webpack_require__(649);
+var pascal = __webpack_require__(652);
+var cu = __webpack_require__(653);
/**
* Optionally define a custom `cache` namespace to use.
@@ -72266,7 +72448,7 @@ module.exports.namespace = namespace;
/***/ }),
-/* 626 */
+/* 628 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72279,7 +72461,7 @@ module.exports.namespace = namespace;
-var isDescriptor = __webpack_require__(591);
+var isDescriptor = __webpack_require__(593);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -72304,21 +72486,21 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 627 */
+/* 629 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(590);
-var Emitter = __webpack_require__(628);
-var visit = __webpack_require__(629);
-var toPath = __webpack_require__(632);
-var union = __webpack_require__(634);
-var del = __webpack_require__(638);
-var get = __webpack_require__(636);
-var has = __webpack_require__(643);
-var set = __webpack_require__(646);
+var isObject = __webpack_require__(592);
+var Emitter = __webpack_require__(630);
+var visit = __webpack_require__(631);
+var toPath = __webpack_require__(634);
+var union = __webpack_require__(636);
+var del = __webpack_require__(640);
+var get = __webpack_require__(638);
+var has = __webpack_require__(645);
+var set = __webpack_require__(648);
/**
* Create a `Cache` constructor that when instantiated will
@@ -72572,7 +72754,7 @@ module.exports.namespace = namespace;
/***/ }),
-/* 628 */
+/* 630 */
/***/ (function(module, exports, __webpack_require__) {
@@ -72741,7 +72923,7 @@ Emitter.prototype.hasListeners = function(event){
/***/ }),
-/* 629 */
+/* 631 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72754,8 +72936,8 @@ Emitter.prototype.hasListeners = function(event){
-var visit = __webpack_require__(630);
-var mapVisit = __webpack_require__(631);
+var visit = __webpack_require__(632);
+var mapVisit = __webpack_require__(633);
module.exports = function(collection, method, val) {
var result;
@@ -72778,7 +72960,7 @@ module.exports = function(collection, method, val) {
/***/ }),
-/* 630 */
+/* 632 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72791,7 +72973,7 @@ module.exports = function(collection, method, val) {
-var isObject = __webpack_require__(590);
+var isObject = __webpack_require__(592);
module.exports = function visit(thisArg, method, target, val) {
if (!isObject(thisArg) && typeof thisArg !== 'function') {
@@ -72818,14 +73000,14 @@ module.exports = function visit(thisArg, method, target, val) {
/***/ }),
-/* 631 */
+/* 633 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(112);
-var visit = __webpack_require__(630);
+var visit = __webpack_require__(632);
/**
* Map `visit` over an array of objects.
@@ -72862,7 +73044,7 @@ function isObject(val) {
/***/ }),
-/* 632 */
+/* 634 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72875,7 +73057,7 @@ function isObject(val) {
-var typeOf = __webpack_require__(633);
+var typeOf = __webpack_require__(635);
module.exports = function toPath(args) {
if (typeOf(args) !== 'arguments') {
@@ -72902,10 +73084,10 @@ function filter(arr) {
/***/ }),
-/* 633 */
+/* 635 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -73024,16 +73206,16 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 634 */
+/* 636 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(604);
-var union = __webpack_require__(635);
-var get = __webpack_require__(636);
-var set = __webpack_require__(637);
+var isObject = __webpack_require__(606);
+var union = __webpack_require__(637);
+var get = __webpack_require__(638);
+var set = __webpack_require__(639);
module.exports = function unionValue(obj, prop, value) {
if (!isObject(obj)) {
@@ -73061,7 +73243,7 @@ function arrayify(val) {
/***/ }),
-/* 635 */
+/* 637 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73097,7 +73279,7 @@ module.exports = function union(init) {
/***/ }),
-/* 636 */
+/* 638 */
/***/ (function(module, exports) {
/*!
@@ -73153,7 +73335,7 @@ function toString(val) {
/***/ }),
-/* 637 */
+/* 639 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73166,10 +73348,10 @@ function toString(val) {
-var split = __webpack_require__(607);
-var extend = __webpack_require__(603);
-var isPlainObject = __webpack_require__(597);
-var isObject = __webpack_require__(604);
+var split = __webpack_require__(609);
+var extend = __webpack_require__(605);
+var isPlainObject = __webpack_require__(599);
+var isObject = __webpack_require__(606);
module.exports = function(obj, prop, val) {
if (!isObject(obj)) {
@@ -73215,7 +73397,7 @@ function isValidKey(key) {
/***/ }),
-/* 638 */
+/* 640 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73228,8 +73410,8 @@ function isValidKey(key) {
-var isObject = __webpack_require__(590);
-var has = __webpack_require__(639);
+var isObject = __webpack_require__(592);
+var has = __webpack_require__(641);
module.exports = function unset(obj, prop) {
if (!isObject(obj)) {
@@ -73254,7 +73436,7 @@ module.exports = function unset(obj, prop) {
/***/ }),
-/* 639 */
+/* 641 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73267,9 +73449,9 @@ module.exports = function unset(obj, prop) {
-var isObject = __webpack_require__(640);
-var hasValues = __webpack_require__(642);
-var get = __webpack_require__(636);
+var isObject = __webpack_require__(642);
+var hasValues = __webpack_require__(644);
+var get = __webpack_require__(638);
module.exports = function(obj, prop, noZero) {
if (isObject(obj)) {
@@ -73280,7 +73462,7 @@ module.exports = function(obj, prop, noZero) {
/***/ }),
-/* 640 */
+/* 642 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73293,7 +73475,7 @@ module.exports = function(obj, prop, noZero) {
-var isArray = __webpack_require__(641);
+var isArray = __webpack_require__(643);
module.exports = function isObject(val) {
return val != null && typeof val === 'object' && isArray(val) === false;
@@ -73301,7 +73483,7 @@ module.exports = function isObject(val) {
/***/ }),
-/* 641 */
+/* 643 */
/***/ (function(module, exports) {
var toString = {}.toString;
@@ -73312,7 +73494,7 @@ module.exports = Array.isArray || function (arr) {
/***/ }),
-/* 642 */
+/* 644 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73355,7 +73537,7 @@ module.exports = function hasValue(o, noZero) {
/***/ }),
-/* 643 */
+/* 645 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73368,9 +73550,9 @@ module.exports = function hasValue(o, noZero) {
-var isObject = __webpack_require__(590);
-var hasValues = __webpack_require__(644);
-var get = __webpack_require__(636);
+var isObject = __webpack_require__(592);
+var hasValues = __webpack_require__(646);
+var get = __webpack_require__(638);
module.exports = function(val, prop) {
return hasValues(isObject(val) && prop ? get(val, prop) : val);
@@ -73378,7 +73560,7 @@ module.exports = function(val, prop) {
/***/ }),
-/* 644 */
+/* 646 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73391,8 +73573,8 @@ module.exports = function(val, prop) {
-var typeOf = __webpack_require__(645);
-var isNumber = __webpack_require__(612);
+var typeOf = __webpack_require__(647);
+var isNumber = __webpack_require__(614);
module.exports = function hasValue(val) {
// is-number checks for NaN and other edge cases
@@ -73445,10 +73627,10 @@ module.exports = function hasValue(val) {
/***/ }),
-/* 645 */
+/* 647 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -73570,7 +73752,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 646 */
+/* 648 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73583,10 +73765,10 @@ module.exports = function kindOf(val) {
-var split = __webpack_require__(607);
-var extend = __webpack_require__(603);
-var isPlainObject = __webpack_require__(597);
-var isObject = __webpack_require__(604);
+var split = __webpack_require__(609);
+var extend = __webpack_require__(605);
+var isPlainObject = __webpack_require__(599);
+var isObject = __webpack_require__(606);
module.exports = function(obj, prop, val) {
if (!isObject(obj)) {
@@ -73632,14 +73814,14 @@ function isValidKey(key) {
/***/ }),
-/* 647 */
+/* 649 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(648);
-var forIn = __webpack_require__(649);
+var isExtendable = __webpack_require__(650);
+var forIn = __webpack_require__(651);
function mixinDeep(target, objects) {
var len = arguments.length, i = 0;
@@ -73703,7 +73885,7 @@ module.exports = mixinDeep;
/***/ }),
-/* 648 */
+/* 650 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73716,7 +73898,7 @@ module.exports = mixinDeep;
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -73724,7 +73906,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 649 */
+/* 651 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73747,7 +73929,7 @@ module.exports = function forIn(obj, fn, thisArg) {
/***/ }),
-/* 650 */
+/* 652 */
/***/ (function(module, exports) {
/*!
@@ -73774,14 +73956,14 @@ module.exports = pascalcase;
/***/ }),
-/* 651 */
+/* 653 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(112);
-var utils = __webpack_require__(652);
+var utils = __webpack_require__(654);
/**
* Expose class utils
@@ -74146,7 +74328,7 @@ cu.bubble = function(Parent, events) {
/***/ }),
-/* 652 */
+/* 654 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74160,10 +74342,10 @@ var utils = {};
* Lazily required module dependencies
*/
-utils.union = __webpack_require__(635);
-utils.define = __webpack_require__(653);
-utils.isObj = __webpack_require__(590);
-utils.staticExtend = __webpack_require__(660);
+utils.union = __webpack_require__(637);
+utils.define = __webpack_require__(655);
+utils.isObj = __webpack_require__(592);
+utils.staticExtend = __webpack_require__(662);
/**
@@ -74174,7 +74356,7 @@ module.exports = utils;
/***/ }),
-/* 653 */
+/* 655 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74187,7 +74369,7 @@ module.exports = utils;
-var isDescriptor = __webpack_require__(654);
+var isDescriptor = __webpack_require__(656);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -74212,7 +74394,7 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 654 */
+/* 656 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74225,9 +74407,9 @@ module.exports = function defineProperty(obj, prop, val) {
-var typeOf = __webpack_require__(655);
-var isAccessor = __webpack_require__(656);
-var isData = __webpack_require__(658);
+var typeOf = __webpack_require__(657);
+var isAccessor = __webpack_require__(658);
+var isData = __webpack_require__(660);
module.exports = function isDescriptor(obj, key) {
if (typeOf(obj) !== 'object') {
@@ -74241,7 +74423,7 @@ module.exports = function isDescriptor(obj, key) {
/***/ }),
-/* 655 */
+/* 657 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -74394,7 +74576,7 @@ function isBuffer(val) {
/***/ }),
-/* 656 */
+/* 658 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74407,7 +74589,7 @@ function isBuffer(val) {
-var typeOf = __webpack_require__(657);
+var typeOf = __webpack_require__(659);
// accessor descriptor properties
var accessor = {
@@ -74470,10 +74652,10 @@ module.exports = isAccessorDescriptor;
/***/ }),
-/* 657 */
+/* 659 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -74592,7 +74774,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 658 */
+/* 660 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74605,7 +74787,7 @@ module.exports = function kindOf(val) {
-var typeOf = __webpack_require__(659);
+var typeOf = __webpack_require__(661);
// data descriptor properties
var data = {
@@ -74654,10 +74836,10 @@ module.exports = isDataDescriptor;
/***/ }),
-/* 659 */
+/* 661 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -74776,7 +74958,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 660 */
+/* 662 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74789,8 +74971,8 @@ module.exports = function kindOf(val) {
-var copy = __webpack_require__(661);
-var define = __webpack_require__(653);
+var copy = __webpack_require__(663);
+var define = __webpack_require__(655);
var util = __webpack_require__(112);
/**
@@ -74873,15 +75055,15 @@ module.exports = extend;
/***/ }),
-/* 661 */
+/* 663 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var typeOf = __webpack_require__(662);
-var copyDescriptor = __webpack_require__(663);
-var define = __webpack_require__(653);
+var typeOf = __webpack_require__(664);
+var copyDescriptor = __webpack_require__(665);
+var define = __webpack_require__(655);
/**
* Copy static properties, prototype properties, and descriptors from one object to another.
@@ -75054,10 +75236,10 @@ module.exports.has = has;
/***/ }),
-/* 662 */
+/* 664 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(614);
+var isBuffer = __webpack_require__(616);
var toString = Object.prototype.toString;
/**
@@ -75176,7 +75358,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 663 */
+/* 665 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75264,16 +75446,16 @@ function isObject(val) {
/***/ }),
-/* 664 */
+/* 666 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var use = __webpack_require__(665);
-var define = __webpack_require__(653);
-var debug = __webpack_require__(543)('snapdragon:compiler');
-var utils = __webpack_require__(667);
+var use = __webpack_require__(667);
+var define = __webpack_require__(655);
+var debug = __webpack_require__(545)('snapdragon:compiler');
+var utils = __webpack_require__(669);
/**
* Create a new `Compiler` with the given `options`.
@@ -75427,7 +75609,7 @@ Compiler.prototype = {
// source map support
if (opts.sourcemap) {
- var sourcemaps = __webpack_require__(686);
+ var sourcemaps = __webpack_require__(688);
sourcemaps(this);
this.mapVisit(this.ast.nodes);
this.applySourceMaps();
@@ -75448,7 +75630,7 @@ module.exports = Compiler;
/***/ }),
-/* 665 */
+/* 667 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75461,7 +75643,7 @@ module.exports = Compiler;
-var utils = __webpack_require__(666);
+var utils = __webpack_require__(668);
module.exports = function base(app, opts) {
if (!utils.isObject(app) && typeof app !== 'function') {
@@ -75576,7 +75758,7 @@ module.exports = function base(app, opts) {
/***/ }),
-/* 666 */
+/* 668 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75590,8 +75772,8 @@ var utils = {};
* Lazily required module dependencies
*/
-utils.define = __webpack_require__(653);
-utils.isObject = __webpack_require__(590);
+utils.define = __webpack_require__(655);
+utils.isObject = __webpack_require__(592);
utils.isString = function(val) {
@@ -75606,7 +75788,7 @@ module.exports = utils;
/***/ }),
-/* 667 */
+/* 669 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75616,9 +75798,9 @@ module.exports = utils;
* Module dependencies
*/
-exports.extend = __webpack_require__(603);
-exports.SourceMap = __webpack_require__(668);
-exports.sourceMapResolve = __webpack_require__(679);
+exports.extend = __webpack_require__(605);
+exports.SourceMap = __webpack_require__(670);
+exports.sourceMapResolve = __webpack_require__(681);
/**
* Convert backslash in the given string to forward slashes
@@ -75661,7 +75843,7 @@ exports.last = function(arr, n) {
/***/ }),
-/* 668 */
+/* 670 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -75669,13 +75851,13 @@ exports.last = function(arr, n) {
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
-exports.SourceMapGenerator = __webpack_require__(669).SourceMapGenerator;
-exports.SourceMapConsumer = __webpack_require__(675).SourceMapConsumer;
-exports.SourceNode = __webpack_require__(678).SourceNode;
+exports.SourceMapGenerator = __webpack_require__(671).SourceMapGenerator;
+exports.SourceMapConsumer = __webpack_require__(677).SourceMapConsumer;
+exports.SourceNode = __webpack_require__(680).SourceNode;
/***/ }),
-/* 669 */
+/* 671 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -75685,10 +75867,10 @@ exports.SourceNode = __webpack_require__(678).SourceNode;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var base64VLQ = __webpack_require__(670);
-var util = __webpack_require__(672);
-var ArraySet = __webpack_require__(673).ArraySet;
-var MappingList = __webpack_require__(674).MappingList;
+var base64VLQ = __webpack_require__(672);
+var util = __webpack_require__(674);
+var ArraySet = __webpack_require__(675).ArraySet;
+var MappingList = __webpack_require__(676).MappingList;
/**
* An instance of the SourceMapGenerator represents a source map which is
@@ -76097,7 +76279,7 @@ exports.SourceMapGenerator = SourceMapGenerator;
/***/ }),
-/* 670 */
+/* 672 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76137,7 +76319,7 @@ exports.SourceMapGenerator = SourceMapGenerator;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-var base64 = __webpack_require__(671);
+var base64 = __webpack_require__(673);
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
@@ -76243,7 +76425,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
/***/ }),
-/* 671 */
+/* 673 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76316,7 +76498,7 @@ exports.decode = function (charCode) {
/***/ }),
-/* 672 */
+/* 674 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76739,7 +76921,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate
/***/ }),
-/* 673 */
+/* 675 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76749,7 +76931,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(672);
+var util = __webpack_require__(674);
var has = Object.prototype.hasOwnProperty;
var hasNativeMap = typeof Map !== "undefined";
@@ -76866,7 +77048,7 @@ exports.ArraySet = ArraySet;
/***/ }),
-/* 674 */
+/* 676 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76876,7 +77058,7 @@ exports.ArraySet = ArraySet;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(672);
+var util = __webpack_require__(674);
/**
* Determine whether mappingB is after mappingA with respect to generated
@@ -76951,7 +77133,7 @@ exports.MappingList = MappingList;
/***/ }),
-/* 675 */
+/* 677 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -76961,11 +77143,11 @@ exports.MappingList = MappingList;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(672);
-var binarySearch = __webpack_require__(676);
-var ArraySet = __webpack_require__(673).ArraySet;
-var base64VLQ = __webpack_require__(670);
-var quickSort = __webpack_require__(677).quickSort;
+var util = __webpack_require__(674);
+var binarySearch = __webpack_require__(678);
+var ArraySet = __webpack_require__(675).ArraySet;
+var base64VLQ = __webpack_require__(672);
+var quickSort = __webpack_require__(679).quickSort;
function SourceMapConsumer(aSourceMap) {
var sourceMap = aSourceMap;
@@ -78039,7 +78221,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
/***/ }),
-/* 676 */
+/* 678 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -78156,7 +78338,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
/***/ }),
-/* 677 */
+/* 679 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -78276,7 +78458,7 @@ exports.quickSort = function (ary, comparator) {
/***/ }),
-/* 678 */
+/* 680 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -78286,8 +78468,8 @@ exports.quickSort = function (ary, comparator) {
* http://opensource.org/licenses/BSD-3-Clause
*/
-var SourceMapGenerator = __webpack_require__(669).SourceMapGenerator;
-var util = __webpack_require__(672);
+var SourceMapGenerator = __webpack_require__(671).SourceMapGenerator;
+var util = __webpack_require__(674);
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
// operating systems these days (capturing the result).
@@ -78695,17 +78877,17 @@ exports.SourceNode = SourceNode;
/***/ }),
-/* 679 */
+/* 681 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014, 2015, 2016, 2017 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
-var sourceMappingURL = __webpack_require__(680)
-var resolveUrl = __webpack_require__(681)
-var decodeUriComponent = __webpack_require__(682)
-var urix = __webpack_require__(684)
-var atob = __webpack_require__(685)
+var sourceMappingURL = __webpack_require__(682)
+var resolveUrl = __webpack_require__(683)
+var decodeUriComponent = __webpack_require__(684)
+var urix = __webpack_require__(686)
+var atob = __webpack_require__(687)
@@ -79003,7 +79185,7 @@ module.exports = {
/***/ }),
-/* 680 */
+/* 682 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell
@@ -79066,7 +79248,7 @@ void (function(root, factory) {
/***/ }),
-/* 681 */
+/* 683 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014 Simon Lydell
@@ -79084,13 +79266,13 @@ module.exports = resolveUrl
/***/ }),
-/* 682 */
+/* 684 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2017 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
-var decodeUriComponent = __webpack_require__(683)
+var decodeUriComponent = __webpack_require__(685)
function customDecodeUriComponent(string) {
// `decodeUriComponent` turns `+` into ` `, but that's not wanted.
@@ -79101,7 +79283,7 @@ module.exports = customDecodeUriComponent
/***/ }),
-/* 683 */
+/* 685 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79202,7 +79384,7 @@ module.exports = function (encodedURI) {
/***/ }),
-/* 684 */
+/* 686 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014 Simon Lydell
@@ -79225,7 +79407,7 @@ module.exports = urix
/***/ }),
-/* 685 */
+/* 687 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79239,7 +79421,7 @@ module.exports = atob.atob = atob;
/***/ }),
-/* 686 */
+/* 688 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79247,8 +79429,8 @@ module.exports = atob.atob = atob;
var fs = __webpack_require__(134);
var path = __webpack_require__(4);
-var define = __webpack_require__(653);
-var utils = __webpack_require__(667);
+var define = __webpack_require__(655);
+var utils = __webpack_require__(669);
/**
* Expose `mixin()`.
@@ -79391,19 +79573,19 @@ exports.comment = function(node) {
/***/ }),
-/* 687 */
+/* 689 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var use = __webpack_require__(665);
+var use = __webpack_require__(667);
var util = __webpack_require__(112);
-var Cache = __webpack_require__(688);
-var define = __webpack_require__(653);
-var debug = __webpack_require__(543)('snapdragon:parser');
-var Position = __webpack_require__(689);
-var utils = __webpack_require__(667);
+var Cache = __webpack_require__(690);
+var define = __webpack_require__(655);
+var debug = __webpack_require__(545)('snapdragon:parser');
+var Position = __webpack_require__(691);
+var utils = __webpack_require__(669);
/**
* Create a new `Parser` with the given `input` and `options`.
@@ -79931,7 +80113,7 @@ module.exports = Parser;
/***/ }),
-/* 688 */
+/* 690 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -80038,13 +80220,13 @@ MapCache.prototype.del = function mapDelete(key) {
/***/ }),
-/* 689 */
+/* 691 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var define = __webpack_require__(653);
+var define = __webpack_require__(655);
/**
* Store position for a node
@@ -80059,14 +80241,14 @@ module.exports = function Position(start, parser) {
/***/ }),
-/* 690 */
+/* 692 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(691);
-var assignSymbols = __webpack_require__(598);
+var isExtendable = __webpack_require__(693);
+var assignSymbols = __webpack_require__(600);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -80126,7 +80308,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 691 */
+/* 693 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -80139,7 +80321,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -80147,14 +80329,14 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 692 */
+/* 694 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var nanomatch = __webpack_require__(693);
-var extglob = __webpack_require__(707);
+var nanomatch = __webpack_require__(695);
+var extglob = __webpack_require__(709);
module.exports = function(snapdragon) {
var compilers = snapdragon.compiler.compilers;
@@ -80231,7 +80413,7 @@ function escapeExtglobs(compiler) {
/***/ }),
-/* 693 */
+/* 695 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -80242,17 +80424,17 @@ function escapeExtglobs(compiler) {
*/
var util = __webpack_require__(112);
-var toRegex = __webpack_require__(582);
-var extend = __webpack_require__(694);
+var toRegex = __webpack_require__(584);
+var extend = __webpack_require__(696);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(696);
-var parsers = __webpack_require__(697);
-var cache = __webpack_require__(700);
-var utils = __webpack_require__(702);
+var compilers = __webpack_require__(698);
+var parsers = __webpack_require__(699);
+var cache = __webpack_require__(702);
+var utils = __webpack_require__(704);
var MAX_LENGTH = 1024 * 64;
/**
@@ -81076,14 +81258,14 @@ module.exports = nanomatch;
/***/ }),
-/* 694 */
+/* 696 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(695);
-var assignSymbols = __webpack_require__(598);
+var isExtendable = __webpack_require__(697);
+var assignSymbols = __webpack_require__(600);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -81143,7 +81325,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 695 */
+/* 697 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -81156,7 +81338,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(597);
+var isPlainObject = __webpack_require__(599);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -81164,7 +81346,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 696 */
+/* 698 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -81510,15 +81692,15 @@ module.exports = function(nanomatch, options) {
/***/ }),
-/* 697 */
+/* 699 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var regexNot = __webpack_require__(599);
-var toRegex = __webpack_require__(582);
-var isOdd = __webpack_require__(698);
+var regexNot = __webpack_require__(601);
+var toRegex = __webpack_require__(584);
+var isOdd = __webpack_require__(700);
/**
* Characters to use in negation regex (we want to "not" match
@@ -81904,7 +82086,7 @@ module.exports.not = NOT_REGEX;
/***/ }),
-/* 698 */
+/* 700 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -81917,7 +82099,7 @@ module.exports.not = NOT_REGEX;
-var isNumber = __webpack_require__(699);
+var isNumber = __webpack_require__(701);
module.exports = function isOdd(i) {
if (!isNumber(i)) {
@@ -81931,7 +82113,7 @@ module.exports = function isOdd(i) {
/***/ }),
-/* 699 */
+/* 701 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -81959,14 +82141,14 @@ module.exports = function isNumber(num) {
/***/ }),
-/* 700 */
+/* 702 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = new (__webpack_require__(701))();
+module.exports = new (__webpack_require__(703))();
/***/ }),
-/* 701 */
+/* 703 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -81979,7 +82161,7 @@ module.exports = new (__webpack_require__(701))();
-var MapCache = __webpack_require__(688);
+var MapCache = __webpack_require__(690);
/**
* Create a new `FragmentCache` with an optional object to use for `caches`.
@@ -82101,7 +82283,7 @@ exports = module.exports = FragmentCache;
/***/ }),
-/* 702 */
+/* 704 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -82114,14 +82296,14 @@ var path = __webpack_require__(4);
* Module dependencies
*/
-var isWindows = __webpack_require__(703)();
-var Snapdragon = __webpack_require__(624);
-utils.define = __webpack_require__(704);
-utils.diff = __webpack_require__(705);
-utils.extend = __webpack_require__(694);
-utils.pick = __webpack_require__(706);
-utils.typeOf = __webpack_require__(592);
-utils.unique = __webpack_require__(602);
+var isWindows = __webpack_require__(705)();
+var Snapdragon = __webpack_require__(626);
+utils.define = __webpack_require__(706);
+utils.diff = __webpack_require__(707);
+utils.extend = __webpack_require__(696);
+utils.pick = __webpack_require__(708);
+utils.typeOf = __webpack_require__(594);
+utils.unique = __webpack_require__(604);
/**
* Returns true if the given value is effectively an empty string
@@ -82487,7 +82669,7 @@ utils.unixify = function(options) {
/***/ }),
-/* 703 */
+/* 705 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
@@ -82515,7 +82697,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
/***/ }),
-/* 704 */
+/* 706 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -82528,8 +82710,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
-var isobject = __webpack_require__(590);
-var isDescriptor = __webpack_require__(591);
+var isobject = __webpack_require__(592);
+var isDescriptor = __webpack_require__(593);
var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
? Reflect.defineProperty
: Object.defineProperty;
@@ -82560,7 +82742,7 @@ module.exports = function defineProperty(obj, key, val) {
/***/ }),
-/* 705 */
+/* 707 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -82614,7 +82796,7 @@ function diffArray(one, two) {
/***/ }),
-/* 706 */
+/* 708 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -82627,7 +82809,7 @@ function diffArray(one, two) {
-var isObject = __webpack_require__(590);
+var isObject = __webpack_require__(592);
module.exports = function pick(obj, keys) {
if (!isObject(obj) && typeof obj !== 'function') {
@@ -82656,7 +82838,7 @@ module.exports = function pick(obj, keys) {
/***/ }),
-/* 707 */
+/* 709 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -82666,18 +82848,18 @@ module.exports = function pick(obj, keys) {
* Module dependencies
*/
-var extend = __webpack_require__(603);
-var unique = __webpack_require__(602);
-var toRegex = __webpack_require__(582);
+var extend = __webpack_require__(605);
+var unique = __webpack_require__(604);
+var toRegex = __webpack_require__(584);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(708);
-var parsers = __webpack_require__(714);
-var Extglob = __webpack_require__(717);
-var utils = __webpack_require__(716);
+var compilers = __webpack_require__(710);
+var parsers = __webpack_require__(716);
+var Extglob = __webpack_require__(719);
+var utils = __webpack_require__(718);
var MAX_LENGTH = 1024 * 64;
/**
@@ -82994,13 +83176,13 @@ module.exports = extglob;
/***/ }),
-/* 708 */
+/* 710 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var brackets = __webpack_require__(709);
+var brackets = __webpack_require__(711);
/**
* Extglob compilers
@@ -83170,7 +83352,7 @@ module.exports = function(extglob) {
/***/ }),
-/* 709 */
+/* 711 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -83180,17 +83362,17 @@ module.exports = function(extglob) {
* Local dependencies
*/
-var compilers = __webpack_require__(710);
-var parsers = __webpack_require__(712);
+var compilers = __webpack_require__(712);
+var parsers = __webpack_require__(714);
/**
* Module dependencies
*/
-var debug = __webpack_require__(543)('expand-brackets');
-var extend = __webpack_require__(603);
-var Snapdragon = __webpack_require__(624);
-var toRegex = __webpack_require__(582);
+var debug = __webpack_require__(545)('expand-brackets');
+var extend = __webpack_require__(605);
+var Snapdragon = __webpack_require__(626);
+var toRegex = __webpack_require__(584);
/**
* Parses the given POSIX character class `pattern` and returns a
@@ -83388,13 +83570,13 @@ module.exports = brackets;
/***/ }),
-/* 710 */
+/* 712 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var posix = __webpack_require__(711);
+var posix = __webpack_require__(713);
module.exports = function(brackets) {
brackets.compiler
@@ -83482,7 +83664,7 @@ module.exports = function(brackets) {
/***/ }),
-/* 711 */
+/* 713 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -83511,14 +83693,14 @@ module.exports = {
/***/ }),
-/* 712 */
+/* 714 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(713);
-var define = __webpack_require__(653);
+var utils = __webpack_require__(715);
+var define = __webpack_require__(655);
/**
* Text regex
@@ -83737,14 +83919,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX;
/***/ }),
-/* 713 */
+/* 715 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toRegex = __webpack_require__(582);
-var regexNot = __webpack_require__(599);
+var toRegex = __webpack_require__(584);
+var regexNot = __webpack_require__(601);
var cached;
/**
@@ -83778,15 +83960,15 @@ exports.createRegex = function(pattern, include) {
/***/ }),
-/* 714 */
+/* 716 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var brackets = __webpack_require__(709);
-var define = __webpack_require__(715);
-var utils = __webpack_require__(716);
+var brackets = __webpack_require__(711);
+var define = __webpack_require__(717);
+var utils = __webpack_require__(718);
/**
* Characters to use in text regex (we want to "not" match
@@ -83941,7 +84123,7 @@ module.exports = parsers;
/***/ }),
-/* 715 */
+/* 717 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -83954,7 +84136,7 @@ module.exports = parsers;
-var isDescriptor = __webpack_require__(591);
+var isDescriptor = __webpack_require__(593);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -83979,14 +84161,14 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 716 */
+/* 718 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var regex = __webpack_require__(599);
-var Cache = __webpack_require__(701);
+var regex = __webpack_require__(601);
+var Cache = __webpack_require__(703);
/**
* Utils
@@ -84055,7 +84237,7 @@ utils.createRegex = function(str) {
/***/ }),
-/* 717 */
+/* 719 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84065,16 +84247,16 @@ utils.createRegex = function(str) {
* Module dependencies
*/
-var Snapdragon = __webpack_require__(624);
-var define = __webpack_require__(715);
-var extend = __webpack_require__(603);
+var Snapdragon = __webpack_require__(626);
+var define = __webpack_require__(717);
+var extend = __webpack_require__(605);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(708);
-var parsers = __webpack_require__(714);
+var compilers = __webpack_require__(710);
+var parsers = __webpack_require__(716);
/**
* Customize Snapdragon parser and renderer
@@ -84140,16 +84322,16 @@ module.exports = Extglob;
/***/ }),
-/* 718 */
+/* 720 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extglob = __webpack_require__(707);
-var nanomatch = __webpack_require__(693);
-var regexNot = __webpack_require__(599);
-var toRegex = __webpack_require__(582);
+var extglob = __webpack_require__(709);
+var nanomatch = __webpack_require__(695);
+var regexNot = __webpack_require__(601);
+var toRegex = __webpack_require__(584);
var not;
/**
@@ -84230,14 +84412,14 @@ function textRegex(pattern) {
/***/ }),
-/* 719 */
+/* 721 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = new (__webpack_require__(701))();
+module.exports = new (__webpack_require__(703))();
/***/ }),
-/* 720 */
+/* 722 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84250,13 +84432,13 @@ var path = __webpack_require__(4);
* Module dependencies
*/
-var Snapdragon = __webpack_require__(624);
-utils.define = __webpack_require__(721);
-utils.diff = __webpack_require__(705);
-utils.extend = __webpack_require__(690);
-utils.pick = __webpack_require__(706);
-utils.typeOf = __webpack_require__(592);
-utils.unique = __webpack_require__(602);
+var Snapdragon = __webpack_require__(626);
+utils.define = __webpack_require__(723);
+utils.diff = __webpack_require__(707);
+utils.extend = __webpack_require__(692);
+utils.pick = __webpack_require__(708);
+utils.typeOf = __webpack_require__(594);
+utils.unique = __webpack_require__(604);
/**
* Returns true if the platform is windows, or `path.sep` is `\\`.
@@ -84553,7 +84735,7 @@ utils.unixify = function(options) {
/***/ }),
-/* 721 */
+/* 723 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84566,8 +84748,8 @@ utils.unixify = function(options) {
-var isobject = __webpack_require__(590);
-var isDescriptor = __webpack_require__(591);
+var isobject = __webpack_require__(592);
+var isDescriptor = __webpack_require__(593);
var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
? Reflect.defineProperty
: Object.defineProperty;
@@ -84598,7 +84780,7 @@ module.exports = function defineProperty(obj, key, val) {
/***/ }),
-/* 722 */
+/* 724 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84617,9 +84799,9 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var readdir = __webpack_require__(723);
-var reader_1 = __webpack_require__(736);
-var fs_stream_1 = __webpack_require__(740);
+var readdir = __webpack_require__(725);
+var reader_1 = __webpack_require__(738);
+var fs_stream_1 = __webpack_require__(742);
var ReaderAsync = /** @class */ (function (_super) {
__extends(ReaderAsync, _super);
function ReaderAsync() {
@@ -84680,15 +84862,15 @@ exports.default = ReaderAsync;
/***/ }),
-/* 723 */
+/* 725 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const readdirSync = __webpack_require__(724);
-const readdirAsync = __webpack_require__(732);
-const readdirStream = __webpack_require__(735);
+const readdirSync = __webpack_require__(726);
+const readdirAsync = __webpack_require__(734);
+const readdirStream = __webpack_require__(737);
module.exports = exports = readdirAsyncPath;
exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath;
@@ -84772,7 +84954,7 @@ function readdirStreamStat (dir, options) {
/***/ }),
-/* 724 */
+/* 726 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84780,11 +84962,11 @@ function readdirStreamStat (dir, options) {
module.exports = readdirSync;
-const DirectoryReader = __webpack_require__(725);
+const DirectoryReader = __webpack_require__(727);
let syncFacade = {
- fs: __webpack_require__(730),
- forEach: __webpack_require__(731),
+ fs: __webpack_require__(732),
+ forEach: __webpack_require__(733),
sync: true
};
@@ -84813,7 +84995,7 @@ function readdirSync (dir, options, internalOptions) {
/***/ }),
-/* 725 */
+/* 727 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -84822,9 +85004,9 @@ function readdirSync (dir, options, internalOptions) {
const Readable = __webpack_require__(138).Readable;
const EventEmitter = __webpack_require__(156).EventEmitter;
const path = __webpack_require__(4);
-const normalizeOptions = __webpack_require__(726);
-const stat = __webpack_require__(728);
-const call = __webpack_require__(729);
+const normalizeOptions = __webpack_require__(728);
+const stat = __webpack_require__(730);
+const call = __webpack_require__(731);
/**
* Asynchronously reads the contents of a directory and streams the results
@@ -85200,14 +85382,14 @@ module.exports = DirectoryReader;
/***/ }),
-/* 726 */
+/* 728 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(4);
-const globToRegExp = __webpack_require__(727);
+const globToRegExp = __webpack_require__(729);
module.exports = normalizeOptions;
@@ -85384,7 +85566,7 @@ function normalizeOptions (options, internalOptions) {
/***/ }),
-/* 727 */
+/* 729 */
/***/ (function(module, exports) {
module.exports = function (glob, opts) {
@@ -85521,13 +85703,13 @@ module.exports = function (glob, opts) {
/***/ }),
-/* 728 */
+/* 730 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const call = __webpack_require__(729);
+const call = __webpack_require__(731);
module.exports = stat;
@@ -85602,7 +85784,7 @@ function symlinkStat (fs, path, lstats, callback) {
/***/ }),
-/* 729 */
+/* 731 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85663,14 +85845,14 @@ function callOnce (fn) {
/***/ }),
-/* 730 */
+/* 732 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(134);
-const call = __webpack_require__(729);
+const call = __webpack_require__(731);
/**
* A facade around {@link fs.readdirSync} that allows it to be called
@@ -85734,7 +85916,7 @@ exports.lstat = function (path, callback) {
/***/ }),
-/* 731 */
+/* 733 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85763,7 +85945,7 @@ function syncForEach (array, iterator, done) {
/***/ }),
-/* 732 */
+/* 734 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85771,12 +85953,12 @@ function syncForEach (array, iterator, done) {
module.exports = readdirAsync;
-const maybe = __webpack_require__(733);
-const DirectoryReader = __webpack_require__(725);
+const maybe = __webpack_require__(735);
+const DirectoryReader = __webpack_require__(727);
let asyncFacade = {
fs: __webpack_require__(134),
- forEach: __webpack_require__(734),
+ forEach: __webpack_require__(736),
async: true
};
@@ -85818,7 +86000,7 @@ function readdirAsync (dir, options, callback, internalOptions) {
/***/ }),
-/* 733 */
+/* 735 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85845,7 +86027,7 @@ module.exports = function maybe (cb, promise) {
/***/ }),
-/* 734 */
+/* 736 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85881,7 +86063,7 @@ function asyncForEach (array, iterator, done) {
/***/ }),
-/* 735 */
+/* 737 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -85889,11 +86071,11 @@ function asyncForEach (array, iterator, done) {
module.exports = readdirStream;
-const DirectoryReader = __webpack_require__(725);
+const DirectoryReader = __webpack_require__(727);
let streamFacade = {
fs: __webpack_require__(134),
- forEach: __webpack_require__(734),
+ forEach: __webpack_require__(736),
async: true
};
@@ -85913,16 +86095,16 @@ function readdirStream (dir, options, internalOptions) {
/***/ }),
-/* 736 */
+/* 738 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var path = __webpack_require__(4);
-var deep_1 = __webpack_require__(737);
-var entry_1 = __webpack_require__(739);
-var pathUtil = __webpack_require__(738);
+var deep_1 = __webpack_require__(739);
+var entry_1 = __webpack_require__(741);
+var pathUtil = __webpack_require__(740);
var Reader = /** @class */ (function () {
function Reader(options) {
this.options = options;
@@ -85988,14 +86170,14 @@ exports.default = Reader;
/***/ }),
-/* 737 */
+/* 739 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var pathUtils = __webpack_require__(738);
-var patternUtils = __webpack_require__(576);
+var pathUtils = __webpack_require__(740);
+var patternUtils = __webpack_require__(578);
var DeepFilter = /** @class */ (function () {
function DeepFilter(options, micromatchOptions) {
this.options = options;
@@ -86078,7 +86260,7 @@ exports.default = DeepFilter;
/***/ }),
-/* 738 */
+/* 740 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86109,14 +86291,14 @@ exports.makeAbsolute = makeAbsolute;
/***/ }),
-/* 739 */
+/* 741 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var pathUtils = __webpack_require__(738);
-var patternUtils = __webpack_require__(576);
+var pathUtils = __webpack_require__(740);
+var patternUtils = __webpack_require__(578);
var EntryFilter = /** @class */ (function () {
function EntryFilter(options, micromatchOptions) {
this.options = options;
@@ -86201,7 +86383,7 @@ exports.default = EntryFilter;
/***/ }),
-/* 740 */
+/* 742 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86221,8 +86403,8 @@ var __extends = (this && this.__extends) || (function () {
})();
Object.defineProperty(exports, "__esModule", { value: true });
var stream = __webpack_require__(138);
-var fsStat = __webpack_require__(741);
-var fs_1 = __webpack_require__(745);
+var fsStat = __webpack_require__(743);
+var fs_1 = __webpack_require__(747);
var FileSystemStream = /** @class */ (function (_super) {
__extends(FileSystemStream, _super);
function FileSystemStream() {
@@ -86272,14 +86454,14 @@ exports.default = FileSystemStream;
/***/ }),
-/* 741 */
+/* 743 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const optionsManager = __webpack_require__(742);
-const statProvider = __webpack_require__(744);
+const optionsManager = __webpack_require__(744);
+const statProvider = __webpack_require__(746);
/**
* Asynchronous API.
*/
@@ -86310,13 +86492,13 @@ exports.statSync = statSync;
/***/ }),
-/* 742 */
+/* 744 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsAdapter = __webpack_require__(743);
+const fsAdapter = __webpack_require__(745);
function prepare(opts) {
const options = Object.assign({
fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined),
@@ -86329,7 +86511,7 @@ exports.prepare = prepare;
/***/ }),
-/* 743 */
+/* 745 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86352,7 +86534,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter;
/***/ }),
-/* 744 */
+/* 746 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86404,7 +86586,7 @@ exports.isFollowedSymlink = isFollowedSymlink;
/***/ }),
-/* 745 */
+/* 747 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86435,7 +86617,7 @@ exports.default = FileSystem;
/***/ }),
-/* 746 */
+/* 748 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86455,9 +86637,9 @@ var __extends = (this && this.__extends) || (function () {
})();
Object.defineProperty(exports, "__esModule", { value: true });
var stream = __webpack_require__(138);
-var readdir = __webpack_require__(723);
-var reader_1 = __webpack_require__(736);
-var fs_stream_1 = __webpack_require__(740);
+var readdir = __webpack_require__(725);
+var reader_1 = __webpack_require__(738);
+var fs_stream_1 = __webpack_require__(742);
var TransformStream = /** @class */ (function (_super) {
__extends(TransformStream, _super);
function TransformStream(reader) {
@@ -86525,7 +86707,7 @@ exports.default = ReaderStream;
/***/ }),
-/* 747 */
+/* 749 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86544,9 +86726,9 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var readdir = __webpack_require__(723);
-var reader_1 = __webpack_require__(736);
-var fs_sync_1 = __webpack_require__(748);
+var readdir = __webpack_require__(725);
+var reader_1 = __webpack_require__(738);
+var fs_sync_1 = __webpack_require__(750);
var ReaderSync = /** @class */ (function (_super) {
__extends(ReaderSync, _super);
function ReaderSync() {
@@ -86606,7 +86788,7 @@ exports.default = ReaderSync;
/***/ }),
-/* 748 */
+/* 750 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86625,8 +86807,8 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var fsStat = __webpack_require__(741);
-var fs_1 = __webpack_require__(745);
+var fsStat = __webpack_require__(743);
+var fs_1 = __webpack_require__(747);
var FileSystemSync = /** @class */ (function (_super) {
__extends(FileSystemSync, _super);
function FileSystemSync() {
@@ -86672,7 +86854,7 @@ exports.default = FileSystemSync;
/***/ }),
-/* 749 */
+/* 751 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86688,7 +86870,7 @@ exports.flatten = flatten;
/***/ }),
-/* 750 */
+/* 752 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86709,13 +86891,13 @@ exports.merge = merge;
/***/ }),
-/* 751 */
+/* 753 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(4);
-const pathType = __webpack_require__(752);
+const pathType = __webpack_require__(754);
const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];
@@ -86781,13 +86963,13 @@ module.exports.sync = (input, opts) => {
/***/ }),
-/* 752 */
+/* 754 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(134);
-const pify = __webpack_require__(753);
+const pify = __webpack_require__(755);
function type(fn, fn2, fp) {
if (typeof fp !== 'string') {
@@ -86830,7 +87012,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink');
/***/ }),
-/* 753 */
+/* 755 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -86921,17 +87103,17 @@ module.exports = (obj, opts) => {
/***/ }),
-/* 754 */
+/* 756 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(134);
const path = __webpack_require__(4);
-const fastGlob = __webpack_require__(572);
-const gitIgnore = __webpack_require__(755);
-const pify = __webpack_require__(756);
-const slash = __webpack_require__(757);
+const fastGlob = __webpack_require__(574);
+const gitIgnore = __webpack_require__(757);
+const pify = __webpack_require__(758);
+const slash = __webpack_require__(759);
const DEFAULT_IGNORE = [
'**/node_modules/**',
@@ -87029,7 +87211,7 @@ module.exports.sync = options => {
/***/ }),
-/* 755 */
+/* 757 */
/***/ (function(module, exports) {
// A simple implementation of make-array
@@ -87498,7 +87680,7 @@ module.exports = options => new IgnoreBase(options)
/***/ }),
-/* 756 */
+/* 758 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -87573,7 +87755,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 757 */
+/* 759 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -87591,7 +87773,7 @@ module.exports = input => {
/***/ }),
-/* 758 */
+/* 760 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -87604,7 +87786,7 @@ module.exports = input => {
-var isGlob = __webpack_require__(759);
+var isGlob = __webpack_require__(761);
module.exports = function hasGlob(val) {
if (val == null) return false;
@@ -87624,7 +87806,7 @@ module.exports = function hasGlob(val) {
/***/ }),
-/* 759 */
+/* 761 */
/***/ (function(module, exports, __webpack_require__) {
/*!
@@ -87655,17 +87837,17 @@ module.exports = function isGlob(str) {
/***/ }),
-/* 760 */
+/* 762 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(4);
const {constants: fsConstants} = __webpack_require__(134);
-const pEvent = __webpack_require__(761);
-const CpFileError = __webpack_require__(764);
-const fs = __webpack_require__(766);
-const ProgressEmitter = __webpack_require__(769);
+const pEvent = __webpack_require__(763);
+const CpFileError = __webpack_require__(766);
+const fs = __webpack_require__(768);
+const ProgressEmitter = __webpack_require__(771);
const cpFileAsync = async (source, destination, options, progressEmitter) => {
let readError;
@@ -87779,12 +87961,12 @@ module.exports.sync = (source, destination, options) => {
/***/ }),
-/* 761 */
+/* 763 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const pTimeout = __webpack_require__(762);
+const pTimeout = __webpack_require__(764);
const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator';
@@ -88075,12 +88257,12 @@ module.exports.iterator = (emitter, event, options) => {
/***/ }),
-/* 762 */
+/* 764 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const pFinally = __webpack_require__(763);
+const pFinally = __webpack_require__(765);
class TimeoutError extends Error {
constructor(message) {
@@ -88126,7 +88308,7 @@ module.exports.TimeoutError = TimeoutError;
/***/ }),
-/* 763 */
+/* 765 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -88148,12 +88330,12 @@ module.exports = (promise, onFinally) => {
/***/ }),
-/* 764 */
+/* 766 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const NestedError = __webpack_require__(765);
+const NestedError = __webpack_require__(767);
class CpFileError extends NestedError {
constructor(message, nested) {
@@ -88167,7 +88349,7 @@ module.exports = CpFileError;
/***/ }),
-/* 765 */
+/* 767 */
/***/ (function(module, exports, __webpack_require__) {
var inherits = __webpack_require__(112).inherits;
@@ -88223,16 +88405,16 @@ module.exports = NestedError;
/***/ }),
-/* 766 */
+/* 768 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const {promisify} = __webpack_require__(112);
const fs = __webpack_require__(133);
-const makeDir = __webpack_require__(767);
-const pEvent = __webpack_require__(761);
-const CpFileError = __webpack_require__(764);
+const makeDir = __webpack_require__(769);
+const pEvent = __webpack_require__(763);
+const CpFileError = __webpack_require__(766);
const stat = promisify(fs.stat);
const lstat = promisify(fs.lstat);
@@ -88329,7 +88511,7 @@ exports.copyFileSync = (source, destination, flags) => {
/***/ }),
-/* 767 */
+/* 769 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -88337,7 +88519,7 @@ exports.copyFileSync = (source, destination, flags) => {
const fs = __webpack_require__(134);
const path = __webpack_require__(4);
const {promisify} = __webpack_require__(112);
-const semver = __webpack_require__(768);
+const semver = __webpack_require__(770);
const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0');
@@ -88492,7 +88674,7 @@ module.exports.sync = (input, options) => {
/***/ }),
-/* 768 */
+/* 770 */
/***/ (function(module, exports) {
exports = module.exports = SemVer
@@ -90094,7 +90276,7 @@ function coerce (version, options) {
/***/ }),
-/* 769 */
+/* 771 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90135,7 +90317,7 @@ module.exports = ProgressEmitter;
/***/ }),
-/* 770 */
+/* 772 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90181,12 +90363,12 @@ exports.default = module.exports;
/***/ }),
-/* 771 */
+/* 773 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const pMap = __webpack_require__(772);
+const pMap = __webpack_require__(774);
const pFilter = async (iterable, filterer, options) => {
const values = await pMap(
@@ -90203,7 +90385,7 @@ module.exports.default = pFilter;
/***/ }),
-/* 772 */
+/* 774 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90282,12 +90464,12 @@ module.exports.default = pMap;
/***/ }),
-/* 773 */
+/* 775 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const NestedError = __webpack_require__(765);
+const NestedError = __webpack_require__(767);
class CpyError extends NestedError {
constructor(message, nested) {
@@ -90301,7 +90483,7 @@ module.exports = CpyError;
/***/ }),
-/* 774 */
+/* 776 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90309,10 +90491,10 @@ module.exports = CpyError;
const fs = __webpack_require__(134);
const arrayUnion = __webpack_require__(145);
const merge2 = __webpack_require__(146);
-const fastGlob = __webpack_require__(775);
+const fastGlob = __webpack_require__(777);
const dirGlob = __webpack_require__(232);
-const gitignore = __webpack_require__(810);
-const {FilterStream, UniqueStream} = __webpack_require__(811);
+const gitignore = __webpack_require__(812);
+const {FilterStream, UniqueStream} = __webpack_require__(813);
const DEFAULT_FILTER = () => false;
@@ -90489,17 +90671,17 @@ module.exports.gitignore = gitignore;
/***/ }),
-/* 775 */
+/* 777 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const taskManager = __webpack_require__(776);
-const async_1 = __webpack_require__(796);
-const stream_1 = __webpack_require__(806);
-const sync_1 = __webpack_require__(807);
-const settings_1 = __webpack_require__(809);
-const utils = __webpack_require__(777);
+const taskManager = __webpack_require__(778);
+const async_1 = __webpack_require__(798);
+const stream_1 = __webpack_require__(808);
+const sync_1 = __webpack_require__(809);
+const settings_1 = __webpack_require__(811);
+const utils = __webpack_require__(779);
async function FastGlob(source, options) {
assertPatternsInput(source);
const works = getWorks(source, async_1.default, options);
@@ -90563,14 +90745,14 @@ module.exports = FastGlob;
/***/ }),
-/* 776 */
+/* 778 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0;
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
function generate(patterns, settings) {
const positivePatterns = getPositivePatterns(patterns);
const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore);
@@ -90635,31 +90817,31 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask;
/***/ }),
-/* 777 */
+/* 779 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0;
-const array = __webpack_require__(778);
+const array = __webpack_require__(780);
exports.array = array;
-const errno = __webpack_require__(779);
+const errno = __webpack_require__(781);
exports.errno = errno;
-const fs = __webpack_require__(780);
+const fs = __webpack_require__(782);
exports.fs = fs;
-const path = __webpack_require__(781);
+const path = __webpack_require__(783);
exports.path = path;
-const pattern = __webpack_require__(782);
+const pattern = __webpack_require__(784);
exports.pattern = pattern;
-const stream = __webpack_require__(794);
+const stream = __webpack_require__(796);
exports.stream = stream;
-const string = __webpack_require__(795);
+const string = __webpack_require__(797);
exports.string = string;
/***/ }),
-/* 778 */
+/* 780 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90688,7 +90870,7 @@ exports.splitWhen = splitWhen;
/***/ }),
-/* 779 */
+/* 781 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90702,7 +90884,7 @@ exports.isEnoentCodeError = isEnoentCodeError;
/***/ }),
-/* 780 */
+/* 782 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90728,7 +90910,7 @@ exports.createDirentFromStats = createDirentFromStats;
/***/ }),
-/* 781 */
+/* 783 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90768,7 +90950,7 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment;
/***/ }),
-/* 782 */
+/* 784 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -90777,7 +90959,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0;
const path = __webpack_require__(4);
const globParent = __webpack_require__(171);
-const micromatch = __webpack_require__(783);
+const micromatch = __webpack_require__(785);
const picomatch = __webpack_require__(185);
const GLOBSTAR = '**';
const ESCAPE_SYMBOL = '\\';
@@ -90907,14 +91089,14 @@ exports.matchAny = matchAny;
/***/ }),
-/* 783 */
+/* 785 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const util = __webpack_require__(112);
-const braces = __webpack_require__(784);
+const braces = __webpack_require__(786);
const picomatch = __webpack_require__(185);
const utils = __webpack_require__(188);
const isEmptyString = val => typeof val === 'string' && (val === '' || val === './');
@@ -91381,16 +91563,16 @@ module.exports = micromatch;
/***/ }),
-/* 784 */
+/* 786 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringify = __webpack_require__(785);
-const compile = __webpack_require__(787);
-const expand = __webpack_require__(791);
-const parse = __webpack_require__(792);
+const stringify = __webpack_require__(787);
+const compile = __webpack_require__(789);
+const expand = __webpack_require__(793);
+const parse = __webpack_require__(794);
/**
* Expand the given pattern or create a regex-compatible string.
@@ -91558,13 +91740,13 @@ module.exports = braces;
/***/ }),
-/* 785 */
+/* 787 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const utils = __webpack_require__(786);
+const utils = __webpack_require__(788);
module.exports = (ast, options = {}) => {
let stringify = (node, parent = {}) => {
@@ -91597,7 +91779,7 @@ module.exports = (ast, options = {}) => {
/***/ }),
-/* 786 */
+/* 788 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -91716,14 +91898,14 @@ exports.flatten = (...args) => {
/***/ }),
-/* 787 */
+/* 789 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const fill = __webpack_require__(788);
-const utils = __webpack_require__(786);
+const fill = __webpack_require__(790);
+const utils = __webpack_require__(788);
const compile = (ast, options = {}) => {
let walk = (node, parent = {}) => {
@@ -91780,7 +91962,7 @@ module.exports = compile;
/***/ }),
-/* 788 */
+/* 790 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -91794,7 +91976,7 @@ module.exports = compile;
const util = __webpack_require__(112);
-const toRegexRange = __webpack_require__(789);
+const toRegexRange = __webpack_require__(791);
const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
@@ -92036,7 +92218,7 @@ module.exports = fill;
/***/ }),
-/* 789 */
+/* 791 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92049,7 +92231,7 @@ module.exports = fill;
-const isNumber = __webpack_require__(790);
+const isNumber = __webpack_require__(792);
const toRegexRange = (min, max, options) => {
if (isNumber(min) === false) {
@@ -92331,7 +92513,7 @@ module.exports = toRegexRange;
/***/ }),
-/* 790 */
+/* 792 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92356,15 +92538,15 @@ module.exports = function(num) {
/***/ }),
-/* 791 */
+/* 793 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const fill = __webpack_require__(788);
-const stringify = __webpack_require__(785);
-const utils = __webpack_require__(786);
+const fill = __webpack_require__(790);
+const stringify = __webpack_require__(787);
+const utils = __webpack_require__(788);
const append = (queue = '', stash = '', enclose = false) => {
let result = [];
@@ -92476,13 +92658,13 @@ module.exports = expand;
/***/ }),
-/* 792 */
+/* 794 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringify = __webpack_require__(785);
+const stringify = __webpack_require__(787);
/**
* Constants
@@ -92504,7 +92686,7 @@ const {
CHAR_SINGLE_QUOTE, /* ' */
CHAR_NO_BREAK_SPACE,
CHAR_ZERO_WIDTH_NOBREAK_SPACE
-} = __webpack_require__(793);
+} = __webpack_require__(795);
/**
* parse
@@ -92816,7 +92998,7 @@ module.exports = parse;
/***/ }),
-/* 793 */
+/* 795 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92880,7 +93062,7 @@ module.exports = {
/***/ }),
-/* 794 */
+/* 796 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92904,7 +93086,7 @@ function propagateCloseEventToSources(streams) {
/***/ }),
-/* 795 */
+/* 797 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92922,14 +93104,14 @@ exports.isEmpty = isEmpty;
/***/ }),
-/* 796 */
+/* 798 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const stream_1 = __webpack_require__(797);
-const provider_1 = __webpack_require__(799);
+const stream_1 = __webpack_require__(799);
+const provider_1 = __webpack_require__(801);
class ProviderAsync extends provider_1.default {
constructor() {
super(...arguments);
@@ -92957,7 +93139,7 @@ exports.default = ProviderAsync;
/***/ }),
-/* 797 */
+/* 799 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -92966,7 +93148,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = __webpack_require__(138);
const fsStat = __webpack_require__(195);
const fsWalk = __webpack_require__(200);
-const reader_1 = __webpack_require__(798);
+const reader_1 = __webpack_require__(800);
class ReaderStream extends reader_1.default {
constructor() {
super(...arguments);
@@ -93019,7 +93201,7 @@ exports.default = ReaderStream;
/***/ }),
-/* 798 */
+/* 800 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -93027,7 +93209,7 @@ exports.default = ReaderStream;
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(4);
const fsStat = __webpack_require__(195);
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
class Reader {
constructor(_settings) {
this._settings = _settings;
@@ -93059,17 +93241,17 @@ exports.default = Reader;
/***/ }),
-/* 799 */
+/* 801 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(4);
-const deep_1 = __webpack_require__(800);
-const entry_1 = __webpack_require__(803);
-const error_1 = __webpack_require__(804);
-const entry_2 = __webpack_require__(805);
+const deep_1 = __webpack_require__(802);
+const entry_1 = __webpack_require__(805);
+const error_1 = __webpack_require__(806);
+const entry_2 = __webpack_require__(807);
class Provider {
constructor(_settings) {
this._settings = _settings;
@@ -93114,14 +93296,14 @@ exports.default = Provider;
/***/ }),
-/* 800 */
+/* 802 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(777);
-const partial_1 = __webpack_require__(801);
+const utils = __webpack_require__(779);
+const partial_1 = __webpack_require__(803);
class DeepFilter {
constructor(_settings, _micromatchOptions) {
this._settings = _settings;
@@ -93183,13 +93365,13 @@ exports.default = DeepFilter;
/***/ }),
-/* 801 */
+/* 803 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const matcher_1 = __webpack_require__(802);
+const matcher_1 = __webpack_require__(804);
class PartialMatcher extends matcher_1.default {
match(filepath) {
const parts = filepath.split('/');
@@ -93228,13 +93410,13 @@ exports.default = PartialMatcher;
/***/ }),
-/* 802 */
+/* 804 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
class Matcher {
constructor(_patterns, _settings, _micromatchOptions) {
this._patterns = _patterns;
@@ -93285,13 +93467,13 @@ exports.default = Matcher;
/***/ }),
-/* 803 */
+/* 805 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
class EntryFilter {
constructor(_settings, _micromatchOptions) {
this._settings = _settings;
@@ -93348,13 +93530,13 @@ exports.default = EntryFilter;
/***/ }),
-/* 804 */
+/* 806 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
class ErrorFilter {
constructor(_settings) {
this._settings = _settings;
@@ -93370,13 +93552,13 @@ exports.default = ErrorFilter;
/***/ }),
-/* 805 */
+/* 807 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(777);
+const utils = __webpack_require__(779);
class EntryTransformer {
constructor(_settings) {
this._settings = _settings;
@@ -93403,15 +93585,15 @@ exports.default = EntryTransformer;
/***/ }),
-/* 806 */
+/* 808 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = __webpack_require__(138);
-const stream_2 = __webpack_require__(797);
-const provider_1 = __webpack_require__(799);
+const stream_2 = __webpack_require__(799);
+const provider_1 = __webpack_require__(801);
class ProviderStream extends provider_1.default {
constructor() {
super(...arguments);
@@ -93441,14 +93623,14 @@ exports.default = ProviderStream;
/***/ }),
-/* 807 */
+/* 809 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const sync_1 = __webpack_require__(808);
-const provider_1 = __webpack_require__(799);
+const sync_1 = __webpack_require__(810);
+const provider_1 = __webpack_require__(801);
class ProviderSync extends provider_1.default {
constructor() {
super(...arguments);
@@ -93471,7 +93653,7 @@ exports.default = ProviderSync;
/***/ }),
-/* 808 */
+/* 810 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -93479,7 +93661,7 @@ exports.default = ProviderSync;
Object.defineProperty(exports, "__esModule", { value: true });
const fsStat = __webpack_require__(195);
const fsWalk = __webpack_require__(200);
-const reader_1 = __webpack_require__(798);
+const reader_1 = __webpack_require__(800);
class ReaderSync extends reader_1.default {
constructor() {
super(...arguments);
@@ -93521,7 +93703,7 @@ exports.default = ReaderSync;
/***/ }),
-/* 809 */
+/* 811 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -93585,7 +93767,7 @@ exports.default = Settings;
/***/ }),
-/* 810 */
+/* 812 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -93593,7 +93775,7 @@ exports.default = Settings;
const {promisify} = __webpack_require__(112);
const fs = __webpack_require__(134);
const path = __webpack_require__(4);
-const fastGlob = __webpack_require__(775);
+const fastGlob = __webpack_require__(777);
const gitIgnore = __webpack_require__(235);
const slash = __webpack_require__(236);
@@ -93712,7 +93894,7 @@ module.exports.sync = options => {
/***/ }),
-/* 811 */
+/* 813 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -93765,7 +93947,7 @@ module.exports = {
/***/ }),
-/* 812 */
+/* 814 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -93773,13 +93955,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return buildNonBazelProductionProjects; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProductionProjects", function() { return getProductionProjects; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProject", function() { return buildProject; });
-/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(565);
+/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(567);
/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(562);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(564);
/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(246);
/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(251);
diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts
index b383a52be63f50..bad6eef3266f89 100644
--- a/packages/kbn-pm/src/commands/bootstrap.ts
+++ b/packages/kbn-pm/src/commands/bootstrap.ts
@@ -66,7 +66,7 @@ export const BootstrapCommand: ICommand = {
await runBazel(['run', '@nodejs//:yarn'], runOffline);
}
- await runBazel(['build', '//packages:build'], runOffline);
+ await runBazel(['build', '//packages:build', '--show_result=1'], runOffline);
// Install monorepo npm dependencies outside of the Bazel managed ones
for (const batch of batchedNonBazelProjects) {
diff --git a/packages/kbn-pm/src/commands/build_bazel.ts b/packages/kbn-pm/src/commands/build_bazel.ts
new file mode 100644
index 00000000000000..f71e2e96e31b0e
--- /dev/null
+++ b/packages/kbn-pm/src/commands/build_bazel.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { runBazel } from '../utils/bazel';
+import { ICommand } from './';
+
+export const BuildBazelCommand: ICommand = {
+ description: 'Runs a build in the Bazel built packages',
+ name: 'build-bazel',
+
+ async run(projects, projectGraph, { options }) {
+ const runOffline = options?.offline === true;
+
+ // Call bazel with the target to build all available packages
+ await runBazel(['build', '//packages:build', '--show_result=1'], runOffline);
+ },
+};
diff --git a/packages/kbn-pm/src/commands/index.ts b/packages/kbn-pm/src/commands/index.ts
index 0ab6bc9c7808a3..2f5c04c2f434f1 100644
--- a/packages/kbn-pm/src/commands/index.ts
+++ b/packages/kbn-pm/src/commands/index.ts
@@ -27,16 +27,20 @@ export interface ICommand {
}
import { BootstrapCommand } from './bootstrap';
+import { BuildBazelCommand } from './build_bazel';
import { CleanCommand } from './clean';
import { ResetCommand } from './reset';
import { RunCommand } from './run';
import { WatchCommand } from './watch';
+import { WatchBazelCommand } from './watch_bazel';
import { Kibana } from '../utils/kibana';
export const commands: { [key: string]: ICommand } = {
bootstrap: BootstrapCommand,
+ 'build-bazel': BuildBazelCommand,
clean: CleanCommand,
reset: ResetCommand,
run: RunCommand,
watch: WatchCommand,
+ 'watch-bazel': WatchBazelCommand,
};
diff --git a/packages/kbn-pm/src/commands/run.ts b/packages/kbn-pm/src/commands/run.ts
index 5535fe0d8358f8..9a3a19d9e625ed 100644
--- a/packages/kbn-pm/src/commands/run.ts
+++ b/packages/kbn-pm/src/commands/run.ts
@@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
+import dedent from 'dedent';
import { CliError } from '../utils/errors';
import { log } from '../utils/log';
import { parallelizeBatches } from '../utils/parallelize';
@@ -13,10 +14,17 @@ import { topologicallyBatchProjects } from '../utils/projects';
import { ICommand } from './';
export const RunCommand: ICommand = {
- description: 'Run script defined in package.json in each package that contains that script.',
+ description:
+ 'Run script defined in package.json in each package that contains that script (only works on packages not using Bazel yet)',
name: 'run',
async run(projects, projectGraph, { extraArgs, options }) {
+ log.warning(dedent`
+ We are migrating packages into the Bazel build system and we will no longer support running npm scripts on
+ packages using 'yarn kbn run' on Bazel built packages. If the package you are trying to act on contains a
+ BUILD.bazel file please just use 'yarn kbn build-bazel' to build it or 'yarn kbn watch-bazel' to watch it
+ `);
+
const batchedProjects = topologicallyBatchProjects(projects, projectGraph);
if (extraArgs.length === 0) {
diff --git a/packages/kbn-pm/src/commands/watch.ts b/packages/kbn-pm/src/commands/watch.ts
index fb398d68521369..5d0f6d086d3e80 100644
--- a/packages/kbn-pm/src/commands/watch.ts
+++ b/packages/kbn-pm/src/commands/watch.ts
@@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
+import dedent from 'dedent';
import { CliError } from '../utils/errors';
import { log } from '../utils/log';
import { parallelizeBatches } from '../utils/parallelize';
@@ -34,10 +35,16 @@ const kibanaProjectName = 'kibana';
* `webpack` and `tsc` only, for the rest we rely on predefined timeouts.
*/
export const WatchCommand: ICommand = {
- description: 'Runs `kbn:watch` script for every project.',
+ description:
+ 'Runs `kbn:watch` script for every project (only works on packages not using Bazel yet)',
name: 'watch',
async run(projects, projectGraph) {
+ log.warning(dedent`
+ We are migrating packages into the Bazel build system. If the package you are trying to watch
+ contains a BUILD.bazel file please just use 'yarn kbn watch-bazel'
+ `);
+
const projectsToWatch: ProjectMap = new Map();
for (const project of projects.values()) {
// We can't watch project that doesn't have `kbn:watch` script.
diff --git a/packages/kbn-pm/src/commands/watch_bazel.ts b/packages/kbn-pm/src/commands/watch_bazel.ts
new file mode 100644
index 00000000000000..1273562dd25116
--- /dev/null
+++ b/packages/kbn-pm/src/commands/watch_bazel.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { runIBazel } from '../utils/bazel';
+import { ICommand } from './';
+
+export const WatchBazelCommand: ICommand = {
+ description: 'Runs a build in the Bazel built packages and keeps watching them for changes',
+ name: 'watch-bazel',
+
+ async run(projects, projectGraph, { options }) {
+ const runOffline = options?.offline === true;
+
+ // Call bazel with the target to build all available packages and run it through iBazel to watch it for changes
+ //
+ // Note: --run_output=false arg will disable the iBazel notifications about gazelle and buildozer when running it
+ // Can also be solved by adding a root `.bazel_fix_commands.json` but its not needed at the moment
+ await runIBazel(['--run_output=false', 'build', '//packages:build'], runOffline);
+ },
+};
diff --git a/packages/kbn-pm/src/utils/bazel/run.ts b/packages/kbn-pm/src/utils/bazel/run.ts
index ab20150768b780..34718606db98e4 100644
--- a/packages/kbn-pm/src/utils/bazel/run.ts
+++ b/packages/kbn-pm/src/utils/bazel/run.ts
@@ -13,8 +13,12 @@ import { tap } from 'rxjs/operators';
import { observeLines } from '@kbn/dev-utils/stdio';
import { spawn } from '../child_process';
import { log } from '../log';
+import { CliError } from '../errors';
-export async function runBazel(
+type BazelCommandRunner = 'bazel' | 'ibazel';
+
+async function runBazelCommandWithRunner(
+ bazelCommandRunner: BazelCommandRunner,
bazelArgs: string[],
offline: boolean = false,
runOpts: execa.Options = {}
@@ -29,7 +33,7 @@ export async function runBazel(
bazelArgs.push('--config=offline');
}
- const bazelProc = spawn('bazel', bazelArgs, bazelOpts);
+ const bazelProc = spawn(bazelCommandRunner, bazelArgs, bazelOpts);
const bazelLogs$ = new Rx.Subject();
@@ -37,15 +41,35 @@ export async function runBazel(
// Therefore we need to get both. In order to get errors we need to parse the actual text line
const bazelLogSubscription = Rx.merge(
observeLines(bazelProc.stdout!).pipe(
- tap((line) => log.info(`${chalk.cyan('[bazel]')} ${line}`))
+ tap((line) => log.info(`${chalk.cyan(`[${bazelCommandRunner}]`)} ${line}`))
),
observeLines(bazelProc.stderr!).pipe(
- tap((line) => log.info(`${chalk.cyan('[bazel]')} ${line}`))
+ tap((line) => log.info(`${chalk.cyan(`[${bazelCommandRunner}]`)} ${line}`))
)
).subscribe(bazelLogs$);
// Wait for process and logs to finish, unsubscribing in the end
- await bazelProc;
+ try {
+ await bazelProc;
+ } catch {
+ throw new CliError(`The bazel command that was running failed to complete.`);
+ }
await bazelLogs$.toPromise();
await bazelLogSubscription.unsubscribe();
}
+
+export async function runBazel(
+ bazelArgs: string[],
+ offline: boolean = false,
+ runOpts: execa.Options = {}
+) {
+ await runBazelCommandWithRunner('bazel', bazelArgs, offline, runOpts);
+}
+
+export async function runIBazel(
+ bazelArgs: string[],
+ offline: boolean = false,
+ runOpts: execa.Options = {}
+) {
+ await runBazelCommandWithRunner('ibazel', bazelArgs, offline, runOpts);
+}
diff --git a/packages/kbn-server-http-tools/package.json b/packages/kbn-server-http-tools/package.json
index 6c65a0dd6e475e..24f8f8d67dfd70 100644
--- a/packages/kbn-server-http-tools/package.json
+++ b/packages/kbn-server-http-tools/package.json
@@ -11,7 +11,6 @@
"kbn:watch": "yarn build --watch"
},
"dependencies": {
- "@kbn/config-schema": "link:../kbn-config-schema",
"@kbn/crypto": "link:../kbn-crypto",
"@kbn/std": "link:../kbn-std"
},
diff --git a/packages/kbn-test/src/jest/utils/testbed/testbed.ts b/packages/kbn-test/src/jest/utils/testbed/testbed.ts
index edb040db8186c2..472b9f2df939cf 100644
--- a/packages/kbn-test/src/jest/utils/testbed/testbed.ts
+++ b/packages/kbn-test/src/jest/utils/testbed/testbed.ts
@@ -6,7 +6,8 @@
* Side Public License, v 1.
*/
-import { ComponentType, ReactWrapper } from 'enzyme';
+import { Component as ReactComponent } from 'react';
+import { ComponentType, HTMLAttributes, ReactWrapper } from 'enzyme';
import { findTestSubject } from '../find_test_subject';
import { reactRouterMock } from '../router_helpers';
@@ -250,8 +251,17 @@ export const registerTestBed = (
component.update();
};
- const getErrorsMessages: TestBed['form']['getErrorsMessages'] = () => {
- const errorMessagesWrappers = component.find('.euiFormErrorText');
+ const getErrorsMessages: TestBed['form']['getErrorsMessages'] = (
+ wrapper?: T | ReactWrapper
+ ) => {
+ let errorMessagesWrappers: ReactWrapper;
+ if (typeof wrapper === 'string') {
+ errorMessagesWrappers = find(wrapper).find('.euiFormErrorText');
+ } else {
+ errorMessagesWrappers = wrapper
+ ? wrapper.find('.euiFormErrorText')
+ : component.find('.euiFormErrorText');
+ }
return errorMessagesWrappers.map((err) => err.text());
};
diff --git a/packages/kbn-test/src/jest/utils/testbed/types.ts b/packages/kbn-test/src/jest/utils/testbed/types.ts
index 338794869d9b18..520a78d03d7013 100644
--- a/packages/kbn-test/src/jest/utils/testbed/types.ts
+++ b/packages/kbn-test/src/jest/utils/testbed/types.ts
@@ -133,7 +133,7 @@ export interface TestBed {
/**
* Get a list of the form error messages that are visible in the DOM.
*/
- getErrorsMessages: () => string[];
+ getErrorsMessages: (wrapper?: T | ReactWrapper) => string[];
};
table: {
getMetaData: (tableTestSubject: T) => EuiTableMetaData;
diff --git a/packages/kbn-tinymath/BUILD.bazel b/packages/kbn-tinymath/BUILD.bazel
new file mode 100644
index 00000000000000..9d521776fb4919
--- /dev/null
+++ b/packages/kbn-tinymath/BUILD.bazel
@@ -0,0 +1,71 @@
+load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm")
+load("@npm//pegjs:index.bzl", "pegjs")
+
+PKG_BASE_NAME = "kbn-tinymath"
+PKG_REQUIRE_NAME = "@kbn/tinymath"
+
+SOURCE_FILES = glob(
+ [
+ "src/**/*",
+ ]
+)
+
+TYPE_FILES = [
+ "index.d.ts",
+]
+
+SRCS = SOURCE_FILES + TYPE_FILES
+
+filegroup(
+ name = "srcs",
+ srcs = SRCS,
+)
+
+NPM_MODULE_EXTRA_FILES = [
+ "package.json",
+ "README.md",
+]
+
+DEPS = [
+ "@npm//lodash",
+]
+
+pegjs(
+ name = "grammar",
+ data = [
+ ":grammar/grammar.pegjs"
+ ],
+ output_dir = True,
+ args = [
+ "-o",
+ "$(@D)/index.js",
+ "./%s/grammar/grammar.pegjs" % package_name()
+ ],
+)
+
+js_library(
+ name = PKG_BASE_NAME,
+ srcs = [
+ ":srcs",
+ ":grammar"
+ ],
+ deps = DEPS,
+ package_name = PKG_REQUIRE_NAME,
+ visibility = ["//visibility:public"],
+)
+
+pkg_npm(
+ name = "npm_module",
+ srcs = NPM_MODULE_EXTRA_FILES,
+ deps = [
+ ":%s" % PKG_BASE_NAME,
+ ]
+)
+
+filegroup(
+ name = "build",
+ srcs = [
+ ":npm_module",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/packages/kbn-tinymath/src/grammar.pegjs b/packages/kbn-tinymath/grammar/grammar.pegjs
similarity index 99%
rename from packages/kbn-tinymath/src/grammar.pegjs
rename to packages/kbn-tinymath/grammar/grammar.pegjs
index 9cb92fa9374a2b..70f275776e45dc 100644
--- a/packages/kbn-tinymath/src/grammar.pegjs
+++ b/packages/kbn-tinymath/grammar/grammar.pegjs
@@ -107,7 +107,7 @@ String
/ [\'] value:(ValidChar)+ [\'] { return value.join(''); }
/ value:(ValidChar)+ { return value.join(''); }
-
+
Argument
= name:[a-zA-Z_]+ _ '=' _ value:(Number / String) _ {
return {
diff --git a/packages/kbn-tinymath/tinymath.d.ts b/packages/kbn-tinymath/index.d.ts
similarity index 100%
rename from packages/kbn-tinymath/tinymath.d.ts
rename to packages/kbn-tinymath/index.d.ts
diff --git a/packages/kbn-tinymath/package.json b/packages/kbn-tinymath/package.json
index cc4fa0a64d9c32..915afda7ba2d2b 100644
--- a/packages/kbn-tinymath/package.json
+++ b/packages/kbn-tinymath/package.json
@@ -4,10 +4,5 @@
"license": "SSPL-1.0 OR Elastic License 2.0",
"private": true,
"main": "src/index.js",
- "types": "tinymath.d.ts",
- "scripts": {
- "kbn:bootstrap": "yarn build",
- "build": "../../node_modules/.bin/pegjs -o src/grammar.js src/grammar.pegjs"
- },
- "dependencies": {}
+ "types": "index.d.ts"
}
\ No newline at end of file
diff --git a/packages/kbn-tinymath/src/grammar.js b/packages/kbn-tinymath/src/grammar.js
deleted file mode 100644
index 5454143530c398..00000000000000
--- a/packages/kbn-tinymath/src/grammar.js
+++ /dev/null
@@ -1,1555 +0,0 @@
-/*
- * Generated by PEG.js 0.10.0.
- *
- * http://pegjs.org/
- */
-
-"use strict";
-
-function peg$subclass(child, parent) {
- function ctor() { this.constructor = child; }
- ctor.prototype = parent.prototype;
- child.prototype = new ctor();
-}
-
-function peg$SyntaxError(message, expected, found, location) {
- this.message = message;
- this.expected = expected;
- this.found = found;
- this.location = location;
- this.name = "SyntaxError";
-
- if (typeof Error.captureStackTrace === "function") {
- Error.captureStackTrace(this, peg$SyntaxError);
- }
-}
-
-peg$subclass(peg$SyntaxError, Error);
-
-peg$SyntaxError.buildMessage = function(expected, found) {
- var DESCRIBE_EXPECTATION_FNS = {
- literal: function(expectation) {
- return "\"" + literalEscape(expectation.text) + "\"";
- },
-
- "class": function(expectation) {
- var escapedParts = "",
- i;
-
- for (i = 0; i < expectation.parts.length; i++) {
- escapedParts += expectation.parts[i] instanceof Array
- ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
- : classEscape(expectation.parts[i]);
- }
-
- return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
- },
-
- any: function(expectation) {
- return "any character";
- },
-
- end: function(expectation) {
- return "end of input";
- },
-
- other: function(expectation) {
- return expectation.description;
- }
- };
-
- function hex(ch) {
- return ch.charCodeAt(0).toString(16).toUpperCase();
- }
-
- function literalEscape(s) {
- return s
- .replace(/\\/g, '\\\\')
- .replace(/"/g, '\\"')
- .replace(/\0/g, '\\0')
- .replace(/\t/g, '\\t')
- .replace(/\n/g, '\\n')
- .replace(/\r/g, '\\r')
- .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
- .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
- }
-
- function classEscape(s) {
- return s
- .replace(/\\/g, '\\\\')
- .replace(/\]/g, '\\]')
- .replace(/\^/g, '\\^')
- .replace(/-/g, '\\-')
- .replace(/\0/g, '\\0')
- .replace(/\t/g, '\\t')
- .replace(/\n/g, '\\n')
- .replace(/\r/g, '\\r')
- .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
- .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
- }
-
- function describeExpectation(expectation) {
- return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
- }
-
- function describeExpected(expected) {
- var descriptions = new Array(expected.length),
- i, j;
-
- for (i = 0; i < expected.length; i++) {
- descriptions[i] = describeExpectation(expected[i]);
- }
-
- descriptions.sort();
-
- if (descriptions.length > 0) {
- for (i = 1, j = 1; i < descriptions.length; i++) {
- if (descriptions[i - 1] !== descriptions[i]) {
- descriptions[j] = descriptions[i];
- j++;
- }
- }
- descriptions.length = j;
- }
-
- switch (descriptions.length) {
- case 1:
- return descriptions[0];
-
- case 2:
- return descriptions[0] + " or " + descriptions[1];
-
- default:
- return descriptions.slice(0, -1).join(", ")
- + ", or "
- + descriptions[descriptions.length - 1];
- }
- }
-
- function describeFound(found) {
- return found ? "\"" + literalEscape(found) + "\"" : "end of input";
- }
-
- return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
-};
-
-function peg$parse(input, options) {
- options = options !== void 0 ? options : {};
-
- var peg$FAILED = {},
-
- peg$startRuleFunctions = { start: peg$parsestart },
- peg$startRuleFunction = peg$parsestart,
-
- peg$c0 = peg$otherExpectation("whitespace"),
- peg$c1 = /^[ \t\n\r]/,
- peg$c2 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false),
- peg$c3 = /^[ ]/,
- peg$c4 = peg$classExpectation([" "], false, false),
- peg$c5 = /^["']/,
- peg$c6 = peg$classExpectation(["\"", "'"], false, false),
- peg$c7 = /^[A-Za-z_@.[\]\-]/,
- peg$c8 = peg$classExpectation([["A", "Z"], ["a", "z"], "_", "@", ".", "[", "]", "-"], false, false),
- peg$c9 = /^[0-9A-Za-z._@[\]\-]/,
- peg$c10 = peg$classExpectation([["0", "9"], ["A", "Z"], ["a", "z"], ".", "_", "@", "[", "]", "-"], false, false),
- peg$c11 = peg$otherExpectation("literal"),
- peg$c12 = function(literal) {
- return literal;
- },
- peg$c13 = function(chars) {
- return {
- type: 'variable',
- value: chars.join(''),
- location: simpleLocation(location()),
- text: text()
- };
- },
- peg$c14 = function(rest) {
- return {
- type: 'variable',
- value: rest.join(''),
- location: simpleLocation(location()),
- text: text()
- };
- },
- peg$c15 = "+",
- peg$c16 = peg$literalExpectation("+", false),
- peg$c17 = "-",
- peg$c18 = peg$literalExpectation("-", false),
- peg$c19 = function(left, rest) {
- return rest.reduce((acc, curr) => ({
- type: 'function',
- name: curr[0] === '+' ? 'add' : 'subtract',
- args: [acc, curr[1]],
- location: simpleLocation(location()),
- text: text()
- }), left)
- },
- peg$c20 = "*",
- peg$c21 = peg$literalExpectation("*", false),
- peg$c22 = "/",
- peg$c23 = peg$literalExpectation("/", false),
- peg$c24 = function(left, rest) {
- return rest.reduce((acc, curr) => ({
- type: 'function',
- name: curr[0] === '*' ? 'multiply' : 'divide',
- args: [acc, curr[1]],
- location: simpleLocation(location()),
- text: text()
- }), left)
- },
- peg$c25 = "(",
- peg$c26 = peg$literalExpectation("(", false),
- peg$c27 = ")",
- peg$c28 = peg$literalExpectation(")", false),
- peg$c29 = function(expr) {
- return expr
- },
- peg$c30 = peg$otherExpectation("arguments"),
- peg$c31 = ",",
- peg$c32 = peg$literalExpectation(",", false),
- peg$c33 = function(first, arg) {return arg},
- peg$c34 = function(first, rest) {
- return [first].concat(rest);
- },
- peg$c35 = /^["]/,
- peg$c36 = peg$classExpectation(["\""], false, false),
- peg$c37 = function(value) { return value.join(''); },
- peg$c38 = /^[']/,
- peg$c39 = peg$classExpectation(["'"], false, false),
- peg$c40 = /^[a-zA-Z_]/,
- peg$c41 = peg$classExpectation([["a", "z"], ["A", "Z"], "_"], false, false),
- peg$c42 = "=",
- peg$c43 = peg$literalExpectation("=", false),
- peg$c44 = function(name, value) {
- return {
- type: 'namedArgument',
- name: name.join(''),
- value: value,
- location: simpleLocation(location()),
- text: text()
- };
- },
- peg$c45 = peg$otherExpectation("function"),
- peg$c46 = /^[a-zA-Z_\-]/,
- peg$c47 = peg$classExpectation([["a", "z"], ["A", "Z"], "_", "-"], false, false),
- peg$c48 = function(name, args) {
- return {
- type: 'function',
- name: name.join(''),
- args: args || [],
- location: simpleLocation(location()),
- text: text()
- };
- },
- peg$c49 = peg$otherExpectation("number"),
- peg$c50 = function() {
- return parseFloat(text());
- },
- peg$c51 = /^[eE]/,
- peg$c52 = peg$classExpectation(["e", "E"], false, false),
- peg$c53 = peg$otherExpectation("exponent"),
- peg$c54 = ".",
- peg$c55 = peg$literalExpectation(".", false),
- peg$c56 = "0",
- peg$c57 = peg$literalExpectation("0", false),
- peg$c58 = /^[1-9]/,
- peg$c59 = peg$classExpectation([["1", "9"]], false, false),
- peg$c60 = /^[0-9]/,
- peg$c61 = peg$classExpectation([["0", "9"]], false, false),
-
- peg$currPos = 0,
- peg$savedPos = 0,
- peg$posDetailsCache = [{ line: 1, column: 1 }],
- peg$maxFailPos = 0,
- peg$maxFailExpected = [],
- peg$silentFails = 0,
-
- peg$result;
-
- if ("startRule" in options) {
- if (!(options.startRule in peg$startRuleFunctions)) {
- throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
- }
-
- peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
- }
-
- function text() {
- return input.substring(peg$savedPos, peg$currPos);
- }
-
- function location() {
- return peg$computeLocation(peg$savedPos, peg$currPos);
- }
-
- function expected(description, location) {
- location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
-
- throw peg$buildStructuredError(
- [peg$otherExpectation(description)],
- input.substring(peg$savedPos, peg$currPos),
- location
- );
- }
-
- function error(message, location) {
- location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
-
- throw peg$buildSimpleError(message, location);
- }
-
- function peg$literalExpectation(text, ignoreCase) {
- return { type: "literal", text: text, ignoreCase: ignoreCase };
- }
-
- function peg$classExpectation(parts, inverted, ignoreCase) {
- return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
- }
-
- function peg$anyExpectation() {
- return { type: "any" };
- }
-
- function peg$endExpectation() {
- return { type: "end" };
- }
-
- function peg$otherExpectation(description) {
- return { type: "other", description: description };
- }
-
- function peg$computePosDetails(pos) {
- var details = peg$posDetailsCache[pos], p;
-
- if (details) {
- return details;
- } else {
- p = pos - 1;
- while (!peg$posDetailsCache[p]) {
- p--;
- }
-
- details = peg$posDetailsCache[p];
- details = {
- line: details.line,
- column: details.column
- };
-
- while (p < pos) {
- if (input.charCodeAt(p) === 10) {
- details.line++;
- details.column = 1;
- } else {
- details.column++;
- }
-
- p++;
- }
-
- peg$posDetailsCache[pos] = details;
- return details;
- }
- }
-
- function peg$computeLocation(startPos, endPos) {
- var startPosDetails = peg$computePosDetails(startPos),
- endPosDetails = peg$computePosDetails(endPos);
-
- return {
- start: {
- offset: startPos,
- line: startPosDetails.line,
- column: startPosDetails.column
- },
- end: {
- offset: endPos,
- line: endPosDetails.line,
- column: endPosDetails.column
- }
- };
- }
-
- function peg$fail(expected) {
- if (peg$currPos < peg$maxFailPos) { return; }
-
- if (peg$currPos > peg$maxFailPos) {
- peg$maxFailPos = peg$currPos;
- peg$maxFailExpected = [];
- }
-
- peg$maxFailExpected.push(expected);
- }
-
- function peg$buildSimpleError(message, location) {
- return new peg$SyntaxError(message, null, null, location);
- }
-
- function peg$buildStructuredError(expected, found, location) {
- return new peg$SyntaxError(
- peg$SyntaxError.buildMessage(expected, found),
- expected,
- found,
- location
- );
- }
-
- function peg$parsestart() {
- var s0;
-
- s0 = peg$parseAddSubtract();
-
- return s0;
- }
-
- function peg$parse_() {
- var s0, s1;
-
- peg$silentFails++;
- s0 = [];
- if (peg$c1.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c2); }
- }
- while (s1 !== peg$FAILED) {
- s0.push(s1);
- if (peg$c1.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c2); }
- }
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c0); }
- }
-
- return s0;
- }
-
- function peg$parseSpace() {
- var s0;
-
- if (peg$c3.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c4); }
- }
-
- return s0;
- }
-
- function peg$parseQuote() {
- var s0;
-
- if (peg$c5.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c6); }
- }
-
- return s0;
- }
-
- function peg$parseStartChar() {
- var s0;
-
- if (peg$c7.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c8); }
- }
-
- return s0;
- }
-
- function peg$parseValidChar() {
- var s0;
-
- if (peg$c9.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c10); }
- }
-
- return s0;
- }
-
- function peg$parseLiteral() {
- var s0, s1, s2, s3;
-
- peg$silentFails++;
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = peg$parseNumber();
- if (s2 === peg$FAILED) {
- s2 = peg$parseVariable();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parse_();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c12(s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c11); }
- }
-
- return s0;
- }
-
- function peg$parseVariable() {
- var s0, s1, s2, s3, s4, s5;
-
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = peg$parseQuote();
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$parseValidChar();
- if (s4 === peg$FAILED) {
- s4 = peg$parseSpace();
- }
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$parseValidChar();
- if (s4 === peg$FAILED) {
- s4 = peg$parseSpace();
- }
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parseQuote();
- if (s4 !== peg$FAILED) {
- s5 = peg$parse_();
- if (s5 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c13(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parseValidChar();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parseValidChar();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parse_();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c14(s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- }
-
- return s0;
- }
-
- function peg$parseAddSubtract() {
- var s0, s1, s2, s3, s4, s5, s6;
-
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = peg$parseMultiplyDivide();
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 43) {
- s5 = peg$c15;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c16); }
- }
- if (s5 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 45) {
- s5 = peg$c17;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c18); }
- }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parseMultiplyDivide();
- if (s6 !== peg$FAILED) {
- s5 = [s5, s6];
- s4 = s5;
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 43) {
- s5 = peg$c15;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c16); }
- }
- if (s5 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 45) {
- s5 = peg$c17;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c18); }
- }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parseMultiplyDivide();
- if (s6 !== peg$FAILED) {
- s5 = [s5, s6];
- s4 = s5;
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c19(s2, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
-
- return s0;
- }
-
- function peg$parseMultiplyDivide() {
- var s0, s1, s2, s3, s4, s5, s6;
-
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = peg$parseFactor();
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 42) {
- s5 = peg$c20;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c21); }
- }
- if (s5 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 47) {
- s5 = peg$c22;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c23); }
- }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parseFactor();
- if (s6 !== peg$FAILED) {
- s5 = [s5, s6];
- s4 = s5;
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 42) {
- s5 = peg$c20;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c21); }
- }
- if (s5 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 47) {
- s5 = peg$c22;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c23); }
- }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parseFactor();
- if (s6 !== peg$FAILED) {
- s5 = [s5, s6];
- s4 = s5;
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- } else {
- peg$currPos = s4;
- s4 = peg$FAILED;
- }
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c24(s2, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
-
- return s0;
- }
-
- function peg$parseFactor() {
- var s0;
-
- s0 = peg$parseGroup();
- if (s0 === peg$FAILED) {
- s0 = peg$parseFunction();
- if (s0 === peg$FAILED) {
- s0 = peg$parseLiteral();
- }
- }
-
- return s0;
- }
-
- function peg$parseGroup() {
- var s0, s1, s2, s3, s4, s5, s6, s7;
-
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 40) {
- s2 = peg$c25;
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c26); }
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parse_();
- if (s3 !== peg$FAILED) {
- s4 = peg$parseAddSubtract();
- if (s4 !== peg$FAILED) {
- s5 = peg$parse_();
- if (s5 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 41) {
- s6 = peg$c27;
- peg$currPos++;
- } else {
- s6 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c28); }
- }
- if (s6 !== peg$FAILED) {
- s7 = peg$parse_();
- if (s7 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c29(s4);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
-
- return s0;
- }
-
- function peg$parseArgument_List() {
- var s0, s1, s2, s3, s4, s5, s6, s7;
-
- peg$silentFails++;
- s0 = peg$currPos;
- s1 = peg$parseArgument();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$currPos;
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 44) {
- s5 = peg$c31;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c32); }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parse_();
- if (s6 !== peg$FAILED) {
- s7 = peg$parseArgument();
- if (s7 !== peg$FAILED) {
- peg$savedPos = s3;
- s4 = peg$c33(s1, s7);
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$currPos;
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 44) {
- s5 = peg$c31;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c32); }
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parse_();
- if (s6 !== peg$FAILED) {
- s7 = peg$parseArgument();
- if (s7 !== peg$FAILED) {
- peg$savedPos = s3;
- s4 = peg$c33(s1, s7);
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$FAILED;
- }
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parse_();
- if (s3 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 44) {
- s4 = peg$c31;
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c32); }
- }
- if (s4 === peg$FAILED) {
- s4 = null;
- }
- if (s4 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c34(s1, s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c30); }
- }
-
- return s0;
- }
-
- function peg$parseString() {
- var s0, s1, s2, s3;
-
- s0 = peg$currPos;
- if (peg$c35.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c36); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parseValidChar();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parseValidChar();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- if (peg$c35.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c36); }
- }
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c37(s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (peg$c38.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c39); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parseValidChar();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parseValidChar();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- if (peg$c38.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c39); }
- }
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c37(s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- s1 = [];
- s2 = peg$parseValidChar();
- if (s2 !== peg$FAILED) {
- while (s2 !== peg$FAILED) {
- s1.push(s2);
- s2 = peg$parseValidChar();
- }
- } else {
- s1 = peg$FAILED;
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c37(s1);
- }
- s0 = s1;
- }
- }
-
- return s0;
- }
-
- function peg$parseArgument() {
- var s0, s1, s2, s3, s4, s5, s6;
-
- s0 = peg$currPos;
- s1 = [];
- if (peg$c40.test(input.charAt(peg$currPos))) {
- s2 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c41); }
- }
- if (s2 !== peg$FAILED) {
- while (s2 !== peg$FAILED) {
- s1.push(s2);
- if (peg$c40.test(input.charAt(peg$currPos))) {
- s2 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c41); }
- }
- }
- } else {
- s1 = peg$FAILED;
- }
- if (s1 !== peg$FAILED) {
- s2 = peg$parse_();
- if (s2 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 61) {
- s3 = peg$c42;
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c43); }
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- s5 = peg$parseNumber();
- if (s5 === peg$FAILED) {
- s5 = peg$parseString();
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parse_();
- if (s6 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c44(s1, s5);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$parseAddSubtract();
- }
-
- return s0;
- }
-
- function peg$parseFunction() {
- var s0, s1, s2, s3, s4, s5, s6, s7, s8;
-
- peg$silentFails++;
- s0 = peg$currPos;
- s1 = peg$parse_();
- if (s1 !== peg$FAILED) {
- s2 = [];
- if (peg$c46.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
- }
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- if (peg$c46.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
- }
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 40) {
- s3 = peg$c25;
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c26); }
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- s5 = peg$parseArgument_List();
- if (s5 === peg$FAILED) {
- s5 = null;
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parse_();
- if (s6 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 41) {
- s7 = peg$c27;
- peg$currPos++;
- } else {
- s7 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c28); }
- }
- if (s7 !== peg$FAILED) {
- s8 = peg$parse_();
- if (s8 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c48(s2, s5);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c45); }
- }
-
- return s0;
- }
-
- function peg$parseNumber() {
- var s0, s1, s2, s3, s4;
-
- peg$silentFails++;
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 45) {
- s1 = peg$c17;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c18); }
- }
- if (s1 === peg$FAILED) {
- s1 = null;
- }
- if (s1 !== peg$FAILED) {
- s2 = peg$parseInteger();
- if (s2 !== peg$FAILED) {
- s3 = peg$parseFraction();
- if (s3 === peg$FAILED) {
- s3 = null;
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parseExp();
- if (s4 === peg$FAILED) {
- s4 = null;
- }
- if (s4 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c50();
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c49); }
- }
-
- return s0;
- }
-
- function peg$parseE() {
- var s0;
-
- if (peg$c51.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c52); }
- }
-
- return s0;
- }
-
- function peg$parseExp() {
- var s0, s1, s2, s3, s4;
-
- peg$silentFails++;
- s0 = peg$currPos;
- s1 = peg$parseE();
- if (s1 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 45) {
- s2 = peg$c17;
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c18); }
- }
- if (s2 === peg$FAILED) {
- s2 = null;
- }
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$parseDigit();
- if (s4 !== peg$FAILED) {
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$parseDigit();
- }
- } else {
- s3 = peg$FAILED;
- }
- if (s3 !== peg$FAILED) {
- s1 = [s1, s2, s3];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c53); }
- }
-
- return s0;
- }
-
- function peg$parseFraction() {
- var s0, s1, s2, s3;
-
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 46) {
- s1 = peg$c54;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c55); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parseDigit();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parseDigit();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s1 = [s1, s2];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
-
- return s0;
- }
-
- function peg$parseInteger() {
- var s0, s1, s2, s3;
-
- if (input.charCodeAt(peg$currPos) === 48) {
- s0 = peg$c56;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c57); }
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (peg$c58.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c59); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parseDigit();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parseDigit();
- }
- if (s2 !== peg$FAILED) {
- s1 = [s1, s2];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- }
-
- return s0;
- }
-
- function peg$parseDigit() {
- var s0;
-
- if (peg$c60.test(input.charAt(peg$currPos))) {
- s0 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c61); }
- }
-
- return s0;
- }
-
-
- function simpleLocation (location) {
- // Returns an object representing the position of the function within the expression,
- // demarcated by the position of its first character and last character. We calculate these values
- // using the offset because the expression could span multiple lines, and we don't want to deal
- // with column and line values.
- return {
- min: location.start.offset,
- max: location.end.offset
- }
- }
-
-
- peg$result = peg$startRuleFunction();
-
- if (peg$result !== peg$FAILED && peg$currPos === input.length) {
- return peg$result;
- } else {
- if (peg$result !== peg$FAILED && peg$currPos < input.length) {
- peg$fail(peg$endExpectation());
- }
-
- throw peg$buildStructuredError(
- peg$maxFailExpected,
- peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
- peg$maxFailPos < input.length
- ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
- : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
- );
- }
-}
-
-module.exports = {
- SyntaxError: peg$SyntaxError,
- parse: peg$parse
-};
diff --git a/packages/kbn-tinymath/src/index.js b/packages/kbn-tinymath/src/index.js
index 4db7df9c573156..9f1bb7b8514634 100644
--- a/packages/kbn-tinymath/src/index.js
+++ b/packages/kbn-tinymath/src/index.js
@@ -7,7 +7,8 @@
*/
const { get } = require('lodash');
-const { parse: parseFn } = require('./grammar');
+// eslint-disable-next-line import/no-unresolved
+const { parse: parseFn } = require('../grammar');
const { functions: includedFunctions } = require('./functions');
module.exports = { parse, evaluate, interpret };
diff --git a/packages/kbn-tinymath/test/library.test.js b/packages/kbn-tinymath/test/library.test.js
index d11822625b98f5..5ddf1b049b8d4f 100644
--- a/packages/kbn-tinymath/test/library.test.js
+++ b/packages/kbn-tinymath/test/library.test.js
@@ -11,7 +11,7 @@
Need tests for spacing, etc
*/
-import { evaluate, parse } from '..';
+import { evaluate, parse } from '@kbn/tinymath';
function variableEqual(value) {
return expect.objectContaining({ type: 'variable', value });
diff --git a/packages/kbn-tinymath/tsconfig.json b/packages/kbn-tinymath/tsconfig.json
index 62a7376efdfa6d..73133b7318a0d6 100644
--- a/packages/kbn-tinymath/tsconfig.json
+++ b/packages/kbn-tinymath/tsconfig.json
@@ -1,7 +1,4 @@
{
"extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "tsBuildInfoFile": "../../build/tsbuildinfo/packages/kbn-tinymath"
- },
- "include": ["tinymath.d.ts"]
+ "include": ["index.d.ts"]
}
diff --git a/packages/kbn-utils/package.json b/packages/kbn-utils/package.json
index b6bb7759c40efe..2c3c0c11b65ab8 100644
--- a/packages/kbn-utils/package.json
+++ b/packages/kbn-utils/package.json
@@ -9,8 +9,5 @@
"build": "rm -rf target && ../../node_modules/.bin/tsc",
"kbn:bootstrap": "yarn build",
"kbn:watch": "yarn build --watch"
- },
- "dependencies": {
- "@kbn/config-schema": "link:../kbn-config-schema"
}
}
\ No newline at end of file
diff --git a/src/cli_keystore/utils/prompt.js b/src/cli_keystore/utils/prompt.js
index d681f7de2e32cb..195f794db3e6e5 100644
--- a/src/cli_keystore/utils/prompt.js
+++ b/src/cli_keystore/utils/prompt.js
@@ -75,6 +75,7 @@ export function question(question, options = {}) {
});
rl.question(questionPrompt, (value) => {
+ rl.close();
resolve(value);
});
});
diff --git a/src/cli_keystore/utils/prompt.test.js b/src/cli_keystore/utils/prompt.test.js
index 306d4b2bd66df5..e7ccac4e83e113 100644
--- a/src/cli_keystore/utils/prompt.test.js
+++ b/src/cli_keystore/utils/prompt.test.js
@@ -6,14 +6,11 @@
* Side Public License, v 1.
*/
-import sinon from 'sinon';
import { PassThrough } from 'stream';
import { confirm, question } from './prompt';
describe('prompt', () => {
- const sandbox = sinon.createSandbox();
-
let input;
let output;
@@ -23,30 +20,27 @@ describe('prompt', () => {
});
afterEach(() => {
- sandbox.restore();
+ input.end();
+ output.end();
});
describe('confirm', () => {
it('prompts for question', async () => {
- const onData = sandbox.stub(output, 'write');
-
- confirm('my question', { output });
+ const write = jest.spyOn(output, 'write');
- sinon.assert.calledOnce(onData);
+ process.nextTick(() => input.write('Y\n'));
+ await confirm('my question', { input, output });
- const { args } = onData.getCall(0);
- expect(args[0]).toEqual('my question [y/N] ');
+ expect(write).toHaveBeenCalledWith('my question [y/N] ');
});
it('prompts for question with default true', async () => {
- const onData = sandbox.stub(output, 'write');
-
- confirm('my question', { output, default: true });
+ const write = jest.spyOn(output, 'write');
- sinon.assert.calledOnce(onData);
+ process.nextTick(() => input.write('Y\n'));
+ await confirm('my question', { input, output, default: true });
- const { args } = onData.getCall(0);
- expect(args[0]).toEqual('my question [Y/n] ');
+ expect(write).toHaveBeenCalledWith('my question [Y/n] ');
});
it('defaults to false', async () => {
@@ -87,14 +81,12 @@ describe('prompt', () => {
describe('question', () => {
it('prompts for question', async () => {
- const onData = sandbox.stub(output, 'write');
-
- question('my question', { output });
+ const write = jest.spyOn(output, 'write');
- sinon.assert.calledOnce(onData);
+ process.nextTick(() => input.write('my answer\n'));
+ await question('my question', { input, output });
- const { args } = onData.getCall(0);
- expect(args[0]).toEqual('my question: ');
+ expect(write).toHaveBeenCalledWith('my question: ');
});
it('can be answered', async () => {
diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap
index 00cc827a1e83f1..29407c54e28345 100644
--- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap
+++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap
@@ -4072,8 +4072,34 @@ exports[`Header renders 1`] = `
aria-expanded={false}
aria-haspopup="true"
aria-label="Help menu"
- buttonRef={null}
- className="euiHeaderSectionItem__button"
+ buttonRef={
+ Object {
+ "current": ,
+ }
+ }
+ className="euiHeaderSectionItemButton"
color="text"
onClick={[Function]}
>
@@ -4081,7 +4107,7 @@ exports[`Header renders 1`] = `
aria-expanded={false}
aria-haspopup="true"
aria-label="Help menu"
- className="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItem__button"
+ className="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItemButton"
disabled={false}
onClick={[Function]}
type="button"
@@ -4101,15 +4127,19 @@ exports[`Header renders 1`] = `
-
-
-
+ type="help"
+ >
+
+
+
@@ -4226,7 +4256,7 @@ exports[`Header renders 1`] = `
aria-expanded="false"
aria-label="Toggle primary navigation"
aria-pressed="false"
- class="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItem__button"
+ class="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItemButton"
data-test-subj="toggleNavButton"
type="button"
>
@@ -4237,14 +4267,18 @@ exports[`Header renders 1`] = `
class="euiButtonEmpty__text"
>
+ class="euiHeaderSectionItemButton__content"
+ >
+
+
,
}
}
- className="euiHeaderSectionItem__button"
+ className="euiHeaderSectionItemButton"
color="text"
data-test-subj="toggleNavButton"
onClick={[Function]}
@@ -4254,7 +4288,7 @@ exports[`Header renders 1`] = `
aria-expanded={false}
aria-label="Toggle primary navigation"
aria-pressed={false}
- className="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItem__button"
+ className="euiButtonEmpty euiButtonEmpty--text euiHeaderSectionItemButton"
data-test-subj="toggleNavButton"
disabled={false}
onClick={[Function]}
@@ -4275,15 +4309,19 @@ exports[`Header renders 1`] = `
-
-
-
+ type="menu"
+ >
+
+
+
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index 16c89fdca380ab..67cdd24aae8487 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -98,7 +98,7 @@ export function Header({
);
}
- const toggleCollapsibleNavRef = createRef();
+ const toggleCollapsibleNavRef = createRef void }>();
const navId = htmlIdGenerator()();
const className = classnames('hide-for-sharing', 'headerGlobalNav');
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index baf8ed2a61645b..4220d3e490f63a 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -109,6 +109,7 @@ export class DocLinksService {
top_hits: `${ELASTICSEARCH_DOCS}search-aggregations-metrics-top-hits-aggregation.html`,
},
runtimeFields: {
+ overview: `${ELASTICSEARCH_DOCS}runtime.html`,
mapping: `${ELASTICSEARCH_DOCS}runtime-mapping-fields.html`,
},
scriptedFields: {
@@ -129,9 +130,51 @@ export class DocLinksService {
},
addData: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/connect-to-elasticsearch.html`,
kibana: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index.html`,
+ upgradeAssistant: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/upgrade-assistant.html`,
elasticsearch: {
+ docsBase: `${ELASTICSEARCH_DOCS}`,
+ asyncSearch: `${ELASTICSEARCH_DOCS}async-search-intro.html`,
+ dataStreams: `${ELASTICSEARCH_DOCS}data-streams.html`,
indexModules: `${ELASTICSEARCH_DOCS}index-modules.html`,
+ indexSettings: `${ELASTICSEARCH_DOCS}index-modules.html#index-modules-settings`,
+ indexTemplates: `${ELASTICSEARCH_DOCS}indices-templates.html`,
mapping: `${ELASTICSEARCH_DOCS}mapping.html`,
+ mappingAnalyzer: `${ELASTICSEARCH_DOCS}analyzer.html`,
+ mappingCoerce: `${ELASTICSEARCH_DOCS}coerce.html`,
+ mappingCopyTo: `${ELASTICSEARCH_DOCS}copy-to.html`,
+ mappingDocValues: `${ELASTICSEARCH_DOCS}doc-values.html`,
+ mappingDynamic: `${ELASTICSEARCH_DOCS}dynamic.html`,
+ mappingDynamicFields: `${ELASTICSEARCH_DOCS}dynamic-field-mapping.html`,
+ mappingDynamicTemplates: `${ELASTICSEARCH_DOCS}dynamic-templates.html`,
+ mappingEagerGlobalOrdinals: `${ELASTICSEARCH_DOCS}eager-global-ordinals.html`,
+ mappingEnabled: `${ELASTICSEARCH_DOCS}enabled.html`,
+ mappingFieldData: `${ELASTICSEARCH_DOCS}text.html#fielddata-mapping-param`,
+ mappingFieldDataEnable: `${ELASTICSEARCH_DOCS}text.html#before-enabling-fielddata`,
+ mappingFieldDataFilter: `${ELASTICSEARCH_DOCS}text.html#field-data-filtering`,
+ mappingFieldDataTypes: `${ELASTICSEARCH_DOCS}mapping-types.html`,
+ mappingFormat: `${ELASTICSEARCH_DOCS}mapping-date-format.html`,
+ mappingIgnoreAbove: `${ELASTICSEARCH_DOCS}ignore-above.html`,
+ mappingIgnoreMalformed: `${ELASTICSEARCH_DOCS}ignore-malformed.html`,
+ mappingIndex: `${ELASTICSEARCH_DOCS}mapping-index.html`,
+ mappingIndexOptions: `${ELASTICSEARCH_DOCS}index-options.html`,
+ mappingIndexPhrases: `${ELASTICSEARCH_DOCS}index-phrases.html`,
+ mappingIndexPrefixes: `${ELASTICSEARCH_DOCS}index-prefixes.html`,
+ mappingJoinFieldsPerformance: `${ELASTICSEARCH_DOCS}parent-join.html#_parent_join_and_performance`,
+ mappingMeta: `${ELASTICSEARCH_DOCS}mapping-field-meta.html`,
+ mappingMetaFields: `${ELASTICSEARCH_DOCS}mapping-meta-field.html`,
+ mappingNormalizer: `${ELASTICSEARCH_DOCS}normalizer.html`,
+ mappingNorms: `${ELASTICSEARCH_DOCS}norms.html`,
+ mappingNullValue: `${ELASTICSEARCH_DOCS}null-value.html`,
+ mappingParameters: `${ELASTICSEARCH_DOCS}mapping-params.html`,
+ mappingPositionIncrementGap: `${ELASTICSEARCH_DOCS}position-increment-gap.html`,
+ mappingRankFeatureFields: `${ELASTICSEARCH_DOCS}rank-feature.html`,
+ mappingRouting: `${ELASTICSEARCH_DOCS}mapping-routing-field.html`,
+ mappingSimilarity: `${ELASTICSEARCH_DOCS}similarity.html`,
+ mappingSourceFields: `${ELASTICSEARCH_DOCS}mapping-source-field.html`,
+ mappingSourceFieldsDisable: `${ELASTICSEARCH_DOCS}mapping-source-field.html#disable-source-field`,
+ mappingStore: `${ELASTICSEARCH_DOCS}mapping-store.html`,
+ mappingTermVector: `${ELASTICSEARCH_DOCS}term-vector.html`,
+ mappingTypesRemoval: `${ELASTICSEARCH_DOCS}removal-of-types.html`,
nodeRoles: `${ELASTICSEARCH_DOCS}modules-node.html#node-roles`,
remoteClusters: `${ELASTICSEARCH_DOCS}modules-remote-clusters.html`,
remoteClustersProxy: `${ELASTICSEARCH_DOCS}modules-remote-clusters.html#proxy-mode`,
@@ -139,6 +182,7 @@ export class DocLinksService {
scriptParameters: `${ELASTICSEARCH_DOCS}modules-scripting-using.html#prefer-params`,
transportSettings: `${ELASTICSEARCH_DOCS}modules-transport.html`,
typesRemoval: `${ELASTICSEARCH_DOCS}removal-of-types.html`,
+ deprecationLogging: `${ELASTICSEARCH_DOCS}logging.html#deprecation-logging`,
},
siem: {
guide: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`,
@@ -146,17 +190,19 @@ export class DocLinksService {
},
query: {
eql: `${ELASTICSEARCH_DOCS}eql.html`,
+ kueryQuerySyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kuery-query.html`,
luceneQuerySyntax: `${ELASTICSEARCH_DOCS}query-dsl-query-string-query.html#query-string-syntax`,
+ percolate: `${ELASTICSEARCH_DOCS}query-dsl-percolate-query.html`,
queryDsl: `${ELASTICSEARCH_DOCS}query-dsl.html`,
- kueryQuerySyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kuery-query.html`,
},
date: {
dateMath: `${ELASTICSEARCH_DOCS}common-options.html#date-math`,
dateMathIndexNames: `${ELASTICSEARCH_DOCS}date-math-index-names.html`,
},
management: {
- kibanaSearchSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/advanced-options.html#kibana-search-settings`,
dashboardSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/advanced-options.html#kibana-dashboard-settings`,
+ indexManagement: `${ELASTICSEARCH_DOCS}index-mgmt.html`,
+ kibanaSearchSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/advanced-options.html#kibana-search-settings`,
visualizationSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/advanced-options.html#kibana-visualization-settings`,
},
ml: {
@@ -258,6 +304,7 @@ export class DocLinksService {
skippingDisconnectedClusters: `${ELASTICSEARCH_DOCS}modules-cross-cluster-search.html#skip-unavailable-clusters`,
},
apis: {
+ bulkIndexAlias: `${ELASTICSEARCH_DOCS}indices-aliases.html`,
createIndex: `${ELASTICSEARCH_DOCS}indices-create-index.html`,
createSnapshotLifecyclePolicy: `${ELASTICSEARCH_DOCS}slm-api-put-policy.html`,
createRoleMapping: `${ELASTICSEARCH_DOCS}security-api-put-role-mapping.html`,
@@ -274,6 +321,7 @@ export class DocLinksService {
painlessExecuteAPIContexts: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/painless/${DOC_LINK_VERSION}/painless-execute-api.html#_contexts`,
putComponentTemplateMetadata: `${ELASTICSEARCH_DOCS}indices-component-template.html#component-templates-metadata`,
putEnrichPolicy: `${ELASTICSEARCH_DOCS}put-enrich-policy-api.html`,
+ putIndexTemplateV1: `${ELASTICSEARCH_DOCS}indices-templates-v1.html`,
putSnapshotLifecyclePolicy: `${ELASTICSEARCH_DOCS}slm-api-put-policy.html`,
putWatch: `${ELASTICSEARCH_DOCS}watcher-api-put-watch.html`,
simulatePipeline: `${ELASTICSEARCH_DOCS}simulate-pipeline-api.html`,
@@ -429,6 +477,7 @@ export interface DocLinksStart {
readonly top_hits: string;
};
readonly runtimeFields: {
+ readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
@@ -448,6 +497,7 @@ export interface DocLinksStart {
};
readonly addData: string;
readonly kibana: string;
+ readonly upgradeAssistant: string;
readonly elasticsearch: Record;
readonly siem: {
readonly guide: string;
@@ -455,9 +505,10 @@ export interface DocLinksStart {
};
readonly query: {
readonly eql: string;
+ readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
+ readonly percolate: string;
readonly queryDsl: string;
- readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
@@ -468,6 +519,7 @@ export interface DocLinksStart {
readonly transforms: Record;
readonly visualize: Record;
readonly apis: Readonly<{
+ bulkIndexAlias: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
@@ -484,6 +536,7 @@ export interface DocLinksStart {
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
+ putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
updateTransform: string;
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 750f2e27dc9504..ca432d6b8269fa 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -67,7 +67,12 @@ import { DocLinksStart } from './doc_links';
import { SavedObjectsStart } from './saved_objects';
import { DeprecationsServiceStart } from './deprecations';
-export type { PackageInfo, EnvironmentMode, IExternalUrlPolicy } from '../server/types';
+export type {
+ PackageInfo,
+ EnvironmentMode,
+ IExternalUrlPolicy,
+ DomainDeprecationDetails,
+} from '../server/types';
export type { CoreContext, CoreSystem } from './core_system';
export { DEFAULT_APP_CATEGORIES } from '../utils';
export type {
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 8327428991e13b..661ac51c4983c6 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -476,7 +476,6 @@ export const DEFAULT_APP_CATEGORIES: Record;
// @public
export interface DeprecationsServiceStart {
- // Warning: (ae-forgotten-export) The symbol "DomainDeprecationDetails" needs to be exported by the entry point index.d.ts
getAllDeprecations: () => Promise;
getDeprecations: (domainId: string) => Promise;
isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean;
@@ -571,6 +570,7 @@ export interface DocLinksStart {
readonly top_hits: string;
};
readonly runtimeFields: {
+ readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
@@ -590,6 +590,7 @@ export interface DocLinksStart {
};
readonly addData: string;
readonly kibana: string;
+ readonly upgradeAssistant: string;
readonly elasticsearch: Record;
readonly siem: {
readonly guide: string;
@@ -597,9 +598,10 @@ export interface DocLinksStart {
};
readonly query: {
readonly eql: string;
+ readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
+ readonly percolate: string;
readonly queryDsl: string;
- readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
@@ -610,6 +612,7 @@ export interface DocLinksStart {
readonly transforms: Record;
readonly visualize: Record;
readonly apis: Readonly<{
+ bulkIndexAlias: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
@@ -626,6 +629,7 @@ export interface DocLinksStart {
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
+ putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
updateTransform: string;
@@ -654,6 +658,15 @@ export interface DocLinksStart {
};
}
+// Warning: (ae-forgotten-export) The symbol "DeprecationsDetails" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "DomainDeprecationDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface DomainDeprecationDetails extends DeprecationsDetails {
+ // (undocumented)
+ domainId: string;
+}
+
export { EnvironmentMode }
// @public
diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts
index 2fc78fc619cab5..1d2ec6abc0dd14 100644
--- a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts
+++ b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts
@@ -425,6 +425,22 @@ describe('ElasticIndex', () => {
type: 'tsvb-validation-telemetry',
},
},
+ {
+ bool: {
+ must: [
+ {
+ match: {
+ type: 'search-session',
+ },
+ },
+ {
+ match: {
+ 'search-session.persisted': false,
+ },
+ },
+ ],
+ },
+ },
],
},
},
diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.ts b/src/core/server/saved_objects/migrations/core/elastic_index.ts
index 462425ff6e3e0e..460aabbc77415c 100644
--- a/src/core/server/saved_objects/migrations/core/elastic_index.ts
+++ b/src/core/server/saved_objects/migrations/core/elastic_index.ts
@@ -29,6 +29,46 @@ export interface FullIndexInfo {
mappings: IndexMapping;
}
+// When migrating from the outdated index we use a read query which excludes
+// saved objects which are no longer used. These saved objects will still be
+// kept in the outdated index for backup purposes, but won't be availble in
+// the upgraded index.
+export const excludeUnusedTypesQuery: estypes.QueryContainer = {
+ bool: {
+ must_not: [
+ // https://github.com/elastic/kibana/issues/91869
+ {
+ term: {
+ type: 'fleet-agent-events',
+ },
+ },
+ // https://github.com/elastic/kibana/issues/95617
+ {
+ term: {
+ type: 'tsvb-validation-telemetry',
+ },
+ },
+ // https://github.com/elastic/kibana/issues/96131
+ {
+ bool: {
+ must: [
+ {
+ match: {
+ type: 'search-session',
+ },
+ },
+ {
+ match: {
+ 'search-session.persisted': false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+};
+
/**
* A slight enhancement to indices.get, that adds indexName, and validates that the
* index mappings are somewhat what we expect.
@@ -69,23 +109,6 @@ export function reader(
const scroll = scrollDuration;
let scrollId: string | undefined;
- // When migrating from the outdated index we use a read query which excludes
- // saved object types which are no longer used. These saved objects will
- // still be kept in the outdated index for backup purposes, but won't be
- // availble in the upgraded index.
- const EXCLUDE_UNUSED_TYPES = [
- 'fleet-agent-events', // https://github.com/elastic/kibana/issues/91869
- 'tsvb-validation-telemetry', // https://github.com/elastic/kibana/issues/95617
- ];
-
- const excludeUnusedTypesQuery = {
- bool: {
- must_not: EXCLUDE_UNUSED_TYPES.map((type) => ({
- term: { type },
- })),
- },
- };
-
const nextBatch = () =>
scrollId !== undefined
? client.scroll>({
diff --git a/src/core/server/saved_objects/migrations/core/index.ts b/src/core/server/saved_objects/migrations/core/index.ts
index 322150e2b850eb..1e51983a0ffbdb 100644
--- a/src/core/server/saved_objects/migrations/core/index.ts
+++ b/src/core/server/saved_objects/migrations/core/index.ts
@@ -14,3 +14,4 @@ export type { LogFn, SavedObjectsMigrationLogger } from './migration_logger';
export type { MigrationResult, MigrationStatus } from './migration_coordinator';
export { createMigrationEsClient } from './migration_es_client';
export type { MigrationEsClient } from './migration_es_client';
+export { excludeUnusedTypesQuery } from './elastic_index';
diff --git a/src/core/server/saved_objects/migrationsv2/actions/index.ts b/src/core/server/saved_objects/migrationsv2/actions/index.ts
index 9d6afbd3b0d87c..02d3f8e21a5106 100644
--- a/src/core/server/saved_objects/migrationsv2/actions/index.ts
+++ b/src/core/server/saved_objects/migrationsv2/actions/index.ts
@@ -14,7 +14,6 @@ import { errors as EsErrors } from '@elastic/elasticsearch';
import type { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors';
import { pipe } from 'fp-ts/lib/pipeable';
import { flow } from 'fp-ts/lib/function';
-import { QueryContainer } from '@elastic/eui/src/components/search_bar/query/ast_to_es_query_dsl';
import { ElasticsearchClient } from '../../../elasticsearch';
import { IndexMapping } from '../../mappings';
import { SavedObjectsRawDoc, SavedObjectsRawDocSource } from '../../serialization';
@@ -440,9 +439,9 @@ export const reindex = (
requireAlias: boolean,
/* When reindexing we use a source query to exclude saved objects types which
* are no longer used. These saved objects will still be kept in the outdated
- * index for backup purposes, but won't be availble in the upgraded index.
+ * index for backup purposes, but won't be available in the upgraded index.
*/
- unusedTypesToExclude: Option.Option
+ unusedTypesQuery: Option.Option
): TaskEither.TaskEither => () => {
return client
.reindex({
@@ -457,14 +456,10 @@ export const reindex = (
// Set reindex batch size
size: BATCH_SIZE,
// Exclude saved object types
- query: Option.fold(
+ query: Option.fold(
() => undefined,
- (types) => ({
- bool: {
- must_not: types.map((type) => ({ term: { type } })),
- },
- })
- )(unusedTypesToExclude),
+ (query) => query
+ )(unusedTypesQuery),
},
dest: {
index: targetIndex,
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts
index 21c05d22b05819..3905044f04e2fc 100644
--- a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts
+++ b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts
@@ -416,14 +416,20 @@ describe('migration actions', () => {
]
`);
});
- it('resolves right and excludes all unusedTypesToExclude documents', async () => {
+ it('resolves right and excludes all documents not matching the unusedTypesQuery', async () => {
const res = (await reindex(
client,
'existing_index_with_docs',
'reindex_target_excluded_docs',
Option.none,
false,
- Option.some(['f_agent_event', 'another_unused_type'])
+ Option.of({
+ bool: {
+ must_not: ['f_agent_event', 'another_unused_type'].map((type) => ({
+ term: { type },
+ })),
+ },
+ })
)()) as Either.Right;
const task = waitForReindexTask(client, res.right.taskId, '10s');
await expect(task()).resolves.toMatchInlineSnapshot(`
diff --git a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts
index bec09c4b243280..a6617fc2fb7f48 100644
--- a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts
+++ b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts
@@ -256,12 +256,40 @@ describe('migrationsStateActionMachine', () => {
},
},
},
- "unusedTypesToExclude": Object {
+ "unusedTypesQuery": Object {
"_tag": "Some",
- "value": Array [
- "fleet-agent-events",
- "tsvb-validation-telemetry",
- ],
+ "value": Object {
+ "bool": Object {
+ "must_not": Array [
+ Object {
+ "term": Object {
+ "type": "fleet-agent-events",
+ },
+ },
+ Object {
+ "term": Object {
+ "type": "tsvb-validation-telemetry",
+ },
+ },
+ Object {
+ "bool": Object {
+ "must": Array [
+ Object {
+ "match": Object {
+ "type": "search-session",
+ },
+ },
+ Object {
+ "match": Object {
+ "search-session.persisted": false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
},
"versionAlias": ".my-so-index_7.11.0",
"versionIndex": ".my-so-index_7.11.0_001",
@@ -328,12 +356,40 @@ describe('migrationsStateActionMachine', () => {
},
},
},
- "unusedTypesToExclude": Object {
+ "unusedTypesQuery": Object {
"_tag": "Some",
- "value": Array [
- "fleet-agent-events",
- "tsvb-validation-telemetry",
- ],
+ "value": Object {
+ "bool": Object {
+ "must_not": Array [
+ Object {
+ "term": Object {
+ "type": "fleet-agent-events",
+ },
+ },
+ Object {
+ "term": Object {
+ "type": "tsvb-validation-telemetry",
+ },
+ },
+ Object {
+ "bool": Object {
+ "must": Array [
+ Object {
+ "match": Object {
+ "type": "search-session",
+ },
+ },
+ Object {
+ "match": Object {
+ "search-session.persisted": false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
},
"versionAlias": ".my-so-index_7.11.0",
"versionIndex": ".my-so-index_7.11.0_001",
@@ -485,12 +541,40 @@ describe('migrationsStateActionMachine', () => {
},
},
},
- "unusedTypesToExclude": Object {
+ "unusedTypesQuery": Object {
"_tag": "Some",
- "value": Array [
- "fleet-agent-events",
- "tsvb-validation-telemetry",
- ],
+ "value": Object {
+ "bool": Object {
+ "must_not": Array [
+ Object {
+ "term": Object {
+ "type": "fleet-agent-events",
+ },
+ },
+ Object {
+ "term": Object {
+ "type": "tsvb-validation-telemetry",
+ },
+ },
+ Object {
+ "bool": Object {
+ "must": Array [
+ Object {
+ "match": Object {
+ "type": "search-session",
+ },
+ },
+ Object {
+ "match": Object {
+ "search-session.persisted": false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
},
"versionAlias": ".my-so-index_7.11.0",
"versionIndex": ".my-so-index_7.11.0_001",
@@ -552,12 +636,40 @@ describe('migrationsStateActionMachine', () => {
},
},
},
- "unusedTypesToExclude": Object {
+ "unusedTypesQuery": Object {
"_tag": "Some",
- "value": Array [
- "fleet-agent-events",
- "tsvb-validation-telemetry",
- ],
+ "value": Object {
+ "bool": Object {
+ "must_not": Array [
+ Object {
+ "term": Object {
+ "type": "fleet-agent-events",
+ },
+ },
+ Object {
+ "term": Object {
+ "type": "tsvb-validation-telemetry",
+ },
+ },
+ Object {
+ "bool": Object {
+ "must": Array [
+ Object {
+ "match": Object {
+ "type": "search-session",
+ },
+ },
+ Object {
+ "match": Object {
+ "search-session.persisted": false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
},
"versionAlias": ".my-so-index_7.11.0",
"versionIndex": ".my-so-index_7.11.0_001",
diff --git a/src/core/server/saved_objects/migrationsv2/model.test.ts b/src/core/server/saved_objects/migrationsv2/model.test.ts
index 8aad62f13b8fea..0267ae33dd157c 100644
--- a/src/core/server/saved_objects/migrationsv2/model.test.ts
+++ b/src/core/server/saved_objects/migrationsv2/model.test.ts
@@ -70,7 +70,17 @@ describe('migrations v2 model', () => {
versionAlias: '.kibana_7.11.0',
versionIndex: '.kibana_7.11.0_001',
tempIndex: '.kibana_7.11.0_reindex_temp',
- unusedTypesToExclude: Option.some(['unused-fleet-agent-events']),
+ unusedTypesQuery: Option.of({
+ bool: {
+ must_not: [
+ {
+ term: {
+ type: 'unused-fleet-agent-events',
+ },
+ },
+ ],
+ },
+ }),
};
describe('exponential retry delays for retryable_es_client_error', () => {
@@ -1177,12 +1187,40 @@ describe('migrations v2 model', () => {
},
},
},
- "unusedTypesToExclude": Object {
+ "unusedTypesQuery": Object {
"_tag": "Some",
- "value": Array [
- "fleet-agent-events",
- "tsvb-validation-telemetry",
- ],
+ "value": Object {
+ "bool": Object {
+ "must_not": Array [
+ Object {
+ "term": Object {
+ "type": "fleet-agent-events",
+ },
+ },
+ Object {
+ "term": Object {
+ "type": "tsvb-validation-telemetry",
+ },
+ },
+ Object {
+ "bool": Object {
+ "must": Array [
+ Object {
+ "match": Object {
+ "type": "search-session",
+ },
+ },
+ Object {
+ "match": Object {
+ "search-session.persisted": false,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
},
"versionAlias": ".kibana_task_manager_8.1.0",
"versionIndex": ".kibana_task_manager_8.1.0_001",
diff --git a/src/core/server/saved_objects/migrationsv2/model.ts b/src/core/server/saved_objects/migrationsv2/model.ts
index ee78692a7044f0..acf0f620136a2c 100644
--- a/src/core/server/saved_objects/migrationsv2/model.ts
+++ b/src/core/server/saved_objects/migrationsv2/model.ts
@@ -16,6 +16,7 @@ import { IndexMapping } from '../mappings';
import { ResponseType } from './next';
import { SavedObjectsMigrationVersion } from '../types';
import { disableUnknownTypeMappingFields } from '../migrations/core/migration_context';
+import { excludeUnusedTypesQuery } from '../migrations/core';
import { SavedObjectsMigrationConfigType } from '../saved_objects_config';
/**
@@ -74,6 +75,7 @@ function indexBelongsToLaterVersion(indexName: string, kibanaVersion: string): b
const version = valid(indexVersion(indexName));
return version != null ? gt(version, kibanaVersion) : false;
}
+
/**
* Extracts the version number from a >= 7.11 index
* @param indexName A >= v7.11 index name
@@ -781,11 +783,6 @@ export const createInitialState = ({
},
};
- const unusedTypesToExclude = Option.some([
- 'fleet-agent-events', // https://github.com/elastic/kibana/issues/91869
- 'tsvb-validation-telemetry', // https://github.com/elastic/kibana/issues/95617
- ]);
-
const initialState: InitState = {
controlState: 'INIT',
indexPrefix,
@@ -804,7 +801,7 @@ export const createInitialState = ({
retryAttempts: migrationsConfig.retryAttempts,
batchSize: migrationsConfig.batchSize,
logs: [],
- unusedTypesToExclude,
+ unusedTypesQuery: Option.of(excludeUnusedTypesQuery),
};
return initialState;
};
diff --git a/src/core/server/saved_objects/migrationsv2/next.ts b/src/core/server/saved_objects/migrationsv2/next.ts
index 5cbda741a0ce5a..bb506cbca66fb1 100644
--- a/src/core/server/saved_objects/migrationsv2/next.ts
+++ b/src/core/server/saved_objects/migrationsv2/next.ts
@@ -70,7 +70,7 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra
state.tempIndex,
Option.none,
false,
- state.unusedTypesToExclude
+ state.unusedTypesQuery
),
SET_TEMP_WRITE_BLOCK: (state: SetTempWriteBlock) =>
Actions.setWriteBlock(client, state.tempIndex),
@@ -115,7 +115,7 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra
state.sourceIndex.value,
state.preMigrationScript,
false,
- state.unusedTypesToExclude
+ state.unusedTypesQuery
),
LEGACY_REINDEX_WAIT_FOR_TASK: (state: LegacyReindexWaitForTaskState) =>
Actions.waitForReindexTask(client, state.legacyReindexTaskId, '60s'),
diff --git a/src/core/server/saved_objects/migrationsv2/types.ts b/src/core/server/saved_objects/migrationsv2/types.ts
index e9b351c0152fc0..5e84bc23b1d161 100644
--- a/src/core/server/saved_objects/migrationsv2/types.ts
+++ b/src/core/server/saved_objects/migrationsv2/types.ts
@@ -7,6 +7,7 @@
*/
import * as Option from 'fp-ts/lib/Option';
+import { estypes } from '@elastic/elasticsearch';
import { ControlState } from './state_action_machine';
import { AliasAction } from './actions';
import { IndexMapping } from '../mappings';
@@ -91,9 +92,9 @@ export interface BaseState extends ControlState {
readonly tempIndex: string;
/* When reindexing we use a source query to exclude saved objects types which
* are no longer used. These saved objects will still be kept in the outdated
- * index for backup purposes, but won't be availble in the upgraded index.
+ * index for backup purposes, but won't be available in the upgraded index.
*/
- readonly unusedTypesToExclude: Option.Option;
+ readonly unusedTypesQuery: Option.Option;
}
export type InitState = BaseState & {
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index 53c1a82db6abdc..3c43947f9fd857 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -368,7 +368,7 @@ export const config: {
healthCheck: import("@kbn/config-schema").ObjectType<{
delay: Type;
}>;
- ignoreVersionMismatch: import("@kbn/config-schema/target/types/types").ConditionalType;
+ ignoreVersionMismatch: import("@kbn/config-schema/target/types").ConditionalType;
}>;
};
logging: {
diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
index 1ad15592889922..c65a3569448a38 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
+++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
@@ -200,6 +200,8 @@ kibana_vars=(
xpack.fleet.agents.elasticsearch.host
xpack.fleet.agents.kibana.host
xpack.fleet.agents.tlsCheckDisabled
+ xpack.fleet.agentPolicies
+ xpack.fleet.packages
xpack.fleet.registryUrl
xpack.graph.canEditDrillDownUrls
xpack.graph.enabled
diff --git a/src/plugins/dashboard/.storybook/storyshots.test.tsx b/src/plugins/dashboard/.storybook/storyshots.test.tsx
deleted file mode 100644
index 80e8aa795ed400..00000000000000
--- a/src/plugins/dashboard/.storybook/storyshots.test.tsx
+++ /dev/null
@@ -1,76 +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
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-import fs from 'fs';
-import { ReactChildren } from 'react';
-import path from 'path';
-import moment from 'moment';
-import 'moment-timezone';
-import ReactDOM from 'react-dom';
-
-import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
-// @ts-ignore
-import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer';
-import { addSerializer } from 'jest-specific-snapshot';
-
-// Set our default timezone to UTC for tests so we can generate predictable snapshots
-moment.tz.setDefault('UTC');
-
-// Freeze time for the tests for predictable snapshots
-const testTime = new Date(Date.UTC(2019, 5, 1)); // June 1 2019
-Date.now = jest.fn(() => testTime.getTime());
-
-// Mock React Portal for components that use modals, tooltips, etc
-// @ts-expect-error Portal mocks are notoriously difficult to type
-ReactDOM.createPortal = jest.fn((element) => element);
-
-// Mock EUI generated ids to be consistently predictable for snapshots.
-jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
-
-// Mock react-datepicker dep used by eui to avoid rendering the entire large component
-jest.mock('@elastic/eui/packages/react-datepicker', () => {
- return {
- __esModule: true,
- default: 'ReactDatePicker',
- };
-});
-
-// Mock the EUI HTML ID Generator so elements have a predictable ID in snapshots
-jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => {
- return {
- htmlIdGenerator: () => () => `generated-id`,
- };
-});
-
-// To be resolved by EUI team.
-// https://github.com/elastic/eui/issues/3712
-jest.mock('@elastic/eui/lib/components/overlay_mask/overlay_mask', () => {
- return {
- EuiOverlayMask: ({ children }: { children: ReactChildren }) => children,
- };
-});
-
-// @ts-ignore
-import { EuiObserver } from '@elastic/eui/test-env/components/observer/observer';
-jest.mock('@elastic/eui/test-env/components/observer/observer');
-EuiObserver.mockImplementation(() => 'EuiObserver');
-
-// Some of the code requires that this directory exists, but the tests don't actually require any css to be present
-const cssDir = path.resolve(__dirname, '../../../../built_assets/css');
-if (!fs.existsSync(cssDir)) {
- fs.mkdirSync(cssDir, { recursive: true });
-}
-
-addSerializer(styleSheetSerializer);
-
-// Initialize Storyshots and build the Jest Snapshots
-initStoryshots({
- configPath: path.resolve(__dirname, './../.storybook'),
- framework: 'react',
- test: multiSnapshotWithOptions({}),
-});
diff --git a/src/plugins/dashboard/kibana.json b/src/plugins/dashboard/kibana.json
index 32507cbc5e5f47..41335069461fae 100644
--- a/src/plugins/dashboard/kibana.json
+++ b/src/plugins/dashboard/kibana.json
@@ -23,6 +23,7 @@
"requiredBundles": [
"home",
"kibanaReact",
- "kibanaUtils"
+ "kibanaUtils",
+ "presentationUtil"
]
}
diff --git a/src/plugins/dashboard/public/application/embeddable/empty_screen/__snapshots__/dashboard_empty_screen.test.tsx.snap b/src/plugins/dashboard/public/application/embeddable/empty_screen/__snapshots__/dashboard_empty_screen.test.tsx.snap
index 9e3018fb512c37..4cd3eb13f36095 100644
--- a/src/plugins/dashboard/public/application/embeddable/empty_screen/__snapshots__/dashboard_empty_screen.test.tsx.snap
+++ b/src/plugins/dashboard/public/application/embeddable/empty_screen/__snapshots__/dashboard_empty_screen.test.tsx.snap
@@ -617,9 +617,11 @@ exports[`DashboardEmptyScreen renders correctly with readonly mode 1`] = `
({ chromeIsVisible: false });
const [isSaveInProgress, setIsSaveInProgress] = useState(false);
+ const stateTransferService = embeddable.getStateTransfer();
+
useEffect(() => {
const visibleSubscription = chrome.getIsVisible$().subscribe((chromeIsVisible) => {
setState((s) => ({ ...s, chromeIsVisible }));
@@ -147,12 +155,26 @@ export function DashboardTopNav({
const createNew = useCallback(async () => {
const type = 'visualization';
const factory = embeddable.getEmbeddableFactory(type);
+
if (!factory) {
throw new EmbeddableFactoryNotFoundError(type);
}
+
await factory.create({} as EmbeddableInput, dashboardContainer);
}, [dashboardContainer, embeddable]);
+ const createNewVisType = useCallback(
+ (newVisType: string) => async () => {
+ stateTransferService.navigateToEditor('visualize', {
+ path: `#/create?type=${encodeURIComponent(newVisType)}`,
+ state: {
+ originatingApp: DashboardConstants.DASHBOARDS_ID,
+ },
+ });
+ },
+ [stateTransferService]
+ );
+
const clearAddPanel = useCallback(() => {
if (state.addPanelOverlay) {
state.addPanelOverlay.close();
@@ -540,11 +562,51 @@ export function DashboardTopNav({
};
const { TopNavMenu } = navigation.ui;
+
+ const quickButtons = [
+ {
+ iconType: 'visText',
+ createType: i18n.translate('dashboard.solutionToolbar.markdownQuickButtonLabel', {
+ defaultMessage: 'Markdown',
+ }),
+ onClick: createNewVisType('markdown'),
+ 'data-test-subj': 'dashboardMarkdownQuickButton',
+ },
+ {
+ iconType: 'controlsHorizontal',
+ createType: i18n.translate('dashboard.solutionToolbar.inputControlsQuickButtonLabel', {
+ defaultMessage: 'Input control',
+ }),
+ onClick: createNewVisType('input_control_vis'),
+ 'data-test-subj': 'dashboardInputControlsQuickButton',
+ },
+ ];
+
return (
<>
{viewMode !== ViewMode.VIEW ? (
-
+
+ {{
+ primaryActionButton: (
+
+ ),
+ quickButtonGroup: ,
+ addFromLibraryButton: (
+
+ ),
+ }}
+
) : null}
>
);
diff --git a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/__snapshots__/panel_toolbar.stories.storyshot b/src/plugins/dashboard/public/application/top_nav/panel_toolbar/__snapshots__/panel_toolbar.stories.storyshot
deleted file mode 100644
index afbbecb3935e0e..00000000000000
--- a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/__snapshots__/panel_toolbar.stories.storyshot
+++ /dev/null
@@ -1,71 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots components/PanelToolbar default 1`] = `
-
-`;
diff --git a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.tsx b/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.tsx
deleted file mode 100644
index 0449fae80186d0..00000000000000
--- a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.tsx
+++ /dev/null
@@ -1,51 +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
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-import './panel_toolbar.scss';
-import React, { FC } from 'react';
-import { i18n } from '@kbn/i18n';
-import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-
-interface Props {
- /** The click handler for the Add Panel button for creating new panels */
- onAddPanelClick: () => void;
- /** The click handler for the Library button for adding existing visualizations/embeddables */
- onLibraryClick: () => void;
-}
-
-export const PanelToolbar: FC = ({ onAddPanelClick, onLibraryClick }) => (
-
-
-
- {i18n.translate('dashboard.panelToolbar.addPanelButtonLabel', {
- defaultMessage: 'Create panel',
- })}
-
-
-
-
- {i18n.translate('dashboard.panelToolbar.libraryButtonLabel', {
- defaultMessage: 'Add from library',
- })}
-
-
-
-);
diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json
index dd99119cfb4570..12820fc08310d6 100644
--- a/src/plugins/dashboard/tsconfig.json
+++ b/src/plugins/dashboard/tsconfig.json
@@ -32,5 +32,8 @@
{ "path": "../saved_objects/tsconfig.json" },
{ "path": "../ui_actions/tsconfig.json" },
{ "path": "../spaces_oss/tsconfig.json" },
+ { "path": "../charts/tsconfig.json" },
+ { "path": "../discover/tsconfig.json" },
+ { "path": "../visualizations/tsconfig.json" },
]
}
diff --git a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
index b8af6ad3a99e58..3dda97566da5ad 100644
--- a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
+++ b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
@@ -59,7 +59,7 @@ export const setupValueSuggestionProvider = (
return core.http
.fetch(`/api/kibana/suggestions/values/${index}`, {
method: 'POST',
- body: JSON.stringify({ query, field: field.name, filters }),
+ body: JSON.stringify({ query, field: field.name, fieldMeta: field?.toSpec?.(), filters }),
signal,
})
.then((r) => {
diff --git a/src/plugins/data/public/utils/table_inspector_view/components/__snapshots__/data_view.test.tsx.snap b/src/plugins/data/public/utils/table_inspector_view/components/__snapshots__/data_view.test.tsx.snap
index 837cff41ccd6bc..4436efb1f3508f 100644
--- a/src/plugins/data/public/utils/table_inspector_view/components/__snapshots__/data_view.test.tsx.snap
+++ b/src/plugins/data/public/utils/table_inspector_view/components/__snapshots__/data_view.test.tsx.snap
@@ -1472,13 +1472,13 @@ exports[`Inspector Data View component should render single table without select
href="#__table_generated-id"
isDisabled={true}
onClick={[Function]}
- size="xs"
+ size="s"
>
{
const config = await config$.pipe(first()).toPromise();
- const { field: fieldName, query, filters } = request.body;
+ const { field: fieldName, query, filters, fieldMeta } = request.body;
const { index } = request.params;
const { client } = context.core.elasticsearch.legacy;
const signal = getRequestAbortedSignal(request.events.aborted$);
@@ -53,9 +54,14 @@ export function registerValueSuggestionsRoute(
terminate_after: config.kibana.autocompleteTerminateAfter.asMilliseconds(),
};
- const indexPattern = await findIndexPatternById(context.core.savedObjects.client, index);
+ let field: IFieldType | undefined = fieldMeta;
+
+ if (!field?.name && !field?.type) {
+ const indexPattern = await findIndexPatternById(context.core.savedObjects.client, index);
+
+ field = indexPattern && getFieldByName(fieldName, indexPattern);
+ }
- const field = indexPattern && getFieldByName(fieldName, indexPattern);
const body = await getBody(autocompleteSearchOptions, field || fieldName, query, filters);
const result = await client.callAsCurrentUser('search', { index, body }, { signal });
diff --git a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
index 941a90f500ab66..0ed84d4eee3b7a 100644
--- a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
+++ b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
@@ -12,6 +12,7 @@ import {
IIndexPatternsApiClient,
GetFieldsOptionsTimePattern,
} from '../../common/index_patterns/types';
+import { IndexPatternMissingIndices } from '../../common/index_patterns/lib';
import { IndexPatternsFetcher } from './fetcher';
export class IndexPatternsApiServer implements IIndexPatternsApiClient {
@@ -27,12 +28,23 @@ export class IndexPatternsApiServer implements IIndexPatternsApiClient {
allowNoIndex,
}: GetFieldsOptions) {
const indexPatterns = new IndexPatternsFetcher(this.esClient, allowNoIndex);
- return await indexPatterns.getFieldsForWildcard({
- pattern,
- metaFields,
- type,
- rollupIndex,
- });
+ return await indexPatterns
+ .getFieldsForWildcard({
+ pattern,
+ metaFields,
+ type,
+ rollupIndex,
+ })
+ .catch((err) => {
+ if (
+ err.output.payload.statusCode === 404 &&
+ err.output.payload.code === 'no_matching_indices'
+ ) {
+ throw new IndexPatternMissingIndices(pattern);
+ } else {
+ throw err;
+ }
+ });
}
async getFieldsForTimePattern(options: GetFieldsOptionsTimePattern) {
const indexPatterns = new IndexPatternsFetcher(this.esClient);
diff --git a/src/plugins/data/server/index_patterns/index_patterns_service.ts b/src/plugins/data/server/index_patterns/index_patterns_service.ts
index c4cc2073ef78f0..c7fd1f7914df9f 100644
--- a/src/plugins/data/server/index_patterns/index_patterns_service.ts
+++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts
@@ -71,7 +71,7 @@ export const indexPatternsServiceFactory = ({
logger.error(error);
},
onNotification: ({ title, text }) => {
- logger.warn(`${title} : ${text}`);
+ logger.warn(`${title}${text ? ` : ${text}` : ''}`);
},
});
};
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index 0ea3af60e9b5d3..622356c4441ac3 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -56,6 +56,7 @@ import { PublicMethodsOf } from '@kbn/utility-types';
import { RecursiveReadonly } from '@kbn/utility-types';
import { RequestAdapter } from 'src/plugins/inspector/common';
import { RequestHandlerContext } from 'src/core/server';
+import * as Rx from 'rxjs';
import { SavedObject } from 'kibana/server';
import { SavedObject as SavedObject_2 } from 'src/core/server';
import { SavedObjectsClientContract } from 'src/core/server';
diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts
index 45cc95ee40804d..dd7f9c41a223d5 100644
--- a/src/plugins/discover/common/index.ts
+++ b/src/plugins/discover/common/index.ts
@@ -18,3 +18,4 @@ export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields';
export const DOC_TABLE_LEGACY = 'doc_table:legacy';
export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch';
export const SEARCH_FIELDS_FROM_SOURCE = 'discover:searchFieldsFromSource';
+export const MAX_DOC_FIELDS_DISPLAYED = 'discover:maxDocFieldsDisplayed';
diff --git a/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts b/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts
index 4c6b9002ce867e..ca5cdbd8086061 100644
--- a/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts
+++ b/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts
@@ -10,6 +10,7 @@ import { formatRow, formatTopLevelObject } from './row_formatter';
import { stubbedSavedObjectIndexPattern } from '../../../__mocks__/stubbed_saved_object_index_pattern';
import { IndexPattern } from '../../../../../data/common/index_patterns/index_patterns';
import { fieldFormatsMock } from '../../../../../data/common/field_formats/mocks';
+import { setServices } from '../../../kibana_services';
describe('Row formatter', () => {
const hit = {
@@ -58,6 +59,11 @@ describe('Row formatter', () => {
beforeEach(() => {
// @ts-expect-error
indexPattern.formatHit = formatHitMock;
+ setServices({
+ uiSettings: {
+ get: () => 100,
+ },
+ });
});
it('formats document properly', () => {
@@ -66,6 +72,17 @@ describe('Row formatter', () => {
);
});
+ it('limits number of rendered items', () => {
+ setServices({
+ uiSettings: {
+ get: () => 1,
+ },
+ });
+ expect(formatRow(hit, indexPattern).trim()).toMatchInlineSnapshot(
+ `"also: with \\\\"quotes\\\\" or 'single qoutes' "`
+ );
+ });
+
it('formats document with highlighted fields first', () => {
expect(
formatRow({ ...hit, highlight: { number: '42' } }, indexPattern).trim()
diff --git a/src/plugins/discover/public/application/angular/helpers/row_formatter.ts b/src/plugins/discover/public/application/angular/helpers/row_formatter.ts
index 02902b06347974..b219dda19e10a8 100644
--- a/src/plugins/discover/public/application/angular/helpers/row_formatter.ts
+++ b/src/plugins/discover/public/application/angular/helpers/row_formatter.ts
@@ -7,7 +7,8 @@
*/
import { template } from 'lodash';
-import { IndexPattern } from '../../../kibana_services';
+import { MAX_DOC_FIELDS_DISPLAYED } from '../../../../common';
+import { getServices, IndexPattern } from '../../../kibana_services';
function noWhiteSpace(html: string) {
const TAGS_WITH_WS = />\s+, indexPattern: IndexPattern)
const pairs = highlights[key] ? highlightPairs : sourcePairs;
pairs.push([displayKey ? displayKey : key, val]);
});
- return doTemplate({ defPairs: [...highlightPairs, ...sourcePairs] });
+ const maxEntries = getServices().uiSettings.get(MAX_DOC_FIELDS_DISPLAYED);
+ return doTemplate({ defPairs: [...highlightPairs, ...sourcePairs].slice(0, maxEntries) });
};
export const formatTopLevelObject = (
@@ -67,5 +69,6 @@ export const formatTopLevelObject = (
const pairs = highlights[key] ? highlightPairs : sourcePairs;
pairs.push([displayKey ? displayKey : key, formatted]);
});
- return doTemplate({ defPairs: [...highlightPairs, ...sourcePairs] });
+ const maxEntries = getServices().uiSettings.get(MAX_DOC_FIELDS_DISPLAYED);
+ return doTemplate({ defPairs: [...highlightPairs, ...sourcePairs].slice(0, maxEntries) });
};
diff --git a/src/plugins/discover/public/application/components/discover.tsx b/src/plugins/discover/public/application/components/discover.tsx
index 6b71bd892b5208..0df921dc99ad73 100644
--- a/src/plugins/discover/public/application/components/discover.tsx
+++ b/src/plugins/discover/public/application/components/discover.tsx
@@ -43,6 +43,7 @@ import { DiscoverTopNav } from './discover_topnav';
import { ElasticSearchHit } from '../doc_views/doc_views_types';
import { setBreadcrumbsTitle } from '../helpers/breadcrumbs';
import { addHelpMenuToAppChrome } from './help_menu/help_menu_util';
+import { InspectorSession } from '../../../../inspector/public';
const DocTableLegacyMemoized = React.memo(DocTableLegacy);
const SidebarMemoized = React.memo(DiscoverSidebarResponsive);
@@ -71,6 +72,7 @@ export function Discover({
refreshAppState,
}: DiscoverProps) {
const [expandedDoc, setExpandedDoc] = useState(undefined);
+ const [inspectorSession, setInspectorSession] = useState(undefined);
const scrollableDesktop = useRef(null);
const collapseIcon = useRef(null);
const isMobile = () => {
@@ -131,7 +133,20 @@ export function Discover({
const onOpenInspector = useCallback(() => {
// prevent overlapping
setExpandedDoc(undefined);
- }, [setExpandedDoc]);
+ const session = services.inspector.open(opts.inspectorAdapters, {
+ title: savedSearch.title,
+ });
+ setInspectorSession(session);
+ }, [setExpandedDoc, opts.inspectorAdapters, savedSearch, services.inspector]);
+
+ useEffect(() => {
+ return () => {
+ if (inspectorSession) {
+ // Close the inspector if this scope is destroyed (e.g. because the user navigates away).
+ inspectorSession.close();
+ }
+ };
+ }, [inspectorSession]);
const onSort = useCallback(
(sort: string[][]) => {
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid.test.tsx
new file mode 100644
index 00000000000000..8037022085f024
--- /dev/null
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.test.tsx
@@ -0,0 +1,146 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import React from 'react';
+import { ReactWrapper } from 'enzyme';
+import { EuiCopy } from '@elastic/eui';
+import { act } from 'react-dom/test-utils';
+import { findTestSubject } from '@elastic/eui/lib/test';
+import { esHits } from '../../../__mocks__/es_hits';
+import { indexPatternMock } from '../../../__mocks__/index_pattern';
+import { mountWithIntl } from '@kbn/test/jest';
+import { DiscoverGrid, DiscoverGridProps } from './discover_grid';
+import { uiSettingsMock } from '../../../__mocks__/ui_settings';
+import { DiscoverServices } from '../../../build_services';
+import { ElasticSearchHit } from '../../doc_views/doc_views_types';
+import { getDocId } from './discover_grid_document_selection';
+
+function getProps() {
+ const servicesMock = {
+ uiSettings: uiSettingsMock,
+ } as DiscoverServices;
+ return {
+ ariaLabelledBy: '',
+ columns: [],
+ indexPattern: indexPatternMock,
+ isLoading: false,
+ expandedDoc: undefined,
+ onAddColumn: jest.fn(),
+ onFilter: jest.fn(),
+ onRemoveColumn: jest.fn(),
+ onResize: jest.fn(),
+ onSetColumns: jest.fn(),
+ onSort: jest.fn(),
+ rows: esHits,
+ sampleSize: 30,
+ searchDescription: '',
+ searchTitle: '',
+ services: servicesMock,
+ setExpandedDoc: jest.fn(),
+ settings: {},
+ showTimeCol: true,
+ sort: [],
+ useNewFieldsApi: true,
+ };
+}
+
+function getComponent() {
+ return mountWithIntl( );
+}
+
+function getSelectedDocNr(component: ReactWrapper) {
+ const gridSelectionBtn = findTestSubject(component, 'dscGridSelectionBtn');
+ if (!gridSelectionBtn.length) {
+ return 0;
+ }
+ const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-selected-documents');
+ return Number(selectedNr);
+}
+
+function getDisplayedDocNr(component: ReactWrapper) {
+ const gridSelectionBtn = findTestSubject(component, 'discoverDocTable');
+ if (!gridSelectionBtn.length) {
+ return 0;
+ }
+ const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-document-number');
+ return Number(selectedNr);
+}
+
+async function toggleDocSelection(
+ component: ReactWrapper,
+ document: ElasticSearchHit
+) {
+ act(() => {
+ const docId = getDocId(document);
+ findTestSubject(component, `dscGridSelectDoc-${docId}`).simulate('change');
+ });
+ component.update();
+}
+
+describe('DiscoverGrid', () => {
+ describe('Document selection', () => {
+ let component: ReactWrapper;
+ beforeEach(() => {
+ component = getComponent();
+ });
+
+ test('no documents are selected initially', async () => {
+ expect(getSelectedDocNr(component)).toBe(0);
+ expect(getDisplayedDocNr(component)).toBe(5);
+ });
+
+ test('Allows selection/deselection of multiple documents', async () => {
+ await toggleDocSelection(component, esHits[0]);
+ expect(getSelectedDocNr(component)).toBe(1);
+ await toggleDocSelection(component, esHits[1]);
+ expect(getSelectedDocNr(component)).toBe(2);
+ await toggleDocSelection(component, esHits[1]);
+ expect(getSelectedDocNr(component)).toBe(1);
+ });
+
+ test('deselection of all selected documents', async () => {
+ await toggleDocSelection(component, esHits[0]);
+ await toggleDocSelection(component, esHits[1]);
+ expect(getSelectedDocNr(component)).toBe(2);
+ findTestSubject(component, 'dscGridSelectionBtn').simulate('click');
+ findTestSubject(component, 'dscGridClearSelectedDocuments').simulate('click');
+ expect(getSelectedDocNr(component)).toBe(0);
+ });
+
+ test('showing only selected documents and undo selection', async () => {
+ await toggleDocSelection(component, esHits[0]);
+ await toggleDocSelection(component, esHits[1]);
+ expect(getSelectedDocNr(component)).toBe(2);
+ findTestSubject(component, 'dscGridSelectionBtn').simulate('click');
+ findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click');
+ expect(getDisplayedDocNr(component)).toBe(2);
+ findTestSubject(component, 'dscGridSelectionBtn').simulate('click');
+ component.update();
+ findTestSubject(component, 'dscGridShowAllDocuments').simulate('click');
+ expect(getDisplayedDocNr(component)).toBe(5);
+ });
+
+ test('showing only selected documents and remove filter deselecting each doc manually', async () => {
+ await toggleDocSelection(component, esHits[0]);
+ findTestSubject(component, 'dscGridSelectionBtn').simulate('click');
+ findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click');
+ expect(getDisplayedDocNr(component)).toBe(1);
+ await toggleDocSelection(component, esHits[0]);
+ expect(getDisplayedDocNr(component)).toBe(5);
+ await toggleDocSelection(component, esHits[0]);
+ expect(getDisplayedDocNr(component)).toBe(5);
+ });
+
+ test('copying selected documents to clipboard', async () => {
+ await toggleDocSelection(component, esHits[0]);
+ findTestSubject(component, 'dscGridSelectionBtn').simulate('click');
+ expect(component.find(EuiCopy).prop('textToCopy')).toMatchInlineSnapshot(
+ `"[{\\"_index\\":\\"i\\",\\"_id\\":\\"1\\",\\"_score\\":1,\\"_type\\":\\"_doc\\",\\"_source\\":{\\"date\\":\\"2020-20-01T12:12:12.123\\",\\"message\\":\\"test1\\",\\"bytes\\":20}}]"`
+ );
+ });
+ });
+});
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
index 1888ae8562a37f..be38f166fa1c0b 100644
--- a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
@@ -37,6 +37,8 @@ import { defaultPageSize, gridStyle, pageSizeArr, toolbarVisibility } from './co
import { DiscoverServices } from '../../../build_services';
import { getDisplayedColumns } from '../../helpers/columns';
import { KibanaContextProvider } from '../../../../../kibana_react/public';
+import { MAX_DOC_FIELDS_DISPLAYED } from '../../../../common';
+import { DiscoverGridDocumentToolbarBtn, getDocId } from './discover_grid_document_selection';
interface SortObj {
id: string;
@@ -158,14 +160,27 @@ export const DiscoverGrid = ({
sort,
useNewFieldsApi,
}: DiscoverGridProps) => {
+ const [selectedDocs, setSelectedDocs] = useState([]);
+ const [isFilterActive, setIsFilterActive] = useState(false);
const displayedColumns = getDisplayedColumns(columns, indexPattern);
const defaultColumns = displayedColumns.includes('_source');
+ const displayedRows = useMemo(() => {
+ if (!rows) {
+ return [];
+ }
+ if (!isFilterActive || selectedDocs.length === 0) {
+ return rows;
+ }
+ return rows.filter((row) => {
+ return selectedDocs.includes(getDocId(row));
+ });
+ }, [rows, selectedDocs, isFilterActive]);
/**
* Pagination
*/
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: defaultPageSize });
- const rowCount = useMemo(() => (rows ? rows.length : 0), [rows]);
+ const rowCount = useMemo(() => (displayedRows ? displayedRows.length : 0), [displayedRows]);
const pageCount = useMemo(() => Math.ceil(rowCount / pagination.pageSize), [
rowCount,
pagination,
@@ -207,11 +222,12 @@ export const DiscoverGrid = ({
() =>
getRenderCellValueFn(
indexPattern,
- rows,
- rows ? rows.map((hit) => indexPattern.flattenHit(hit)) : [],
- useNewFieldsApi
+ displayedRows,
+ displayedRows ? displayedRows.map((hit) => indexPattern.flattenHit(hit)) : [],
+ useNewFieldsApi,
+ services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)
),
- [rows, indexPattern, useNewFieldsApi]
+ [displayedRows, indexPattern, useNewFieldsApi, services.uiSettings]
);
/**
@@ -240,6 +256,20 @@ export const DiscoverGrid = ({
]);
const lead = useMemo(() => getLeadControlColumns(), []);
+ const additionalControls = useMemo(
+ () =>
+ selectedDocs.length ? (
+
+ ) : null,
+ [selectedDocs, isFilterActive, rows, setIsFilterActive]
+ );
+
if (!rowCount) {
return (
@@ -257,10 +287,17 @@ export const DiscoverGrid = ({
value={{
expanded: expandedDoc,
setExpanded: setExpandedDoc,
- rows: rows || [],
+ rows: displayedRows,
onFilter,
indexPattern,
isDarkMode: services.uiSettings.get('theme:darkMode'),
+ selectedDocs,
+ setSelectedDocs: (newSelectedDocs) => {
+ setSelectedDocs(newSelectedDocs);
+ if (isFilterActive && newSelectedDocs.length === 0) {
+ setIsFilterActive(false);
+ }
+ },
}}
>
@@ -335,7 +377,7 @@ export const DiscoverGrid = ({
(
+
+
+ {i18n.translate('discover.selectColumnHeader', {
+ defaultMessage: 'Select column',
+ })}
+
+
+ ),
+ },
];
}
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx
index 46169e1e1325f5..e57d3fb8362aed 100644
--- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx
@@ -17,6 +17,8 @@ export interface GridContext {
onFilter: DocViewFilterFn;
indexPattern: IndexPattern;
isDarkMode: boolean;
+ selectedDocs: string[];
+ setSelectedDocs: (selected: string[]) => void;
}
const defaultContext = ({} as unknown) as GridContext;
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.test.tsx
new file mode 100644
index 00000000000000..9ebe3ee95f7974
--- /dev/null
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.test.tsx
@@ -0,0 +1,143 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import React from 'react';
+import { mountWithIntl } from '@kbn/test/jest';
+import { findTestSubject } from '@elastic/eui/lib/test';
+import {
+ DiscoverGridDocumentToolbarBtn,
+ getDocId,
+ SelectButton,
+} from './discover_grid_document_selection';
+import { esHits } from '../../../__mocks__/es_hits';
+import { indexPatternMock } from '../../../__mocks__/index_pattern';
+import { DiscoverGridContext } from './discover_grid_context';
+
+describe('document selection', () => {
+ describe('getDocId', () => {
+ test('doc with custom routing', () => {
+ const doc = {
+ _id: 'test-id',
+ _index: 'test-indices',
+ _routing: 'why-not',
+ };
+ expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::why-not"`);
+ });
+ test('doc without custom routing', () => {
+ const doc = {
+ _id: 'test-id',
+ _index: 'test-indices',
+ };
+ expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::"`);
+ });
+ });
+
+ describe('SelectButton', () => {
+ test('is not checked', () => {
+ const contextMock = {
+ expanded: undefined,
+ setExpanded: jest.fn(),
+ rows: esHits,
+ onFilter: jest.fn(),
+ indexPattern: indexPatternMock,
+ isDarkMode: false,
+ selectedDocs: [],
+ setSelectedDocs: jest.fn(),
+ };
+
+ const component = mountWithIntl(
+
+
+
+ );
+
+ const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
+ expect(checkBox.props().checked).toBeFalsy();
+ });
+
+ test('is checked', () => {
+ const contextMock = {
+ expanded: undefined,
+ setExpanded: jest.fn(),
+ rows: esHits,
+ onFilter: jest.fn(),
+ indexPattern: indexPatternMock,
+ isDarkMode: false,
+ selectedDocs: ['i::1::'],
+ setSelectedDocs: jest.fn(),
+ };
+
+ const component = mountWithIntl(
+
+
+
+ );
+
+ const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
+ expect(checkBox.props().checked).toBeTruthy();
+ });
+
+ test('adding a selection', () => {
+ const contextMock = {
+ expanded: undefined,
+ setExpanded: jest.fn(),
+ rows: esHits,
+ onFilter: jest.fn(),
+ indexPattern: indexPatternMock,
+ isDarkMode: false,
+ selectedDocs: [],
+ setSelectedDocs: jest.fn(),
+ };
+
+ const component = mountWithIntl(
+
+
+
+ );
+
+ const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
+ checkBox.simulate('change');
+ expect(contextMock.setSelectedDocs).toHaveBeenCalledWith(['i::1::']);
+ });
+ test('removing a selection', () => {
+ const contextMock = {
+ expanded: undefined,
+ setExpanded: jest.fn(),
+ rows: esHits,
+ onFilter: jest.fn(),
+ indexPattern: indexPatternMock,
+ isDarkMode: false,
+ selectedDocs: ['i::1::'],
+ setSelectedDocs: jest.fn(),
+ };
+
+ const component = mountWithIntl(
+
+
+
+ );
+
+ const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
+ checkBox.simulate('change');
+ expect(contextMock.setSelectedDocs).toHaveBeenCalledWith([]);
+ });
+ });
+ describe('DiscoverGridDocumentToolbarBtn', () => {
+ test('it renders a button clickable button', () => {
+ const props = {
+ isFilterActive: false,
+ rows: esHits,
+ selectedDocs: ['i::1::'],
+ setIsFilterActive: jest.fn(),
+ setSelectedDocs: jest.fn(),
+ };
+ const component = mountWithIntl( );
+ const button = findTestSubject(component, 'dscGridSelectionBtn');
+ expect(button.length).toBe(1);
+ });
+ });
+});
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.tsx
new file mode 100644
index 00000000000000..4aaefc99479c1d
--- /dev/null
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_document_selection.tsx
@@ -0,0 +1,170 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import React, { useCallback, useState, useContext, useMemo } from 'react';
+import {
+ EuiButtonEmpty,
+ EuiContextMenuItem,
+ EuiContextMenuPanel,
+ EuiCopy,
+ EuiPopover,
+ EuiCheckbox,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import classNames from 'classnames';
+import { ElasticSearchHit } from '../../doc_views/doc_views_types';
+import { DiscoverGridContext } from './discover_grid_context';
+
+/**
+ * Returning a generated id of a given ES document, since `_id` can be the same
+ * when using different indices and shard routing
+ */
+export const getDocId = (doc: ElasticSearchHit & { _routing?: string }) => {
+ const routing = doc._routing ? doc._routing : '';
+ return [doc._index, doc._id, routing].join('::');
+};
+export const SelectButton = ({ rowIndex }: { rowIndex: number }) => {
+ const ctx = useContext(DiscoverGridContext);
+ const doc = useMemo(() => ctx.rows[rowIndex], [ctx.rows, rowIndex]);
+ const id = useMemo(() => getDocId(doc), [doc]);
+ const checked = useMemo(() => ctx.selectedDocs.includes(id), [ctx.selectedDocs, id]);
+
+ return (
+ {
+ if (checked) {
+ const newSelection = ctx.selectedDocs.filter((docId) => docId !== id);
+ ctx.setSelectedDocs(newSelection);
+ } else {
+ ctx.setSelectedDocs([...ctx.selectedDocs, id]);
+ }
+ }}
+ />
+ );
+};
+
+export function DiscoverGridDocumentToolbarBtn({
+ isFilterActive,
+ rows,
+ selectedDocs,
+ setIsFilterActive,
+ setSelectedDocs,
+}: {
+ isFilterActive: boolean;
+ rows: ElasticSearchHit[];
+ selectedDocs: string[];
+ setIsFilterActive: (value: boolean) => void;
+ setSelectedDocs: (value: string[]) => void;
+}) {
+ const [isSelectionPopoverOpen, setIsSelectionPopoverOpen] = useState(false);
+
+ const getMenuItems = useCallback(() => {
+ return [
+ isFilterActive ? (
+ {
+ setIsSelectionPopoverOpen(false);
+ setIsFilterActive(false);
+ }}
+ >
+
+
+ ) : (
+ {
+ setIsSelectionPopoverOpen(false);
+ setIsFilterActive(true);
+ }}
+ >
+
+
+ ),
+
+ {
+ setIsSelectionPopoverOpen(false);
+ setSelectedDocs([]);
+ setIsFilterActive(false);
+ }}
+ >
+
+ ,
+ selectedDocs.includes(getDocId(row)))) : ''
+ }
+ >
+ {(copy) => (
+
+
+
+ )}
+ ,
+ ];
+ }, [
+ isFilterActive,
+ rows,
+ selectedDocs,
+ setIsFilterActive,
+ setIsSelectionPopoverOpen,
+ setSelectedDocs,
+ ]);
+
+ return (
+ setIsSelectionPopoverOpen(false)}
+ isOpen={isSelectionPopoverOpen}
+ panelPaddingSize="none"
+ button={
+ setIsSelectionPopoverOpen(true)}
+ data-selected-documents={selectedDocs.length}
+ data-test-subj="dscGridSelectionBtn"
+ isSelected={isFilterActive}
+ className={classNames({
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ euiDataGrid__controlBtn: true,
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ 'euiDataGrid__controlBtn--active': isFilterActive,
+ })}
+ >
+
+
+ }
+ >
+ {isSelectionPopoverOpen && }
+
+ );
+}
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx
index 98a12054838085..d1299b39a25b2e 100644
--- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx
@@ -23,6 +23,8 @@ describe('Discover grid view button ', function () {
onFilter: jest.fn(),
indexPattern: indexPatternMock,
isDarkMode: false,
+ selectedDocs: [],
+ setSelectedDocs: jest.fn(),
};
const component = mountWithIntl(
@@ -49,6 +51,8 @@ describe('Discover grid view button ', function () {
onFilter: jest.fn(),
indexPattern: indexPatternMock,
isDarkMode: false,
+ selectedDocs: [],
+ setSelectedDocs: jest.fn(),
};
const component = mountWithIntl(
@@ -75,6 +79,8 @@ describe('Discover grid view button ', function () {
onFilter: jest.fn(),
indexPattern: indexPatternMock,
isDarkMode: false,
+ selectedDocs: [],
+ setSelectedDocs: jest.fn(),
};
const component = mountWithIntl(
diff --git a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx
index 74cf083d82653f..b7e37a28fe539d 100644
--- a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx
@@ -74,7 +74,8 @@ describe('Discover grid cell rendering', function () {
indexPatternMock,
rowsSource,
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
- false
+ false,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- false
+ false,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- false
+ false,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
{
+ const DiscoverGridCellValue = getRenderCellValueFn(
+ indexPatternMock,
+ rowsFields,
+ rowsFields.map((row) => indexPatternMock.flattenHit(row)),
+ true,
+ // this is the number of rendered items
+ 1
+ );
+ const component = shallow(
+
+ );
+ expect(component).toMatchInlineSnapshot(`
+
+
+ extension
+
+
+
+ `);
+ });
+
it('renders fields-based column correctly when isDetails is set to true', () => {
const DiscoverGridCellValue = getRenderCellValueFn(
indexPatternMock,
rowsFields,
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- true
+ true,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- false
+ false,
+ 100
);
const component = shallow(
indexPatternMock.flattenHit(row)),
- false
+ false,
+ 100
);
const component = shallow(
>,
- useNewFieldsApi: boolean
+ useNewFieldsApi: boolean,
+ maxDocFieldsDisplayed: number
) => ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => {
const row = rows ? rows[rowIndex] : undefined;
const rowFlattened = rowsFlattened
@@ -98,7 +99,7 @@ export const getRenderCellValueFn = (
return (
- {[...highlightPairs, ...sourcePairs].map(([key, value]) => (
+ {[...highlightPairs, ...sourcePairs].slice(0, maxDocFieldsDisplayed).map(([key, value]) => (
{key}
- {[...highlightPairs, ...sourcePairs].map(([key, value]) => (
+ {[...highlightPairs, ...sourcePairs].slice(0, maxDocFieldsDisplayed).map(([key, value]) => (
{key}
{
+ test('changing columns triggers an update', () => {
+ const props = {
+ title: 'test',
+ component: jest.fn(),
+ id: 1,
+ render: jest.fn(),
+ renderProps: {
+ hit: {} as ElasticSearchHit,
+ columns: ['test'],
+ },
+ };
+
+ const wrapper = shallow( );
+
+ const nextProps = {
+ ...props,
+ renderProps: {
+ hit: {} as ElasticSearchHit,
+ columns: ['test2'],
+ },
+ };
+
+ const shouldUpdate = (wrapper!.instance() as DocViewerTab).shouldComponentUpdate(nextProps, {
+ hasError: false,
+ error: '',
+ });
+ expect(shouldUpdate).toBe(true);
+ });
+});
diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.tsx b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.tsx
index 25454a3bad38ab..1ad6500771d483 100644
--- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.tsx
+++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.tsx
@@ -7,6 +7,7 @@
*/
import React from 'react';
+import { isEqual } from 'lodash';
import { I18nProvider } from '@kbn/i18n/react';
import { DocViewRenderTab } from './doc_viewer_render_tab';
import { DocViewerError } from './doc_viewer_render_error';
@@ -46,6 +47,7 @@ export class DocViewerTab extends React.Component {
return (
nextProps.renderProps.hit._id !== this.props.renderProps.hit._id ||
nextProps.id !== this.props.id ||
+ !isEqual(nextProps.renderProps.columns, this.props.renderProps.columns) ||
nextState.hasError
);
}
diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.test.ts b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.test.ts
index 30edb102c420aa..f6e9e70b337bae 100644
--- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.test.ts
+++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.test.ts
@@ -8,7 +8,6 @@
import { ISearchSource } from 'src/plugins/data/public';
import { getTopNavLinks } from './get_top_nav_links';
-import { inspectorPluginMock } from '../../../../../inspector/public/mocks';
import { indexPatternMock } from '../../../__mocks__/index_pattern';
import { savedSearchMock } from '../../../__mocks__/saved_search';
import { DiscoverServices } from '../../../build_services';
@@ -28,7 +27,6 @@ test('getTopNavLinks result', () => {
const topNavLinks = getTopNavLinks({
getFieldCounts: jest.fn(),
indexPattern: indexPatternMock,
- inspectorAdapters: inspectorPluginMock,
navigateTo: jest.fn(),
onOpenInspector: jest.fn(),
savedSearch: savedSearchMock,
diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.ts b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.ts
index 65fef2e4d030fc..635684177e1e36 100644
--- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.ts
+++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.ts
@@ -11,7 +11,6 @@ import { showOpenSearchPanel } from './show_open_search_panel';
import { getSharingData, showPublicUrlSwitch } from '../../helpers/get_sharing_data';
import { unhashUrl } from '../../../../../kibana_utils/public';
import { DiscoverServices } from '../../../build_services';
-import { Adapters } from '../../../../../inspector/common/adapters';
import { SavedSearch } from '../../../saved_searches';
import { onSaveSearch } from './on_save_search';
import { GetStateReturn } from '../../angular/discover_state';
@@ -23,7 +22,6 @@ import { IndexPattern, ISearchSource } from '../../../kibana_services';
export const getTopNavLinks = ({
getFieldCounts,
indexPattern,
- inspectorAdapters,
navigateTo,
savedSearch,
services,
@@ -33,7 +31,6 @@ export const getTopNavLinks = ({
}: {
getFieldCounts: () => Promise>;
indexPattern: IndexPattern;
- inspectorAdapters: Adapters;
navigateTo: (url: string) => void;
savedSearch: SavedSearch;
services: DiscoverServices;
@@ -127,9 +124,6 @@ export const getTopNavLinks = ({
testId: 'openInspectorButton',
run: () => {
onOpenInspector();
- services.inspector.open(inspectorAdapters, {
- title: savedSearch.title,
- });
},
};
diff --git a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
index ebb1946b524cd0..6a51c085ebbc98 100644
--- a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
+++ b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
@@ -6,13 +6,12 @@
* Side Public License, v 1.
*/
-import { Capabilities } from 'kibana/public';
-import { getSharingData, showPublicUrlSwitch } from './get_sharing_data';
-import { IUiSettingsClient } from 'kibana/public';
+import { Capabilities, IUiSettingsClient } from 'kibana/public';
+import { IndexPattern } from 'src/plugins/data/public';
import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks';
-import { indexPatternMock } from '../../__mocks__/index_pattern';
import { DOC_HIDE_TIME_COLUMN_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common';
-import { IndexPattern } from 'src/plugins/data/public';
+import { indexPatternMock } from '../../__mocks__/index_pattern';
+import { getSharingData, showPublicUrlSwitch } from './get_sharing_data';
describe('getSharingData', () => {
let mockConfig: IUiSettingsClient;
@@ -36,6 +35,32 @@ describe('getSharingData', () => {
const result = await getSharingData(searchSourceMock, { columns: [] }, mockConfig);
expect(result).toMatchInlineSnapshot(`
Object {
+ "columns": Array [],
+ "searchSource": Object {
+ "index": "the-index-pattern-id",
+ "sort": Array [
+ Object {
+ "_score": "desc",
+ },
+ ],
+ },
+ }
+ `);
+ });
+
+ test('returns valid data for sharing when columns are selected', async () => {
+ const searchSourceMock = createSearchSourceMock({ index: indexPatternMock });
+ const result = await getSharingData(
+ searchSourceMock,
+ { columns: ['column_a', 'column_b'] },
+ mockConfig
+ );
+ expect(result).toMatchInlineSnapshot(`
+ Object {
+ "columns": Array [
+ "column_a",
+ "column_b",
+ ],
"searchSource": Object {
"index": "the-index-pattern-id",
"sort": Array [
@@ -69,16 +94,16 @@ describe('getSharingData', () => {
);
expect(result).toMatchInlineSnapshot(`
Object {
+ "columns": Array [
+ "cool-timefield",
+ "cool-field-1",
+ "cool-field-2",
+ "cool-field-3",
+ "cool-field-4",
+ "cool-field-5",
+ "cool-field-6",
+ ],
"searchSource": Object {
- "fields": Array [
- "cool-timefield",
- "cool-field-1",
- "cool-field-2",
- "cool-field-3",
- "cool-field-4",
- "cool-field-5",
- "cool-field-6",
- ],
"index": "the-index-pattern-id",
"sort": Array [
Object {
@@ -120,15 +145,15 @@ describe('getSharingData', () => {
);
expect(result).toMatchInlineSnapshot(`
Object {
+ "columns": Array [
+ "cool-field-1",
+ "cool-field-2",
+ "cool-field-3",
+ "cool-field-4",
+ "cool-field-5",
+ "cool-field-6",
+ ],
"searchSource": Object {
- "fields": Array [
- "cool-field-1",
- "cool-field-2",
- "cool-field-3",
- "cool-field-4",
- "cool-field-5",
- "cool-field-6",
- ],
"index": "the-index-pattern-id",
"sort": Array [
Object {
diff --git a/src/plugins/discover/public/application/helpers/get_sharing_data.ts b/src/plugins/discover/public/application/helpers/get_sharing_data.ts
index f0e07ccc38deb3..47be4b80371522 100644
--- a/src/plugins/discover/public/application/helpers/get_sharing_data.ts
+++ b/src/plugins/discover/public/application/helpers/get_sharing_data.ts
@@ -7,11 +7,11 @@
*/
import type { Capabilities, IUiSettingsClient } from 'kibana/public';
-import { DOC_HIDE_TIME_COLUMN_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common';
-import { getSortForSearchSource } from '../angular/doc_table';
import { ISearchSource } from '../../../../data/common';
-import { AppState } from '../angular/discover_state';
+import { DOC_HIDE_TIME_COLUMN_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common';
import type { SavedSearch, SortOrder } from '../../saved_searches/types';
+import { AppState } from '../angular/discover_state';
+import { getSortForSearchSource } from '../angular/doc_table';
/**
* Preparing data to share the current state as link or CSV/Report
@@ -23,10 +23,6 @@ export async function getSharingData(
) {
const searchSource = currentSearchSource.createCopy();
const index = searchSource.getField('index')!;
- const fields = {
- fields: searchSource.getField('fields'),
- fieldsFromSource: searchSource.getField('fieldsFromSource'),
- };
searchSource.setField(
'sort',
@@ -37,7 +33,7 @@ export async function getSharingData(
searchSource.removeField('aggs');
searchSource.removeField('size');
- // fields get re-set to match the saved search columns
+ // Columns that the user has selected in the saved search
let columns = state.columns || [];
if (columns && columns.length > 0) {
@@ -50,14 +46,11 @@ export async function getSharingData(
if (timeFieldName && !columns.includes(timeFieldName)) {
columns = [timeFieldName, ...columns];
}
-
- // if columns were selected in the saved search, use them for the searchSource's fields
- const fieldsKey = fields.fieldsFromSource ? 'fieldsFromSource' : 'fields';
- searchSource.setField(fieldsKey, columns);
}
return {
searchSource: searchSource.getSerializedFields(true),
+ columns,
};
}
diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts
index cedc713b44f637..d3fdb6e72c6510 100644
--- a/src/plugins/discover/server/ui_settings.ts
+++ b/src/plugins/discover/server/ui_settings.ts
@@ -24,6 +24,7 @@ import {
DOC_TABLE_LEGACY,
MODIFY_COLUMNS_ON_SWITCH,
SEARCH_FIELDS_FROM_SOURCE,
+ MAX_DOC_FIELDS_DISPLAYED,
} from '../common';
export const uiSettings: Record = {
@@ -38,6 +39,17 @@ export const uiSettings: Record = {
category: ['discover'],
schema: schema.arrayOf(schema.string()),
},
+ [MAX_DOC_FIELDS_DISPLAYED]: {
+ name: i18n.translate('discover.advancedSettings.maxDocFieldsDisplayedTitle', {
+ defaultMessage: 'Maximum document fields displayed',
+ }),
+ value: 200,
+ description: i18n.translate('discover.advancedSettings.maxDocFieldsDisplayedText', {
+ defaultMessage: 'Maximum number of fields rendered in the document column',
+ }),
+ category: ['discover'],
+ schema: schema.number(),
+ },
[SAMPLE_SIZE_SETTING]: {
name: i18n.translate('discover.advancedSettings.sampleSizeTitle', {
defaultMessage: 'Number of rows',
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.test.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.test.ts
new file mode 100644
index 00000000000000..cff179f64ea081
--- /dev/null
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.test.ts
@@ -0,0 +1,71 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { errors } from '@elastic/elasticsearch';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { kibanaResponseFactory as response } from 'src/core/server';
+import { handleEsError } from './handle_es_error';
+
+const { ResponseError } = errors;
+
+const anyObject: any = {};
+
+describe('handleEsError', () => {
+ test('top-level reason is an empty string', () => {
+ const emptyReasonError = new ResponseError({
+ warnings: [],
+ meta: anyObject,
+ body: {
+ error: {
+ root_cause: [],
+ type: 'search_phase_execution_exception',
+ reason: '', // Empty reason
+ phase: 'fetch',
+ grouped: true,
+ failed_shards: [],
+ caused_by: {
+ type: 'too_many_buckets_exception',
+ reason: 'This is the nested reason',
+ max_buckets: 100,
+ },
+ },
+ },
+ statusCode: 503,
+ headers: {},
+ });
+
+ const { payload, status } = handleEsError({ error: emptyReasonError, response });
+
+ expect(payload.message).toEqual('This is the nested reason');
+ expect(status).toBe(503);
+ });
+
+ test('empty error', () => {
+ const { payload, status } = handleEsError({
+ error: new ResponseError({
+ body: {},
+ statusCode: 400,
+ headers: {},
+ meta: anyObject,
+ warnings: [],
+ }),
+ response,
+ });
+
+ expect(payload).toEqual({
+ attributes: { causes: undefined, error: undefined },
+ message: 'Response Error',
+ });
+
+ expect(status).toBe(400);
+ });
+
+ test('unknown object', () => {
+ expect(() => handleEsError({ error: anyObject, response })).toThrow();
+ });
+});
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts
index 42e18b72057ce3..678c46f69d51fa 100644
--- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts
@@ -17,8 +17,10 @@ interface EsErrorHandlerParams {
handleCustomError?: () => IKibanaResponse;
}
-/*
+/**
* For errors returned by the new elasticsearch js client.
+ *
+ * @throws If "error" is not an error from the elasticsearch client this handler will throw "error".
*/
export const handleEsError = ({
error,
@@ -36,12 +38,14 @@ export const handleEsError = ({
return response.customError({
statusCode,
body: {
- message: body.error?.reason ?? error.message ?? 'Unknown error',
+ message:
+ // We use || instead of ?? as the switch here because reason could be an empty string
+ body?.error?.reason || body?.error?.caused_by?.reason || error.message || 'Unknown error',
attributes: {
// The full original ES error object
- error: body.error,
+ error: body?.error,
// We assume that this is an ES error object with a nested caused by chain if we can see the "caused_by" field at the top-level
- causes: body.error?.caused_by ? getEsCause(body.error) : undefined,
+ causes: body?.error?.caused_by ? getEsCause(body.error) : undefined,
},
},
});
diff --git a/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.test.tsx b/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.test.tsx
index 7d79200bc6f877..b3fada3dbd00ff 100644
--- a/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.test.tsx
+++ b/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.test.tsx
@@ -268,7 +268,7 @@ describe(' ', () => {
expect(form.getErrorsMessages()).toEqual(['Awwww! Painless syntax error']);
// We change the type and expect the form error to not be there anymore
- await changeFieldType('long');
+ await changeFieldType('keyword');
expect(form.getErrorsMessages()).toEqual([]);
});
});
diff --git a/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.tsx b/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.tsx
index 3785096e206273..fc25879b128ec0 100644
--- a/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.tsx
+++ b/src/plugins/index_pattern_field_editor/public/components/field_editor/field_editor.tsx
@@ -15,6 +15,7 @@ import {
EuiSpacer,
EuiComboBoxOptionOption,
EuiCode,
+ EuiCallOut,
} from '@elastic/eui';
import type { CoreStart } from 'src/core/public';
@@ -138,6 +139,11 @@ const geti18nTexts = (): {
},
});
+const changeWarning = i18n.translate('indexPatternFieldEditor.editor.form.changeWarning', {
+ defaultMessage:
+ 'Changing name or type can break searches and visualizations that rely on this field.',
+});
+
const formDeserializer = (field: Field): FieldFormInternal => {
let fieldType: Array>;
if (!field.type) {
@@ -204,6 +210,11 @@ const FieldEditorComponent = ({
clearSyntaxError();
}, [type, clearSyntaxError]);
+ const [{ name: updatedName, type: updatedType }] = useFormData({ form });
+ const nameHasChanged = Boolean(field?.name) && field?.name !== updatedName;
+ const typeHasChanged =
+ Boolean(field?.type) && field?.type !== (updatedType && updatedType[0].value);
+
return (
+
-
`;
diff --git a/src/plugins/visualizations/public/components/visualization_error.tsx b/src/plugins/visualizations/public/components/visualization_error.tsx
index 81600a4e3601c5..c72933df43491a 100644
--- a/src/plugins/visualizations/public/components/visualization_error.tsx
+++ b/src/plugins/visualizations/public/components/visualization_error.tsx
@@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
-import { EuiEmptyPrompt } from '@elastic/eui';
+import { EuiEmptyPrompt, EuiText } from '@elastic/eui';
import React from 'react';
interface VisualizationNoResultsProps {
onInit?: () => void;
- error: string;
+ error: string | Error;
}
export class VisualizationError extends React.Component {
@@ -21,7 +21,11 @@ export class VisualizationError extends React.Component{this.props.error}
}
+ body={
+
+ {typeof this.props.error === 'string' ? this.props.error : this.props.error.message}
+
+ }
/>
);
}
diff --git a/src/plugins/visualizations/public/components/visualization_noresults.tsx b/src/plugins/visualizations/public/components/visualization_noresults.tsx
index 92983982dd1529..71bf1e8a7e4b00 100644
--- a/src/plugins/visualizations/public/components/visualization_noresults.tsx
+++ b/src/plugins/visualizations/public/components/visualization_noresults.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
+import { EuiEmptyPrompt, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
@@ -15,26 +15,21 @@ interface VisualizationNoResultsProps {
}
export class VisualizationNoResults extends React.Component {
- private containerDiv = React.createRef();
-
public render() {
return (
-
-
-
-
-
-
-
-
-
+
+
{i18n.translate('visualizations.noResultsFoundTitle', {
defaultMessage: 'No results found',
})}
-
-
-
-
+
+ }
+ />
);
}
diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
index c2b9fcd77757a4..2b5a611cd946e8 100644
--- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
+++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
@@ -58,7 +58,7 @@ interface VisualizationAttributes extends SavedObjectAttributes {
export interface VisualizeEmbeddableFactoryDeps {
start: StartServicesGetter<
- Pick
+ Pick
>;
}
diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts
index 8f1ebe25b50599..901593626a9451 100644
--- a/src/plugins/visualizations/public/mocks.ts
+++ b/src/plugins/visualizations/public/mocks.ts
@@ -17,7 +17,6 @@ import { dataPluginMock } from '../../../plugins/data/public/mocks';
import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks';
import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks';
import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks';
-import { dashboardPluginMock } from '../../../plugins/dashboard/public/mocks';
import { savedObjectsPluginMock } from '../../../plugins/saved_objects/public/mocks';
const createSetupContract = (): VisualizationsSetup => ({
@@ -62,7 +61,6 @@ const createInstance = async () => {
uiActions: uiActionsPluginMock.createStartContract(),
application: applicationServiceMock.createStartContract(),
embeddable: embeddablePluginMock.createStartContract(),
- dashboard: dashboardPluginMock.createStartContract(),
getAttributeService: jest.fn(),
savedObjectsClient: coreMock.createStart().savedObjects.client,
savedObjects: savedObjectsPluginMock.createStartContract(),
diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts
index d4e7132a1a21ea..081f5d65103c20 100644
--- a/src/plugins/visualizations/public/plugin.ts
+++ b/src/plugins/visualizations/public/plugin.ts
@@ -62,7 +62,6 @@ import {
convertToSerializedVis,
} from './saved_visualizations/_saved_vis';
import { createSavedSearchesLoader } from '../../discover/public';
-import { DashboardStart } from '../../dashboard/public';
import { SavedObjectsStart } from '../../saved_objects/public';
/**
@@ -97,7 +96,6 @@ export interface VisualizationsStartDeps {
inspector: InspectorStart;
uiActions: UiActionsStart;
application: ApplicationStart;
- dashboard: DashboardStart;
getAttributeService: EmbeddableStart['getAttributeService'];
savedObjects: SavedObjectsStart;
savedObjectsClient: SavedObjectsClientContract;
@@ -145,7 +143,7 @@ export class VisualizationsPlugin
public start(
core: CoreStart,
- { data, expressions, uiActions, embeddable, dashboard, savedObjects }: VisualizationsStartDeps
+ { data, expressions, uiActions, embeddable, savedObjects }: VisualizationsStartDeps
): VisualizationsStart {
const types = this.types.start();
setTypes(types);
diff --git a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts
index 743ec29fe9af7c..a3617631f734ba 100644
--- a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts
+++ b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts
@@ -8,7 +8,7 @@
import { of } from 'rxjs';
import { mockStats, mockGetStats } from './get_usage_collector.mock';
-import { createUsageCollectionSetupMock } from 'src/plugins/usage_collection/server/usage_collection.mock';
+import { createUsageCollectionSetupMock } from 'src/plugins/usage_collection/server/mocks';
import { createCollectorFetchContextMock } from 'src/plugins/usage_collection/server/mocks';
import { registerVisualizationsCollector } from './register_visualizations_collector';
diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json
index d7c5e6a4b43663..356448aa59771e 100644
--- a/src/plugins/visualizations/tsconfig.json
+++ b/src/plugins/visualizations/tsconfig.json
@@ -15,7 +15,6 @@
"references": [
{ "path": "../../core/tsconfig.json" },
{ "path": "../data/tsconfig.json" },
- { "path": "../dashboard/tsconfig.json" },
{ "path": "../expressions/tsconfig.json" },
{ "path": "../ui_actions/tsconfig.json" },
{ "path": "../embeddable/tsconfig.json" },
diff --git a/test/api_integration/apis/index_patterns/fields_api/update_fields/main.ts b/test/api_integration/apis/index_patterns/fields_api/update_fields/main.ts
index 33a840fd093fc7..c75b6c607f56e3 100644
--- a/test/api_integration/apis/index_patterns/fields_api/update_fields/main.ts
+++ b/test/api_integration/apis/index_patterns/fields_api/update_fields/main.ts
@@ -430,7 +430,8 @@ export default function ({ getService }: FtrProviderContext) {
});
it('can set field "format" on an existing field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = indexPattern.title;
+ await supertest.delete(`/api/index_patterns/index_pattern/${indexPattern.id}`);
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
diff --git a/test/api_integration/apis/index_patterns/scripted_fields_crud/create_scripted_field/main.ts b/test/api_integration/apis/index_patterns/scripted_fields_crud/create_scripted_field/main.ts
index 75450b034f2fda..f9ab482f98b764 100644
--- a/test/api_integration/apis/index_patterns/scripted_fields_crud/create_scripted_field/main.ts
+++ b/test/api_integration/apis/index_patterns/scripted_fields_crud/create_scripted_field/main.ts
@@ -11,8 +11,17 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
describe('main', () => {
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ });
+
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ });
+
it('can create a new scripted field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
@@ -40,7 +49,7 @@ export default function ({ getService }: FtrProviderContext) {
});
it('newly created scripted field is materialized in the index_pattern object', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
@@ -51,7 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/scripted_field`)
.send({
field: {
- name: 'bar',
+ name: 'bar2',
type: 'number',
scripted: true,
script: "doc['field_name'].value",
@@ -64,12 +73,15 @@ export default function ({ getService }: FtrProviderContext) {
expect(response2.status).to.be(200);
- const field = response2.body.index_pattern.fields.bar;
+ const field = response2.body.index_pattern.fields.bar2;
- expect(field.name).to.be('bar');
+ expect(field.name).to.be('bar2');
expect(field.type).to.be('number');
expect(field.scripted).to.be(true);
expect(field.script).to.be("doc['field_name'].value");
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
});
}
diff --git a/test/api_integration/apis/index_patterns/scripted_fields_crud/delete_scripted_field/main.ts b/test/api_integration/apis/index_patterns/scripted_fields_crud/delete_scripted_field/main.ts
index 030679a4dd48a6..40f57cd914a2f4 100644
--- a/test/api_integration/apis/index_patterns/scripted_fields_crud/delete_scripted_field/main.ts
+++ b/test/api_integration/apis/index_patterns/scripted_fields_crud/delete_scripted_field/main.ts
@@ -11,16 +11,25 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
describe('main', () => {
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ });
+
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ });
+
it('can remove a scripted field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fields: {
bar: {
- name: 'bar',
+ name: 'bar2',
type: 'number',
scripted: true,
script: "doc['field_name'].value",
@@ -33,10 +42,10 @@ export default function ({ getService }: FtrProviderContext) {
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
- expect(typeof response2.body.index_pattern.fields.bar).to.be('object');
+ expect(typeof response2.body.index_pattern.fields.bar2).to.be('object');
const response3 = await supertest.delete(
- `/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/scripted_field/bar`
+ `/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/scripted_field/bar2`
);
expect(response3.status).to.be(200);
@@ -45,7 +54,10 @@ export default function ({ getService }: FtrProviderContext) {
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
- expect(typeof response4.body.index_pattern.fields.bar).to.be('undefined');
+ expect(typeof response4.body.index_pattern.fields.bar2).to.be('undefined');
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
});
}
diff --git a/test/api_integration/apis/index_patterns/scripted_fields_crud/get_scripted_field/main.ts b/test/api_integration/apis/index_patterns/scripted_fields_crud/get_scripted_field/main.ts
index c23f41f8b31ddd..7fff720e5195f3 100644
--- a/test/api_integration/apis/index_patterns/scripted_fields_crud/get_scripted_field/main.ts
+++ b/test/api_integration/apis/index_patterns/scripted_fields_crud/get_scripted_field/main.ts
@@ -11,10 +11,19 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
describe('main', () => {
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ });
+
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ });
+
it('can fetch a scripted field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
@@ -47,6 +56,9 @@ export default function ({ getService }: FtrProviderContext) {
expect(response2.body.field.type).to.be('number');
expect(response2.body.field.scripted).to.be(true);
expect(response2.body.field.script).to.be("doc['field_name'].value");
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
});
}
diff --git a/test/api_integration/apis/index_patterns/scripted_fields_crud/put_scripted_field/main.ts b/test/api_integration/apis/index_patterns/scripted_fields_crud/put_scripted_field/main.ts
index 3029a351fdae1d..dec20961b0de09 100644
--- a/test/api_integration/apis/index_patterns/scripted_fields_crud/put_scripted_field/main.ts
+++ b/test/api_integration/apis/index_patterns/scripted_fields_crud/put_scripted_field/main.ts
@@ -11,10 +11,19 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
describe('main', () => {
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ });
+
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ });
+
it('can overwrite an existing field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
@@ -63,10 +72,13 @@ export default function ({ getService }: FtrProviderContext) {
expect(response3.status).to.be(200);
expect(response3.body.field.type).to.be('string');
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
it('can add a new scripted field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
@@ -100,6 +112,9 @@ export default function ({ getService }: FtrProviderContext) {
expect(response2.status).to.be(200);
expect(response2.body.field.script).to.be("doc['bar'].value");
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
});
}
diff --git a/test/api_integration/apis/index_patterns/scripted_fields_crud/update_scripted_field/main.ts b/test/api_integration/apis/index_patterns/scripted_fields_crud/update_scripted_field/main.ts
index 943601d1b2a762..ac6b11522124ba 100644
--- a/test/api_integration/apis/index_patterns/scripted_fields_crud/update_scripted_field/main.ts
+++ b/test/api_integration/apis/index_patterns/scripted_fields_crud/update_scripted_field/main.ts
@@ -11,10 +11,19 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
+ const esArchiver = getService('esArchiver');
describe('main', () => {
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ });
+
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ });
+
it('can update an existing field', async () => {
- const title = `foo-${Date.now()}-${Math.random()}*`;
+ const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
@@ -56,6 +65,9 @@ export default function ({ getService }: FtrProviderContext) {
expect(response3.status).to.be(200);
expect(response3.body.field.type).to.be('string');
expect(response3.body.field.script).to.be("doc['bar'].value");
+ await supertest.delete(
+ '/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
+ );
});
});
}
diff --git a/test/api_integration/apis/telemetry/__fixtures__/ui_counters.ts b/test/api_integration/apis/telemetry/__fixtures__/ui_counters.ts
index 762b9179182026..07a11f3876d868 100644
--- a/test/api_integration/apis/telemetry/__fixtures__/ui_counters.ts
+++ b/test/api_integration/apis/telemetry/__fixtures__/ui_counters.ts
@@ -8,6 +8,14 @@
export const basicUiCounters = {
dailyEvents: [
+ {
+ appName: 'myApp',
+ eventName: 'some_app_event',
+ lastUpdatedAt: '2021-11-20T11:43:00.961Z',
+ fromTimestamp: '2021-11-20T00:00:00Z',
+ counterType: 'count',
+ total: 2,
+ },
{
appName: 'myApp',
eventName: 'my_event_885082425109579',
diff --git a/test/api_integration/apis/telemetry/__fixtures__/usage_counters.ts b/test/api_integration/apis/telemetry/__fixtures__/usage_counters.ts
new file mode 100644
index 00000000000000..988bc2e77528de
--- /dev/null
+++ b/test/api_integration/apis/telemetry/__fixtures__/usage_counters.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export const basicUsageCounters = {
+ dailyEvents: [
+ {
+ domainId: 'anotherDomainId',
+ counterName: 'some_event_name',
+ counterType: 'count',
+ lastUpdatedAt: '2021-11-20T11:43:00.961Z',
+ fromTimestamp: '2021-11-20T00:00:00Z',
+ total: 3,
+ },
+ {
+ domainId: 'anotherDomainId',
+ counterName: 'some_event_name',
+ counterType: 'count',
+ lastUpdatedAt: '2021-04-09T11:43:00.961Z',
+ fromTimestamp: '2021-04-09T00:00:00Z',
+ total: 2,
+ },
+ {
+ domainId: 'anotherDomainId2',
+ counterName: 'some_event_name',
+ counterType: 'count',
+ lastUpdatedAt: '2021-04-20T08:18:03.030Z',
+ fromTimestamp: '2021-04-20T00:00:00Z',
+ total: 1,
+ },
+ ],
+};
diff --git a/test/api_integration/apis/telemetry/telemetry_local.ts b/test/api_integration/apis/telemetry/telemetry_local.ts
index d0a09ee58d3359..9b92576c84b3a9 100644
--- a/test/api_integration/apis/telemetry/telemetry_local.ts
+++ b/test/api_integration/apis/telemetry/telemetry_local.ts
@@ -9,6 +9,7 @@
import expect from '@kbn/expect';
import supertestAsPromised from 'supertest-as-promised';
import { basicUiCounters } from './__fixtures__/ui_counters';
+import { basicUsageCounters } from './__fixtures__/usage_counters';
import type { FtrProviderContext } from '../../ftr_provider_context';
import type { SavedObject } from '../../../../src/core/server';
import ossRootTelemetrySchema from '../../../../src/plugins/telemetry/schema/oss_root.json';
@@ -153,6 +154,20 @@ export default function ({ getService }: FtrProviderContext) {
});
});
+ describe('Usage Counters telemetry', () => {
+ before('Add UI Counters saved objects', () =>
+ esArchiver.load('saved_objects/usage_counters')
+ );
+ after('cleanup saved objects changes', () =>
+ esArchiver.unload('saved_objects/usage_counters')
+ );
+
+ it('returns usage counters aggregated by day', async () => {
+ const stats = await retrieveTelemetry(supertest);
+ expect(stats.stack_stats.kibana.plugins.usage_counters).to.eql(basicUsageCounters);
+ });
+ });
+
describe('application usage limits', () => {
function createSavedObject(viewId?: string) {
return supertest
diff --git a/test/api_integration/apis/ui_counters/ui_counters.ts b/test/api_integration/apis/ui_counters/ui_counters.ts
index 2d55e224f31cee..aa201eb6a96ff5 100644
--- a/test/api_integration/apis/ui_counters/ui_counters.ts
+++ b/test/api_integration/apis/ui_counters/ui_counters.ts
@@ -7,11 +7,10 @@
*/
import expect from '@kbn/expect';
-import { ReportManager, METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics';
+import { ReportManager, METRIC_TYPE, UiCounterMetricType, Report } from '@kbn/analytics';
import moment from 'moment';
import { FtrProviderContext } from '../../ftr_provider_context';
-import { SavedObject } from '../../../../src/core/server';
-import { UICounterSavedObjectAttributes } from '../../../../src/plugins/kibana_usage_collection/server/collectors/ui_counters/ui_counter_saved_object_type';
+import { UsageCountersSavedObject } from '../../../../src/plugins/usage_collection/server';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@@ -24,10 +23,22 @@ export default function ({ getService }: FtrProviderContext) {
count,
});
+ const sendReport = async (report: Report) => {
+ await supertest
+ .post('/api/ui_counters/_report')
+ .set('kbn-xsrf', 'kibana')
+ .set('content-type', 'application/json')
+ .send({ report })
+ .expect(200);
+
+ // wait for SO to index data into ES
+ await new Promise((res) => setTimeout(res, 5 * 1000));
+ };
+
const getCounterById = (
- savedObjects: Array>,
+ savedObjects: UsageCountersSavedObject[],
targetId: string
- ): SavedObject => {
+ ): UsageCountersSavedObject => {
const savedObject = savedObjects.find(({ id }: { id: string }) => id === targetId);
if (!savedObject) {
throw new Error(`Unable to find savedObject id ${targetId}`);
@@ -40,30 +51,25 @@ export default function ({ getService }: FtrProviderContext) {
const dayDate = moment().format('DDMMYYYY');
before(async () => await esArchiver.emptyKibanaIndex());
- it('stores ui counter events in savedObjects', async () => {
+ it('stores ui counter events in usage counters savedObjects', async () => {
const reportManager = new ReportManager();
const { report } = reportManager.assignReports([
createUiCounterEvent('my_event', METRIC_TYPE.COUNT),
]);
- await supertest
- .post('/api/ui_counters/_report')
- .set('kbn-xsrf', 'kibana')
- .set('content-type', 'application/json')
- .send({ report })
- .expect(200);
+ await sendReport(report);
const {
body: { saved_objects: savedObjects },
} = await supertest
- .get('/api/saved_objects/_find?type=ui-counter')
+ .get('/api/saved_objects/_find?type=usage-counters')
.set('kbn-xsrf', 'kibana')
.expect(200);
const countTypeEvent = getCounterById(
savedObjects,
- `myApp:${dayDate}:${METRIC_TYPE.COUNT}:my_event`
+ `uiCounter:${dayDate}:${METRIC_TYPE.COUNT}:myApp:my_event`
);
expect(countTypeEvent.attributes.count).to.eql(1);
});
@@ -78,35 +84,31 @@ export default function ({ getService }: FtrProviderContext) {
createUiCounterEvent(`${uniqueEventName}_2`, METRIC_TYPE.COUNT),
createUiCounterEvent(uniqueEventName, METRIC_TYPE.CLICK, 2),
]);
- await supertest
- .post('/api/ui_counters/_report')
- .set('kbn-xsrf', 'kibana')
- .set('content-type', 'application/json')
- .send({ report })
- .expect(200);
+
+ await sendReport(report);
const {
body: { saved_objects: savedObjects },
} = await supertest
- .get('/api/saved_objects/_find?type=ui-counter&fields=count')
+ .get('/api/saved_objects/_find?type=usage-counters&fields=count')
.set('kbn-xsrf', 'kibana')
.expect(200);
const countTypeEvent = getCounterById(
savedObjects,
- `myApp:${dayDate}:${METRIC_TYPE.COUNT}:${uniqueEventName}`
+ `uiCounter:${dayDate}:${METRIC_TYPE.COUNT}:myApp:${uniqueEventName}`
);
expect(countTypeEvent.attributes.count).to.eql(1);
const clickTypeEvent = getCounterById(
savedObjects,
- `myApp:${dayDate}:${METRIC_TYPE.CLICK}:${uniqueEventName}`
+ `uiCounter:${dayDate}:${METRIC_TYPE.CLICK}:myApp:${uniqueEventName}`
);
expect(clickTypeEvent.attributes.count).to.eql(2);
const secondEvent = getCounterById(
savedObjects,
- `myApp:${dayDate}:${METRIC_TYPE.COUNT}:${uniqueEventName}_2`
+ `uiCounter:${dayDate}:${METRIC_TYPE.COUNT}:myApp:${uniqueEventName}_2`
);
expect(secondEvent.attributes.count).to.eql(1);
});
diff --git a/test/api_integration/config.js b/test/api_integration/config.js
index 1c19dd24fa96b6..7bbace4c60570b 100644
--- a/test/api_integration/config.js
+++ b/test/api_integration/config.js
@@ -31,6 +31,8 @@ export default async function ({ readConfigFile }) {
'--server.xsrf.disableProtection=true',
'--server.compression.referrerWhitelist=["some-host.com"]',
`--savedObjects.maxImportExportSize=10001`,
+ // for testing set buffer duration to 0 to immediately flush counters into saved objects.
+ '--usageCollection.usageCounters.bufferDuration=0',
],
},
};
diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json b/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json
new file mode 100644
index 00000000000000..80071fe4227801
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json
@@ -0,0 +1,111 @@
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "ui-counter:myApp:30112020:loaded:my_event_885082425109579",
+ "source": {
+ "ui-counter": {
+ "count": 1
+ },
+ "type": "ui-counter",
+ "updated_at": "2020-11-30T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "ui-counter:myApp:30112020:count:my_event_885082425109579_2",
+ "source": {
+ "ui-counter": {
+ "count": 1
+ },
+ "type": "ui-counter",
+ "updated_at": "2020-11-30T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "ui-counter:myApp:30112020:count:my_event_885082425109579_2",
+ "source": {
+ "ui-counter": {
+ "count": 1
+ },
+ "type": "ui-counter",
+ "updated_at": "2020-10-28T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "ui-counter:myApp:30112020:click:my_event_885082425109579",
+ "source": {
+ "ui-counter": {
+ "count": 2
+ },
+ "type": "ui-counter",
+ "updated_at": "2020-11-30T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "ui-counter:myApp:30112020:click:my_event_885082425109579",
+ "source": {
+ "ui-counter": {
+ "count": 2
+ },
+ "type": "ui-counter",
+ "updated_at": "2020-11-30T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "uiCounter:09042021:count:myApp:some_app_event",
+ "source": {
+ "usage-counters": {
+ "count": 2,
+ "domainId": "uiCounter",
+ "counterName": "myApp:some_app_event",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-11-20T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "anotherDomainId:09042021:count:some_event_name",
+ "source": {
+ "usage-counters": {
+ "count": 2,
+ "domainId": "anotherDomainId",
+ "counterName": "some_event_name",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-11-20T11:43:00.961Z"
+ }
+ }
+}
+
diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json.gz b/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json.gz
deleted file mode 100644
index 3f42c777260b3b..00000000000000
Binary files a/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/data.json.gz and /dev/null differ
diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/mappings.json b/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/mappings.json
index 926fd5d79faa08..39902f8a9211a6 100644
--- a/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/mappings.json
+++ b/test/api_integration/fixtures/es_archiver/saved_objects/ui_counters/mappings.json
@@ -35,6 +35,15 @@
}
}
},
+ "usage-counters": {
+ "dynamic": false,
+ "properties": {
+ "domainId": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ },
"dashboard": {
"properties": {
"description": {
diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/data.json b/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/data.json
new file mode 100644
index 00000000000000..16e0364b24fda8
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/data.json
@@ -0,0 +1,89 @@
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "uiCounter:20112020:count:myApp:some_app_event",
+ "source": {
+ "usage-counters": {
+ "count": 2,
+ "domainId": "uiCounter",
+ "counterName": "myApp:some_app_event",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-11-20T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "anotherDomainId:20112020:count:some_event_name",
+ "source": {
+ "usage-counters": {
+ "count": 3,
+ "domainId": "anotherDomainId",
+ "counterName": "some_event_name",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-11-20T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "anotherDomainId:09042021:count:some_event_name",
+ "source": {
+ "usage-counters": {
+ "count": 2,
+ "domainId": "anotherDomainId",
+ "counterName": "some_event_name",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-04-09T11:43:00.961Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "anotherDomainId2:09042021:count:some_event_name",
+ "source": {
+ "usage-counters": {
+ "count": 1,
+ "domainId": "anotherDomainId2",
+ "counterName": "some_event_name",
+ "counterType": "count"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-04-20T08:18:03.030Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "anotherDomainId3:09042021:custom_type:zero_count",
+ "source": {
+ "usage-counters": {
+ "count": 0,
+ "domainId": "anotherDomainId3",
+ "counterName": "zero_count",
+ "counterType": "custom_type"
+ },
+ "type": "usage-counters",
+ "updated_at": "2021-04-20T08:18:03.030Z"
+ }
+ }
+}
diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/mappings.json b/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/mappings.json
new file mode 100644
index 00000000000000..14ed147b2da8e7
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/saved_objects/usage_counters/mappings.json
@@ -0,0 +1,276 @@
+{
+ "type": "index",
+ "value": {
+ "index": ".kibana",
+ "settings": {
+ "index": {
+ "number_of_shards": "1",
+ "number_of_replicas": "1"
+ }
+ },
+ "mappings": {
+ "dynamic": "strict",
+ "properties": {
+ "config": {
+ "dynamic": "true",
+ "properties": {
+ "buildNum": {
+ "type": "keyword"
+ },
+ "defaultIndex": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ }
+ }
+ },
+ "usage-counters": {
+ "dynamic": false,
+ "properties": {
+ "domainId": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ },
+ "dashboard": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "optionsJSON": {
+ "type": "text"
+ },
+ "panelsJSON": {
+ "type": "text"
+ },
+ "refreshInterval": {
+ "properties": {
+ "display": {
+ "type": "keyword"
+ },
+ "pause": {
+ "type": "boolean"
+ },
+ "section": {
+ "type": "integer"
+ },
+ "value": {
+ "type": "integer"
+ }
+ }
+ },
+ "timeFrom": {
+ "type": "keyword"
+ },
+ "timeRestore": {
+ "type": "boolean"
+ },
+ "timeTo": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "index-pattern": {
+ "properties": {
+ "fieldFormatMap": {
+ "type": "text"
+ },
+ "fields": {
+ "type": "text"
+ },
+ "intervalName": {
+ "type": "keyword"
+ },
+ "notExpandable": {
+ "type": "boolean"
+ },
+ "sourceFilters": {
+ "type": "text"
+ },
+ "timeFieldName": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ }
+ }
+ },
+ "search": {
+ "properties": {
+ "columns": {
+ "type": "keyword"
+ },
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "sort": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "server": {
+ "properties": {
+ "uuid": {
+ "type": "keyword"
+ }
+ }
+ },
+ "timelion-sheet": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "timelion_chart_height": {
+ "type": "integer"
+ },
+ "timelion_columns": {
+ "type": "integer"
+ },
+ "timelion_interval": {
+ "type": "keyword"
+ },
+ "timelion_other_interval": {
+ "type": "keyword"
+ },
+ "timelion_rows": {
+ "type": "integer"
+ },
+ "timelion_sheet": {
+ "type": "text"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "namespace": {
+ "type": "keyword"
+ },
+ "references": {
+ "properties": {
+ "id": {
+ "type": "keyword"
+ },
+ "name": {
+ "type": "keyword"
+ },
+ "type": {
+ "type": "keyword"
+ }
+ },
+ "type": "nested"
+ },
+ "type": {
+ "type": "keyword"
+ },
+ "updated_at": {
+ "type": "date"
+ },
+ "url": {
+ "properties": {
+ "accessCount": {
+ "type": "long"
+ },
+ "accessDate": {
+ "type": "date"
+ },
+ "createDate": {
+ "type": "date"
+ },
+ "url": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 2048
+ }
+ }
+ }
+ }
+ },
+ "visualization": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "savedSearchId": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "visState": {
+ "type": "text"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.ts b/test/functional/apps/dashboard/create_and_add_embeddables.ts
index f4ee4e99047686..9b8fc4785a6718 100644
--- a/test/functional/apps/dashboard/create_and_add_embeddables.ts
+++ b/test/functional/apps/dashboard/create_and_add_embeddables.ts
@@ -69,6 +69,36 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.dashboard.waitForRenderComplete();
});
+ it('adds a markdown visualization via the quick button', async () => {
+ const originalPanelCount = await PageObjects.dashboard.getPanelCount();
+ await PageObjects.dashboard.clickMarkdownQuickButton();
+ await PageObjects.visualize.saveVisualizationExpectSuccess(
+ 'visualization from markdown quick button',
+ { redirectToOrigin: true }
+ );
+
+ await retry.try(async () => {
+ const panelCount = await PageObjects.dashboard.getPanelCount();
+ expect(panelCount).to.eql(originalPanelCount + 1);
+ });
+ await PageObjects.dashboard.waitForRenderComplete();
+ });
+
+ it('adds an input control visualization via the quick button', async () => {
+ const originalPanelCount = await PageObjects.dashboard.getPanelCount();
+ await PageObjects.dashboard.clickInputControlsQuickButton();
+ await PageObjects.visualize.saveVisualizationExpectSuccess(
+ 'visualization from input control quick button',
+ { redirectToOrigin: true }
+ );
+
+ await retry.try(async () => {
+ const panelCount = await PageObjects.dashboard.getPanelCount();
+ expect(panelCount).to.eql(originalPanelCount + 1);
+ });
+ await PageObjects.dashboard.waitForRenderComplete();
+ });
+
it('saves the listing page instead of the visualization to the app link', async () => {
await PageObjects.header.clickVisualize(true);
const currentUrl = await browser.getCurrentUrl();
diff --git a/test/functional/apps/dashboard/edit_visualizations.js b/test/functional/apps/dashboard/edit_visualizations.js
index d5df97881a1d3b..ce32f53587e747 100644
--- a/test/functional/apps/dashboard/edit_visualizations.js
+++ b/test/functional/apps/dashboard/edit_visualizations.js
@@ -15,15 +15,12 @@ export default function ({ getService, getPageObjects }) {
const appsMenu = getService('appsMenu');
const kibanaServer = getService('kibanaServer');
const dashboardPanelActions = getService('dashboardPanelActions');
- const dashboardVisualizations = getService('dashboardVisualizations');
const originalMarkdownText = 'Original markdown text';
const modifiedMarkdownText = 'Modified markdown text';
const createMarkdownVis = async (title) => {
- await testSubjects.click('dashboardAddNewPanelButton');
- await dashboardVisualizations.ensureNewVisualizationDialogIsShowing();
- await PageObjects.visualize.clickMarkdownWidget();
+ await PageObjects.dashboard.clickMarkdownQuickButton();
await PageObjects.visEditor.setMarkdownTxt(originalMarkdownText);
await PageObjects.visEditor.clickGo();
if (title) {
diff --git a/test/functional/apps/dashboard/embeddable_data_grid.ts b/test/functional/apps/dashboard/embeddable_data_grid.ts
index 00a75baae4be7f..a9e0039de1f79f 100644
--- a/test/functional/apps/dashboard/embeddable_data_grid.ts
+++ b/test/functional/apps/dashboard/embeddable_data_grid.ts
@@ -47,12 +47,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('are added when a cell filter is clicked', async function () {
- await find.clickByCssSelector(`[role="gridcell"]:nth-child(3)`);
+ await find.clickByCssSelector(`[role="gridcell"]:nth-child(4)`);
// needs a short delay between becoming visible & being clickable
await PageObjects.common.sleep(250);
await find.clickByCssSelector(`[data-test-subj="filterOutButton"]`);
await PageObjects.header.waitUntilLoadingHasFinished();
- await find.clickByCssSelector(`[role="gridcell"]:nth-child(3)`);
+ await find.clickByCssSelector(`[role="gridcell"]:nth-child(4)`);
await PageObjects.common.sleep(250);
await find.clickByCssSelector(`[data-test-subj="filterForButton"]`);
const filterCount = await filterBar.getFilterCount();
diff --git a/test/functional/apps/discover/_data_grid_doc_table.ts b/test/functional/apps/discover/_data_grid_doc_table.ts
index 85aa96555f20bf..5499f0250eb736 100644
--- a/test/functional/apps/discover/_data_grid_doc_table.ts
+++ b/test/functional/apps/discover/_data_grid_doc_table.ts
@@ -38,10 +38,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await kibanaServer.uiSettings.replace({});
});
- it('should show the first 12 rows by default', async function () {
+ it('should show the first 11 rows by default', async function () {
// with the default range the number of hits is ~14000
const rows = await dataGrid.getDocTableRows();
- expect(rows.length).to.be(12);
+ expect(rows.length).to.be(11);
});
it('should refresh the table content when changing time window', async function () {
diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts
index e8fcb06d06193b..f41a98e2f3364c 100644
--- a/test/functional/apps/discover/_data_grid_field_data.ts
+++ b/test/functional/apps/discover/_data_grid_field_data.ts
@@ -68,7 +68,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.discover.waitUntilSearchingHasFinished();
await retry.waitFor('first cell contains expected timestamp', async () => {
- const cell = await dataGrid.getCellElement(1, 2);
+ const cell = await dataGrid.getCellElement(1, 3);
const text = await cell.getVisibleText();
return text === expectedTimeStamp;
});
diff --git a/test/functional/apps/management/_runtime_fields.js b/test/functional/apps/management/_runtime_fields.js
index e2227d4240d409..44abf07b38ac65 100644
--- a/test/functional/apps/management/_runtime_fields.js
+++ b/test/functional/apps/management/_runtime_fields.js
@@ -55,6 +55,7 @@ export default function ({ getService, getPageObjects }) {
await testSubjects.click('editFieldFormat');
await PageObjects.settings.setFieldType('Long');
await PageObjects.settings.changeFieldScript('emit(6);');
+ await testSubjects.find('changeWarning');
await PageObjects.settings.clickSaveField();
await PageObjects.settings.confirmSave();
});
diff --git a/test/functional/apps/visualize/_data_table.ts b/test/functional/apps/visualize/_data_table.ts
index 96cbf97621b089..1ff5bdcc6da78f 100644
--- a/test/functional/apps/visualize/_data_table.ts
+++ b/test/functional/apps/visualize/_data_table.ts
@@ -267,16 +267,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('should apply correct filter', async () => {
- await retry.try(async () => {
- await PageObjects.visChart.filterOnTableCell(1, 3);
- await PageObjects.visChart.waitForVisualizationRenderingStabilized();
- const data = await PageObjects.visChart.getTableVisContent();
- expect(data).to.be.eql([
- ['png', '1,373'],
- ['gif', '918'],
- ['Other', '445'],
- ]);
- });
+ await PageObjects.visChart.filterOnTableCell(1, 3);
+ await PageObjects.visChart.waitForVisualizationRenderingStabilized();
+ const data = await PageObjects.visChart.getTableVisContent();
+ expect(data).to.be.eql([
+ ['png', '1,373'],
+ ['gif', '918'],
+ ['Other', '445'],
+ ]);
});
});
diff --git a/test/functional/apps/visualize/_heatmap_chart.ts b/test/functional/apps/visualize/_heatmap_chart.ts
index 79a9a6cbd5acae..660f45179631ed 100644
--- a/test/functional/apps/visualize/_heatmap_chart.ts
+++ b/test/functional/apps/visualize/_heatmap_chart.ts
@@ -15,8 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const inspector = getService('inspector');
const PageObjects = getPageObjects(['visualize', 'visEditor', 'visChart', 'timePicker']);
- // FLAKY: https://github.com/elastic/kibana/issues/95642
- describe.skip('heatmap chart', function indexPatternCreation() {
+ describe('heatmap chart', function indexPatternCreation() {
const vizName1 = 'Visualization HeatmapChart';
before(async function () {
diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts
index 0a3632e4aaa814..747494a690c7ed 100644
--- a/test/functional/apps/visualize/index.ts
+++ b/test/functional/apps/visualize/index.ts
@@ -56,11 +56,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./_point_series_options'));
loadTestFile(require.resolve('./_vertical_bar_chart'));
loadTestFile(require.resolve('./_vertical_bar_chart_nontimeindex'));
-
- // Test non-replaced vislib chart types
- loadTestFile(require.resolve('./_gauge_chart'));
- loadTestFile(require.resolve('./_heatmap_chart'));
- loadTestFile(require.resolve('./_pie_chart'));
});
describe('', function () {
diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts
index 9c12296db138c6..34559afdf6ae1a 100644
--- a/test/functional/page_objects/dashboard_page.ts
+++ b/test/functional/page_objects/dashboard_page.ts
@@ -413,6 +413,16 @@ export function DashboardPageProvider({ getService, getPageObjects }: FtrProvide
await testSubjects.click('confirmSaveSavedObjectButton');
}
+ public async clickMarkdownQuickButton() {
+ log.debug('Click markdown quick button');
+ await testSubjects.click('dashboardMarkdownQuickButton');
+ }
+
+ public async clickInputControlsQuickButton() {
+ log.debug('Click input controls quick button');
+ await testSubjects.click('dashboardInputControlsQuickButton');
+ }
+
/**
*
* @param dashboardTitle {String}
diff --git a/test/functional/page_objects/visualize_chart_page.ts b/test/functional/page_objects/visualize_chart_page.ts
index cd1c5cf318e63a..7b69101b92475c 100644
--- a/test/functional/page_objects/visualize_chart_page.ts
+++ b/test/functional/page_objects/visualize_chart_page.ts
@@ -419,12 +419,13 @@ export function VisualizeChartPageProvider({ getService, getPageObjects }: FtrPr
public async filterOnTableCell(columnIndex: number, rowIndex: number) {
await retry.try(async () => {
const cell = await dataGrid.getCellElement(rowIndex, columnIndex);
- await cell.focus();
+ await cell.click();
const filterBtn = await testSubjects.findDescendant(
'tbvChartCell__filterForCellValue',
cell
);
- await filterBtn.click();
+ await common.sleep(2000);
+ filterBtn.click();
});
}
diff --git a/test/functional/page_objects/visualize_editor_page.ts b/test/functional/page_objects/visualize_editor_page.ts
index 5f05d825dd0f45..97627556abc630 100644
--- a/test/functional/page_objects/visualize_editor_page.ts
+++ b/test/functional/page_objects/visualize_editor_page.ts
@@ -128,9 +128,7 @@ export function VisualizeEditorPageProvider({ getService, getPageObjects }: FtrP
}
public async changeHeatmapColorNumbers(value = 6) {
- const input = await testSubjects.find(`heatmapColorsNumber`);
- await input.clearValueWithKeyboard();
- await input.type(`${value}`);
+ await testSubjects.setValue('heatmapColorsNumber', `${value}`);
}
public async getBucketErrorMessage() {
diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts
index c0a7e0f82e6920..87fa59b48a3249 100644
--- a/test/functional/services/data_grid.ts
+++ b/test/functional/services/data_grid.ts
@@ -168,7 +168,7 @@ export function DataGridProvider({ getService, getPageObjects }: FtrProviderCont
const textArr = [];
let idx = 0;
for (const cell of result) {
- if (idx > 0) {
+ if (idx > 1) {
textArr.push(await cell.getVisibleText());
}
idx++;
diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts
index 1651e213ee82d6..d21a157975ac83 100644
--- a/test/plugin_functional/config.ts
+++ b/test/plugin_functional/config.ts
@@ -21,6 +21,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
return {
testFiles: [
+ require.resolve('./test_suites/usage_collection'),
require.resolve('./test_suites/core'),
require.resolve('./test_suites/custom_visualizations'),
require.resolve('./test_suites/panel_actions'),
@@ -59,6 +60,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
'--corePluginDeprecations.oldProperty=hello',
'--corePluginDeprecations.secret=100',
'--corePluginDeprecations.noLongerUsed=still_using',
+ // for testing set buffer duration to 0 to immediately flush counters into saved objects.
+ '--usageCollection.usageCounters.bufferDuration=0',
...plugins.map(
(pluginDir) => `--plugin-path=${path.resolve(__dirname, 'plugins', pluginDir)}`
),
diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts
index db4288d26a3d7b..e051c39f681504 100644
--- a/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts
+++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts
@@ -24,7 +24,7 @@ const configSecretDeprecation: ConfigDeprecation = (settings, fromPath, addDepre
addDeprecation({
documentationUrl: 'config-secret-doc-url',
message:
- 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret ' +
+ 'Kibana plugin functional tests will no longer allow corePluginDeprecations.secret ' +
'config to be set to anything except 42.',
});
}
diff --git a/test/plugin_functional/plugins/usage_collection/kibana.json b/test/plugin_functional/plugins/usage_collection/kibana.json
new file mode 100644
index 00000000000000..c98e3b95d389c9
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/kibana.json
@@ -0,0 +1,9 @@
+{
+ "id": "usageCollectionTestPlugin",
+ "version": "0.0.1",
+ "kibanaVersion": "kibana",
+ "configPath": ["usageCollectionTestPlugin"],
+ "requiredPlugins": ["usageCollection"],
+ "server": true,
+ "ui": false
+}
diff --git a/test/plugin_functional/plugins/usage_collection/package.json b/test/plugin_functional/plugins/usage_collection/package.json
new file mode 100644
index 00000000000000..33289bd8d727f1
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "usage_collection_test_plugin",
+ "version": "1.0.0",
+ "main": "target/test/plugin_functional/plugins/usage_collection",
+ "kibana": {
+ "version": "kibana",
+ "templateVersion": "1.0.0"
+ },
+ "license": "SSPL-1.0 OR Elastic License 2.0",
+ "scripts": {
+ "kbn": "node ../../../../scripts/kbn.js",
+ "build": "rm -rf './target' && ../../../../node_modules/.bin/tsc"
+ }
+}
diff --git a/test/plugin_functional/plugins/usage_collection/server/index.ts b/test/plugin_functional/plugins/usage_collection/server/index.ts
new file mode 100644
index 00000000000000..172f8491a1a407
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/server/index.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { UsageCollectionTestPlugin } from './plugin';
+export const plugin = () => new UsageCollectionTestPlugin();
diff --git a/test/plugin_functional/plugins/usage_collection/server/plugin.ts b/test/plugin_functional/plugins/usage_collection/server/plugin.ts
new file mode 100644
index 00000000000000..523fbcfe058dce
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/server/plugin.ts
@@ -0,0 +1,43 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import type { Plugin, CoreSetup } from 'kibana/server';
+import {
+ UsageCollectionSetup,
+ UsageCounter,
+} from '../../../../../src/plugins/usage_collection/server';
+import { registerRoutes } from './routes';
+
+export interface TestPluginDepsSetup {
+ usageCollection: UsageCollectionSetup;
+}
+
+export class UsageCollectionTestPlugin implements Plugin {
+ private usageCounter?: UsageCounter;
+
+ public setup(core: CoreSetup, { usageCollection }: TestPluginDepsSetup) {
+ const usageCounter = usageCollection.createUsageCounter('usageCollectionTestPlugin');
+
+ registerRoutes(core.http, usageCounter);
+ usageCounter.incrementCounter({
+ counterName: 'duringSetup',
+ incrementBy: 10,
+ });
+ usageCounter.incrementCounter({ counterName: 'duringSetup' });
+ this.usageCounter = usageCounter;
+ }
+
+ public start() {
+ if (!this.usageCounter) {
+ throw new Error('this.usageCounter is expected to be defined during setup.');
+ }
+ this.usageCounter.incrementCounter({ counterName: 'duringStart' });
+ }
+
+ public stop() {}
+}
diff --git a/test/plugin_functional/plugins/usage_collection/server/routes.ts b/test/plugin_functional/plugins/usage_collection/server/routes.ts
new file mode 100644
index 00000000000000..e67e454512779e
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/server/routes.ts
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import type { HttpServiceSetup } from 'kibana/server';
+import { UsageCounter } from '../../../../../src/plugins/usage_collection/server';
+
+export function registerRoutes(http: HttpServiceSetup, usageCounter: UsageCounter) {
+ const router = http.createRouter();
+ router.get(
+ {
+ path: '/api/usage_collection_test_plugin',
+ validate: false,
+ },
+ async (context, req, res) => {
+ usageCounter.incrementCounter({ counterName: 'routeAccessed' });
+ return res.ok();
+ }
+ );
+}
diff --git a/test/plugin_functional/plugins/usage_collection/tsconfig.json b/test/plugin_functional/plugins/usage_collection/tsconfig.json
new file mode 100644
index 00000000000000..3d9d8ca9451d41
--- /dev/null
+++ b/test/plugin_functional/plugins/usage_collection/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "skipLibCheck": true
+ },
+ "include": [
+ "index.ts",
+ "public/**/*.ts",
+ "public/**/*.tsx",
+ "server/**/*.ts",
+ "../../../../typings/**/*",
+ ],
+ "exclude": [],
+ "references": [
+ { "path": "../../../../src/core/tsconfig.json" }
+ ]
+}
diff --git a/test/plugin_functional/test_suites/core/deprecations.ts b/test/plugin_functional/test_suites/core/deprecations.ts
index c44781ab284c66..a78527d0d82e25 100644
--- a/test/plugin_functional/test_suites/core/deprecations.ts
+++ b/test/plugin_functional/test_suites/core/deprecations.ts
@@ -42,7 +42,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
{
level: 'critical',
message:
- 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.',
+ 'Kibana plugin functional tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.',
correctiveActions: {},
documentationUrl: 'config-secret-doc-url',
domainId: 'corePluginDeprecations',
diff --git a/test/plugin_functional/test_suites/usage_collection/index.ts b/test/plugin_functional/test_suites/usage_collection/index.ts
new file mode 100644
index 00000000000000..201b7b04ff2222
--- /dev/null
+++ b/test/plugin_functional/test_suites/usage_collection/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { PluginFunctionalProviderContext } from '../../services';
+
+export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
+ describe('usage collection', function () {
+ loadTestFile(require.resolve('./usage_counters'));
+ });
+}
diff --git a/test/plugin_functional/test_suites/usage_collection/usage_counters.ts b/test/plugin_functional/test_suites/usage_collection/usage_counters.ts
new file mode 100644
index 00000000000000..f1591165b8d650
--- /dev/null
+++ b/test/plugin_functional/test_suites/usage_collection/usage_counters.ts
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import expect from '@kbn/expect';
+import { PluginFunctionalProviderContext } from '../../services';
+import {
+ UsageCountersSavedObject,
+ serializeCounterKey,
+} from '../../../../src/plugins/usage_collection/server/usage_counters';
+
+export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
+ const supertest = getService('supertest');
+
+ async function getSavedObjectCounters() {
+ // wait until ES indexes the counter SavedObject;
+ await new Promise((res) => setTimeout(res, 7 * 1000));
+
+ return await supertest
+ .get('/api/saved_objects/_find?type=usage-counters')
+ .set('kbn-xsrf', 'true')
+ .expect(200)
+ .then(({ body }) => {
+ expect(body.total).to.above(1);
+ return (body.saved_objects as UsageCountersSavedObject[]).reduce((acc, savedObj) => {
+ const { count, counterName, domainId } = savedObj.attributes;
+ if (domainId === 'usageCollectionTestPlugin') {
+ acc[counterName] = count;
+ }
+
+ return acc;
+ }, {} as Record);
+ });
+ }
+
+ describe('Usage Counters service', () => {
+ before(async () => {
+ const key = serializeCounterKey({
+ counterName: 'routeAccessed',
+ counterType: 'count',
+ domainId: 'usageCollectionTestPlugin',
+ date: Date.now(),
+ });
+
+ await supertest.delete(`/api/saved_objects/usage-counters/${key}`).set('kbn-xsrf', 'true');
+ });
+
+ it('stores usage counters sent during start and setup', async () => {
+ const { duringSetup, duringStart, routeAccessed } = await getSavedObjectCounters();
+
+ expect(duringSetup).to.be(11);
+ expect(duringStart).to.be(1);
+ expect(routeAccessed).to.be(undefined);
+ });
+
+ it('stores usage counters triggered by runtime activities', async () => {
+ await supertest.get('/api/usage_collection_test_plugin').set('kbn-xsrf', 'true').expect(200);
+
+ const { routeAccessed } = await getSavedObjectCounters();
+ expect(routeAccessed).to.be(1);
+ });
+ });
+}
diff --git a/x-pack/examples/reporting_example/.eslintrc.js b/x-pack/examples/reporting_example/.eslintrc.js
deleted file mode 100644
index b267018448ba62..00000000000000
--- a/x-pack/examples/reporting_example/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = {
- root: true,
- extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'],
- rules: {
- '@kbn/eslint/require-license-header': 'off',
- },
-};
diff --git a/x-pack/examples/reporting_example/common/index.ts b/x-pack/examples/reporting_example/common/index.ts
index e47604bd7b8231..f01f2673eff569 100644
--- a/x-pack/examples/reporting_example/common/index.ts
+++ b/x-pack/examples/reporting_example/common/index.ts
@@ -1,2 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
export const PLUGIN_ID = 'reportingExample';
export const PLUGIN_NAME = 'reportingExample';
diff --git a/x-pack/examples/reporting_example/public/application.tsx b/x-pack/examples/reporting_example/public/application.tsx
index 1bb944faad3eae..25a1cc767f1f51 100644
--- a/x-pack/examples/reporting_example/public/application.tsx
+++ b/x-pack/examples/reporting_example/public/application.tsx
@@ -1,3 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
import React from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreStart } from '../../../../src/core/public';
diff --git a/x-pack/examples/reporting_example/public/components/app.tsx b/x-pack/examples/reporting_example/public/components/app.tsx
index 8f7176675f2c2d..fd4a85dd067790 100644
--- a/x-pack/examples/reporting_example/public/components/app.tsx
+++ b/x-pack/examples/reporting_example/public/components/app.tsx
@@ -1,3 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
import {
EuiCard,
EuiCode,
diff --git a/x-pack/examples/reporting_example/public/index.ts b/x-pack/examples/reporting_example/public/index.ts
index a490cf96895be9..f9f749e2b0cd02 100644
--- a/x-pack/examples/reporting_example/public/index.ts
+++ b/x-pack/examples/reporting_example/public/index.ts
@@ -1,3 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
import { ReportingExamplePlugin } from './plugin';
export function plugin() {
diff --git a/x-pack/examples/reporting_example/public/plugin.ts b/x-pack/examples/reporting_example/public/plugin.ts
index 95b4d917f549ae..6ac1cbe01db92f 100644
--- a/x-pack/examples/reporting_example/public/plugin.ts
+++ b/x-pack/examples/reporting_example/public/plugin.ts
@@ -1,3 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
import {
AppMountParameters,
AppNavLinkStatus,
diff --git a/x-pack/examples/reporting_example/public/types.ts b/x-pack/examples/reporting_example/public/types.ts
index d574053266fae8..56e8c34d9dae44 100644
--- a/x-pack/examples/reporting_example/public/types.ts
+++ b/x-pack/examples/reporting_example/public/types.ts
@@ -1,3 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
import { DeveloperExamplesSetup } from '../../../../examples/developer_examples/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';
import { ReportingStart } from '../../../plugins/reporting/public';
diff --git a/x-pack/package.json b/x-pack/package.json
index 9e963881450380..36a6d120d946bd 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -38,7 +38,6 @@
},
"dependencies": {
"@elastic/safer-lodash-set": "link:../packages/elastic-safer-lodash-set",
- "@kbn/config-schema": "link:../packages/kbn-config-schema",
"@kbn/i18n": "link:../packages/kbn-i18n",
"@kbn/interpreter": "link:../packages/kbn-interpreter",
"@kbn/ui-framework": "link:../packages/kbn-ui-framework"
diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
index 352733494df40d..adf6a560c6c4aa 100644
--- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
@@ -701,6 +701,282 @@ describe('7.11.2', () => {
});
});
+describe('7.13.0', () => {
+ beforeEach(() => {
+ jest.resetAllMocks();
+ encryptedSavedObjectsSetup.createMigration.mockImplementation(
+ (shouldMigrateWhenPredicate, migration) => migration
+ );
+ });
+ test('security solution alerts get migrated and remove null values', () => {
+ const migration713 = getMigrations(encryptedSavedObjectsSetup)['7.13.0'];
+ const alert = getMockData({
+ alertTypeId: 'siem.signals',
+ params: {
+ author: ['Elastic'],
+ buildingBlockType: null,
+ description:
+ "This rule detects a known command and control pattern in network events. The FIN7 threat group is known to use this command and control technique, while maintaining persistence in their target's network.",
+ ruleId: '4a4e23cf-78a2-449c-bac3-701924c269d3',
+ index: ['packetbeat-*'],
+ falsePositives: [
+ "This rule could identify benign domains that are formatted similarly to FIN7's command and control algorithm. Alerts should be investigated by an analyst to assess the validity of the individual observations.",
+ ],
+ from: 'now-6m',
+ immutable: true,
+ query:
+ 'event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-zA-Z]{4,5}.(pw|us|club|info|site|top)/ AND NOT destination.domain:zoom.us',
+ language: 'lucene',
+ license: 'Elastic License',
+ outputIndex: '.siem-signals-rylandherrick_2-default',
+ savedId: null,
+ timelineId: null,
+ timelineTitle: null,
+ meta: null,
+ filters: null,
+ maxSignals: 100,
+ riskScore: 73,
+ riskScoreMapping: [],
+ ruleNameOverride: null,
+ severity: 'high',
+ severityMapping: null,
+ threat: null,
+ threatFilters: null,
+ timestampOverride: null,
+ to: 'now',
+ type: 'query',
+ references: [
+ 'https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html',
+ ],
+ note:
+ 'In the event this rule identifies benign domains in your environment, the `destination.domain` field in the rule can be modified to include those domains. Example: `...AND NOT destination.domain:(zoom.us OR benign.domain1 OR benign.domain2)`.',
+ version: 1,
+ exceptionsList: null,
+ threshold: {
+ field: null,
+ value: 5,
+ },
+ },
+ });
+
+ expect(migration713(alert, migrationContext)).toEqual({
+ ...alert,
+ attributes: {
+ ...alert.attributes,
+ params: {
+ author: ['Elastic'],
+ description:
+ "This rule detects a known command and control pattern in network events. The FIN7 threat group is known to use this command and control technique, while maintaining persistence in their target's network.",
+ ruleId: '4a4e23cf-78a2-449c-bac3-701924c269d3',
+ index: ['packetbeat-*'],
+ falsePositives: [
+ "This rule could identify benign domains that are formatted similarly to FIN7's command and control algorithm. Alerts should be investigated by an analyst to assess the validity of the individual observations.",
+ ],
+ from: 'now-6m',
+ immutable: true,
+ query:
+ 'event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-zA-Z]{4,5}.(pw|us|club|info|site|top)/ AND NOT destination.domain:zoom.us',
+ language: 'lucene',
+ license: 'Elastic License',
+ outputIndex: '.siem-signals-rylandherrick_2-default',
+ maxSignals: 100,
+ riskScore: 73,
+ riskScoreMapping: [],
+ severity: 'high',
+ severityMapping: [],
+ threat: [],
+ to: 'now',
+ type: 'query',
+ references: [
+ 'https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html',
+ ],
+ note:
+ 'In the event this rule identifies benign domains in your environment, the `destination.domain` field in the rule can be modified to include those domains. Example: `...AND NOT destination.domain:(zoom.us OR benign.domain1 OR benign.domain2)`.',
+ version: 1,
+ exceptionsList: [],
+ threshold: {
+ field: [],
+ value: 5,
+ cardinality: [],
+ },
+ },
+ },
+ });
+ });
+
+ test('non-null values in security solution alerts are not modified', () => {
+ const migration713 = getMigrations(encryptedSavedObjectsSetup)['7.13.0'];
+ const alert = getMockData({
+ alertTypeId: 'siem.signals',
+ params: {
+ author: ['Elastic'],
+ buildingBlockType: 'default',
+ description:
+ "This rule detects a known command and control pattern in network events. The FIN7 threat group is known to use this command and control technique, while maintaining persistence in their target's network.",
+ ruleId: '4a4e23cf-78a2-449c-bac3-701924c269d3',
+ index: ['packetbeat-*'],
+ falsePositives: [
+ "This rule could identify benign domains that are formatted similarly to FIN7's command and control algorithm. Alerts should be investigated by an analyst to assess the validity of the individual observations.",
+ ],
+ from: 'now-6m',
+ immutable: true,
+ query:
+ 'event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-zA-Z]{4,5}.(pw|us|club|info|site|top)/ AND NOT destination.domain:zoom.us',
+ language: 'lucene',
+ license: 'Elastic License',
+ outputIndex: '.siem-signals-rylandherrick_2-default',
+ savedId: 'saved-id',
+ timelineId: 'timeline-id',
+ timelineTitle: 'timeline-title',
+ meta: {
+ field: 'value',
+ },
+ filters: ['filters'],
+ maxSignals: 100,
+ riskScore: 73,
+ riskScoreMapping: ['risk-score-mapping'],
+ ruleNameOverride: 'field.name',
+ severity: 'high',
+ severityMapping: ['severity-mapping'],
+ threat: [
+ {
+ framework: 'MITRE ATT&CK',
+ tactic: {
+ id: 'TA0011',
+ name: 'Command and Control',
+ reference: 'https://attack.mitre.org/tactics/TA0011/',
+ },
+ technique: [
+ {
+ id: 'T1483',
+ name: 'Domain Generation Algorithms',
+ reference: 'https://attack.mitre.org/techniques/T1483/',
+ },
+ ],
+ },
+ ],
+ threatFilters: ['threat-filter'],
+ timestampOverride: 'event.ingested',
+ to: 'now',
+ type: 'query',
+ references: [
+ 'https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html',
+ ],
+ note:
+ 'In the event this rule identifies benign domains in your environment, the `destination.domain` field in the rule can be modified to include those domains. Example: `...AND NOT destination.domain:(zoom.us OR benign.domain1 OR benign.domain2)`.',
+ version: 1,
+ exceptionsList: ['exceptions-list'],
+ },
+ });
+
+ expect(migration713(alert, migrationContext)).toEqual(alert);
+ });
+
+ test('security solution threshold alert with string in threshold.field is migrated to array', () => {
+ const migration713 = getMigrations(encryptedSavedObjectsSetup)['7.13.0'];
+ const alert = getMockData({
+ alertTypeId: 'siem.signals',
+ params: {
+ threshold: {
+ field: 'host.id',
+ value: 5,
+ },
+ },
+ });
+
+ expect(migration713(alert, migrationContext)).toEqual({
+ ...alert,
+ attributes: {
+ ...alert.attributes,
+ params: {
+ threshold: {
+ field: ['host.id'],
+ value: 5,
+ cardinality: [],
+ },
+ exceptionsList: [],
+ riskScoreMapping: [],
+ severityMapping: [],
+ threat: [],
+ },
+ },
+ });
+ });
+
+ test('security solution threshold alert with empty string in threshold.field is migrated to empty array', () => {
+ const migration713 = getMigrations(encryptedSavedObjectsSetup)['7.13.0'];
+ const alert = getMockData({
+ alertTypeId: 'siem.signals',
+ params: {
+ threshold: {
+ field: '',
+ value: 5,
+ },
+ },
+ });
+
+ expect(migration713(alert, migrationContext)).toEqual({
+ ...alert,
+ attributes: {
+ ...alert.attributes,
+ params: {
+ threshold: {
+ field: [],
+ value: 5,
+ cardinality: [],
+ },
+ exceptionsList: [],
+ riskScoreMapping: [],
+ severityMapping: [],
+ threat: [],
+ },
+ },
+ });
+ });
+
+ test('security solution threshold alert with array in threshold.field and cardinality is left alone', () => {
+ const migration713 = getMigrations(encryptedSavedObjectsSetup)['7.13.0'];
+ const alert = getMockData({
+ alertTypeId: 'siem.signals',
+ params: {
+ threshold: {
+ field: ['host.id'],
+ value: 5,
+ cardinality: [
+ {
+ field: 'source.ip',
+ value: 10,
+ },
+ ],
+ },
+ },
+ });
+
+ expect(migration713(alert, migrationContext)).toEqual({
+ ...alert,
+ attributes: {
+ ...alert.attributes,
+ params: {
+ threshold: {
+ field: ['host.id'],
+ value: 5,
+ cardinality: [
+ {
+ field: 'source.ip',
+ value: 10,
+ },
+ ],
+ },
+ exceptionsList: [],
+ riskScoreMapping: [],
+ severityMapping: [],
+ threat: [],
+ },
+ },
+ });
+ });
+});
+
function getUpdatedAt(): string {
const updatedAt = new Date();
updatedAt.setHours(updatedAt.getHours() + 2);
diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
index a241198e106767..96f819b3aca05c 100644
--- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
@@ -12,6 +12,7 @@ import {
SavedObjectMigrationFn,
SavedObjectMigrationContext,
SavedObjectAttributes,
+ SavedObjectAttribute,
} from '../../../../../src/core/server';
import { RawAlert, RawAlertAction } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
@@ -35,6 +36,9 @@ export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc): boolean =>
+ doc.attributes.alertTypeId === 'siem.signals';
+
export function getMigrations(
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
): SavedObjectMigrationMap {
@@ -64,10 +68,16 @@ export function getMigrations(
pipeMigrations(restructureConnectorsThatSupportIncident)
);
+ const migrationSecurityRules713 = encryptedSavedObjects.createMigration(
+ (doc): doc is SavedObjectUnsanitizedDoc => isSecuritySolutionRule(doc),
+ pipeMigrations(removeNullsFromSecurityRules)
+ );
+
return {
'7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'),
'7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'),
'7.11.2': executeMigrationWithErrorHandling(migrationActions7112, '7.11.2'),
+ '7.13.0': executeMigrationWithErrorHandling(migrationSecurityRules713, '7.13.0'),
};
}
@@ -342,6 +352,68 @@ function restructureConnectorsThatSupportIncident(
};
}
+function convertNullToUndefined(attribute: SavedObjectAttribute) {
+ return attribute != null ? attribute : undefined;
+}
+
+function removeNullsFromSecurityRules(
+ doc: SavedObjectUnsanitizedDoc
+): SavedObjectUnsanitizedDoc {
+ const {
+ attributes: { params },
+ } = doc;
+ return {
+ ...doc,
+ attributes: {
+ ...doc.attributes,
+ params: {
+ ...params,
+ buildingBlockType: convertNullToUndefined(params.buildingBlockType),
+ note: convertNullToUndefined(params.note),
+ index: convertNullToUndefined(params.index),
+ language: convertNullToUndefined(params.language),
+ license: convertNullToUndefined(params.license),
+ outputIndex: convertNullToUndefined(params.outputIndex),
+ savedId: convertNullToUndefined(params.savedId),
+ timelineId: convertNullToUndefined(params.timelineId),
+ timelineTitle: convertNullToUndefined(params.timelineTitle),
+ meta: convertNullToUndefined(params.meta),
+ query: convertNullToUndefined(params.query),
+ filters: convertNullToUndefined(params.filters),
+ riskScoreMapping: params.riskScoreMapping != null ? params.riskScoreMapping : [],
+ ruleNameOverride: convertNullToUndefined(params.ruleNameOverride),
+ severityMapping: params.severityMapping != null ? params.severityMapping : [],
+ threat: params.threat != null ? params.threat : [],
+ threshold:
+ params.threshold != null &&
+ typeof params.threshold === 'object' &&
+ !Array.isArray(params.threshold)
+ ? {
+ field: Array.isArray(params.threshold.field)
+ ? params.threshold.field
+ : params.threshold.field === '' || params.threshold.field == null
+ ? []
+ : [params.threshold.field],
+ value: params.threshold.value,
+ cardinality:
+ params.threshold.cardinality != null ? params.threshold.cardinality : [],
+ }
+ : undefined,
+ timestampOverride: convertNullToUndefined(params.timestampOverride),
+ exceptionsList:
+ params.exceptionsList != null
+ ? params.exceptionsList
+ : params.exceptions_list != null
+ ? params.exceptions_list
+ : params.lists != null
+ ? params.lists
+ : [],
+ threatFilters: convertNullToUndefined(params.threatFilters),
+ },
+ },
+ };
+}
+
function pipeMigrations(...migrations: AlertMigration[]): AlertMigration {
return (doc: SavedObjectUnsanitizedDoc) =>
migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc);
diff --git a/x-pack/plugins/apm/common/i18n.ts b/x-pack/plugins/apm/common/i18n.ts
index c5bbef0db244e4..8bce2acdf4dca8 100644
--- a/x-pack/plugins/apm/common/i18n.ts
+++ b/x-pack/plugins/apm/common/i18n.ts
@@ -13,10 +13,3 @@ export const NOT_AVAILABLE_LABEL = i18n.translate(
defaultMessage: 'N/A',
}
);
-
-export const UNIDENTIFIED_SERVICE_NODES_LABEL = i18n.translate(
- 'xpack.apm.serviceNodeNameMissing',
- {
- defaultMessage: '(Empty)',
- }
-);
diff --git a/x-pack/plugins/apm/common/service_nodes.ts b/x-pack/plugins/apm/common/service_nodes.ts
index d744330f17b66f..ad75bd025069d4 100644
--- a/x-pack/plugins/apm/common/service_nodes.ts
+++ b/x-pack/plugins/apm/common/service_nodes.ts
@@ -5,4 +5,19 @@
* 2.0.
*/
+import { i18n } from '@kbn/i18n';
+
export const SERVICE_NODE_NAME_MISSING = '_service_node_name_missing_';
+
+const UNIDENTIFIED_SERVICE_NODES_LABEL = i18n.translate(
+ 'xpack.apm.serviceNodeNameMissing',
+ {
+ defaultMessage: '(Empty)',
+ }
+);
+
+export function getServiceNodeName(serviceNodeName?: string) {
+ return serviceNodeName === SERVICE_NODE_NAME_MISSING || !serviceNodeName
+ ? UNIDENTIFIED_SERVICE_NODES_LABEL
+ : serviceNodeName;
+}
diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
index a7cbd7a79b4a7f..0ed9c5c919ddb1 100644
--- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
@@ -9,8 +9,7 @@ import { i18n } from '@kbn/i18n';
import React from 'react';
import { Redirect, RouteComponentProps } from 'react-router-dom';
import { ApmServiceContextProvider } from '../../../../context/apm_service/apm_service_context';
-import { UNIDENTIFIED_SERVICE_NODES_LABEL } from '../../../../../common/i18n';
-import { SERVICE_NODE_NAME_MISSING } from '../../../../../common/service_nodes';
+import { getServiceNodeName } from '../../../../../common/service_nodes';
import { APMRouteDefinition } from '../../../../application/routes';
import { toQuery } from '../../../shared/Links/url_helpers';
import { ErrorGroupDetails } from '../../ErrorGroupDetails';
@@ -294,15 +293,7 @@ export const routes: APMRouteDefinition[] = [
exact: true,
path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
component: withApmServiceContext(ServiceNodeMetrics),
- breadcrumb: ({ match }) => {
- const { serviceNodeName } = match.params;
-
- if (serviceNodeName === SERVICE_NODE_NAME_MISSING) {
- return UNIDENTIFIED_SERVICE_NODES_LABEL;
- }
-
- return serviceNodeName || '';
- },
+ breadcrumb: ({ match }) => getServiceNodeName(match.params.serviceNodeName),
},
{
exact: true,
diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap b/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap
index 22a12db680334d..f521695177e05f 100644
--- a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap
+++ b/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap
@@ -1745,7 +1745,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
aria-controls="generated-id"
aria-current={true}
aria-label="Page 1 of 1"
- className="euiButtonEmpty euiButtonEmpty--text euiButtonEmpty--xSmall euiButtonEmpty-isDisabled euiPaginationButton euiPaginationButton-isActive euiPaginationButton--hideOnMobile"
+ className="euiButtonEmpty euiButtonEmpty--text euiButtonEmpty--small euiButtonEmpty-isDisabled euiPaginationButton euiPaginationButton-isActive euiPaginationButton--hideOnMobile"
data-test-subj="pagination-button-0"
disabled={true}
onClick={[Function]}
diff --git a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
index fc218f3ba6df30..3d284de621ea38 100644
--- a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
@@ -8,8 +8,10 @@ import { EuiFlexGroup, EuiPage, EuiPanel, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
-import { UNIDENTIFIED_SERVICE_NODES_LABEL } from '../../../../common/i18n';
-import { SERVICE_NODE_NAME_MISSING } from '../../../../common/service_nodes';
+import {
+ getServiceNodeName,
+ SERVICE_NODE_NAME_MISSING,
+} from '../../../../common/service_nodes';
import {
asDynamicBytes,
asInteger,
@@ -83,7 +85,7 @@ function ServiceNodeOverview({ serviceName }: ServiceNodeOverviewProps) {
const { displayedName, tooltip } =
name === SERVICE_NODE_NAME_MISSING
? {
- displayedName: UNIDENTIFIED_SERVICE_NODES_LABEL,
+ displayedName: getServiceNodeName(name),
tooltip: i18n.translate(
'xpack.apm.jvmsTable.explainServiceNodeNameMissing',
{
diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx
index 13322b094c65ee..55eb2e3ddab732 100644
--- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx
@@ -13,19 +13,13 @@ import { useApmServiceContext } from '../../../context/apm_service/use_apm_servi
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
import { APIReturnType } from '../../../services/rest/createCallApmApi';
+import { InstancesLatencyDistributionChart } from '../../shared/charts/instances_latency_distribution_chart';
import { getTimeRangeComparison } from '../../shared/time_comparison/get_time_range_comparison';
import {
ServiceOverviewInstancesTable,
TableOptions,
} from './service_overview_instances_table';
-// We're hiding this chart until these issues are resolved in the 7.13 timeframe:
-//
-// * [[APM] Tooltips for instances latency distribution chart](https://github.com/elastic/kibana/issues/88852)
-// * [[APM] x-axis on the instance bubble chart is broken](https://github.com/elastic/kibana/issues/92631)
-//
-// import { InstancesLatencyDistributionChart } from '../../shared/charts/instances_latency_distribution_chart';
-
interface ServiceOverviewInstancesChartAndTableProps {
chartHeight: number;
serviceName: string;
@@ -215,13 +209,13 @@ export function ServiceOverviewInstancesChartAndTable({
return (
<>
- {/*
+
- */}
+
{
+ const datum = (value.datum as unknown) as PrimaryStatsServiceInstanceItem;
+ return datum.latency ?? 0;
+ })
+ );
+ return getDurationFormatter(maxLatency);
+}
+
+export default {
+ title: 'shared/charts/InstancesLatencyDistributionChart/CustomTooltip',
+ component: CustomTooltip,
+ decorators: [
+ (Story: ComponentType) => (
+
+
+
+ ),
+ ],
+};
+
+export function Example(props: TooltipInfo) {
+ return (
+
+ );
+}
+Example.args = {
+ header: {
+ seriesIdentifier: {
+ key:
+ 'groupId{__global__}spec{Instances}yAccessor{(index:0)}splitAccessors{}',
+ specId: 'Instances',
+ yAccessor: '(index:0)',
+ splitAccessors: {},
+ seriesKeys: ['(index:0)'],
+ },
+ valueAccessor: 'y1',
+ label: 'Instances',
+ value: 9.473837632998105,
+ formattedValue: '9.473837632998105',
+ markValue: null,
+ color: '#6092c0',
+ isHighlighted: false,
+ isVisible: true,
+ datum: {
+ serviceNodeName:
+ '2f3221afa3f00d3bc07069d69efd5bd4c1607be6155a204551c8fe2e2b5dd750',
+ errorRate: 0.03496503496503497,
+ latency: 1057231.4125874126,
+ throughput: 9.473837632998105,
+ cpuUsage: 0.000033333333333333335,
+ memoryUsage: 0.18701022939403547,
+ },
+ },
+ values: [
+ {
+ seriesIdentifier: {
+ key:
+ 'groupId{__global__}spec{Instances}yAccessor{(index:0)}splitAccessors{}',
+ specId: 'Instances',
+ },
+ valueAccessor: 'y1',
+ label: 'Instances',
+ value: 1057231.4125874126,
+ formattedValue: '1057231.4125874126',
+ markValue: null,
+ color: '#6092c0',
+ isHighlighted: true,
+ isVisible: true,
+ datum: {
+ serviceNodeName:
+ '2f3221afa3f00d3bc07069d69efd5bd4c1607be6155a204551c8fe2e2b5dd750',
+ errorRate: 0.03496503496503497,
+ latency: 1057231.4125874126,
+ throughput: 9.473837632998105,
+ cpuUsage: 0.000033333333333333335,
+ memoryUsage: 0.18701022939403547,
+ },
+ },
+ ],
+} as TooltipInfo;
+
+export function MultipleInstances(props: TooltipInfo) {
+ return (
+
+ );
+}
+MultipleInstances.args = {
+ header: {
+ seriesIdentifier: {
+ key:
+ 'groupId{__global__}spec{Instances}yAccessor{(index:0)}splitAccessors{}',
+ specId: 'Instances',
+ yAccessor: '(index:0)',
+ splitAccessors: {},
+ seriesKeys: ['(index:0)'],
+ },
+ valueAccessor: 'y1',
+ label: 'Instances',
+ value: 9.606338858634443,
+ formattedValue: '9.606338858634443',
+ markValue: null,
+ color: '#6092c0',
+ isHighlighted: false,
+ isVisible: true,
+ datum: {
+ serviceNodeName:
+ '3b50ad269c45be69088905c4b355cc75ab94aaac1b35432bb752050438f4216f',
+ errorRate: 0.006896551724137931,
+ latency: 56465.53793103448,
+ throughput: 9.606338858634443,
+ cpuUsage: 0.0001,
+ memoryUsage: 0.1872131360014741,
+ },
+ },
+ values: [
+ {
+ seriesIdentifier: {
+ key:
+ 'groupId{__global__}spec{Instances}yAccessor{(index:0)}splitAccessors{}',
+ specId: 'Instances',
+ },
+ valueAccessor: 'y1',
+ label: 'Instances',
+ value: 56465.53793103448,
+ formattedValue: '56465.53793103448',
+ markValue: null,
+ color: '#6092c0',
+ isHighlighted: true,
+ isVisible: true,
+ datum: {
+ serviceNodeName:
+ '3b50ad269c45be69088905c4b355cc75ab94aaac1b35432bb752050438f4216f',
+ errorRate: 0.006896551724137931,
+ latency: 56465.53793103448,
+ throughput: 9.606338858634443,
+ cpuUsage: 0.0001,
+ memoryUsage: 0.1872131360014741,
+ },
+ },
+ {
+ seriesIdentifier: {
+ key:
+ 'groupId{__global__}spec{Instances}yAccessor{(index:0)}splitAccessors{}',
+ specId: 'Instances',
+ },
+ valueAccessor: 'y1',
+ label: 'Instances',
+ value: 56465.53793103448,
+ formattedValue: '56465.53793103448',
+ markValue: null,
+ color: '#6092c0',
+ isHighlighted: true,
+ isVisible: true,
+ datum: {
+ serviceNodeName:
+ '3b50ad269c45be69088905c4b355cc75ab94aaac1b35432bb752050438f4216f (2)',
+ errorRate: 0.006896551724137931,
+ latency: 56465.53793103448,
+ throughput: 9.606338858634443,
+ cpuUsage: 0.0001,
+ memoryUsage: 0.1872131360014741,
+ },
+ },
+ ],
+} as TooltipInfo;
diff --git a/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/custom_tooltip.tsx b/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/custom_tooltip.tsx
new file mode 100644
index 00000000000000..2280fa91a659c0
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/custom_tooltip.tsx
@@ -0,0 +1,214 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { TooltipInfo } from '@elastic/charts';
+import { EuiIcon } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import { getServiceNodeName } from '../../../../../common/service_nodes';
+import {
+ asTransactionRate,
+ TimeFormatter,
+} from '../../../../../common/utils/formatters';
+import { useTheme } from '../../../../hooks/use_theme';
+import { PrimaryStatsServiceInstanceItem } from '../../../app/service_overview/service_overview_instances_chart_and_table';
+
+const latencyLabel = i18n.translate(
+ 'xpack.apm.instancesLatencyDistributionChartTooltipLatencyLabel',
+ {
+ defaultMessage: 'Latency',
+ }
+);
+
+const throughputLabel = i18n.translate(
+ 'xpack.apm.instancesLatencyDistributionChartTooltipThroughputLabel',
+ {
+ defaultMessage: 'Throughput',
+ }
+);
+
+const clickToFilterDescription = i18n.translate(
+ 'xpack.apm.instancesLatencyDistributionChartTooltipClickToFilterDescription',
+ { defaultMessage: 'Click to filter by instance' }
+);
+
+/**
+ * Tooltip for a single instance
+ */
+function SingleInstanceCustomTooltip({
+ latencyFormatter,
+ values,
+}: {
+ latencyFormatter: TimeFormatter;
+ values: TooltipInfo['values'];
+}) {
+ const value = values[0];
+ const { color } = value;
+ const datum = (value.datum as unknown) as PrimaryStatsServiceInstanceItem;
+ const { latency, serviceNodeName, throughput } = datum;
+
+ return (
+ <>
+
+ {getServiceNodeName(serviceNodeName)}
+
+
+
+
+
+ {latencyLabel}
+
+ {latencyFormatter(latency).formatted}
+
+
+
+
+
+
+ {throughputLabel}
+
+ {asTransactionRate(throughput)}
+
+
+
+
+ >
+ );
+}
+
+/**
+ * Tooltip for a multiple instances
+ */
+function MultipleInstanceCustomTooltip({
+ latencyFormatter,
+ values,
+}: TooltipInfo & { latencyFormatter: TimeFormatter }) {
+ const theme = useTheme();
+
+ return (
+ <>
+
+ {i18n.translate(
+ 'xpack.apm.instancesLatencyDistributionChartTooltipInstancesTitle',
+ {
+ defaultMessage:
+ '{instancesCount} {instancesCount, plural, one {instance} other {instances}}',
+ values: { instancesCount: values.length },
+ }
+ )}
+
+ {values.map((value) => {
+ const { color } = value;
+ const datum = (value.datum as unknown) as PrimaryStatsServiceInstanceItem;
+ const { latency, serviceNodeName, throughput } = datum;
+ return (
+
+
+
+
+
+ {getServiceNodeName(serviceNodeName)}
+
+
+
+
+
+
+ {latencyLabel}
+
+ {latencyFormatter(latency).formatted}
+
+
+
+
+
+
+ {throughputLabel}
+
+ {asTransactionRate(throughput)}
+
+
+
+
+ );
+ })}
+ >
+ );
+}
+
+/**
+ * Custom tooltip for instances latency distribution chart.
+ *
+ * The styling provided here recreates that in the Elastic Charts tooltip: https://github.com/elastic/elastic-charts/blob/58e6b5fbf77f4471d2a9a41c45a61f79ebd89b65/src/components/tooltip/tooltip.tsx
+ *
+ * We probably won't need to do all of this once https://github.com/elastic/elastic-charts/issues/615 is completed.
+ */
+export function CustomTooltip(
+ props: TooltipInfo & { latencyFormatter: TimeFormatter }
+) {
+ const { values } = props;
+ const theme = useTheme();
+
+ return (
+
+ {values.length > 1 ? (
+
+ ) : (
+
+ )}
+
+ {clickToFilterDescription}
+
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/index.tsx
index 5bcf0d161653ee..57ecbd4ca0b78b 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/instances_latency_distribution_chart/index.tsx
@@ -9,14 +9,21 @@ import {
Axis,
BubbleSeries,
Chart,
+ ElementClickListener,
+ GeometryValue,
Position,
ScaleType,
Settings,
+ TooltipInfo,
+ TooltipProps,
+ TooltipType,
} from '@elastic/charts';
import { EuiPanel, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
+import { useHistory } from 'react-router-dom';
import { useChartTheme } from '../../../../../../observability/public';
+import { SERVICE_NODE_NAME } from '../../../../../common/elasticsearch_fieldnames';
import {
asTransactionRate,
getDurationFormatter,
@@ -24,10 +31,12 @@ import {
import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
import { useTheme } from '../../../../hooks/use_theme';
import { PrimaryStatsServiceInstanceItem } from '../../../app/service_overview/service_overview_instances_chart_and_table';
+import * as urlHelpers from '../../Links/url_helpers';
import { ChartContainer } from '../chart_container';
import { getResponseTimeTickFormatter } from '../transaction_charts/helper';
+import { CustomTooltip } from './custom_tooltip';
-interface InstancesLatencyDistributionChartProps {
+export interface InstancesLatencyDistributionChartProps {
height: number;
items?: PrimaryStatsServiceInstanceItem[];
status: FETCH_STATUS;
@@ -38,6 +47,7 @@ export function InstancesLatencyDistributionChart({
items = [],
status,
}: InstancesLatencyDistributionChartProps) {
+ const history = useHistory();
const hasData = items.length > 0;
const theme = useTheme();
@@ -51,6 +61,43 @@ export function InstancesLatencyDistributionChart({
const maxLatency = Math.max(...items.map((item) => item.latency ?? 0));
const latencyFormatter = getDurationFormatter(maxLatency);
+ const tooltip: TooltipProps = {
+ type: TooltipType.Follow,
+ snap: false,
+ customTooltip: (props: TooltipInfo) => (
+
+ ),
+ };
+
+ /**
+ * Handle click events on the items.
+ *
+ * Due to how we handle filtering by using the kuery bar, it's difficult to
+ * modify existing queries. If you have an existing query in the bar, this will
+ * wipe it out. This is ok for now, since we probably will be replacing this
+ * interaction with something nicer in a future release.
+ *
+ * The event object has an array two items for each point, one of which has
+ * the serviceNodeName, so we flatten the list and get the items we need to
+ * form a query.
+ */
+ const handleElementClick: ElementClickListener = (event) => {
+ const serviceNodeNamesQuery = event
+ .flat()
+ .flatMap((value) => (value as GeometryValue).datum?.serviceNodeName)
+ .filter((serviceNodeName) => !!serviceNodeName)
+ .map((serviceNodeName) => `${SERVICE_NODE_NAME}:"${serviceNodeName}"`)
+ .join(' OR ');
+
+ urlHelpers.push(history, { query: { kuery: serviceNodeNamesQuery } });
+ };
+
+ // With a linear scale, if all the instances have similar throughput (or if
+ // there's just a single instance) they'll show along the origin. Make sure
+ // the x-axis domain is [0, maxThroughput].
+ const maxThroughput = Math.max(...items.map((item) => item.throughput ?? 0));
+ const xDomain = { min: 0, max: maxThroughput };
+
return (
@@ -64,9 +111,11 @@ export function InstancesLatencyDistributionChart({
(
+
+
+
+ ),
+ ],
+};
+
+export function Example({ items }: InstancesLatencyDistributionChartProps) {
+ return (
+
+ );
+}
+Example.args = {
+ items: [
+ {
+ serviceNodeName:
+ '3f67bfc39c7891dc0c5657befb17bf58c19cf10f99472cf8df263c8e5bb1c766',
+ latency: 15802930.92133213,
+ throughput: 0.4019360641691481,
+ },
+ {
+ serviceNodeName:
+ 'd52c64bea9327f3e960ac1cb63c1b7ea922e3cb3d76ab9b254e57a7cb2f760a0',
+ latency: 8296442.578550679,
+ throughput: 0.3932978392703585,
+ },
+ {
+ serviceNodeName:
+ '797e0a906ad342223468ca51b663e1af8bdeb40bab376c46c7f7fa2021349290',
+ latency: 34842576.51204916,
+ throughput: 0.3353931699532713,
+ },
+ {
+ serviceNodeName:
+ '21e1c648bd73434a8a1bf6e849817930e8b43eacf73a5c39c30520ee3b79d8c0',
+ latency: 40713854.354498595,
+ throughput: 0.32947224189485164,
+ },
+ {
+ serviceNodeName:
+ 'a1c99c8675372af4c74bb01cc48e75989faa6f010a4ccb027df1c410dde0c72c',
+ latency: 18565471.348388012,
+ throughput: 0.3261219384041683,
+ },
+ {
+ serviceNodeName: '_service_node_name_missing_',
+ latency: 20065471.348388012,
+ throughput: 0.3261219384041683,
+ },
+ ],
+} as InstancesLatencyDistributionChartProps;
+
+export function SimilarThroughputInstances({
+ items,
+}: InstancesLatencyDistributionChartProps) {
+ return (
+
+ );
+}
+SimilarThroughputInstances.args = {
+ items: [
+ {
+ serviceNodeName:
+ '21e1c648bd73434a8a1bf6e849817930e8b43eacf73a5c39c30520ee3b79d8c0',
+ latency: 40713854.354498595,
+ throughput: 0.3261219384041683,
+ },
+ {
+ serviceNodeName:
+ 'a1c99c8675372af4c74bb01cc48e75989faa6f010a4ccb027df1c410dde0c72c',
+ latency: 18565471.348388012,
+ throughput: 0.3261219384041683,
+ },
+ {
+ serviceNodeName: '_service_node_name_missing_',
+ latency: 20065471.348388012,
+ throughput: 0.3261219384041683,
+ },
+ ],
+} as InstancesLatencyDistributionChartProps;
diff --git a/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/__snapshots__/custom_element_modal.stories.storyshot b/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/__snapshots__/custom_element_modal.stories.storyshot
index 9b5540b95e844d..f59abc4fec6f96 100644
--- a/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/__snapshots__/custom_element_modal.stories.storyshot
+++ b/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/__snapshots__/custom_element_modal.stories.storyshot
@@ -212,8 +212,7 @@ exports[`Storyshots components/Elements/CustomElementModal with description 1`]
className="euiSpacer euiSpacer--s"
/>
(
.catch((err: Error) => {
services.notify.error(err, {
title: strings.getExportPDFErrorTitle(workpad.name),
+ 'data-test-subj': 'queueReportError',
});
});
case 'json':
diff --git a/x-pack/plugins/canvas/public/components/workpad_templates/examples/__snapshots__/workpad_templates.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_templates/examples/__snapshots__/workpad_templates.stories.storyshot
index f3913b83966b49..2a65ea4fd0f5f6 100644
--- a/x-pack/plugins/canvas/public/components/workpad_templates/examples/__snapshots__/workpad_templates.stories.storyshot
+++ b/x-pack/plugins/canvas/public/components/workpad_templates/examples/__snapshots__/workpad_templates.stories.storyshot
@@ -527,7 +527,7 @@ exports[`Storyshots components/WorkpadTemplates default 1`] = `
{
describe('renders', () => {
const docLinks: DocLinksStart = {
- ELASTIC_WEBSITE_URL: 'boo/',
- DOC_LINK_VERSION: '#foo',
- links: {} as any,
+ ELASTIC_WEBSITE_URL: `boo/`,
+ DOC_LINK_VERSION: `#foo`,
+ links: {
+ elasticsearch: { asyncSearch: `mock-url` } as any,
+ } as any,
};
let main: ReactWrapper;
@@ -93,9 +95,7 @@ describe('Background Search Session Management Main', () => {
test('documentation link', () => {
const docLink = main.find('a[href]').first();
expect(docLink.text()).toBe('Documentation');
- expect(docLink.prop('href')).toBe(
- 'boo/guide/en/elasticsearch/reference/#foo/async-search-intro.html'
- );
+ expect(docLink.prop('href')).toBe('mock-url');
});
test('table is present', () => {
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/documentation.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/documentation.ts
index 19d37891446cff..38db89e88a6e1f 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/documentation.ts
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/documentation.ts
@@ -8,16 +8,15 @@
import { DocLinksStart } from 'kibana/public';
export class AsyncSearchIntroDocumentation {
- private docsBasePath: string = '';
+ private docUrl: string = '';
constructor(docs: DocLinksStart) {
- const { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } = docs;
- const docsBase = `${ELASTIC_WEBSITE_URL}guide/en`;
+ const { links } = docs;
// TODO: There should be Kibana documentation link about Search Sessions in Kibana
- this.docsBasePath = `${docsBase}/elasticsearch/reference/${DOC_LINK_VERSION}`;
+ this.docUrl = links.elasticsearch.asyncSearch;
}
public getElasticsearchDocLink() {
- return `${this.docsBasePath}/async-search-intro.html`;
+ return `${this.docUrl}`;
}
}
diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
index c96d821641dd61..a16557b50700ea 100644
--- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
@@ -60,7 +60,6 @@ test("shouldn't show indicator in case no active search session", async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService,
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -89,7 +88,6 @@ test("shouldn't show indicator in case app hasn't opt-in", async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService,
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -120,7 +118,6 @@ test('should show indicator in case there is an active search session', async ()
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -146,7 +143,6 @@ test('should be disabled in case uiConfig says so ', async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -171,7 +167,6 @@ test('should be disabled in case not enough permissions', async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$, hasAccess: () => false },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
basePath,
@@ -191,38 +186,6 @@ test('should be disabled in case not enough permissions', async () => {
expect(screen.getByRole('button', { name: 'Manage sessions' })).toBeDisabled();
});
-test('should be disabled during auto-refresh', async () => {
- const state$ = new BehaviorSubject(SearchSessionState.Loading);
-
- const SearchSessionIndicator = createConnectedSearchSessionIndicator({
- sessionService: { ...sessionService, state$ },
- application,
- timeFilter,
- storage,
- disableSaveAfterSessionCompletesTimeout,
- usageCollector,
- basePath,
- });
-
- render(
-
-
-
- );
-
- await waitFor(() => screen.getByTestId('searchSessionIndicator'));
-
- await userEvent.click(screen.getByLabelText('Search session loading'));
-
- expect(screen.getByRole('button', { name: 'Save session' })).not.toBeDisabled();
-
- act(() => {
- refreshInterval$.next({ value: 0, pause: false });
- });
-
- expect(screen.getByRole('button', { name: 'Save session' })).toBeDisabled();
-});
-
describe('Completed inactivity', () => {
beforeEach(() => {
jest.useFakeTimers();
@@ -236,7 +199,6 @@ describe('Completed inactivity', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -298,7 +260,6 @@ describe('tour steps', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -340,7 +301,6 @@ describe('tour steps', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -376,7 +336,6 @@ describe('tour steps', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
@@ -404,7 +363,6 @@ describe('tour steps', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
index 630aea417c84e1..603df09e1c4c65 100644
--- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
@@ -6,7 +6,7 @@
*/
import React, { useCallback, useEffect, useState } from 'react';
-import { debounce, distinctUntilChanged, map, mapTo, switchMap, tap } from 'rxjs/operators';
+import { debounce, distinctUntilChanged, mapTo, switchMap, tap } from 'rxjs/operators';
import { merge, of, timer } from 'rxjs';
import useObservable from 'react-use/lib/useObservable';
import { i18n } from '@kbn/i18n';
@@ -14,7 +14,6 @@ import { SearchSessionIndicator, SearchSessionIndicatorRef } from '../search_ses
import {
ISessionService,
SearchSessionState,
- TimefilterContract,
SearchUsageCollector,
} from '../../../../../../../src/plugins/data/public';
import { RedirectAppLinks } from '../../../../../../../src/plugins/kibana_react/public';
@@ -24,7 +23,6 @@ import { useSearchSessionTour } from './search_session_tour';
export interface SearchSessionIndicatorDeps {
sessionService: ISessionService;
- timeFilter: TimefilterContract;
application: ApplicationStart;
basePath: IBasePath;
storage: IStorageWrapper;
@@ -39,17 +37,12 @@ export interface SearchSessionIndicatorDeps {
export const createConnectedSearchSessionIndicator = ({
sessionService,
application,
- timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
usageCollector,
basePath,
}: SearchSessionIndicatorDeps): React.FC => {
const searchSessionsManagementUrl = basePath.prepend('/app/management/kibana/search_sessions');
- const isAutoRefreshEnabled = () => !timeFilter.getRefreshInterval().pause;
- const isAutoRefreshEnabled$ = timeFilter
- .getRefreshIntervalUpdate$()
- .pipe(map(isAutoRefreshEnabled), distinctUntilChanged());
const debouncedSessionServiceState$ = sessionService.state$.pipe(
debounce((_state) => timer(_state === SearchSessionState.None ? 50 : 300)) // switch to None faster to quickly remove indicator when navigating away
@@ -69,7 +62,6 @@ export const createConnectedSearchSessionIndicator = ({
return () => {
const state = useObservable(debouncedSessionServiceState$, SearchSessionState.None);
- const autoRefreshEnabled = useObservable(isAutoRefreshEnabled$, isAutoRefreshEnabled());
const isSaveDisabledByApp = sessionService.getSearchSessionIndicatorUiConfig().isDisabled();
const disableSaveAfterSessionCompleteTimedOut = useObservable(
disableSaveAfterSessionCompleteTimedOut$,
@@ -91,16 +83,6 @@ export const createConnectedSearchSessionIndicator = ({
let managementDisabled = false;
let managementDisabledReasonText: string = '';
- if (autoRefreshEnabled) {
- saveDisabled = true;
- saveDisabledReasonText = i18n.translate(
- 'xpack.data.searchSessionIndicator.disabledDueToAutoRefreshMessage',
- {
- defaultMessage: 'Saving search session is not available when auto refresh is enabled.',
- }
- );
- }
-
if (disableSaveAfterSessionCompleteTimedOut) {
saveDisabled = true;
saveDisabledReasonText = i18n.translate(
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts
index 485ac19f2eb820..d16391089120a2 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts
@@ -6,6 +6,7 @@
*/
import { EngineDetails } from '../components/engine/types';
+import { ENGINES_TITLE } from '../components/engines';
import { generateEncodedPath } from '../utils/encode_path_params';
export const mockEngineValues = {
@@ -20,6 +21,11 @@ export const mockEngineActions = {
export const mockGenerateEnginePath = jest.fn((path, pathParams = {}) =>
generateEncodedPath(path, { engineName: mockEngineValues.engineName, ...pathParams })
);
+export const mockGetEngineBreadcrumbs = jest.fn((breadcrumbs = []) => [
+ ENGINES_TITLE,
+ mockEngineValues.engineName,
+ ...breadcrumbs,
+]);
jest.mock('../components/engine', () => ({
EngineLogic: {
@@ -27,4 +33,5 @@ jest.mock('../components/engine', () => ({
actions: mockEngineActions,
},
generateEnginePath: mockGenerateEnginePath,
+ getEngineBreadcrumbs: mockGetEngineBreadcrumbs,
}));
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx
index 3940151d3b7cdf..68f08d8d847245 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx
@@ -18,7 +18,7 @@ import { AnalyticsRouter } from './';
describe('AnalyticsRouter', () => {
// Detailed route testing is better done via E2E tests
it('renders', () => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find(Switch)).toHaveLength(1);
expect(wrapper.find(Route)).toHaveLength(9);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx
index 7bd4664cdbfa3a..397f1f1e1e1c38 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx
@@ -10,7 +10,6 @@ import { Route, Switch, Redirect } from 'react-router-dom';
import { APP_SEARCH_PLUGIN } from '../../../../../common/constants';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
-import { BreadcrumbTrail } from '../../../shared/kibana_chrome/generate_breadcrumbs';
import { NotFound } from '../../../shared/not_found';
import {
ENGINE_ANALYTICS_PATH,
@@ -22,7 +21,7 @@ import {
ENGINE_ANALYTICS_QUERY_DETAILS_PATH,
ENGINE_ANALYTICS_QUERY_DETAIL_PATH,
} from '../../routes';
-import { generateEnginePath } from '../engine';
+import { generateEnginePath, getEngineBreadcrumbs } from '../engine';
import {
ANALYTICS_TITLE,
@@ -42,11 +41,8 @@ import {
QueryDetail,
} from './views';
-interface Props {
- engineBreadcrumb: BreadcrumbTrail;
-}
-export const AnalyticsRouter: React.FC = ({ engineBreadcrumb }) => {
- const ANALYTICS_BREADCRUMB = [...engineBreadcrumb, ANALYTICS_TITLE];
+export const AnalyticsRouter: React.FC = () => {
+ const ANALYTICS_BREADCRUMB = getEngineBreadcrumbs([ANALYTICS_TITLE]);
return (
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.test.tsx
index 1945dde84ec450..cb29d92030ad7f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.test.tsx
@@ -7,10 +7,11 @@
import { setMockValues, setMockActions, rerender } from '../../../__mocks__';
import '../../../__mocks__/shallow_useeffect.mock';
+import '../../__mocks__/engine_logic.mock';
import React from 'react';
-import { shallow, ShallowWrapper } from 'enzyme';
+import { shallow } from 'enzyme';
import { EuiPageHeader } from '@elastic/eui';
@@ -32,16 +33,14 @@ describe('ApiLogs', () => {
pollForApiLogs: jest.fn(),
};
- let wrapper: ShallowWrapper;
-
beforeEach(() => {
jest.clearAllMocks();
setMockValues(values);
setMockActions(actions);
- wrapper = shallow( );
});
it('renders', () => {
+ const wrapper = shallow( );
expect(wrapper.find(EuiPageHeader).prop('pageTitle')).toEqual('API Logs');
expect(wrapper.find(ApiLogsTable)).toHaveLength(1);
expect(wrapper.find(NewApiEventsPrompt)).toHaveLength(1);
@@ -52,13 +51,14 @@ describe('ApiLogs', () => {
it('renders a loading screen', () => {
setMockValues({ ...values, dataLoading: true, apiLogs: [] });
- rerender(wrapper);
+ const wrapper = shallow( );
expect(wrapper.find(Loading)).toHaveLength(1);
});
describe('effects', () => {
it('calls a manual fetchApiLogs on page load and pagination', () => {
+ const wrapper = shallow( );
expect(actions.fetchApiLogs).toHaveBeenCalledTimes(1);
setMockValues({ ...values, meta: { page: { current: 2 } } });
@@ -68,6 +68,7 @@ describe('ApiLogs', () => {
});
it('starts pollForApiLogs on page load', () => {
+ shallow( );
expect(actions.pollForApiLogs).toHaveBeenCalledTimes(1);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.tsx
index 4690911fad7724..b8179163c93f94 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs.tsx
@@ -21,9 +21,9 @@ import {
import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
-import { BreadcrumbTrail } from '../../../shared/kibana_chrome/generate_breadcrumbs';
import { Loading } from '../../../shared/loading';
+import { getEngineBreadcrumbs } from '../engine';
import { LogRetentionCallout, LogRetentionTooltip, LogRetentionOptions } from '../log_retention';
import { ApiLogFlyout } from './api_log';
@@ -32,10 +32,7 @@ import { API_LOGS_TITLE, RECENT_API_EVENTS } from './constants';
import { ApiLogsLogic } from './';
-interface Props {
- engineBreadcrumb: BreadcrumbTrail;
-}
-export const ApiLogs: React.FC = ({ engineBreadcrumb }) => {
+export const ApiLogs: React.FC = () => {
const { dataLoading, apiLogs, meta } = useValues(ApiLogsLogic);
const { fetchApiLogs, pollForApiLogs } = useActions(ApiLogsLogic);
@@ -51,7 +48,7 @@ export const ApiLogs: React.FC = ({ engineBreadcrumb }) => {
return (
<>
-
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx
index 09340d37fcf7b2..274bda56a2fc12 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx
@@ -87,7 +87,7 @@ describe('CredentialsList', () => {
});
describe('empty state', () => {
- it('renders an EuiEmptyState when no credentials are available', () => {
+ it('renders an EuiEmptyPrompt when no credentials are available', () => {
setMockValues({
...values,
apiTokens: [],
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx
index f0eafb13bb9b05..9598212d3e0c98 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx
@@ -5,6 +5,8 @@
* 2.0.
*/
+import '../../__mocks__/engine_logic.mock';
+
import React from 'react';
import { Route, Switch } from 'react-router-dom';
@@ -14,7 +16,7 @@ import { CurationsRouter } from './';
describe('CurationsRouter', () => {
it('renders', () => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find(Switch)).toHaveLength(1);
expect(wrapper.find(Route)).toHaveLength(4);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx
index e080f7de133906..28ce311b438875 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx
@@ -10,23 +10,20 @@ import { Route, Switch } from 'react-router-dom';
import { APP_SEARCH_PLUGIN } from '../../../../../common/constants';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
-import { BreadcrumbTrail } from '../../../shared/kibana_chrome/generate_breadcrumbs';
import { NotFound } from '../../../shared/not_found';
import {
ENGINE_CURATIONS_PATH,
ENGINE_CURATIONS_NEW_PATH,
ENGINE_CURATION_PATH,
} from '../../routes';
+import { getEngineBreadcrumbs } from '../engine';
import { CURATIONS_TITLE, CREATE_NEW_CURATION_TITLE } from './constants';
import { Curation } from './curation';
import { Curations, CurationCreation } from './views';
-interface Props {
- engineBreadcrumb: BreadcrumbTrail;
-}
-export const CurationsRouter: React.FC = ({ engineBreadcrumb }) => {
- const CURATIONS_BREADCRUMB = [...engineBreadcrumb, CURATIONS_TITLE];
+export const CurationsRouter: React.FC = () => {
+ const CURATIONS_BREADCRUMB = getEngineBreadcrumbs([CURATIONS_TITLE]);
return (
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx
index a33161918c7f5f..c4563b43571345 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx
@@ -5,9 +5,10 @@
* 2.0.
*/
-import '../../../__mocks__/react_router_history.mock';
import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock';
import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock';
+import '../../../__mocks__/react_router_history.mock';
+import '../../__mocks__/engine_logic.mock';
import React from 'react';
import { useParams } from 'react-router-dom';
@@ -44,17 +45,17 @@ describe('DocumentDetail', () => {
});
it('renders', () => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find(EuiPageContent).length).toBe(1);
});
it('initializes data on mount', () => {
- shallow( );
+ shallow( );
expect(actions.getDocumentDetails).toHaveBeenCalledWith('1');
});
it('calls setFields on unmount', () => {
- shallow( );
+ shallow( );
unmountHandler();
expect(actions.setFields).toHaveBeenCalledWith([]);
});
@@ -65,7 +66,7 @@ describe('DocumentDetail', () => {
dataLoading: true,
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find(Loading).length).toBe(1);
});
@@ -80,7 +81,7 @@ describe('DocumentDetail', () => {
};
beforeEach(() => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
columns = wrapper.find(EuiBasicTable).props().columns;
});
@@ -101,7 +102,7 @@ describe('DocumentDetail', () => {
});
it('will delete the document when the delete button is pressed', () => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
const header = wrapper.find(EuiPageHeader).dive().children().dive();
const button = header.find('[data-test-subj="DeleteDocumentButton"]');
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx
index fefe983df33420..314c3529cf4db7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx
@@ -25,6 +25,7 @@ import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { Loading } from '../../../shared/loading';
import { useDecodedParams } from '../../utils/encode_path_params';
+import { getEngineBreadcrumbs } from '../engine';
import { ResultFieldValue } from '../result';
import { DOCUMENTS_TITLE } from './constants';
@@ -36,11 +37,8 @@ const DOCUMENT_DETAIL_TITLE = (documentId: string) =>
defaultMessage: 'Document: {documentId}',
values: { documentId },
});
-interface Props {
- engineBreadcrumb: string[];
-}
-export const DocumentDetail: React.FC = ({ engineBreadcrumb }) => {
+export const DocumentDetail: React.FC = () => {
const { dataLoading, fields } = useValues(DocumentDetailLogic);
const { deleteDocument, getDocumentDetails, setFields } = useActions(DocumentDetailLogic);
@@ -77,7 +75,7 @@ export const DocumentDetail: React.FC = ({ engineBreadcrumb }) => {
return (
<>
-
+
{
});
it('renders', () => {
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find(SearchExperience).exists()).toBe(true);
});
@@ -44,7 +45,7 @@ describe('Documents', () => {
myRole: { canManageEngineDocuments: true },
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(true);
});
@@ -54,7 +55,7 @@ describe('Documents', () => {
myRole: { canManageEngineDocuments: false },
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(false);
});
@@ -65,7 +66,7 @@ describe('Documents', () => {
isMetaEngine: true,
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(false);
});
});
@@ -77,7 +78,7 @@ describe('Documents', () => {
isMetaEngine: true,
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find('[data-test-subj="MetaEnginesCallout"]').exists()).toBe(true);
});
@@ -87,7 +88,7 @@ describe('Documents', () => {
isMetaEngine: false,
});
- const wrapper = shallow( );
+ const wrapper = shallow( );
expect(wrapper.find('[data-test-subj="MetaEnginesCallout"]').exists()).toBe(false);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx
index 84fcab53e96041..58aa6acc59783a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx
@@ -16,23 +16,19 @@ import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { AppLogic } from '../../app_logic';
-import { EngineLogic } from '../engine';
+import { EngineLogic, getEngineBreadcrumbs } from '../engine';
import { DOCUMENTS_TITLE } from './constants';
import { DocumentCreationButton } from './document_creation_button';
import { SearchExperience } from './search_experience';
-interface Props {
- engineBreadcrumb: string[];
-}
-
-export const Documents: React.FC = ({ engineBreadcrumb }) => {
+export const Documents: React.FC = () => {
const { isMetaEngine } = useValues(EngineLogic);
const { myRole } = useValues(AppLogic);
return (
<>
-
+
{
const {
@@ -85,43 +84,41 @@ export const EngineRouter: React.FC = () => {
const isLoadingNewEngine = engineName !== engineNameFromUrl;
if (isLoadingNewEngine || dataLoading) return ;
- const engineBreadcrumb = [ENGINES_TITLE, engineName];
-
return (
{canViewEngineAnalytics && (
-
+
)}
-
+
-
+
{canManageEngineCurations && (
-
+
)}
{canManageEngineRelevanceTuning && (
-
+
)}
{canManageEngineResultSettings && (
-
+
)}
{canViewEngineApiLogs && (
-
+
)}
-
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts
index 80c36822ccde0f..2a5b3351f41f70 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts
@@ -8,4 +8,4 @@
export { EngineRouter } from './engine_router';
export { EngineNav } from './engine_nav';
export { EngineLogic } from './engine_logic';
-export { generateEnginePath } from './utils';
+export { generateEnginePath, getEngineBreadcrumbs } from './utils';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.test.ts
index 867ed14fcc0527..be6b9a53bd0d5a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.test.ts
@@ -7,10 +7,12 @@
import { mockEngineValues } from '../../__mocks__';
-import { generateEnginePath } from './utils';
+import { generateEnginePath, getEngineBreadcrumbs } from './utils';
describe('generateEnginePath', () => {
- mockEngineValues.engineName = 'hello-world';
+ beforeEach(() => {
+ mockEngineValues.engineName = 'hello-world';
+ });
it('generates paths with engineName filled from state', () => {
expect(generateEnginePath('/engines/:engineName/example')).toEqual(
@@ -27,3 +29,15 @@ describe('generateEnginePath', () => {
).toEqual('/engines/override/foo/baz');
});
});
+
+describe('getEngineBreadcrumbs', () => {
+ beforeEach(() => {
+ mockEngineValues.engineName = 'foo';
+ });
+
+ it('generates breadcrumbs with engineName filled from state', () => {
+ expect(getEngineBreadcrumbs(['bar', 'baz'])).toEqual(['Engines', 'foo', 'bar', 'baz']);
+ expect(getEngineBreadcrumbs(['bar'])).toEqual(['Engines', 'foo', 'bar']);
+ expect(getEngineBreadcrumbs()).toEqual(['Engines', 'foo']);
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts
index 7b8521105875c6..820d89e4739222 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts
@@ -5,8 +5,11 @@
* 2.0.
*/
+import { BreadcrumbTrail } from '../../../shared/kibana_chrome/generate_breadcrumbs';
import { generateEncodedPath } from '../../utils/encode_path_params';
+import { ENGINES_TITLE } from '../engines';
+
import { EngineLogic } from './';
/**
@@ -16,3 +19,11 @@ export const generateEnginePath = (path: string, pathParams: object = {}) => {
const { engineName } = EngineLogic.values;
return generateEncodedPath(path, { engineName, ...pathParams });
};
+
+/**
+ * Generate a breadcrumb trail with engineName automatically filled from EngineLogic state
+ */
+export const getEngineBreadcrumbs = (breadcrumbs: BreadcrumbTrail = []) => {
+ const { engineName } = EngineLogic.values;
+ return [ENGINES_TITLE, engineName, ...breadcrumbs];
+};
diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/shared/is_object_with_keys.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/__mocks__/engines_logic.mock.ts
similarity index 64%
rename from x-pack/plugins/ingest_pipelines/server/routes/api/shared/is_object_with_keys.ts
rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/__mocks__/engines_logic.mock.ts
index f25b07e1913297..4ab9137436ffe2 100644
--- a/x-pack/plugins/ingest_pipelines/server/routes/api/shared/is_object_with_keys.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/__mocks__/engines_logic.mock.ts
@@ -5,6 +5,6 @@
* 2.0.
*/
-export const isObjectWithKeys = (value: unknown) => {
- return typeof value === 'object' && !!value && Object.keys(value).length > 0;
-};
+jest.mock('../../../../engines', () => ({
+ EnginesLogic: { actions: { deleteEngine: jest.fn() } },
+}));
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.test.tsx
new file mode 100644
index 00000000000000..5d91c724068e75
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.test.tsx
@@ -0,0 +1,47 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { mockKibanaValues, mockTelemetryActions } from '../../../../../__mocks__';
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiLinkTo } from '../../../../../shared/react_router_helpers';
+
+import { navigateToEngine, renderEngineLink } from './engine_link_helpers';
+
+describe('navigateToEngine', () => {
+ const { navigateToUrl } = mockKibanaValues;
+ const { sendAppSearchTelemetry } = mockTelemetryActions;
+
+ it('sends the user to the engine page and triggers a telemetry event', () => {
+ navigateToEngine('engine-a');
+ expect(navigateToUrl).toHaveBeenCalledWith('/engines/engine-a');
+ expect(sendAppSearchTelemetry).toHaveBeenCalledWith({
+ action: 'clicked',
+ metric: 'engine_table_link',
+ });
+ });
+});
+
+describe('renderEngineLink', () => {
+ const { sendAppSearchTelemetry } = mockTelemetryActions;
+
+ it('renders a link to the engine with telemetry', () => {
+ const wrapper = shallow({renderEngineLink('engine-b')}
);
+ const link = wrapper.find(EuiLinkTo);
+
+ expect(link.prop('to')).toEqual('/engines/engine-b');
+
+ link.simulate('click');
+ expect(sendAppSearchTelemetry).toHaveBeenCalledWith({
+ action: 'clicked',
+ metric: 'engine_table_link',
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.tsx
new file mode 100644
index 00000000000000..a3350d1ef9939c
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engine_link_helpers.tsx
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { KibanaLogic } from '../../../../../shared/kibana';
+import { EuiLinkTo } from '../../../../../shared/react_router_helpers';
+import { TelemetryLogic } from '../../../../../shared/telemetry';
+import { ENGINE_PATH } from '../../../../routes';
+import { generateEncodedPath } from '../../../../utils/encode_path_params';
+
+const sendEngineTableLinkClickTelemetry = () => {
+ TelemetryLogic.actions.sendAppSearchTelemetry({
+ action: 'clicked',
+ metric: 'engine_table_link',
+ });
+};
+
+export const navigateToEngine = (engineName: string) => {
+ sendEngineTableLinkClickTelemetry();
+ KibanaLogic.values.navigateToUrl(generateEncodedPath(ENGINE_PATH, { engineName }));
+};
+
+export const renderEngineLink = (engineName: string) => (
+
+ {engineName}
+
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.test.tsx
new file mode 100644
index 00000000000000..8d3b4b2a5e6cac
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.test.tsx
@@ -0,0 +1,85 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { mountWithIntl, setMockValues } from '../../../../../__mocks__';
+import '../../../../../__mocks__/enterprise_search_url.mock';
+import './__mocks__/engines_logic.mock';
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiBasicTable } from '@elastic/eui';
+
+import { EngineDetails } from '../../../engine/types';
+
+import { EnginesTable } from './engines_table';
+
+import { runSharedColumnsTests, runSharedPropsTests } from './test_helpers';
+
+describe('EnginesTable', () => {
+ const data = [
+ {
+ name: 'test-engine',
+ created_at: 'Fri, 1 Jan 1970 12:00:00 +0000',
+ language: 'English',
+ isMeta: false,
+ document_count: 99999,
+ field_count: 10,
+ } as EngineDetails,
+ ];
+ const props = {
+ items: data,
+ loading: false,
+ pagination: {
+ pageIndex: 0,
+ pageSize: 10,
+ totalItemCount: 1,
+ hidePerPageOptions: true,
+ },
+ onChange: () => {},
+ };
+ setMockValues({ myRole: { canManageEngines: false } });
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('renders', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiBasicTable)).toHaveLength(1);
+ });
+
+ describe('columns', () => {
+ const wrapper = shallow( );
+ const tableContent = mountWithIntl( )
+ .find(EuiBasicTable)
+ .text();
+ runSharedColumnsTests(wrapper, tableContent);
+ });
+
+ describe('language column', () => {
+ it('renders language when set', () => {
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(EuiBasicTable).text()).toContain('German');
+ });
+
+ it('renders the language as Universal if no language is set', () => {
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(EuiBasicTable).text()).toContain('Universal');
+ });
+ });
+
+ describe('passed props', () => {
+ const wrapper = shallow( );
+ runSharedPropsTests(wrapper);
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.tsx
new file mode 100644
index 00000000000000..563e272a4a7303
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/engines_table.tsx
@@ -0,0 +1,74 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { useValues } from 'kea';
+
+import { EuiBasicTable, EuiBasicTableColumn, EuiTableFieldDataColumnType } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { AppLogic } from '../../../../app_logic';
+import { UNIVERSAL_LANGUAGE } from '../../../../constants';
+import { EngineDetails } from '../../../engine/types';
+
+import { renderEngineLink } from './engine_link_helpers';
+import {
+ ACTIONS_COLUMN,
+ CREATED_AT_COLUMN,
+ DOCUMENT_COUNT_COLUMN,
+ FIELD_COUNT_COLUMN,
+ NAME_COLUMN,
+} from './shared_columns';
+import { EnginesTableProps } from './types';
+
+const LANGUAGE_COLUMN: EuiTableFieldDataColumnType = {
+ field: 'language',
+ name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.language', {
+ defaultMessage: 'Language',
+ }),
+ dataType: 'string',
+ render: (language: string) => language || UNIVERSAL_LANGUAGE,
+};
+
+export const EnginesTable: React.FC = ({
+ items,
+ loading,
+ noItemsMessage,
+ pagination,
+ onChange,
+}) => {
+ const {
+ myRole: { canManageEngines },
+ } = useValues(AppLogic);
+
+ const columns: Array> = [
+ {
+ ...NAME_COLUMN,
+ render: (name: string) => renderEngineLink(name),
+ },
+ CREATED_AT_COLUMN,
+ LANGUAGE_COLUMN,
+ DOCUMENT_COUNT_COLUMN,
+ FIELD_COUNT_COLUMN,
+ ];
+
+ if (canManageEngines) {
+ columns.push(ACTIONS_COLUMN);
+ }
+
+ return (
+
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.test.tsx
new file mode 100644
index 00000000000000..430539c10bbf37
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.test.tsx
@@ -0,0 +1,100 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { mountWithIntl, setMockValues } from '../../../../../__mocks__';
+import '../../../../../__mocks__/enterprise_search_url.mock';
+import './__mocks__/engines_logic.mock';
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiBasicTable } from '@elastic/eui';
+
+import { EngineDetails } from '../../../engine/types';
+
+import { MetaEnginesTable } from './meta_engines_table';
+import { MetaEnginesTableExpandedRow } from './meta_engines_table_expanded_row';
+import { MetaEnginesTableNameColumnContent } from './meta_engines_table_name_column_content';
+
+import { runSharedColumnsTests, runSharedPropsTests } from './test_helpers';
+
+describe('MetaEnginesTable', () => {
+ const data = [
+ {
+ name: 'test-engine',
+ created_at: 'Fri, 1 Jan 1970 12:00:00 +0000',
+ isMeta: true,
+ document_count: 99999,
+ field_count: 10,
+ includedEngines: [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ } as EngineDetails,
+ ];
+ const props = {
+ items: data,
+ loading: false,
+ pagination: {
+ pageIndex: 0,
+ pageSize: 10,
+ totalItemCount: 1,
+ hidePerPageOptions: true,
+ },
+ onChange: () => {},
+ };
+
+ const DEFAULT_VALUES = {
+ myRole: {
+ canManageMetaEngines: false,
+ },
+ expandedSourceEngines: {},
+ hideRow: jest.fn(),
+ fetchOrDisplayRow: jest.fn(),
+ };
+ setMockValues(DEFAULT_VALUES);
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('renders', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiBasicTable)).toHaveLength(1);
+ });
+
+ describe('columns', () => {
+ const wrapper = shallow( );
+ const tableContent = mountWithIntl( )
+ .find(EuiBasicTable)
+ .text();
+ runSharedColumnsTests(wrapper, tableContent, DEFAULT_VALUES);
+ });
+
+ describe('passed props', () => {
+ const wrapper = shallow( );
+ runSharedPropsTests(wrapper);
+ });
+
+ describe('expanded source engines', () => {
+ it('is hidden by default', () => {
+ const wrapper = shallow( );
+ const table = wrapper.find(EuiBasicTable).dive();
+
+ expect(table.find(MetaEnginesTableNameColumnContent)).toHaveLength(1);
+ expect(table.find(MetaEnginesTableExpandedRow)).toHaveLength(0);
+ });
+
+ it('is visible when the row has been expanded', () => {
+ setMockValues({
+ ...DEFAULT_VALUES,
+ expandedSourceEngines: { 'test-engine': true },
+ });
+ const wrapper = shallow( );
+ const table = wrapper.find(EuiBasicTable);
+ expect(table.dive().find(MetaEnginesTableExpandedRow)).toHaveLength(1);
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.tsx
new file mode 100644
index 00000000000000..f99dc7e15eaec5
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table.tsx
@@ -0,0 +1,113 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { ReactNode, useMemo } from 'react';
+
+import { useActions, useValues } from 'kea';
+
+import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
+
+import { AppLogic } from '../../../../app_logic';
+import { EngineDetails } from '../../../engine/types';
+
+import { MetaEnginesTableExpandedRow } from './meta_engines_table_expanded_row';
+import { MetaEnginesTableLogic } from './meta_engines_table_logic';
+import { MetaEnginesTableNameColumnContent } from './meta_engines_table_name_column_content';
+import {
+ ACTIONS_COLUMN,
+ BLANK_COLUMN,
+ CREATED_AT_COLUMN,
+ DOCUMENT_COUNT_COLUMN,
+ FIELD_COUNT_COLUMN,
+ NAME_COLUMN,
+} from './shared_columns';
+import { EnginesTableProps } from './types';
+import { getConflictingEnginesSet } from './utils';
+
+interface IItemIdToExpandedRowMap {
+ [id: string]: ReactNode;
+}
+
+export interface ConflictingEnginesSets {
+ [key: string]: Set;
+}
+
+export const MetaEnginesTable: React.FC = ({
+ items,
+ loading,
+ noItemsMessage,
+ pagination,
+ onChange,
+}) => {
+ const { expandedSourceEngines } = useValues(MetaEnginesTableLogic);
+ const { hideRow, fetchOrDisplayRow } = useActions(MetaEnginesTableLogic);
+ const {
+ myRole: { canManageMetaEngines },
+ } = useValues(AppLogic);
+
+ const conflictingEnginesSets: ConflictingEnginesSets = useMemo(
+ () =>
+ items.reduce((accumulator, metaEngine) => {
+ return {
+ ...accumulator,
+ [metaEngine.name]: getConflictingEnginesSet(metaEngine),
+ };
+ }, {}),
+ [items]
+ );
+
+ const itemIdToExpandedRowMap: IItemIdToExpandedRowMap = useMemo(
+ () =>
+ Object.keys(expandedSourceEngines).reduce((accumulator, engineName) => {
+ return {
+ ...accumulator,
+ [engineName]: (
+
+ ),
+ };
+ }, {}),
+ [expandedSourceEngines, conflictingEnginesSets]
+ );
+
+ const columns: Array> = [
+ {
+ ...NAME_COLUMN,
+ render: (_, item: EngineDetails) => (
+
+ ),
+ },
+ CREATED_AT_COLUMN,
+ BLANK_COLUMN,
+ DOCUMENT_COUNT_COLUMN,
+ FIELD_COUNT_COLUMN,
+ ];
+
+ if (canManageMetaEngines) {
+ columns.push(ACTIONS_COLUMN);
+ }
+
+ return (
+
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.scss
new file mode 100644
index 00000000000000..e6f627458f43e7
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.scss
@@ -0,0 +1,21 @@
+.metaEnginesSourceEnginesTable {
+ margin: (-$euiSizeS) (-$euiSizeS) $euiSizeS (-$euiSizeS);
+
+ thead {
+ display: none;
+ }
+
+ @include euiBreakpoint('l', 'xl') {
+ .euiTableRowCell {
+ border-top: none;
+ }
+
+ .euiTitle {
+ display: none;
+ }
+ }
+
+ .euiTableHeaderMobile {
+ display: none
+ }
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.test.tsx
new file mode 100644
index 00000000000000..dcaa1a2b7c2461
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.test.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { mountWithIntl } from '../../../../../__mocks__';
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiBasicTable, EuiHealth } from '@elastic/eui';
+
+import { EngineDetails } from '../../../engine/types';
+
+import { MetaEnginesTableExpandedRow } from './meta_engines_table_expanded_row';
+
+const SOURCE_ENGINES = [
+ {
+ name: 'source-engine-1',
+ created_at: 'Fri, 1 Jan 1970 12:00:00 +0000',
+ language: 'English',
+ isMeta: true,
+ document_count: 99999,
+ field_count: 10,
+ },
+ {
+ name: 'source-engine-2',
+ created_at: 'Fri, 1 Jan 1970 12:00:00 +0000',
+ language: 'English',
+ isMeta: true,
+ document_count: 55555,
+ field_count: 7,
+ },
+] as EngineDetails[];
+
+describe('MetaEnginesTableExpandedRow', () => {
+ it('contains relevant source engine information', () => {
+ const wrapper = mountWithIntl(
+
+ );
+ const table = wrapper.find(EuiBasicTable);
+
+ expect(table).toHaveLength(1);
+
+ const tableContent = table.text();
+ expect(tableContent).toContain('source-engine-1');
+ expect(tableContent).toContain('99,999');
+ expect(tableContent).toContain('10');
+
+ expect(tableContent).toContain('source-engine-2');
+ expect(tableContent).toContain('55,555');
+ expect(tableContent).toContain('7');
+ });
+
+ it('indicates when a meta-engine has conflicts', () => {
+ const wrapper = shallow(
+
+ );
+
+ const table = wrapper.find(EuiBasicTable);
+ expect(table.dive().find(EuiHealth)).toHaveLength(2);
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.tsx
new file mode 100644
index 00000000000000..0f974581ca73cd
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_expanded_row.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { EuiBasicTable, EuiHealth, EuiTitle } from '@elastic/eui';
+
+import { EngineDetails } from '../../../engine/types';
+import { SOURCE_ENGINES_TITLE } from '../../constants';
+
+import {
+ BLANK_COLUMN,
+ CREATED_AT_COLUMN,
+ DOCUMENT_COUNT_COLUMN,
+ FIELD_COUNT_COLUMN,
+ NAME_COLUMN,
+} from './shared_columns';
+
+import './meta_engines_table_expanded_row.scss';
+
+interface MetaEnginesTableExpandedRowProps {
+ sourceEngines: EngineDetails[];
+ conflictingEngines: Set;
+}
+
+export const MetaEnginesTableExpandedRow: React.FC = ({
+ sourceEngines,
+ conflictingEngines,
+}) => (
+
+
+ {SOURCE_ENGINES_TITLE}
+
+ (
+ <>
+ {conflictingEngines.has(engineDetails.name) ? (
+ {engineDetails.field_count}
+ ) : (
+ engineDetails.field_count
+ )}
+ >
+ ),
+ },
+ BLANK_COLUMN,
+ ]}
+ />
+
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.test.ts
new file mode 100644
index 00000000000000..b90207331ffd66
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.test.ts
@@ -0,0 +1,255 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { LogicMounter, mockFlashMessageHelpers, mockHttpValues } from '../../../../../__mocks__';
+
+import { nextTick } from '@kbn/test/jest';
+
+import { EngineDetails } from '../../../engine/types';
+
+import { MetaEnginesTableLogic } from './meta_engines_table_logic';
+
+describe('MetaEnginesTableLogic', () => {
+ const DEFAULT_VALUES = {
+ expandedRows: {},
+ sourceEngines: {},
+ expandedSourceEngines: {},
+ };
+
+ const SOURCE_ENGINES = [
+ {
+ name: 'source-engine-1',
+ },
+ {
+ name: 'source-engine-2',
+ },
+ ] as EngineDetails[];
+
+ const META_ENGINES = [
+ {
+ name: 'test-engine-1',
+ includedEngines: SOURCE_ENGINES,
+ },
+ {
+ name: 'test-engine-2',
+ includedEngines: SOURCE_ENGINES,
+ },
+ ] as EngineDetails[];
+
+ const DEFAULT_PROPS = {
+ metaEngines: [...SOURCE_ENGINES, ...META_ENGINES] as EngineDetails[],
+ };
+
+ const { http } = mockHttpValues;
+ const { mount } = new LogicMounter(MetaEnginesTableLogic);
+ const { flashAPIErrors } = mockFlashMessageHelpers;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('has expected default values', async () => {
+ mount({}, DEFAULT_PROPS);
+ expect(MetaEnginesTableLogic.values).toEqual(DEFAULT_VALUES);
+ });
+
+ describe('reducers', () => {
+ describe('expandedRows', () => {
+ it('displayRow adds an expanded row entry for provided itemId', () => {
+ mount(DEFAULT_VALUES, DEFAULT_PROPS);
+ MetaEnginesTableLogic.actions.displayRow('source-engine-1');
+
+ expect(MetaEnginesTableLogic.values.expandedRows).toEqual({
+ 'source-engine-1': true,
+ });
+ });
+
+ it('hideRow removes any expanded row entry for provided itemId', () => {
+ mount({ ...DEFAULT_VALUES, expandedRows: { 'source-engine-1': true } }, DEFAULT_PROPS);
+
+ MetaEnginesTableLogic.actions.hideRow('source-engine-1');
+
+ expect(MetaEnginesTableLogic.values.expandedRows).toEqual({});
+ });
+ });
+
+ it('sourceEngines is updated by addSourceEngines', () => {
+ mount({
+ ...DEFAULT_VALUES,
+ sourceEngines: {
+ 'test-engine-1': [
+ { name: 'source-engine-1' },
+ { name: 'source-engine-2' },
+ ] as EngineDetails[],
+ },
+ });
+
+ MetaEnginesTableLogic.actions.addSourceEngines({
+ 'test-engine-2': [
+ { name: 'source-engine-1' },
+ { name: 'source-engine-2' },
+ ] as EngineDetails[],
+ });
+
+ expect(MetaEnginesTableLogic.values.sourceEngines).toEqual({
+ 'test-engine-1': [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ 'test-engine-2': [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ });
+ });
+ });
+
+ describe('listeners', () => {
+ describe('fetchOrDisplayRow', () => {
+ it('calls displayRow when it already has data for the itemId', () => {
+ mount({
+ ...DEFAULT_VALUES,
+ sourceEngines: {
+ 'test-engine-1': [
+ { name: 'source-engine-1' },
+ { name: 'source-engine-2' },
+ ] as EngineDetails[],
+ },
+ });
+ jest.spyOn(MetaEnginesTableLogic.actions, 'displayRow');
+
+ MetaEnginesTableLogic.actions.fetchOrDisplayRow('test-engine-1');
+
+ expect(MetaEnginesTableLogic.actions.displayRow).toHaveBeenCalled();
+ });
+
+ it('calls fetchSourceEngines when it needs to fetch data for the itemId', () => {
+ http.get.mockReturnValueOnce(
+ Promise.resolve({
+ meta: {
+ page: {
+ total_pages: 1,
+ },
+ },
+ results: [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ })
+ );
+ mount();
+ jest.spyOn(MetaEnginesTableLogic.actions, 'fetchSourceEngines');
+
+ MetaEnginesTableLogic.actions.fetchOrDisplayRow('test-engine-1');
+
+ expect(MetaEnginesTableLogic.actions.fetchSourceEngines).toHaveBeenCalled();
+ });
+ });
+
+ describe('fetchSourceEngines', () => {
+ it('calls addSourceEngines and displayRow when it has retrieved all pages', async () => {
+ mount();
+ http.get.mockReturnValueOnce(
+ Promise.resolve({
+ meta: {
+ page: {
+ total_pages: 1,
+ },
+ },
+ results: [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ })
+ );
+ jest.spyOn(MetaEnginesTableLogic.actions, 'displayRow');
+ jest.spyOn(MetaEnginesTableLogic.actions, 'addSourceEngines');
+
+ MetaEnginesTableLogic.actions.fetchSourceEngines('test-engine-1');
+ await nextTick();
+
+ expect(http.get).toHaveBeenCalledWith(
+ '/api/app_search/engines/test-engine-1/source_engines',
+ {
+ query: {
+ 'page[current]': 1,
+ 'page[size]': 25,
+ },
+ }
+ );
+ expect(MetaEnginesTableLogic.actions.addSourceEngines).toHaveBeenCalledWith({
+ 'test-engine-1': [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ });
+ expect(MetaEnginesTableLogic.actions.displayRow).toHaveBeenCalledWith('test-engine-1');
+ });
+
+ it('display a flash message on error', async () => {
+ http.get.mockReturnValueOnce(Promise.reject());
+ mount();
+
+ MetaEnginesTableLogic.actions.fetchSourceEngines('test-engine-1');
+ await nextTick();
+
+ expect(flashAPIErrors).toHaveBeenCalledTimes(1);
+ });
+
+ it('recursively fetches a number of pages', async () => {
+ mount();
+ jest.spyOn(MetaEnginesTableLogic.actions, 'addSourceEngines');
+
+ // First page
+ http.get.mockReturnValueOnce(
+ Promise.resolve({
+ meta: {
+ page: {
+ total_pages: 2,
+ },
+ },
+ results: [{ name: 'source-engine-1' }],
+ })
+ );
+
+ // Second and final page
+ http.get.mockReturnValueOnce(
+ Promise.resolve({
+ meta: {
+ page: {
+ total_pages: 2,
+ },
+ },
+ results: [{ name: 'source-engine-2' }],
+ })
+ );
+
+ MetaEnginesTableLogic.actions.fetchSourceEngines('test-engine-1');
+ await nextTick();
+
+ expect(MetaEnginesTableLogic.actions.addSourceEngines).toHaveBeenCalledWith({
+ 'test-engine-1': [
+ // First page
+ { name: 'source-engine-1' },
+ // Second and final page
+ { name: 'source-engine-2' },
+ ],
+ });
+ });
+ });
+ });
+
+ describe('selectors', () => {
+ it('expandedSourceEngines includes all source engines that have been expanded ', () => {
+ mount({
+ ...DEFAULT_VALUES,
+ sourceEngines: {
+ 'test-engine-1': [
+ { name: 'source-engine-1' },
+ { name: 'source-engine-2' },
+ ] as EngineDetails[],
+ 'test-engine-2': [
+ { name: 'source-engine-1' },
+ { name: 'source-engine-2' },
+ ] as EngineDetails[],
+ },
+ expandedRows: {
+ 'test-engine-1': true,
+ },
+ });
+
+ expect(MetaEnginesTableLogic.values.expandedSourceEngines).toEqual({
+ 'test-engine-1': [{ name: 'source-engine-1' }, { name: 'source-engine-2' }],
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.ts
new file mode 100644
index 00000000000000..04e1ee5c1b61ae
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_logic.ts
@@ -0,0 +1,127 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { kea, MakeLogicType } from 'kea';
+
+import { Meta } from '../../../../../../../common/types';
+import { flashAPIErrors } from '../../../../../shared/flash_messages';
+
+import { HttpLogic } from '../../../../../shared/http';
+
+import { EngineDetails } from '../../../engine/types';
+
+interface MetaEnginesTableValues {
+ expandedRows: { [id: string]: boolean };
+ sourceEngines: { [id: string]: EngineDetails[] };
+ expandedSourceEngines: { [id: string]: EngineDetails[] };
+}
+
+interface MetaEnginesTableActions {
+ addSourceEngines(
+ sourceEngines: MetaEnginesTableValues['sourceEngines']
+ ): { sourceEngines: MetaEnginesTableValues['sourceEngines'] };
+ displayRow(itemId: string): { itemId: string };
+ fetchOrDisplayRow(itemId: string): { itemId: string };
+ fetchSourceEngines(engineName: string): { engineName: string };
+ hideRow(itemId: string): { itemId: string };
+}
+
+interface EnginesAPIResponse {
+ results: EngineDetails[];
+ meta: Meta;
+}
+
+export const MetaEnginesTableLogic = kea<
+ MakeLogicType
+>({
+ path: ['enterprise_search', 'app_search', 'meta_engines_table_logic'],
+ actions: () => ({
+ addSourceEngines: (sourceEngines) => ({ sourceEngines }),
+ displayRow: (itemId) => ({ itemId }),
+ hideRow: (itemId) => ({ itemId }),
+ fetchOrDisplayRow: (itemId) => ({ itemId }),
+ fetchSourceEngines: (engineName) => ({ engineName }),
+ }),
+ reducers: () => ({
+ expandedRows: [
+ {},
+ {
+ displayRow: (expandedRows, { itemId }) => ({
+ ...expandedRows,
+ [itemId]: true,
+ }),
+ hideRow: (expandedRows, { itemId }) => {
+ const newRows = { ...expandedRows };
+ delete newRows[itemId];
+ return newRows;
+ },
+ },
+ ],
+ sourceEngines: [
+ {},
+ {
+ addSourceEngines: (currentSourceEngines, { sourceEngines: newSourceEngines }) => ({
+ ...currentSourceEngines,
+ ...newSourceEngines,
+ }),
+ },
+ ],
+ }),
+ selectors: {
+ expandedSourceEngines: [
+ (selectors) => [selectors.sourceEngines, selectors.expandedRows],
+ (sourceEngines: MetaEnginesTableValues['sourceEngines'], expandedRows: string[]) => {
+ return Object.keys(expandedRows).reduce((expandedRowMap, engineName) => {
+ expandedRowMap[engineName] = sourceEngines[engineName];
+ return expandedRowMap;
+ }, {} as MetaEnginesTableValues['sourceEngines']);
+ },
+ ],
+ },
+ listeners: ({ actions, values }) => ({
+ fetchOrDisplayRow: ({ itemId }) => {
+ const sourceEngines = values.sourceEngines;
+ if (sourceEngines[itemId]) {
+ actions.displayRow(itemId);
+ } else {
+ actions.fetchSourceEngines(itemId);
+ }
+ },
+ fetchSourceEngines: ({ engineName }) => {
+ const { http } = HttpLogic.values;
+
+ let enginesAccumulator: EngineDetails[] = [];
+
+ const recursiveFetchSourceEngines = async (page = 1) => {
+ try {
+ const { meta, results }: EnginesAPIResponse = await http.get(
+ `/api/app_search/engines/${engineName}/source_engines`,
+ {
+ query: {
+ 'page[current]': page,
+ 'page[size]': 25,
+ },
+ }
+ );
+
+ enginesAccumulator = [...enginesAccumulator, ...results];
+
+ if (page >= meta.page.total_pages) {
+ actions.addSourceEngines({ [engineName]: enginesAccumulator });
+ actions.displayRow(engineName);
+ } else {
+ recursiveFetchSourceEngines(page + 1);
+ }
+ } catch (e) {
+ flashAPIErrors(e);
+ }
+ };
+
+ recursiveFetchSourceEngines();
+ },
+ }),
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.test.tsx
new file mode 100644
index 00000000000000..df65f2f86e1749
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.test.tsx
@@ -0,0 +1,154 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiHealth } from '@elastic/eui';
+
+import { SchemaConflictFieldTypes, SchemaConflicts } from '../../../../../shared/types';
+import { EngineDetails } from '../../../engine/types';
+
+import { MetaEnginesTableNameColumnContent } from './meta_engines_table_name_column_content';
+
+describe('MetaEnginesTableNameColumnContent', () => {
+ it('includes the name of the engine', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.find('[data-test-subj="EngineName"]')).toHaveLength(1);
+ });
+
+ describe('toggle button', () => {
+ it('displays expanded row when the row is currently hidden', () => {
+ const showRow = jest.fn();
+
+ const wrapper = shallow(
+
+ );
+ wrapper.find('[data-test-subj="ExpandRowButton"]').at(0).simulate('click');
+
+ expect(showRow).toHaveBeenCalled();
+ });
+
+ it('hides expanded row when the row is currently visible', () => {
+ const hideRow = jest.fn();
+
+ const wrapper = shallow(
+
+ );
+ wrapper.find('[data-test-subj="ExpandRowButton"]').at(0).simulate('click');
+
+ expect(hideRow).toHaveBeenCalled();
+ });
+ });
+
+ describe('engine count', () => {
+ it('is included and labelled', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.find('[data-test-subj="SourceEnginesCount"]')).toHaveLength(1);
+ });
+ });
+
+ it('indicates the precense of field-type conflicts', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.find(EuiHealth)).toHaveLength(1);
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.tsx
new file mode 100644
index 00000000000000..e05246ab4d92cf
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/meta_engines_table_name_column_content.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { EuiFlexGroup, EuiIcon, EuiHealth, EuiFlexItem } from '@elastic/eui';
+
+import { i18n } from '@kbn/i18n';
+
+import { EngineDetails } from '../../../engine/types';
+
+import { renderEngineLink } from './engine_link_helpers';
+
+interface MetaEnginesTableNameContentProps {
+ isExpanded: boolean;
+ item: EngineDetails;
+ hideRow: (name: string) => void;
+ showRow: (name: string) => void;
+}
+
+export const MetaEnginesTableNameColumnContent: React.FC = ({
+ item: { name, schemaConflicts, engine_count: engineCount },
+ isExpanded,
+ hideRow,
+ showRow,
+}) => (
+
+ {renderEngineLink(name)}
+ (isExpanded ? hideRow(name) : showRow(name))}
+ aria-expanded={isExpanded}
+ data-test-subj="ExpandRowButton"
+ >
+
+
+
+
+
+ {i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.engines.metaEnginesTable.sourceEnginesCount',
+ {
+ defaultMessage: '{sourceEnginesCount, plural, one {# engine} other {# engines}}',
+ values: { sourceEnginesCount: engineCount || 0 },
+ }
+ )}
+
+ {schemaConflicts && Object.keys(schemaConflicts).length > 0 && (
+
+
+ {i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.engines.metaEnginesTable.fieldTypeConflictWarning',
+ {
+ defaultMessage: 'Field-type conflict',
+ }
+ )}
+
+
+ )}
+
+
+
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/shared_columns.tsx
new file mode 100644
index 00000000000000..3375b25cdcd6ca
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/shared_columns.tsx
@@ -0,0 +1,127 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import {
+ EuiTableFieldDataColumnType,
+ EuiTableComputedColumnType,
+ EuiTableActionsColumnType,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedNumber } from '@kbn/i18n/react';
+
+import { MANAGE_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../../../shared/constants';
+import { FormattedDateTime } from '../../../../utils/formatted_date_time';
+import { EngineDetails } from '../../../engine/types';
+import { EnginesLogic } from '../../../engines';
+
+import { navigateToEngine } from './engine_link_helpers';
+
+export const BLANK_COLUMN: EuiTableComputedColumnType = {
+ render: () => <>>,
+ 'aria-hidden': true,
+};
+
+export const NAME_COLUMN: EuiTableFieldDataColumnType = {
+ field: 'name',
+ name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name', {
+ defaultMessage: 'Name',
+ }),
+ width: '30%',
+ truncateText: true,
+ mobileOptions: {
+ header: true,
+ // Note: the below props are valid props per https://elastic.github.io/eui/#/tabular-content/tables (Responsive tables), but EUI's types have a bug reporting it as an error
+ // @ts-ignore
+ enlarge: true,
+ width: '100%',
+ truncateText: false,
+ },
+};
+
+export const CREATED_AT_COLUMN: EuiTableFieldDataColumnType = {
+ field: 'created_at',
+ name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.createdAt', {
+ defaultMessage: 'Created at',
+ }),
+ dataType: 'string',
+ render: (dateString: string) => ,
+};
+
+export const DOCUMENT_COUNT_COLUMN: EuiTableFieldDataColumnType = {
+ field: 'document_count',
+ name: i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.enginesOverview.table.column.documentCount',
+ {
+ defaultMessage: 'Document count',
+ }
+ ),
+ dataType: 'number',
+ render: (number: number) => ,
+ truncateText: true,
+};
+
+export const FIELD_COUNT_COLUMN: EuiTableFieldDataColumnType = {
+ field: 'field_count',
+ name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.fieldCount', {
+ defaultMessage: 'Field count',
+ }),
+ dataType: 'number',
+ render: (number: number) => ,
+ truncateText: true,
+};
+
+export const ACTIONS_COLUMN: EuiTableActionsColumnType = {
+ name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.actions', {
+ defaultMessage: 'Actions',
+ }),
+ actions: [
+ {
+ name: MANAGE_BUTTON_LABEL,
+ description: i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.manage.buttonDescription',
+ {
+ defaultMessage: 'Manage this engine',
+ }
+ ),
+ type: 'icon',
+ icon: 'eye',
+ onClick: (engineDetails) => navigateToEngine(engineDetails.name),
+ },
+ {
+ name: DELETE_BUTTON_LABEL,
+ description: i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.delete.buttonDescription',
+ {
+ defaultMessage: 'Delete this engine',
+ }
+ ),
+ type: 'icon',
+ icon: 'trash',
+ color: 'danger',
+ onClick: (engine) => {
+ if (
+ window.confirm(
+ i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.delete.confirmationPopupMessage',
+ {
+ defaultMessage:
+ 'Are you sure you want to permanently delete "{engineName}" and all of its content?',
+ values: {
+ engineName: engine.name,
+ },
+ }
+ )
+ )
+ ) {
+ EnginesLogic.actions.deleteEngine(engine);
+ }
+ },
+ },
+ ],
+};
diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/index.ts
similarity index 50%
rename from x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts
rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/index.ts
index 67964a7ab26c39..c2989c5d1f9725 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/index.ts
@@ -5,12 +5,5 @@
* 2.0.
*/
-import { FindRulesSchema } from './find_rules_schema';
-import { getRulesSchemaMock } from './rules_schema.mocks';
-
-export const getFindRulesSchemaMock = (): FindRulesSchema => ({
- page: 1,
- perPage: 1,
- total: 1,
- data: [getRulesSchemaMock()],
-});
+export { runSharedColumnsTests } from './shared_columns';
+export { runSharedPropsTests } from './shared_props';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_columns.tsx
new file mode 100644
index 00000000000000..97e2057cea2d96
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_columns.tsx
@@ -0,0 +1,111 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { setMockValues, rerender } from '../../../../../../__mocks__';
+import '../__mocks__/engines_logic.mock';
+
+import { ShallowWrapper } from 'enzyme';
+
+import { EuiBasicTable, EuiButtonIcon } from '@elastic/eui';
+
+import { EnginesLogic } from '../../../../engines';
+
+import * as engineLinkHelpers from '../engine_link_helpers';
+
+export const runSharedColumnsTests = (
+ wrapper: ShallowWrapper,
+ tableContent: string,
+ values: object = {}
+) => {
+ const getTable = () => wrapper.find(EuiBasicTable).dive();
+
+ describe('name column', () => {
+ it('renders', () => {
+ expect(tableContent).toContain('test-engine');
+ });
+
+ // Link behavior is tested in engine_link_helpers.test.tsx
+ });
+
+ describe('created at column', () => {
+ it('renders', () => {
+ expect(tableContent).toContain('Created at');
+ expect(tableContent).toContain('Jan 1, 1970');
+ });
+ });
+
+ describe('document count column', () => {
+ it('renders', () => {
+ expect(tableContent).toContain('Document count');
+ expect(tableContent).toContain('99,999');
+ });
+ });
+
+ describe('field count column', () => {
+ it('renders', () => {
+ expect(tableContent).toContain('Field count');
+ expect(tableContent).toContain('10');
+ });
+ });
+
+ describe('actions column', () => {
+ const getActions = () => getTable().find('ExpandedItemActions');
+ const getActionItems = () => getActions().dive().find('DefaultItemAction');
+
+ it('will hide the action buttons if the user cannot manage/delete engines', () => {
+ setMockValues({
+ ...values,
+ myRole: { canManageEngines: false, canManageMetaEngines: false },
+ });
+ rerender(wrapper);
+ expect(getActions()).toHaveLength(0);
+ });
+
+ describe('when the user can manage/delete engines', () => {
+ const getManageAction = () => getActionItems().at(0).dive().find(EuiButtonIcon);
+ const getDeleteAction = () => getActionItems().at(1).dive().find(EuiButtonIcon);
+
+ beforeAll(() => {
+ setMockValues({
+ ...values,
+ myRole: { canManageEngines: true, canManageMetaEngines: true },
+ });
+ rerender(wrapper);
+ });
+
+ describe('manage action', () => {
+ it('sends the user to the engine overview on click', () => {
+ jest.spyOn(engineLinkHelpers, 'navigateToEngine');
+ const { navigateToEngine } = engineLinkHelpers;
+ getManageAction().simulate('click');
+
+ expect(navigateToEngine).toHaveBeenCalledWith('test-engine');
+ });
+ });
+
+ describe('delete action', () => {
+ const { deleteEngine } = EnginesLogic.actions;
+
+ it('clicking the action and confirming deletes the engine', () => {
+ jest.spyOn(global, 'confirm').mockReturnValueOnce(true);
+ getDeleteAction().simulate('click');
+
+ expect(deleteEngine).toHaveBeenCalledWith(
+ expect.objectContaining({ name: 'test-engine' })
+ );
+ });
+
+ it('clicking the action and not confirming does not delete the engine', () => {
+ jest.spyOn(global, 'confirm').mockReturnValueOnce(false);
+ getDeleteAction().simulate('click');
+
+ expect(deleteEngine).not.toHaveBeenCalled();
+ });
+ });
+ });
+ });
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_props.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_props.tsx
new file mode 100644
index 00000000000000..0b0a8a0a995930
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/test_helpers/shared_props.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ShallowWrapper } from 'enzyme';
+
+import { EuiBasicTable } from '@elastic/eui';
+
+export const runSharedPropsTests = (wrapper: ShallowWrapper) => {
+ it('passes the loading prop', () => {
+ wrapper.setProps({ loading: true });
+ expect(wrapper.find(EuiBasicTable).prop('loading')).toEqual(true);
+ });
+
+ it('passes the noItemsMessage prop', () => {
+ wrapper.setProps({ noItemsMessage: 'No items.' });
+ expect(wrapper.find(EuiBasicTable).prop('noItemsMessage')).toEqual('No items.');
+ });
+
+ describe('pagination', () => {
+ it('passes the pagination prop', () => {
+ const pagination = {
+ pageIndex: 0,
+ pageSize: 10,
+ totalItemCount: 50,
+ };
+ wrapper.setProps({ pagination });
+ expect(wrapper.find(EuiBasicTable).prop('pagination')).toEqual(pagination);
+ });
+
+ it('triggers onChange', () => {
+ const onChange = jest.fn();
+ wrapper.setProps({ onChange });
+
+ wrapper.find(EuiBasicTable).simulate('change', { page: { index: 4 } });
+ expect(onChange).toHaveBeenCalledWith({ page: { index: 4 } });
+ });
+ });
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/types.ts
new file mode 100644
index 00000000000000..707c086e01827f
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/types.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ReactNode } from 'react';
+
+import { CriteriaWithPagination } from '@elastic/eui';
+
+import { EngineDetails } from '../../../engine/types';
+
+export interface EnginesTableProps {
+ items: EngineDetails[];
+ loading: boolean;
+ noItemsMessage?: ReactNode;
+ pagination: {
+ pageIndex: number;
+ pageSize: number;
+ totalItemCount: number;
+ hidePerPageOptions: boolean;
+ };
+ onChange(criteria: CriteriaWithPagination): void;
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.test.ts
new file mode 100644
index 00000000000000..f65a2e52bae064
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.test.ts
@@ -0,0 +1,101 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { SchemaConflictFieldTypes, SchemaConflicts } from '../../../../../shared/types';
+import { EngineDetails } from '../../../engine/types';
+
+import {
+ getConflictingEnginesFromConflictingField,
+ getConflictingEnginesFromSchemaConflicts,
+ getConflictingEnginesSet,
+} from './utils';
+
+describe('getConflictingEnginesFromConflictingField', () => {
+ const CONFLICTING_FIELD: SchemaConflictFieldTypes = {
+ text: ['source-engine-1'],
+ number: ['source-engine-2', 'source-engine-3'],
+ geolocation: ['source-engine-4'],
+ date: ['source-engine-5', 'source-engine-6'],
+ };
+
+ it('returns a flat array of all engines with conflicts across different schema types, including duplicates', () => {
+ const result = getConflictingEnginesFromConflictingField(CONFLICTING_FIELD);
+
+ // we can't guarantee ordering
+ expect(result).toHaveLength(6);
+ expect(result).toContain('source-engine-1');
+ expect(result).toContain('source-engine-2');
+ expect(result).toContain('source-engine-3');
+ expect(result).toContain('source-engine-4');
+ expect(result).toContain('source-engine-5');
+ expect(result).toContain('source-engine-6');
+ });
+});
+
+describe('getConflictingEnginesFromSchemaConflicts', () => {
+ it('returns a flat array of all engines with conflicts across all fields, including duplicates', () => {
+ const SCHEMA_CONFLICTS: SchemaConflicts = {
+ 'conflicting-field-1': {
+ text: ['source-engine-1'],
+ number: ['source-engine-2'],
+ geolocation: [],
+ date: [],
+ },
+ 'conflicting-field-2': {
+ text: [],
+ number: [],
+ geolocation: ['source-engine-2'],
+ date: ['source-engine-3'],
+ },
+ };
+
+ const result = getConflictingEnginesFromSchemaConflicts(SCHEMA_CONFLICTS);
+
+ // we can't guarantee ordering
+ expect(result).toHaveLength(4);
+ expect(result).toContain('source-engine-1');
+ expect(result).toContain('source-engine-2');
+ expect(result).toContain('source-engine-3');
+ });
+});
+
+describe('getConflictingEnginesSet', () => {
+ const DEFAULT_META_ENGINE_DETAILS = {
+ name: 'test-engine-1',
+ includedEngines: [
+ {
+ name: 'source-engine-1',
+ },
+ {
+ name: 'source-engine-2',
+ },
+ {
+ name: 'source-engine-3',
+ },
+ ] as EngineDetails[],
+ schemaConflicts: {
+ 'conflicting-field-1': {
+ text: ['source-engine-1'],
+ number: ['source-engine-2'],
+ geolocation: [],
+ date: [],
+ },
+ 'conflicting-field-2': {
+ text: [],
+ number: [],
+ geolocation: ['source-engine-2'],
+ date: ['source-engine-3'],
+ },
+ } as SchemaConflicts,
+ } as EngineDetails;
+
+ it('generates a set of engine names with any field conflicts for the meta-engine', () => {
+ expect(getConflictingEnginesSet(DEFAULT_META_ENGINE_DETAILS)).toEqual(
+ new Set(['source-engine-1', 'source-engine-2', 'source-engine-3'])
+ );
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.ts
new file mode 100644
index 00000000000000..b1172237e3ad30
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/tables/utils.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { SchemaConflictFieldTypes, SchemaConflicts } from '../../../../../shared/types';
+import { EngineDetails } from '../../../engine/types';
+
+export const getConflictingEnginesFromConflictingField = (
+ conflictingField: SchemaConflictFieldTypes
+): string[] => Object.values(conflictingField).flat();
+
+export const getConflictingEnginesFromSchemaConflicts = (
+ schemaConflicts: SchemaConflicts
+): string[] => Object.values(schemaConflicts).flatMap(getConflictingEnginesFromConflictingField);
+
+// Given a meta-engine (represented by IEngineDetails), generate a Set of all source engines
+// who have schema conflicts in the context of that meta-engine
+//
+// A Set allows us to enforce uniqueness and has O(1) lookup time
+export const getConflictingEnginesSet = (metaEngine: EngineDetails): Set => {
+ const conflictingEngines: string[] = metaEngine.schemaConflicts
+ ? getConflictingEnginesFromSchemaConflicts(metaEngine.schemaConflicts)
+ : [];
+ return new Set(conflictingEngines);
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts
index 1955084393e570..c6c077e984efe7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts
@@ -16,6 +16,11 @@ export const META_ENGINES_TITLE = i18n.translate(
{ defaultMessage: 'Meta Engines' }
);
+export const SOURCE_ENGINES_TITLE = i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.enginesOverview.metaEnginesTable.sourceEngines.title',
+ { defaultMessage: 'Source Engines' }
+);
+
export const CREATE_AN_ENGINE_BUTTON_LABEL = i18n.translate(
'xpack.enterpriseSearch.appSearch.engines.createAnEngineButton.ButtonLabel',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx
index 3ca039907932ee..c47b169ede3644 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx
@@ -15,7 +15,8 @@ import { shallow, ShallowWrapper } from 'enzyme';
import { EuiEmptyPrompt } from '@elastic/eui';
import { LoadingState, EmptyState } from './components';
-import { EnginesTable } from './engines_table';
+import { EnginesTable } from './components/tables/engines_table';
+import { MetaEnginesTable } from './components/tables/meta_engines_table';
import { EnginesOverview } from './';
@@ -41,7 +42,11 @@ describe('EnginesOverview', () => {
},
metaEnginesLoading: false,
hasPlatinumLicense: false,
+ // AppLogic
myRole: { canManageEngines: false },
+ // MetaEnginesTableLogic
+ expandedSourceEngines: {},
+ conflictingEnginesSets: {},
};
const actions = {
loadEngines: jest.fn(),
@@ -120,7 +125,7 @@ describe('EnginesOverview', () => {
});
const wrapper = shallow( );
- expect(wrapper.find(EnginesTable)).toHaveLength(2);
+ expect(wrapper.find(MetaEnginesTable)).toHaveLength(1);
expect(actions.loadMetaEngines).toHaveBeenCalled();
});
@@ -147,7 +152,7 @@ describe('EnginesOverview', () => {
metaEngines: [],
});
const wrapper = shallow( );
- const metaEnginesTable = wrapper.find(EnginesTable).last().dive();
+ const metaEnginesTable = wrapper.find(MetaEnginesTable).dive();
const emptyPrompt = metaEnginesTable.dive().find(EuiEmptyPrompt).dive();
expect(
@@ -199,10 +204,10 @@ describe('EnginesOverview', () => {
const wrapper = shallow( );
const pageEvent = { page: { index: 0 } };
- wrapper.find(EnginesTable).first().simulate('change', pageEvent);
+ wrapper.find(EnginesTable).simulate('change', pageEvent);
expect(actions.onEnginesPagination).toHaveBeenCalledWith(1);
- wrapper.find(EnginesTable).last().simulate('change', pageEvent);
+ wrapper.find(MetaEnginesTable).simulate('change', pageEvent);
expect(actions.onMetaEnginesPagination).toHaveBeenCalledWith(1);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx
index 4d51012f2aa2ab..4e17278d25d1a3 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx
@@ -29,6 +29,8 @@ import { EngineIcon, MetaEngineIcon } from '../../icons';
import { ENGINE_CREATION_PATH, META_ENGINE_CREATION_PATH } from '../../routes';
import { EnginesOverviewHeader, LoadingState, EmptyState } from './components';
+import { EnginesTable } from './components/tables/engines_table';
+import { MetaEnginesTable } from './components/tables/meta_engines_table';
import {
CREATE_AN_ENGINE_BUTTON_LABEL,
CREATE_A_META_ENGINE_BUTTON_LABEL,
@@ -38,7 +40,6 @@ import {
META_ENGINES_TITLE,
} from './constants';
import { EnginesLogic } from './engines_logic';
-import { EnginesTable } from './engines_table';
import './engines_overview.scss';
@@ -58,13 +59,9 @@ export const EnginesOverview: React.FC = () => {
metaEnginesLoading,
} = useValues(EnginesLogic);
- const {
- deleteEngine,
- loadEngines,
- loadMetaEngines,
- onEnginesPagination,
- onMetaEnginesPagination,
- } = useActions(EnginesLogic);
+ const { loadEngines, loadMetaEngines, onEnginesPagination, onMetaEnginesPagination } = useActions(
+ EnginesLogic
+ );
useEffect(() => {
loadEngines();
@@ -116,7 +113,6 @@ export const EnginesOverview: React.FC = () => {
hidePerPageOptions: true,
}}
onChange={handlePageChange(onEnginesPagination)}
- onDeleteEngine={deleteEngine}
/>
@@ -134,8 +130,9 @@ export const EnginesOverview: React.FC = () => {
{canManageEngines && (
@@ -145,7 +142,7 @@ export const EnginesOverview: React.FC = () => {
- {
/>
}
onChange={handlePageChange(onMetaEnginesPagination)}
- onDeleteEngine={deleteEngine}
/>
>
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx
deleted file mode 100644
index fc37c3543af569..00000000000000
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx
+++ /dev/null
@@ -1,245 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import '../../../__mocks__/enterprise_search_url.mock';
-import { mockTelemetryActions, mountWithIntl, setMockValues } from '../../../__mocks__';
-
-import React from 'react';
-
-import { ReactWrapper, shallow } from 'enzyme';
-
-import { EuiBasicTable, EuiPagination, EuiButtonEmpty, EuiIcon, EuiTableRow } from '@elastic/eui';
-
-import { KibanaLogic } from '../../../shared/kibana';
-import { EuiLinkTo } from '../../../shared/react_router_helpers';
-
-import { TelemetryLogic } from '../../../shared/telemetry';
-import { EngineDetails } from '../engine/types';
-
-import { EnginesLogic } from './engines_logic';
-import { EnginesTable } from './engines_table';
-
-describe('EnginesTable', () => {
- const onChange = jest.fn();
- const onDeleteEngine = jest.fn();
-
- const data = [
- {
- name: 'test-engine',
- created_at: 'Fri, 1 Jan 1970 12:00:00 +0000',
- language: 'English',
- isMeta: false,
- document_count: 99999,
- field_count: 10,
- } as EngineDetails,
- ];
- const pagination = {
- pageIndex: 0,
- pageSize: 10,
- totalItemCount: 50,
- hidePerPageOptions: true,
- };
- const props = {
- items: data,
- loading: false,
- pagination,
- onChange,
- onDeleteEngine,
- };
-
- const resetMocks = () => {
- jest.clearAllMocks();
- setMockValues({
- myRole: {
- canManageEngines: false,
- },
- });
- };
-
- describe('basic table', () => {
- let wrapper: ReactWrapper;
- let table: ReactWrapper;
-
- beforeAll(() => {
- resetMocks();
- wrapper = mountWithIntl( );
- table = wrapper.find(EuiBasicTable);
- });
-
- it('renders', () => {
- expect(table).toHaveLength(1);
- expect(table.prop('pagination').totalItemCount).toEqual(50);
-
- const tableContent = table.text();
- expect(tableContent).toContain('test-engine');
- expect(tableContent).toContain('Jan 1, 1970');
- expect(tableContent).toContain('English');
- expect(tableContent).toContain('99,999');
- expect(tableContent).toContain('10');
-
- expect(table.find(EuiPagination).find(EuiButtonEmpty)).toHaveLength(5); // Should display 5 pages at 10 engines per page
- });
-
- it('contains engine links which send telemetry', () => {
- const engineLinks = wrapper.find(EuiLinkTo);
-
- engineLinks.forEach((link) => {
- expect(link.prop('to')).toEqual('/engines/test-engine');
- link.simulate('click');
-
- expect(mockTelemetryActions.sendAppSearchTelemetry).toHaveBeenCalledWith({
- action: 'clicked',
- metric: 'engine_table_link',
- });
- });
- });
-
- it('triggers onPaginate', () => {
- table.prop('onChange')({ page: { index: 4 } });
- expect(onChange).toHaveBeenCalledWith({ page: { index: 4 } });
- });
- });
-
- describe('loading', () => {
- it('passes the loading prop', () => {
- resetMocks();
- const wrapper = mountWithIntl( );
-
- expect(wrapper.find(EuiBasicTable).prop('loading')).toEqual(true);
- });
- });
-
- describe('noItemsMessage', () => {
- it('passes the noItemsMessage prop', () => {
- resetMocks();
- const wrapper = mountWithIntl( );
- expect(wrapper.find(EuiBasicTable).prop('noItemsMessage')).toEqual('No items.');
- });
- });
-
- describe('language field', () => {
- beforeAll(() => {
- resetMocks();
- });
-
- it('renders language when available', () => {
- const wrapper = mountWithIntl(
-
- );
- const tableContent = wrapper.find(EuiBasicTable).text();
- expect(tableContent).toContain('German');
- });
-
- it('renders the language as Universal if no language is set', () => {
- const wrapper = mountWithIntl(
-
- );
- const tableContent = wrapper.find(EuiBasicTable).text();
- expect(tableContent).toContain('Universal');
- });
-
- it('renders no language text if the engine is a Meta Engine', () => {
- const wrapper = mountWithIntl(
-
- );
- const tableContent = wrapper.find(EuiBasicTable).text();
- expect(tableContent).not.toContain('Universal');
- });
- });
-
- describe('actions', () => {
- it('will hide the action buttons if the user cannot manage/delete engines', () => {
- resetMocks();
- const wrapper = shallow( );
- const tableRow = wrapper.find(EuiTableRow).first();
-
- expect(tableRow.find(EuiIcon)).toHaveLength(0);
- });
-
- describe('when the user can manage/delete engines', () => {
- let wrapper: ReactWrapper;
- let tableRow: ReactWrapper;
- let actions: ReactWrapper;
-
- beforeEach(() => {
- resetMocks();
- setMockValues({
- myRole: {
- canManageEngines: true,
- },
- });
-
- wrapper = mountWithIntl( );
- tableRow = wrapper.find(EuiTableRow).first();
- actions = tableRow.find(EuiIcon);
- EnginesLogic.mount();
- });
-
- it('renders a manage action', () => {
- jest.spyOn(TelemetryLogic.actions, 'sendAppSearchTelemetry');
- jest.spyOn(KibanaLogic.values, 'navigateToUrl');
- actions.at(0).simulate('click');
-
- expect(TelemetryLogic.actions.sendAppSearchTelemetry).toHaveBeenCalled();
- expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith('/engines/test-engine');
- });
-
- describe('delete action', () => {
- it('shows the user a confirm message when the action is clicked', () => {
- jest.spyOn(global, 'confirm' as any).mockReturnValueOnce(true);
- actions.at(1).simulate('click');
- expect(global.confirm).toHaveBeenCalled();
- });
-
- it('clicking the action and confirming deletes the engine', () => {
- jest.spyOn(global, 'confirm' as any).mockReturnValueOnce(true);
- jest.spyOn(EnginesLogic.actions, 'deleteEngine');
-
- actions.at(1).simulate('click');
-
- expect(onDeleteEngine).toHaveBeenCalled();
- });
-
- it('clicking the action and not confirming does not delete the engine', () => {
- jest.spyOn(global, 'confirm' as any).mockReturnValueOnce(false);
- jest.spyOn(EnginesLogic.actions, 'deleteEngine');
-
- actions.at(1).simulate('click');
-
- expect(onDeleteEngine).toHaveBeenCalledTimes(0);
- });
- });
- });
- });
-});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx
deleted file mode 100644
index 3a65d9c449d6ec..00000000000000
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx
+++ /dev/null
@@ -1,210 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React, { ReactNode } from 'react';
-
-import { useActions, useValues } from 'kea';
-
-import {
- EuiBasicTable,
- EuiBasicTableColumn,
- CriteriaWithPagination,
- EuiTableActionsColumnType,
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { FormattedNumber } from '@kbn/i18n/react';
-
-import { MANAGE_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../shared/constants';
-import { KibanaLogic } from '../../../shared/kibana';
-import { EuiLinkTo } from '../../../shared/react_router_helpers';
-import { TelemetryLogic } from '../../../shared/telemetry';
-import { AppLogic } from '../../app_logic';
-import { UNIVERSAL_LANGUAGE } from '../../constants';
-import { ENGINE_PATH } from '../../routes';
-import { generateEncodedPath } from '../../utils/encode_path_params';
-import { FormattedDateTime } from '../../utils/formatted_date_time';
-import { EngineDetails } from '../engine/types';
-
-interface EnginesTableProps {
- items: EngineDetails[];
- loading: boolean;
- noItemsMessage?: ReactNode;
- pagination: {
- pageIndex: number;
- pageSize: number;
- totalItemCount: number;
- hidePerPageOptions: boolean;
- };
- onChange(criteria: CriteriaWithPagination): void;
- onDeleteEngine(engine: EngineDetails): void;
-}
-
-export const EnginesTable: React.FC = ({
- items,
- loading,
- noItemsMessage,
- pagination,
- onChange,
- onDeleteEngine,
-}) => {
- const { sendAppSearchTelemetry } = useActions(TelemetryLogic);
- const { navigateToUrl } = useValues(KibanaLogic);
- const {
- myRole: { canManageEngines },
- } = useValues(AppLogic);
-
- const generateEncodedEnginePath = (engineName: string) =>
- generateEncodedPath(ENGINE_PATH, { engineName });
- const sendEngineTableLinkClickTelemetry = () =>
- sendAppSearchTelemetry({
- action: 'clicked',
- metric: 'engine_table_link',
- });
-
- const columns: Array> = [
- {
- field: 'name',
- name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name', {
- defaultMessage: 'Name',
- }),
- render: (name: string) => (
-
- {name}
-
- ),
- width: '30%',
- truncateText: true,
- mobileOptions: {
- header: true,
- // Note: the below props are valid props per https://elastic.github.io/eui/#/tabular-content/tables (Responsive tables), but EUI's types have a bug reporting it as an error
- // @ts-ignore
- enlarge: true,
- fullWidth: true,
- truncateText: false,
- },
- },
- {
- field: 'created_at',
- name: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.column.createdAt',
- {
- defaultMessage: 'Created At',
- }
- ),
- dataType: 'string',
- render: (dateString: string) => ,
- },
- {
- field: 'language',
- name: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.column.language',
- {
- defaultMessage: 'Language',
- }
- ),
- dataType: 'string',
- render: (language: string, engine: EngineDetails) =>
- engine.isMeta ? '' : language || UNIVERSAL_LANGUAGE,
- },
- {
- field: 'document_count',
- name: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.column.documentCount',
- {
- defaultMessage: 'Document Count',
- }
- ),
- dataType: 'number',
- render: (number: number) => ,
- truncateText: true,
- },
- {
- field: 'field_count',
- name: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.column.fieldCount',
- {
- defaultMessage: 'Field Count',
- }
- ),
- dataType: 'number',
- render: (number: number) => ,
- truncateText: true,
- },
- ];
-
- const actionsColumn: EuiTableActionsColumnType = {
- name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.actions', {
- defaultMessage: 'Actions',
- }),
- actions: [
- {
- name: MANAGE_BUTTON_LABEL,
- description: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.manage.buttonDescription',
- {
- defaultMessage: 'Manage this engine',
- }
- ),
- type: 'icon',
- icon: 'eye',
- onClick: (engineDetails) => {
- sendEngineTableLinkClickTelemetry();
- navigateToUrl(generateEncodedEnginePath(engineDetails.name));
- },
- },
- {
- name: DELETE_BUTTON_LABEL,
- description: i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.delete.buttonDescription',
- {
- defaultMessage: 'Delete this engine',
- }
- ),
- type: 'icon',
- icon: 'trash',
- color: 'danger',
- onClick: (engine) => {
- if (
- window.confirm(
- i18n.translate(
- 'xpack.enterpriseSearch.appSearch.enginesOverview.table.action.delete.confirmationPopupMessage',
- {
- defaultMessage:
- 'Are you sure you want to permanently delete "{engineName}" and all of its content?',
- values: {
- engineName: engine.name,
- },
- }
- )
- )
- ) {
- onDeleteEngine(engine);
- }
- },
- },
- ],
- };
-
- if (canManageEngines) {
- columns.push(actionsColumn);
- }
-
- return (
-
- );
-};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx
index e2adce7dd76876..c76c50094aeddc 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx
@@ -4,8 +4,10 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import '../../../__mocks__/shallow_useeffect.mock';
+
import { setMockActions, setMockValues } from '../../../__mocks__/kea.mock';
+import '../../../__mocks__/shallow_useeffect.mock';
+import '../../__mocks__/engine_logic.mock';
import React from 'react';
@@ -37,7 +39,7 @@ describe('RelevanceTuning', () => {
resetSearchSettings: jest.fn(),
};
- const subject = () => shallow( );
+ const subject = () => shallow( );
beforeEach(() => {
jest.clearAllMocks();
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx
index 70adc91dd2b301..ab9bbaa9a1773e 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx
@@ -23,10 +23,6 @@ import { RelevanceTuningPreview } from './relevance_tuning_preview';
import { RelevanceTuningLogic } from '.';
-interface Props {
- engineBreadcrumb: string[];
-}
-
const EmptyCallout: React.FC = () => {
return (
{
);
};
-export const RelevanceTuning: React.FC = ({ engineBreadcrumb }) => {
+export const RelevanceTuning: React.FC = () => {
const { dataLoading, engineHasSchemaFields, unsavedChanges } = useValues(RelevanceTuningLogic);
const { initializeRelevanceTuning } = useActions(RelevanceTuningLogic);
@@ -95,7 +91,7 @@ export const RelevanceTuning: React.FC = ({ engineBreadcrumb }) => {
};
return (
-
+
{body()}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.test.tsx
index 9ed6e17c2bcd94..6f4333d94919b8 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.test.tsx
@@ -6,6 +6,7 @@
*/
import { setMockActions, setMockValues } from '../../../__mocks__/kea.mock';
+import '../../__mocks__/engine_logic.mock';
import React from 'react';
@@ -32,7 +33,7 @@ describe('RelevanceTuningLayout', () => {
setMockActions(actions);
});
- const subject = () => shallow( );
+ const subject = () => shallow( );
const findButtons = (wrapper: ShallowWrapper) =>
wrapper.find(EuiPageHeader).prop('rightSideItems') as React.ReactElement[];
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx
index f29cc12f20a98c..69043d80bd8d00 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx
@@ -17,16 +17,13 @@ import { SAVE_BUTTON_LABEL } from '../../../shared/constants';
import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../constants';
+import { getEngineBreadcrumbs } from '../engine';
import { RELEVANCE_TUNING_TITLE } from './constants';
import { RelevanceTuningCallouts } from './relevance_tuning_callouts';
import { RelevanceTuningLogic } from './relevance_tuning_logic';
-interface Props {
- engineBreadcrumb: string[];
-}
-
-export const RelevanceTuningLayout: React.FC = ({ engineBreadcrumb, children }) => {
+export const RelevanceTuningLayout: React.FC = ({ children }) => {
const { resetSearchSettings, updateSearchSettings } = useActions(RelevanceTuningLogic);
const { engineHasSchemaFields } = useValues(RelevanceTuningLogic);
@@ -66,7 +63,7 @@ export const RelevanceTuningLayout: React.FC = ({ engineBreadcrumb, child
return (
<>
-
+
{pageHeader()}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx
index 5365cc0f029f83..e5a901f8d07790 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx
@@ -5,23 +5,28 @@
* 2.0.
*/
-import '../../../__mocks__/shallow_useeffect.mock';
-
import { setMockValues, setMockActions } from '../../../__mocks__';
+import '../../../__mocks__/shallow_useeffect.mock';
+import '../../__mocks__/engine_logic.mock';
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
-import { EuiPageHeader } from '@elastic/eui';
+import { EuiPageHeader, EuiEmptyPrompt } from '@elastic/eui';
import { ResultSettings } from './result_settings';
import { ResultSettingsTable } from './result_settings_table';
import { SampleResponse } from './sample_response';
-describe('RelevanceTuning', () => {
+describe('ResultSettings', () => {
const values = {
+ schema: {
+ foo: 'text',
+ },
dataLoading: false,
+ stagedUpdates: true,
+ resultFieldsAtDefaultSettings: false,
};
const actions = {
@@ -32,12 +37,12 @@ describe('RelevanceTuning', () => {
};
beforeEach(() => {
+ jest.clearAllMocks();
setMockValues(values);
setMockActions(actions);
- jest.clearAllMocks();
});
- const subject = () => shallow( );
+ const subject = () => shallow( );
const findButtons = (wrapper: ShallowWrapper) =>
wrapper.find(EuiPageHeader).prop('rightSideItems') as React.ReactElement[];
@@ -48,7 +53,7 @@ describe('RelevanceTuning', () => {
});
it('initializes result settings data when mounted', () => {
- shallow( );
+ shallow( );
expect(actions.initializeResultSettingsData).toHaveBeenCalled();
});
@@ -69,6 +74,16 @@ describe('RelevanceTuning', () => {
expect(actions.saveResultSettings).toHaveBeenCalled();
});
+ it('renders the "save" button as disabled if the user has made no changes since the page loaded', () => {
+ setMockValues({
+ ...values,
+ stagedUpdates: false,
+ });
+ const buttons = findButtons(subject());
+ const saveButton = shallow(buttons[0]);
+ expect(saveButton.prop('disabled')).toBe(true);
+ });
+
it('renders a "restore defaults" button that will reset all values to their defaults', () => {
const buttons = findButtons(subject());
expect(buttons.length).toBe(3);
@@ -77,6 +92,16 @@ describe('RelevanceTuning', () => {
expect(actions.confirmResetAllFields).toHaveBeenCalled();
});
+ it('renders the "restore defaults" button as disabled if the values are already at their defaults', () => {
+ setMockValues({
+ ...values,
+ resultFieldsAtDefaultSettings: true,
+ });
+ const buttons = findButtons(subject());
+ const resetButton = shallow(buttons[1]);
+ expect(resetButton.prop('disabled')).toBe(true);
+ });
+
it('renders a "clear" button that will remove all selected options', () => {
const buttons = findButtons(subject());
expect(buttons.length).toBe(3);
@@ -84,4 +109,29 @@ describe('RelevanceTuning', () => {
clearButton.simulate('click');
expect(actions.clearAllFields).toHaveBeenCalled();
});
+
+ describe('when there is no schema yet', () => {
+ let wrapper: ShallowWrapper;
+ beforeAll(() => {
+ setMockValues({
+ ...values,
+ schema: {},
+ });
+ wrapper = subject();
+ });
+
+ it('will not render action buttons', () => {
+ const buttons = findButtons(wrapper);
+ expect(buttons.length).toBe(0);
+ });
+
+ it('will not render the main page content', () => {
+ expect(wrapper.find(ResultSettingsTable).exists()).toBe(false);
+ expect(wrapper.find(SampleResponse).exists()).toBe(false);
+ });
+
+ it('will render an "empty" message', () => {
+ expect(wrapper.find(EuiEmptyPrompt).exists()).toBe(true);
+ });
+ });
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx
index a513d0c1b9f34c..285d8fef357703 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx
@@ -9,7 +9,15 @@ import React, { useEffect } from 'react';
import { useActions, useValues } from 'kea';
-import { EuiPageHeader, EuiFlexGroup, EuiFlexItem, EuiButton, EuiButtonEmpty } from '@elastic/eui';
+import {
+ EuiPageHeader,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiButtonEmpty,
+ EuiEmptyPrompt,
+ EuiPanel,
+} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -18,10 +26,10 @@ import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { Loading } from '../../../shared/loading';
import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../constants';
+import { getEngineBreadcrumbs } from '../engine';
import { RESULT_SETTINGS_TITLE } from './constants';
import { ResultSettingsTable } from './result_settings_table';
-
import { SampleResponse } from './sample_response';
import { ResultSettingsLogic } from '.';
@@ -31,12 +39,10 @@ const CLEAR_BUTTON_LABEL = i18n.translate(
{ defaultMessage: 'Clear all values' }
);
-interface Props {
- engineBreadcrumb: string[];
-}
-
-export const ResultSettings: React.FC = ({ engineBreadcrumb }) => {
- const { dataLoading } = useValues(ResultSettingsLogic);
+export const ResultSettings: React.FC = () => {
+ const { dataLoading, schema, stagedUpdates, resultFieldsAtDefaultSettings } = useValues(
+ ResultSettingsLogic
+ );
const {
initializeResultSettingsData,
saveResultSettings,
@@ -49,46 +55,76 @@ export const ResultSettings: React.FC = ({ engineBreadcrumb }) => {
}, []);
if (dataLoading) return ;
+ const hasSchema = Object.keys(schema).length > 0;
return (
<>
-
+
- {SAVE_BUTTON_LABEL}
- ,
-
- {RESTORE_DEFAULTS_BUTTON_LABEL}
- ,
-
- {CLEAR_BUTTON_LABEL}
- ,
- ]}
+ rightSideItems={
+ hasSchema
+ ? [
+
+ {SAVE_BUTTON_LABEL}
+ ,
+
+ {RESTORE_DEFAULTS_BUTTON_LABEL}
+ ,
+
+ {CLEAR_BUTTON_LABEL}
+ ,
+ ]
+ : []
+ }
/>
-
-
-
-
-
-
-
-
+ {hasSchema ? (
+
+
+
+
+
+
+
+
+ ) : (
+
+
+ {i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.engine.resultSettings.noSchemaTitle',
+ { defaultMessage: 'Engine does not have a schema' }
+ )}
+
+ }
+ body={i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.engine.resultSettings.noSchemaDescription',
+ {
+ defaultMessage:
+ 'You need one! A schema is created for you after you index some documents.',
+ }
+ )}
+ />
+
+ )}
>
);
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.test.ts
index 8d9c33e3c9e680..437949982cb5aa 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.test.ts
@@ -19,6 +19,18 @@ import { ServerFieldResultSettingObject } from './types';
import { ResultSettingsLogic } from '.';
+// toHaveBeenCalledWith uses toEqual which is a more lenient check. We have a couple of
+// methods that need a stricter check, using `toStrictEqual`.
+const expectToHaveBeenCalledWithStrict = (
+ mock: jest.Mock,
+ expectedParam1: string,
+ expectedParam2: object
+) => {
+ const [param1, param2] = mock.mock.calls[0];
+ expect(param1).toEqual(expectedParam1);
+ expect(param2).toStrictEqual(expectedParam2);
+};
+
describe('ResultSettingsLogic', () => {
const { mount } = new LogicMounter(ResultSettingsLogic);
@@ -35,7 +47,6 @@ describe('ResultSettingsLogic', () => {
serverResultFields: {},
reducedServerResultFields: {},
resultFieldsAtDefaultSettings: true,
- resultFieldsEmpty: true,
stagedUpdates: false,
nonTextResultFields: {},
textResultFields: {},
@@ -322,30 +333,6 @@ describe('ResultSettingsLogic', () => {
});
});
- describe('resultFieldsEmpty', () => {
- it('should return true if all fields are empty', () => {
- mount({
- resultFields: {
- foo: {},
- bar: {},
- },
- });
-
- expect(ResultSettingsLogic.values.resultFieldsEmpty).toEqual(true);
- });
-
- it('should return false otherwise', () => {
- mount({
- resultFields: {
- foo: {},
- bar: { raw: true, snippet: true, snippetFallback: false },
- },
- });
-
- expect(ResultSettingsLogic.values.resultFieldsEmpty).toEqual(false);
- });
- });
-
describe('stagedUpdates', () => {
it('should return true if changes have been made since the last save', () => {
mount({
@@ -535,17 +522,20 @@ describe('ResultSettingsLogic', () => {
mount({
resultFields: {
foo: { raw: true, rawSize: 5, snippet: false },
- bar: { raw: true, rawSize: 5, snippet: false },
},
});
jest.spyOn(ResultSettingsLogic.actions, 'updateField');
ResultSettingsLogic.actions.clearRawSizeForField('foo');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('foo', {
- raw: true,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'foo',
+ {
+ raw: true,
+ snippet: false,
+ }
+ );
});
});
@@ -554,17 +544,20 @@ describe('ResultSettingsLogic', () => {
mount({
resultFields: {
foo: { raw: false, snippet: true, snippetSize: 5 },
- bar: { raw: true, rawSize: 5, snippet: false },
},
});
jest.spyOn(ResultSettingsLogic.actions, 'updateField');
ResultSettingsLogic.actions.clearSnippetSizeForField('foo');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('foo', {
- raw: false,
- snippet: true,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'foo',
+ {
+ raw: false,
+ snippet: true,
+ }
+ );
});
});
@@ -572,7 +565,6 @@ describe('ResultSettingsLogic', () => {
it('should toggle the raw value on for a field', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: { raw: false, snippet: false },
},
});
@@ -580,16 +572,19 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleRawForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: true,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: true,
+ snippet: false,
+ }
+ );
});
it('should maintain rawSize if it was set prior', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: { raw: false, rawSize: 10, snippet: false },
},
});
@@ -597,17 +592,20 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleRawForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: true,
- rawSize: 10,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: true,
+ rawSize: 10,
+ snippet: false,
+ }
+ );
});
it('should remove rawSize value when toggling off', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: { raw: true, rawSize: 5, snippet: false },
},
});
@@ -615,16 +613,19 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleRawForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: false,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: false,
+ snippet: false,
+ }
+ );
});
it('should still work if the object is empty', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: {},
},
});
@@ -632,9 +633,13 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleRawForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: true,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: true,
+ }
+ );
});
});
@@ -642,7 +647,6 @@ describe('ResultSettingsLogic', () => {
it('should toggle the raw value on for a field, always setting the snippet size to 100', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: { raw: false, snippet: false },
},
});
@@ -650,17 +654,20 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleSnippetForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: false,
- snippet: true,
- snippetSize: 100,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: false,
+ snippet: true,
+ snippetSize: 100,
+ }
+ );
});
it('should remove rawSize value when toggling off', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: { raw: false, snippet: true, snippetSize: 5 },
},
});
@@ -668,16 +675,19 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleSnippetForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: false,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: false,
+ snippet: false,
+ }
+ );
});
it('should still work if the object is empty', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5 },
bar: {},
},
});
@@ -685,10 +695,14 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.toggleSnippetForField('bar');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- snippet: true,
- snippetSize: 100,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ snippet: true,
+ snippetSize: 100,
+ }
+ );
});
});
@@ -697,19 +711,22 @@ describe('ResultSettingsLogic', () => {
mount({
resultFields: {
foo: { raw: false, snippet: true, snippetSize: 5, snippetFallback: true },
- bar: { raw: false, snippet: false },
},
});
jest.spyOn(ResultSettingsLogic.actions, 'updateField');
ResultSettingsLogic.actions.toggleSnippetFallbackForField('foo');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('foo', {
- raw: false,
- snippet: true,
- snippetSize: 5,
- snippetFallback: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'foo',
+ {
+ raw: false,
+ snippet: true,
+ snippetSize: 5,
+ snippetFallback: false,
+ }
+ );
});
});
@@ -717,7 +734,6 @@ describe('ResultSettingsLogic', () => {
it('should update the rawSize value for a field', () => {
mount({
resultFields: {
- foo: { raw: false, snippet: true, snippetSize: 5, snippetFallback: true },
bar: { raw: true, rawSize: 5, snippet: false },
},
});
@@ -725,11 +741,15 @@ describe('ResultSettingsLogic', () => {
ResultSettingsLogic.actions.updateRawSizeForField('bar', 7);
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('bar', {
- raw: true,
- rawSize: 7,
- snippet: false,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'bar',
+ {
+ raw: true,
+ rawSize: 7,
+ snippet: false,
+ }
+ );
});
});
@@ -738,19 +758,22 @@ describe('ResultSettingsLogic', () => {
mount({
resultFields: {
foo: { raw: false, snippet: true, snippetSize: 5, snippetFallback: true },
- bar: { raw: true, rawSize: 5, snippet: false },
},
});
jest.spyOn(ResultSettingsLogic.actions, 'updateField');
ResultSettingsLogic.actions.updateSnippetSizeForField('foo', 7);
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('foo', {
- raw: false,
- snippet: true,
- snippetSize: 7,
- snippetFallback: true,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'foo',
+ {
+ raw: false,
+ snippet: true,
+ snippetSize: 7,
+ snippetFallback: true,
+ }
+ );
});
});
@@ -759,17 +782,20 @@ describe('ResultSettingsLogic', () => {
mount({
resultFields: {
foo: { raw: false, snippet: true, snippetSize: 5 },
- bar: { raw: true, rawSize: 5, snippet: false },
},
});
jest.spyOn(ResultSettingsLogic.actions, 'updateField');
ResultSettingsLogic.actions.clearSnippetSizeForField('foo');
- expect(ResultSettingsLogic.actions.updateField).toHaveBeenCalledWith('foo', {
- raw: false,
- snippet: true,
- });
+ expectToHaveBeenCalledWithStrict(
+ ResultSettingsLogic.actions.updateField as jest.Mock,
+ 'foo',
+ {
+ raw: false,
+ snippet: true,
+ }
+ );
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts
index f518fc945bfbf0..af78543cda2b23 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts
@@ -24,7 +24,6 @@ import {
import {
areFieldsAtDefaultSettings,
- areFieldsEmpty,
clearAllFields,
convertServerResultFieldsToResultFields,
convertToServerFieldResultSetting,
@@ -198,10 +197,6 @@ export const ResultSettingsLogic = kea [selectors.resultFields],
(resultFields) => areFieldsAtDefaultSettings(resultFields),
],
- resultFieldsEmpty: [
- () => [selectors.resultFields],
- (resultFields) => areFieldsEmpty(resultFields),
- ],
stagedUpdates: [
() => [selectors.lastSavedResultFields, selectors.resultFields],
(lastSavedResultFields, resultFields) => !isEqual(lastSavedResultFields, resultFields),
@@ -256,10 +251,11 @@ export const ResultSettingsLogic = kea {
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.test.ts
index 5797e5c633bc7d..6fee0a25003575 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.test.ts
@@ -9,7 +9,6 @@ import { SchemaTypes } from '../../../shared/types';
import {
areFieldsAtDefaultSettings,
- areFieldsEmpty,
convertServerResultFieldsToResultFields,
convertToServerFieldResultSetting,
clearAllFields,
@@ -145,35 +144,6 @@ describe('splitResultFields', () => {
});
});
-describe('areFieldsEmpty', () => {
- it('should return true if all fields are empty objects', () => {
- expect(
- areFieldsEmpty({
- foo: {},
- bar: {},
- })
- ).toBe(true);
- });
- it('should return false otherwise', () => {
- expect(
- areFieldsEmpty({
- foo: {
- raw: true,
- rawSize: 5,
- snippet: false,
- snippetFallback: false,
- },
- bar: {
- raw: true,
- rawSize: 5,
- snippet: false,
- snippetFallback: false,
- },
- })
- ).toBe(false);
- });
-});
-
describe('areFieldsAtDefaultSettings', () => {
it('will return true if all settings for all fields are at their defaults', () => {
expect(
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.ts
index bde67c268ac168..ff88aaac193d78 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/utils.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { isEqual, isEmpty } from 'lodash';
+import { isEqual } from 'lodash';
import { Schema } from '../../../shared/types';
@@ -112,13 +112,6 @@ export const splitResultFields = (resultFields: FieldResultSettingObject, schema
return { textResultFields, nonTextResultFields };
};
-export const areFieldsEmpty = (fields: FieldResultSettingObject) => {
- const anyNonEmptyField = Object.values(fields).find((resultSettings) => {
- return !isEmpty(resultSettings);
- });
- return !anyNonEmptyField;
-};
-
export const areFieldsAtDefaultSettings = (fields: FieldResultSettingObject) => {
const anyNonDefaultSettingsValue = Object.values(fields).find((resultSettings) => {
return !isEqual(resultSettings, DEFAULT_FIELD_SETTINGS);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts
index 1fed750a86dc4f..2f9ff707f96317 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts
@@ -18,15 +18,6 @@ export const UPDATE_ROLE_MAPPING = i18n.translate(
{ defaultMessage: 'Update role mapping' }
);
-export const ADD_ROLE_MAPPING_TITLE = i18n.translate(
- 'xpack.enterpriseSearch.appSearch.roleMapping.newRoleMappingTitle',
- { defaultMessage: 'Add role mapping' }
-);
-export const MANAGE_ROLE_MAPPING_TITLE = i18n.translate(
- 'xpack.enterpriseSearch.appSearch.roleMapping.manageRoleMappingTitle',
- { defaultMessage: 'Manage role mapping' }
-);
-
export const EMPTY_ROLE_MAPPINGS_BODY = i18n.translate(
'xpack.enterpriseSearch.appSearch.roleMapping.emptyRoleMappingsBody',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
index ebd034caaedb39..610ceae8856f24 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
@@ -33,7 +33,11 @@ import {
DeleteMappingCallout,
RoleSelector,
} from '../../../shared/role_mapping';
-import { ROLE_MAPPINGS_TITLE } from '../../../shared/role_mapping/constants';
+import {
+ ROLE_MAPPINGS_TITLE,
+ ADD_ROLE_MAPPING_TITLE,
+ MANAGE_ROLE_MAPPING_TITLE,
+} from '../../../shared/role_mapping/constants';
import { AppLogic } from '../../app_logic';
import { roleHasScopedEngines } from '../../utils/role/has_scoped_engines';
@@ -42,8 +46,6 @@ import { Engine } from '../engine/types';
import {
SAVE_ROLE_MAPPING,
UPDATE_ROLE_MAPPING,
- ADD_ROLE_MAPPING_TITLE,
- MANAGE_ROLE_MAPPING_TITLE,
ADVANCED_ROLE_TYPES,
STANDARD_ROLE_TYPES,
ADVANCED_ROLE_SELECTORS_TITLE,
@@ -166,7 +168,7 @@ export const RoleMapping: React.FC = ({ isNew }) => {
-
+
{ROLE_TITLE}
@@ -189,7 +191,7 @@ export const RoleMapping: React.FC = ({ isNew }) => {
{hasAdvancedRoles && (
-
+
{ENGINE_ACCESS_TITLE}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
index 2ec2b93d1e24f3..e8d9e06142ef82 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
@@ -17,6 +17,7 @@ import {
EuiPageContent,
EuiPageContentBody,
EuiPageHeader,
+ EuiPanel,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -78,12 +79,14 @@ export const RoleMappings: React.FC = () => {
const addMappingButton = ;
const roleMappingEmptyState = (
- {EMPTY_ROLE_MAPPINGS_TITLE}}
- body={{EMPTY_ROLE_MAPPINGS_BODY}
}
- actions={addMappingButton}
- />
+
+ {EMPTY_ROLE_MAPPINGS_TITLE}}
+ body={{EMPTY_ROLE_MAPPINGS_BODY}
}
+ actions={addMappingButton}
+ />
+
);
const roleMappingsTable = (
@@ -127,7 +130,7 @@ export const RoleMappings: React.FC = () => {
pageTitle={ROLE_MAPPINGS_TITLE}
description={ROLE_MAPPINGS_DESCRIPTION}
/>
-
+ 0}>
{roleMappings.length === 0 ? roleMappingEmptyState : roleMappingsTable}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/add_role_mapping_button.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/add_role_mapping_button.tsx
index 0ae9f16ea2f9be..097302e0aa5f12 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/add_role_mapping_button.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/add_role_mapping_button.tsx
@@ -16,7 +16,7 @@ interface Props {
}
export const AddRoleMappingButton: React.FC = ({ path }) => (
-
+
{ADD_ROLE_MAPPING_BUTTON}
);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/attribute_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/attribute_selector.tsx
index 0417331be208d6..0ee093ed934c9b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/attribute_selector.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/attribute_selector.tsx
@@ -100,7 +100,7 @@ export const AttributeSelector: React.FC = ({
handleAuthProviderChange = () => null,
}) => {
return (
-
+
{ATTRIBUTE_SELECTOR_TITLE}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
index 8abab6d060a96e..a172fbae18d8fe 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
@@ -108,6 +108,16 @@ export const ROLE_MAPPINGS_TITLE = i18n.translate(
}
);
+export const ADD_ROLE_MAPPING_TITLE = i18n.translate(
+ 'xpack.enterpriseSearch.roleMapping.newRoleMappingTitle',
+ { defaultMessage: 'Add role mapping' }
+);
+
+export const MANAGE_ROLE_MAPPING_TITLE = i18n.translate(
+ 'xpack.enterpriseSearch.roleMapping.manageRoleMappingTitle',
+ { defaultMessage: 'Manage role mapping' }
+);
+
export const EMPTY_ROLE_MAPPINGS_TITLE = i18n.translate(
'xpack.enterpriseSearch.roleMapping.emptyRoleMappingsTitle',
{
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.scss
similarity index 81%
rename from x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/index.ts
rename to x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.scss
index c68b2c170df5b1..6eaa3b92579367 100644
--- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.scss
@@ -5,4 +5,8 @@
* 2.0.
*/
-export { EmptyPrompt } from './empty_prompt';
+.roleMappingsTable {
+ td {
+ vertical-align: top;
+ }
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
index 6db62e4c10b6bb..a5f6fb368c96f1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
@@ -29,6 +29,8 @@ import { MANAGE_BUTTON_LABEL } from '../constants';
import { EuiLinkTo } from '../react_router_helpers';
import { RoleRules } from '../types';
+import './role_mappings_table.scss';
+
import {
ANY_AUTH_PROVIDER,
ANY_AUTH_PROVIDER_OPTION_LABEL,
@@ -108,7 +110,7 @@ export const RoleMappingsTable: React.FC = ({
{filteredResults.length > 0 ? (
-
+
{EXTERNAL_ATTRIBUTE_LABEL}
{ATTRIBUTE_VALUE_LABEL}
@@ -152,7 +154,7 @@ export const RoleMappingsTable: React.FC = ({
{authProvider.map(getAuthProviderDisplayValue).join(', ')}
)}
-
+
{id && {MANAGE_BUTTON_LABEL} }
{toolTip && }
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx
index f2edc04a5661c4..51cdcc688e682b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx
@@ -42,7 +42,9 @@ export const WorkplaceSearchNav: React.FC = ({
{NAV.GROUPS}
- {NAV.ROLE_MAPPINGS}
+
+ {NAV.ROLE_MAPPINGS}
+
{NAV.SECURITY}
{NAV.SETTINGS}
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts
index d7716735067617..9f758cacdfce35 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts
@@ -40,7 +40,7 @@ export const NAV = {
defaultMessage: 'Content',
}),
ROLE_MAPPINGS: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.roleMappings', {
- defaultMessage: 'Role Mappings',
+ defaultMessage: 'Users & roles',
}),
SECURITY: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.security', {
defaultMessage: 'Security',
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx
index 1bf8239a6b3994..9689ecfae4a94d 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx
@@ -62,9 +62,10 @@ export const SaveCustom: React.FC = ({
}) => (
<>
{header}
+
-
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx
index c1f526e24b8e22..54be43596a4314 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx
@@ -7,7 +7,6 @@
import '../../../../../__mocks__/shallow_useeffect.mock';
-import { mockKibanaValues } from '../../../../../__mocks__';
import { setMockValues, setMockActions } from '../../../../../__mocks__';
import { exampleResult } from '../../../../__mocks__/content_sources.mock';
@@ -25,11 +24,11 @@ import { DisplaySettings } from './display_settings';
import { FieldEditorModal } from './field_editor_modal';
describe('DisplaySettings', () => {
- const { navigateToUrl } = mockKibanaValues;
const { exampleDocuments, searchResultConfig } = exampleResult;
const initializeDisplaySettings = jest.fn();
const setServerData = jest.fn();
const setColorField = jest.fn();
+ const handleSelectedTabChanged = jest.fn();
const values = {
isOrganization: true,
@@ -46,6 +45,7 @@ describe('DisplaySettings', () => {
initializeDisplaySettings,
setServerData,
setColorField,
+ handleSelectedTabChanged,
});
setMockValues({ ...values });
});
@@ -83,7 +83,7 @@ describe('DisplaySettings', () => {
const tabsEl = wrapper.find(EuiTabbedContent);
tabsEl.prop('onTabClick')!(tabs[0]);
- expect(navigateToUrl).toHaveBeenCalledWith('/sources/123/display_settings/');
+ expect(handleSelectedTabChanged).toHaveBeenCalledWith('search_results');
});
it('handles second tab click', () => {
@@ -91,7 +91,7 @@ describe('DisplaySettings', () => {
const tabsEl = wrapper.find(EuiTabbedContent);
tabsEl.prop('onTabClick')!(tabs[1]);
- expect(navigateToUrl).toHaveBeenCalledWith('/sources/123/display_settings/result_detail');
+ expect(handleSelectedTabChanged).toHaveBeenCalledWith('result_detail');
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx
index e39a8d17e406c9..3441e5fcbaf82c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx
@@ -20,19 +20,11 @@ import {
} from '@elastic/eui';
import { clearFlashMessages } from '../../../../../shared/flash_messages';
-import { KibanaLogic } from '../../../../../shared/kibana';
import { Loading } from '../../../../../shared/loading';
import { UnsavedChangesPrompt } from '../../../../../shared/unsaved_changes_prompt';
-import { AppLogic } from '../../../../app_logic';
import { ViewContentHeader } from '../../../../components/shared/view_content_header';
import { SAVE_BUTTON } from '../../../../constants';
-import {
- DISPLAY_SETTINGS_RESULT_DETAIL_PATH,
- DISPLAY_SETTINGS_SEARCH_RESULT_PATH,
- getContentSourcePath,
-} from '../../../../routes';
-
import {
UNSAVED_MESSAGE,
DISPLAY_SETTINGS_TITLE,
@@ -42,7 +34,7 @@ import {
SEARCH_RESULTS_LABEL,
RESULT_DETAIL_LABEL,
} from './constants';
-import { DisplaySettingsLogic } from './display_settings_logic';
+import { DisplaySettingsLogic, TabId } from './display_settings_logic';
import { FieldEditorModal } from './field_editor_modal';
import { ResultDetail } from './result_detail';
import { SearchResults } from './search_results';
@@ -52,19 +44,20 @@ interface DisplaySettingsProps {
}
export const DisplaySettings: React.FC = ({ tabId }) => {
- const { initializeDisplaySettings, setServerData } = useActions(DisplaySettingsLogic);
+ const { initializeDisplaySettings, setServerData, handleSelectedTabChanged } = useActions(
+ DisplaySettingsLogic
+ );
const {
dataLoading,
- sourceId,
addFieldModalVisible,
unsavedChanges,
exampleDocuments,
+ navigatingBetweenTabs,
} = useValues(DisplaySettingsLogic);
- const { isOrganization } = useValues(AppLogic);
-
const hasDocuments = exampleDocuments.length > 0;
+ const hasUnsavedChanges = hasDocuments && unsavedChanges;
useEffect(() => {
initializeDisplaySettings();
@@ -87,12 +80,7 @@ export const DisplaySettings: React.FC = ({ tabId }) => {
] as EuiTabbedContentTab[];
const onSelectedTabChanged = (tab: EuiTabbedContentTab) => {
- const path =
- tab.id === tabs[1].id
- ? getContentSourcePath(DISPLAY_SETTINGS_RESULT_DETAIL_PATH, sourceId, isOrganization)
- : getContentSourcePath(DISPLAY_SETTINGS_SEARCH_RESULT_PATH, sourceId, isOrganization);
-
- KibanaLogic.values.navigateToUrl(path);
+ handleSelectedTabChanged(tab.id as TabId);
};
const handleFormSubmit = (e: FormEvent) => {
@@ -103,7 +91,7 @@ export const DisplaySettings: React.FC = ({ tabId }) => {
return (
<>