diff --git a/dev_docs/assets/kibana_template_solution_nav.png b/dev_docs/assets/kibana_template_solution_nav.png
new file mode 100644
index 0000000000000..4ffec1990ed0a
Binary files /dev/null and b/dev_docs/assets/kibana_template_solution_nav.png differ
diff --git a/dev_docs/assets/kibana_template_solution_nav_mobile.png b/dev_docs/assets/kibana_template_solution_nav_mobile.png
new file mode 100644
index 0000000000000..487114f7a344a
Binary files /dev/null and b/dev_docs/assets/kibana_template_solution_nav_mobile.png differ
diff --git a/dev_docs/tutorials/kibana_page_template.mdx b/dev_docs/tutorials/kibana_page_template.mdx
index aa38890a8ac9e..d9605ac5643ba 100644
--- a/dev_docs/tutorials/kibana_page_template.mdx
+++ b/dev_docs/tutorials/kibana_page_template.mdx
@@ -9,13 +9,13 @@ tags: ['kibana', 'dev', 'ui', 'tutorials']
`KibanaPageTemplate` is a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements and patterns.
-Refer to EUI's documentation on [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) for constructing page layouts.
+Refer to EUI's documentation on [**EuiPageTemplate**](https://elastic.github.io/eui/#/layout/page) for constructing page layouts.
## `isEmptyState`
Use the `isEmptyState` prop for when there is no page content to show. For example, before the user has created something, when no search results are found, before data is populated, or when permissions aren't met.
-The default empty state uses any `pageHeader` info provided to populate an [`EuiEmptyPrompt`](https://elastic.github.io/eui/#/display/empty-prompt) and uses the `centeredBody` template type.
+The default empty state uses any `pageHeader` info provided to populate an [**EuiEmptyPrompt**](https://elastic.github.io/eui/#/display/empty-prompt) and uses the `centeredBody` template type.
```tsx
+ {...}
+
+```
+
+
+![Screenshot of Stack Management empty state with a provided solution navigation shown on the left, outlined in pink.](../assets/kibana_template_solution_nav.png)
+
+![Screenshots of Stack Management page in mobile view. Menu closed on the left, menu open on the right.](../assets/kibana_template_solution_nav_mobile.png)
diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml
index 7f2d0768a1fb9..a585a0fc7542f 100644
--- a/packages/kbn-optimizer/limits.yml
+++ b/packages/kbn-optimizer/limits.yml
@@ -9,7 +9,7 @@ pageLoadAssetSize:
charts: 195358
cloud: 21076
console: 46091
- core: 414000
+ core: 432925
crossClusterReplication: 65408
dashboard: 374194
dashboardEnhanced: 65646
diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss
index 936b41e7682bb..3a748f3ceb6fd 100644
--- a/src/core/public/rendering/_base.scss
+++ b/src/core/public/rendering/_base.scss
@@ -49,6 +49,13 @@
top: $headerHeight;
height: calc(100% - #{$headerHeight});
}
+
+ @include euiBreakpoint('m', 'l', 'xl') {
+ .euiPageSideBar--sticky {
+ max-height: calc(100vh - #{$headerHeight});
+ top: #{$headerHeight};
+ }
+ }
}
.kbnBody {
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 3b2feeecabb7c..2f54bd1d818b5 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
@@ -276,7 +276,7 @@ kibana_vars=(
xpack.reporting.roles.allow
xpack.reporting.roles.enabled
xpack.rollup.enabled
- xpack.ruleRegistry.unsafe.write.enabled
+ xpack.ruleRegistry.write.enabled
xpack.searchprofiler.enabled
xpack.security.audit.enabled
xpack.security.audit.appender.type
diff --git a/src/plugins/kibana_react/public/page_template/__snapshots__/page_template.test.tsx.snap b/src/plugins/kibana_react/public/page_template/__snapshots__/page_template.test.tsx.snap
index 89fa05615a039..a80e3a67fb2db 100644
--- a/src/plugins/kibana_react/public/page_template/__snapshots__/page_template.test.tsx.snap
+++ b/src/plugins/kibana_react/public/page_template/__snapshots__/page_template.test.tsx.snap
@@ -2,6 +2,7 @@
exports[`KibanaPageTemplate render basic template 1`] = `
`;
exports[`KibanaPageTemplate render custom empty prompt only 1`] = `
@@ -33,6 +45,7 @@ exports[`KibanaPageTemplate render custom empty prompt only 1`] = `
exports[`KibanaPageTemplate render custom empty prompt with page header 1`] = `
@@ -58,6 +76,12 @@ exports[`KibanaPageTemplate render custom empty prompt with page header 1`] = `
exports[`KibanaPageTemplate render default empty prompt 1`] = `
@@ -72,7 +96,76 @@ exports[`KibanaPageTemplate render default empty prompt 1`] = `
test
}
+ iconColor=""
iconType="test"
/>
`;
+
+exports[`KibanaPageTemplate render solutionNav 1`] = `
+
+ }
+ pageSideBarProps={
+ Object {
+ "className": "kbnPageTemplate__pageSideBar",
+ }
+ }
+ restrictWidth={true}
+/>
+`;
diff --git a/src/plugins/kibana_react/public/page_template/page_template.scss b/src/plugins/kibana_react/public/page_template/page_template.scss
new file mode 100644
index 0000000000000..4b8513311114d
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/page_template.scss
@@ -0,0 +1,15 @@
+$euiSideNavEmphasizedBackgroundColor: transparentize($euiColorLightShade, .7);
+
+.kbnPageTemplate__pageSideBar {
+ padding: $euiSizeL;
+ background:
+ linear-gradient(160deg, $euiSideNavEmphasizedBackgroundColor 0, $euiSideNavEmphasizedBackgroundColor $euiSizeXL, rgba(#FFF, 0) 0),
+ linear-gradient(175deg, $euiSideNavEmphasizedBackgroundColor 0, $euiSideNavEmphasizedBackgroundColor $euiSize, rgba(#FFF, 0) 0);
+}
+
+@include euiBreakpoint('xs','s') {
+ .kbnPageTemplate__pageSideBar {
+ width: auto;
+ padding: 0;
+ }
+}
diff --git a/src/plugins/kibana_react/public/page_template/page_template.test.tsx b/src/plugins/kibana_react/public/page_template/page_template.test.tsx
index 2ad9a81e7916c..43f96a6c2b98c 100644
--- a/src/plugins/kibana_react/public/page_template/page_template.test.tsx
+++ b/src/plugins/kibana_react/public/page_template/page_template.test.tsx
@@ -10,6 +10,46 @@ import React from 'react';
import { shallow } from 'enzyme';
import { KibanaPageTemplate } from './page_template';
import { EuiEmptyPrompt } from '@elastic/eui';
+import { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+
+const navItems: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
describe('KibanaPageTemplate', () => {
test('render default empty prompt', () => {
@@ -66,4 +106,23 @@ describe('KibanaPageTemplate', () => {
);
expect(component).toMatchSnapshot();
});
+
+ test('render solutionNav', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
});
diff --git a/src/plugins/kibana_react/public/page_template/page_template.tsx b/src/plugins/kibana_react/public/page_template/page_template.tsx
index eb834d00402ef..0bbf97ca6ddb5 100644
--- a/src/plugins/kibana_react/public/page_template/page_template.tsx
+++ b/src/plugins/kibana_react/public/page_template/page_template.tsx
@@ -5,10 +5,21 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
+import './page_template.scss';
-import { EuiEmptyPrompt, EuiPageTemplate, EuiPageTemplateProps } from '@elastic/eui';
import React, { FunctionComponent } from 'react';
+import classNames from 'classnames';
+
+import { EuiEmptyPrompt, EuiPageTemplate, EuiPageTemplateProps } from '@elastic/eui';
+
+import {
+ KibanaPageTemplateSolutionNav,
+ KibanaPageTemplateSolutionNavProps,
+} from './solution_nav/solution_nav';
+/**
+ * A thin wrapper around EuiPageTemplate with a few Kibana specific additions
+ */
export type KibanaPageTemplateProps = EuiPageTemplateProps & {
/**
* Changes the template type depending on other props provided.
@@ -17,6 +28,10 @@ export type KibanaPageTemplateProps = EuiPageTemplateProps & {
* With `pageHeader` and `children`: Uses `centeredContent`
*/
isEmptyState?: boolean;
+ /**
+ * Quick creation of EuiSideNav. Hooks up mobile instance too
+ */
+ solutionNav?: KibanaPageTemplateSolutionNavProps;
};
export const KibanaPageTemplate: FunctionComponent = ({
@@ -27,6 +42,8 @@ export const KibanaPageTemplate: FunctionComponent = ({
restrictWidth = true,
bottomBar,
bottomBarProps,
+ pageSideBar,
+ solutionNav,
...rest
}) => {
// Needed for differentiating between union types
@@ -38,6 +55,13 @@ export const KibanaPageTemplate: FunctionComponent = ({
};
}
+ /**
+ * Create the solution nav component
+ */
+ if (solutionNav) {
+ pageSideBar = ;
+ }
+
/**
* An easy way to create the right content for empty pages
*/
@@ -48,6 +72,7 @@ export const KibanaPageTemplate: FunctionComponent = ({
children = (
{pageTitle} : undefined}
body={description ? {description}
: undefined}
actions={rightSideItems}
@@ -62,8 +87,14 @@ export const KibanaPageTemplate: FunctionComponent = ({
return (
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap b/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap
new file mode 100644
index 0000000000000..0267357709534
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap
@@ -0,0 +1,238 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplateSolutionNav accepts EuiSideNavProps 1`] = `
+
+
+
+
+ Solution
+
+
+
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
+
+exports[`KibanaPageTemplateSolutionNav renders 1`] = `
+
+
+
+
+ Solution
+
+
+
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
+
+exports[`KibanaPageTemplateSolutionNav renders with icon 1`] = `
+
+
+
+
+
+ Solution
+
+
+
+
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav_avatar.test.tsx.snap b/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav_avatar.test.tsx.snap
new file mode 100644
index 0000000000000..ede09c5652c31
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav_avatar.test.tsx.snap
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplateSolutionNavAvatar renders 1`] = `
+
+`;
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/index.ts b/src/plugins/kibana_react/public/page_template/solution_nav/index.ts
new file mode 100644
index 0000000000000..abbcde9a08486
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/index.ts
@@ -0,0 +1,13 @@
+/*
+ * 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 { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav';
+export {
+ KibanaPageTemplateSolutionNavAvatar,
+ KibanaPageTemplateSolutionNavAvatarProps,
+} from './solution_nav_avatar';
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.scss b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.scss
new file mode 100644
index 0000000000000..bdb88b2ab7baa
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.scss
@@ -0,0 +1,22 @@
+.kbnPageTemplateSolutionNav__title {
+ margin-bottom: $euiSizeL;
+}
+
+@include euiBreakpoint('xs','s') {
+ .kbnPageTemplateSolutionNav {
+ // TODO: Fix in EUI
+ .euiSideNav__mobileToggle {
+ height: auto;
+ font-size: $euiFontSizeM;
+
+ .euiButtonEmpty__text {
+ overflow: visible;
+ }
+ }
+ }
+
+ // Rely on the `mobileToggle` of the EuiSideNav component to title the navigation list
+ .kbnPageTemplateSolutionNav__title {
+ display: none;
+ }
+}
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.test.tsx b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.test.tsx
new file mode 100644
index 0000000000000..1ba6cc924cda1
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.test.tsx
@@ -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 React from 'react';
+import { shallow } from 'enzyme';
+import { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav';
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+describe('KibanaPageTemplateSolutionNav', () => {
+ test('renders', () => {
+ const component = shallow( );
+ expect(component).toMatchSnapshot();
+ });
+
+ test('renders with icon', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
+ test('accepts EuiSideNavProps', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.tsx b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.tsx
new file mode 100644
index 0000000000000..4aa456f716dbd
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav.tsx
@@ -0,0 +1,103 @@
+/*
+ * 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 './solution_nav.scss';
+
+import React, { FunctionComponent, useState } from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { EuiTitle, EuiSideNav, EuiSideNavProps, htmlIdGenerator } from '@elastic/eui';
+
+import {
+ KibanaPageTemplateSolutionNavAvatar,
+ KibanaPageTemplateSolutionNavAvatarProps,
+} from './solution_nav_avatar';
+
+export type KibanaPageTemplateSolutionNavProps = EuiSideNavProps<{}> & {
+ /**
+ * Name of the solution, i.e. "Observability"
+ */
+ name: KibanaPageTemplateSolutionNavAvatarProps['name'];
+ /**
+ * Solution logo, i.e. "logoObservability"
+ */
+ icon?: KibanaPageTemplateSolutionNavAvatarProps['iconType'];
+};
+
+/**
+ * A wrapper around EuiSideNav but also creates the appropriate title with optional solution logo
+ */
+export const KibanaPageTemplateSolutionNav: FunctionComponent = ({
+ name,
+ icon,
+ items,
+ ...rest
+}) => {
+ const [isSideNavOpenOnMobile, setisSideNavOpenOnMobile] = useState(false);
+ const toggleOpenOnMobile = () => {
+ setisSideNavOpenOnMobile(!isSideNavOpenOnMobile);
+ };
+
+ /**
+ * Create the avatar.
+ */
+ let solutionAvatar;
+ if (icon) {
+ solutionAvatar = ;
+ }
+
+ /**
+ * Create the required title.
+ * a11y: Since the heading can't be nested inside ``, we have to hook them up via `aria-labelledby`
+ */
+ const titleID = htmlIdGenerator('kbnPageTemplateSolutionNav__title')();
+ const solutionNavTitle = (
+
+
+ {solutionAvatar}
+ {name}
+
+
+ );
+
+ /**
+ * Create the side nav component
+ */
+ let sideNav;
+ if (items) {
+ const mobileTitleText = (
+
+ );
+
+ sideNav = (
+
+ {solutionAvatar}
+ {mobileTitleText}
+
+ }
+ toggleOpenOnMobile={toggleOpenOnMobile}
+ isOpenOnMobile={isSideNavOpenOnMobile}
+ items={items}
+ {...rest}
+ />
+ );
+ }
+
+ return (
+
+ {solutionNavTitle}
+ {sideNav}
+
+ );
+};
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.scss b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.scss
new file mode 100644
index 0000000000000..1fb22ae4b285b
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.scss
@@ -0,0 +1,4 @@
+.kbnPageTemplateSolutionNavAvatar {
+ @include euiBottomShadowSmall;
+ margin-right: $euiSize;
+}
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.test.tsx b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.test.tsx
new file mode 100644
index 0000000000000..497b14bc70236
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.test.tsx
@@ -0,0 +1,20 @@
+/*
+ * 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 { shallow } from 'enzyme';
+import { KibanaPageTemplateSolutionNavAvatar } from './solution_nav_avatar';
+
+describe('KibanaPageTemplateSolutionNavAvatar', () => {
+ test('renders', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.tsx b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.tsx
new file mode 100644
index 0000000000000..6696e70b9d3aa
--- /dev/null
+++ b/src/plugins/kibana_react/public/page_template/solution_nav/solution_nav_avatar.tsx
@@ -0,0 +1,31 @@
+/*
+ * 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 './solution_nav_avatar.scss';
+
+import React, { FunctionComponent } from 'react';
+import classNames from 'classnames';
+
+import { EuiAvatar, EuiAvatarProps } from '@elastic/eui';
+
+export type KibanaPageTemplateSolutionNavAvatarProps = EuiAvatarProps;
+
+/**
+ * Applies extra styling to a typical EuiAvatar
+ */
+export const KibanaPageTemplateSolutionNavAvatar: FunctionComponent = ({
+ className,
+ ...rest
+}) => {
+ return (
+
+ );
+};
diff --git a/x-pack/plugins/observability/README.md b/x-pack/plugins/observability/README.md
index b882891921cde..943a7482a25ee 100644
--- a/x-pack/plugins/observability/README.md
+++ b/x-pack/plugins/observability/README.md
@@ -19,7 +19,7 @@ This will only enable the UI for these pages. In order to have alert data indexe
you'll need to enable writing in the [Rule Registry plugin](../rule_registry/README.md):
```yaml
-xpack.ruleRegistry.unsafe.write.enabled: true
+xpack.ruleRegistry.write.enabled: true
```
When both of the these are set to `true`, your alerts should show on the alerts page.
@@ -47,3 +47,41 @@ HTML coverage report can be found in target/coverage/jest after tests have run.
```bash
open target/coverage/jest/index.html
```
+
+## API integration testing
+
+API tests are separated in two suites:
+
+- a basic license test suite
+- a trial license test suite (the equivalent of gold+)
+
+This requires separate test servers and test runners.
+
+### Basic
+
+```
+# Start server
+node scripts/functional_tests_server --config x-pack/test/observability_api_integration/basic/config.ts
+
+# Run tests
+node scripts/functional_test_runner --config x-pack/test/observability_api_integration/basic/config.ts
+```
+
+The API tests for "basic" are located in `x-pack/test/observability_api_integration/basic/tests`.
+
+### Trial
+
+```
+# Start server
+node scripts/functional_tests_server --config x-pack/test/observability_api_integration/trial/config.ts
+
+# Run tests
+node scripts/functional_test_runner --config x-pack/test/observability_api_integration/trial/config.ts
+```
+
+The API tests for "trial" are located in `x-pack/test/observability_api_integration/trial/tests`.
+
+### API test tips
+
+- For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme)
+- To update snapshots append `--updateSnapshots` to the functional_test_runner command
diff --git a/x-pack/plugins/observability/common/typings.ts b/x-pack/plugins/observability/common/typings.ts
index 2a7f9edffc4af..bd10543ef389b 100644
--- a/x-pack/plugins/observability/common/typings.ts
+++ b/x-pack/plugins/observability/common/typings.ts
@@ -4,5 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
+import * as t from 'io-ts';
export type Maybe = T | null | undefined;
+
+export const alertStatusRt = t.union([t.literal('all'), t.literal('open'), t.literal('closed')]);
+export type AlertStatus = t.TypeOf;
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table.tsx
index f377186623a03..31e59679854b1 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_table.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table.tsx
@@ -66,16 +66,16 @@ export function AlertsTable(props: AlertsTableProps) {
return active ? (
) : (
diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx
index 1f468a70d0976..7b8055c82f071 100644
--- a/x-pack/plugins/observability/public/pages/alerts/index.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx
@@ -12,21 +12,23 @@ import {
EuiFlexItem,
EuiLink,
EuiPageTemplate,
+ EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import React from 'react';
-import { useHistory } from 'react-router-dom';
-import { format, parse } from 'url';
import {
ALERT_START,
- EVENT_ACTION,
+ ALERT_STATUS,
RULE_ID,
RULE_NAME,
} from '@kbn/rule-data-utils/target/technical_field_names';
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import { format, parse } from 'url';
import {
ParsedTechnicalFields,
parseTechnicalFields,
} from '../../../../rule_registry/common/parse_technical_fields';
+import type { AlertStatus } from '../../../common/typings';
import { asDuration, asPercent } from '../../../common/utils/formatters';
import { ExperimentalBadge } from '../../components/shared/experimental_badge';
import { useFetcher } from '../../hooks/use_fetcher';
@@ -37,6 +39,7 @@ import type { ObservabilityAPIReturnType } from '../../services/call_observabili
import { getAbsoluteDateRange } from '../../utils/date';
import { AlertsSearchBar } from './alerts_search_bar';
import { AlertsTable } from './alerts_table';
+import { StatusFilter } from './status_filter';
export type TopAlertResponse = ObservabilityAPIReturnType<'GET /api/observability/rules/alerts/top'>[number];
@@ -57,7 +60,7 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
const { prepend } = core.http.basePath;
const history = useHistory();
const {
- query: { rangeFrom = 'now-15m', rangeTo = 'now', kuery = '' },
+ query: { rangeFrom = 'now-15m', rangeTo = 'now', kuery = '', status = 'open' },
} = routeParams;
// In a future milestone we'll have a page dedicated to rule management in
@@ -81,6 +84,7 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
start,
end,
kuery,
+ status,
},
},
}).then((alerts) => {
@@ -108,15 +112,24 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
},
})
: undefined,
- active: parsedFields[EVENT_ACTION] !== 'close',
+ active: parsedFields[ALERT_STATUS] !== 'closed',
start: new Date(parsedFields[ALERT_START]!).getTime(),
};
});
});
},
- [kuery, observabilityRuleTypeRegistry, rangeFrom, rangeTo]
+ [kuery, observabilityRuleTypeRegistry, rangeFrom, rangeTo, status]
);
+ function setStatusFilter(value: AlertStatus) {
+ const nextSearchParams = new URLSearchParams(history.location.search);
+ nextSearchParams.set('status', value);
+ history.push({
+ ...history.location,
+ search: nextSearchParams.toString(),
+ });
+ }
+
return (
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
);
diff --git a/x-pack/plugins/observability/public/pages/alerts/status_filter.stories.tsx b/x-pack/plugins/observability/public/pages/alerts/status_filter.stories.tsx
new file mode 100644
index 0000000000000..851e0cb6c3ddd
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/status_filter.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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, { ComponentProps, useState } from 'react';
+import type { AlertStatus } from '../../../common/typings';
+import { StatusFilter } from './status_filter';
+
+type Args = ComponentProps;
+
+export default {
+ title: 'app/Alerts/StatusFilter',
+ component: StatusFilter,
+ argTypes: {
+ onChange: { action: 'change' },
+ },
+};
+
+export function Example({ onChange }: Args) {
+ const [status, setStatus] = useState('open');
+
+ return (
+ {
+ setStatus(value);
+ onChange(value);
+ }}
+ />
+ );
+}
diff --git a/x-pack/plugins/observability/public/pages/alerts/status_filter.test.tsx b/x-pack/plugins/observability/public/pages/alerts/status_filter.test.tsx
new file mode 100644
index 0000000000000..72e07ebb8cadf
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/status_filter.test.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 { render } from '@testing-library/react';
+import React from 'react';
+import type { AlertStatus } from '../../../common/typings';
+import { StatusFilter } from './status_filter';
+
+describe('StatusFilter', () => {
+ describe('render', () => {
+ it('renders', () => {
+ const onChange = jest.fn();
+ const status: AlertStatus = 'all';
+ const props = { onChange, status };
+
+ expect(() => render( )).not.toThrowError();
+ });
+
+ (['all', 'open', 'closed'] as AlertStatus[]).map((status) => {
+ describe(`when clicking the ${status} button`, () => {
+ it('calls the onChange callback with "${status}"', () => {
+ const onChange = jest.fn();
+ const props = { onChange, status };
+
+ const { getByTestId } = render( );
+ const button = getByTestId(`StatusFilter ${status} button`);
+
+ button.click();
+
+ expect(onChange).toHaveBeenCalledWith(status);
+ });
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/observability/public/pages/alerts/status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/status_filter.tsx
new file mode 100644
index 0000000000000..26169717d2967
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/status_filter.tsx
@@ -0,0 +1,56 @@
+/*
+ * 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 { EuiFilterButton, EuiFilterGroup } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import type { AlertStatus } from '../../../common/typings';
+
+export interface StatusFilterProps {
+ status: AlertStatus;
+ onChange: (value: AlertStatus) => void;
+}
+
+export function StatusFilter({ status = 'open', onChange }: StatusFilterProps) {
+ return (
+
+ onChange('open')}
+ withNext={true}
+ >
+ {i18n.translate('xpack.observability.alerts.statusFilter.openButtonLabel', {
+ defaultMessage: 'Open',
+ })}
+
+ onChange('closed')}
+ withNext={true}
+ >
+ {i18n.translate('xpack.observability.alerts.statusFilter.closedButtonLabel', {
+ defaultMessage: 'Closed',
+ })}
+
+ onChange('all')}
+ >
+ {i18n.translate('xpack.observability.alerts.statusFilter.allButtonLabel', {
+ defaultMessage: 'All',
+ })}
+
+
+ );
+}
diff --git a/x-pack/plugins/observability/public/routes/index.tsx b/x-pack/plugins/observability/public/routes/index.tsx
index 0bdb03995ad46..6e180347106d6 100644
--- a/x-pack/plugins/observability/public/routes/index.tsx
+++ b/x-pack/plugins/observability/public/routes/index.tsx
@@ -15,6 +15,7 @@ import { jsonRt } from './json_rt';
import { AlertsPage } from '../pages/alerts';
import { CasesPage } from '../pages/cases';
import { ExploratoryViewPage } from '../components/shared/exploratory_view';
+import { alertStatusRt } from '../../common/typings';
export type RouteParams = DecodeParams;
@@ -105,6 +106,7 @@ export const routes = {
rangeFrom: t.string,
rangeTo: t.string,
kuery: t.string,
+ status: alertStatusRt,
refreshPaused: jsonRt.pipe(t.boolean),
refreshInterval: jsonRt.pipe(t.number),
}),
diff --git a/x-pack/plugins/observability/server/lib/rules/get_top_alerts.ts b/x-pack/plugins/observability/server/lib/rules/get_top_alerts.ts
index ddfc112ab1452..9560de6ec00ff 100644
--- a/x-pack/plugins/observability/server/lib/rules/get_top_alerts.ts
+++ b/x-pack/plugins/observability/server/lib/rules/get_top_alerts.ts
@@ -6,7 +6,8 @@
*/
import { ALERT_UUID, TIMESTAMP } from '@kbn/rule-data-utils/target/technical_field_names';
import { RuleDataClient } from '../../../../rule_registry/server';
-import { kqlQuery, rangeQuery } from '../../utils/queries';
+import type { AlertStatus } from '../../../common/typings';
+import { kqlQuery, rangeQuery, alertStatusQuery } from '../../utils/queries';
export async function getTopAlerts({
ruleDataClient,
@@ -14,18 +15,20 @@ export async function getTopAlerts({
end,
kuery,
size,
+ status,
}: {
ruleDataClient: RuleDataClient;
start: number;
end: number;
kuery?: string;
size: number;
+ status: AlertStatus;
}) {
const response = await ruleDataClient.getReader().search({
body: {
query: {
bool: {
- filter: [...rangeQuery(start, end), ...kqlQuery(kuery)],
+ filter: [...rangeQuery(start, end), ...kqlQuery(kuery), ...alertStatusQuery(status)],
},
},
fields: ['*'],
diff --git a/x-pack/plugins/observability/server/routes/rules.ts b/x-pack/plugins/observability/server/routes/rules.ts
index 1f500adff5dcf..8b33f5ff8d863 100644
--- a/x-pack/plugins/observability/server/routes/rules.ts
+++ b/x-pack/plugins/observability/server/routes/rules.ts
@@ -4,11 +4,12 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import * as t from 'io-ts';
import { isoToEpochRt, toNumberRt } from '@kbn/io-ts-utils';
+import * as t from 'io-ts';
+import { alertStatusRt } from '../../common/typings';
+import { getTopAlerts } from '../lib/rules/get_top_alerts';
import { createObservabilityServerRoute } from './create_observability_server_route';
import { createObservabilityServerRouteRepository } from './create_observability_server_route_repository';
-import { getTopAlerts } from '../lib/rules/get_top_alerts';
const alertsListRoute = createObservabilityServerRoute({
endpoint: 'GET /api/observability/rules/alerts/top',
@@ -20,6 +21,7 @@ const alertsListRoute = createObservabilityServerRoute({
t.type({
start: isoToEpochRt,
end: isoToEpochRt,
+ status: alertStatusRt,
}),
t.partial({
kuery: t.string,
@@ -29,7 +31,7 @@ const alertsListRoute = createObservabilityServerRoute({
}),
handler: async ({ ruleDataClient, context, params }) => {
const {
- query: { start, end, kuery, size = 100 },
+ query: { start, end, kuery, size = 100, status },
} = params;
return getTopAlerts({
@@ -38,6 +40,7 @@ const alertsListRoute = createObservabilityServerRoute({
end,
kuery,
size,
+ status,
});
},
});
diff --git a/x-pack/plugins/observability/server/utils/queries.test.ts b/x-pack/plugins/observability/server/utils/queries.test.ts
new file mode 100644
index 0000000000000..a0a63b73d7170
--- /dev/null
+++ b/x-pack/plugins/observability/server/utils/queries.test.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 { ALERT_STATUS } from '@kbn/rule-data-utils/target/technical_field_names';
+import * as queries from './queries';
+
+describe('queries', () => {
+ describe('alertStatusQuery', () => {
+ describe('given "all"', () => {
+ it('returns an empty array', () => {
+ expect(queries.alertStatusQuery('all')).toEqual([]);
+ });
+ });
+
+ describe('given "open"', () => {
+ it('returns a query for open', () => {
+ expect(queries.alertStatusQuery('open')).toEqual([
+ {
+ term: { [ALERT_STATUS]: 'open' },
+ },
+ ]);
+ });
+ });
+
+ describe('given "closed"', () => {
+ it('returns a query for closed', () => {
+ expect(queries.alertStatusQuery('closed')).toEqual([
+ {
+ term: { [ALERT_STATUS]: 'closed' },
+ },
+ ]);
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/observability/server/utils/queries.ts b/x-pack/plugins/observability/server/utils/queries.ts
index 9e1c110e77587..b7412120365c6 100644
--- a/x-pack/plugins/observability/server/utils/queries.ts
+++ b/x-pack/plugins/observability/server/utils/queries.ts
@@ -6,7 +6,17 @@
*/
import { QueryContainer } from '@elastic/elasticsearch/api/types';
+import { ALERT_STATUS } from '@kbn/rule-data-utils/target/technical_field_names';
import { esKuery } from '../../../../../src/plugins/data/server';
+import { AlertStatus } from '../../common/typings';
+
+export function alertStatusQuery(status: AlertStatus) {
+ if (status === 'all') {
+ return [];
+ }
+
+ return [{ term: { [ALERT_STATUS]: status } }];
+}
export function rangeQuery(start?: number, end?: number, field = '@timestamp'): QueryContainer[] {
return [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts
index a5ebfef9d2c68..8e2f5e92ae502 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts
@@ -92,6 +92,11 @@ export const eqlExecutor = async ({
ruleParams.eventCategoryOverride
);
const eqlSignalSearchStart = performance.now();
+ logger.debug(
+ `EQL query request path: ${request.path}, method: ${request.method}, body: ${JSON.stringify(
+ request.body
+ )}`
+ );
// TODO: fix this later
const { body: response } = (await services.scopedClusterClient.asCurrentUser.transport.request(
request
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index af6cdd1d672a1..a68efbf379ad4 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -17748,9 +17748,7 @@
"xpack.observability.alertsTable.durationColumnDescription": "期間",
"xpack.observability.alertsTable.reasonColumnDescription": "理由",
"xpack.observability.alertsTable.severityColumnDescription": "深刻度",
- "xpack.observability.alertsTable.statusActiveDescription": "アクティブ",
"xpack.observability.alertsTable.statusColumnDescription": "ステータス",
- "xpack.observability.alertsTable.statusRecoveredDescription": "回復済み",
"xpack.observability.alertsTable.triggeredColumnDescription": "実行済み",
"xpack.observability.alertsTable.viewInAppButtonLabel": "アプリで表示",
"xpack.observability.alertsTitle": "アラート",
@@ -23917,7 +23915,6 @@
"xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "より多く表示させるにはフィルターを変更します。",
"xpack.upgradeAssistant.checkupTab.confirmationModal.removeButtonLabel": "削除",
"xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "致命的",
- "xpack.upgradeAssistant.checkupTab.controls.filterBar.warningButtonLabel": "警告",
"xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "インデックス別",
"xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "問題別",
"xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "アップグレード前にこの問題を解決してください。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index c8376b72daef1..233bafeb71f3a 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -17989,9 +17989,7 @@
"xpack.observability.alertsTable.durationColumnDescription": "持续时间",
"xpack.observability.alertsTable.reasonColumnDescription": "原因",
"xpack.observability.alertsTable.severityColumnDescription": "严重性",
- "xpack.observability.alertsTable.statusActiveDescription": "活动",
"xpack.observability.alertsTable.statusColumnDescription": "状态",
- "xpack.observability.alertsTable.statusRecoveredDescription": "已恢复",
"xpack.observability.alertsTable.triggeredColumnDescription": "已触发",
"xpack.observability.alertsTable.viewInAppButtonLabel": "在应用中查看",
"xpack.observability.alertsTitle": "告警",
@@ -24288,7 +24286,6 @@
"xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "更改筛选以显示更多内容。",
"xpack.upgradeAssistant.checkupTab.confirmationModal.removeButtonLabel": "移除",
"xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "紧急",
- "xpack.upgradeAssistant.checkupTab.controls.filterBar.warningButtonLabel": "警告",
"xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "按索引",
"xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "按问题",
"xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "请解决此问题后再升级。",
diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
index fef0fedf4cce6..867440ae0d911 100644
--- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
+++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
@@ -79,7 +79,7 @@ describe('Kibana deprecations', () => {
let modal = document.body.querySelector('[data-test-subj="stepsModal"]');
expect(modal).not.toBe(null);
- expect(modal!.textContent).toContain(`Fix '${deprecation.domainId}'`);
+ expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`);
const steps: NodeListOf | null = modal!.querySelectorAll(
'[data-test-subj="fixDeprecationSteps"] .euiStep'
@@ -127,7 +127,7 @@ describe('Kibana deprecations', () => {
let modal = document.body.querySelector('[data-test-subj="resolveModal"]');
expect(modal).not.toBe(null);
- expect(modal!.textContent).toContain(`Resolve '${deprecation.domainId}'`);
+ expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`);
const confirmButton: HTMLButtonElement | null = modal!.querySelector(
'[data-test-subj="confirmModalConfirmButton"]'
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
index bb8a7366beb4e..a9608109728ba 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
@@ -33,7 +33,8 @@ const i18nTexts = {
defaultMessage: 'Kibana',
}),
pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', {
- defaultMessage: 'Some Kibana issues may require your attention. Resolve them before upgrading.',
+ defaultMessage:
+ 'Review the issues listed here and make the necessary changes before upgrading. Critical issues must be resolved before you upgrade.',
}),
docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', {
defaultMessage: 'Documentation',
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx
index dd78c3513f973..f94512fac5630 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx
@@ -23,7 +23,7 @@ const i18nTexts = {
i18n.translate(
'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle',
{
- defaultMessage: "Resolve '{domainId}'?",
+ defaultMessage: "Resolve deprecation in '{domainId}'?",
values: {
domainId,
},
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx
index 7646fcba6ad3c..98027d4f46aac 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx
@@ -11,7 +11,6 @@ import { i18n } from '@kbn/i18n';
import {
EuiText,
EuiSteps,
- EuiSpacer,
EuiButton,
EuiModal,
EuiModalBody,
@@ -38,7 +37,7 @@ interface Props {
const i18nTexts = {
getModalTitle: (domainId: string) =>
i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle', {
- defaultMessage: "Fix '{domainId}'",
+ defaultMessage: "Resolve deprecation in '{domainId}'",
values: {
domainId,
},
@@ -50,12 +49,6 @@ const i18nTexts = {
step,
},
}),
- modalDescription: i18n.translate(
- 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalDescription',
- {
- defaultMessage: 'Follow the steps below to address this deprecation.',
- }
- ),
docLinkLabel: i18n.translate(
'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel',
{
@@ -84,28 +77,20 @@ export const StepsModal: FunctionComponent = ({ closeModal, modalContent
- <>
-
- {i18nTexts.modalDescription}
-
-
-
-
- {
- return {
- title: i18nTexts.getStepTitle(index + 1),
- children: (
-
- {step}
-
- ),
- };
- })}
- />
- >
+ {
+ return {
+ title: i18nTexts.getStepTitle(index + 1),
+ children: (
+
+ {step}
+
+ ),
+ };
+ })}
+ />
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx
index 362b2af684e27..9bf35668ac88a 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx
@@ -16,10 +16,10 @@ import { COLOR_MAP, REVERSE_LEVEL_MAP } from '../constants';
const LocalizedLevels: { [level: string]: string } = {
warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningLabel', {
- defaultMessage: 'warning',
+ defaultMessage: 'Warning',
}),
critical: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel', {
- defaultMessage: 'critical',
+ defaultMessage: 'Critical',
}),
};
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap
index 64def47db1350..5a8619e1e687b 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap
@@ -10,14 +10,14 @@ exports[`GroupByFilter renders 1`] = `
key="message"
onClick={[Function]}
>
- by issue
+ By issue
- by index
+ By index
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap
index 4865c5fa8eb55..551e212f23dd7 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap
@@ -12,7 +12,7 @@ exports[`DeprecationLevelFilter renders 1`] = `
numFilters={1}
onClick={[Function]}
>
- critical
+ Critical
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx
index d6a3cab9ba160..c37ae47793b95 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx
@@ -14,10 +14,10 @@ import { GroupByOption } from '../../types';
const LocalizedOptions: { [option: string]: string } = {
message: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel', {
- defaultMessage: 'by issue',
+ defaultMessage: 'By issue',
}),
index: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel', {
- defaultMessage: 'by index',
+ defaultMessage: 'By index',
}),
};
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx
index 108087e2ae992..59bfaa595b0a6 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx
@@ -13,15 +13,9 @@ import { i18n } from '@kbn/i18n';
import { LevelFilterOption } from '../../types';
const LocalizedOptions: { [option: string]: string } = {
- warning: i18n.translate(
- 'xpack.upgradeAssistant.checkupTab.controls.filterBar.warningButtonLabel',
- {
- defaultMessage: 'warning',
- }
- ),
critical: i18n.translate(
'xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel',
- { defaultMessage: 'critical' }
+ { defaultMessage: 'Critical' }
),
};
interface DeprecationLevelProps {
diff --git a/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts b/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts
index e0a3e4d3a3f8b..e9392a611b5b7 100644
--- a/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts
+++ b/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts
@@ -400,6 +400,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
query: {
start: new Date(now - 30 * 60 * 1000).toISOString(),
end: new Date(now).toISOString(),
+ status: 'all',
},
})
)
@@ -572,6 +573,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
query: {
start: new Date(now - 30 * 60 * 1000).toISOString(),
end: new Date().toISOString(),
+ status: 'all',
},
})
)