diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/circle.test.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/circle.test.tsx
new file mode 100644
index 0000000000000..e29bb2ac6e92e
--- /dev/null
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/circle.test.tsx
@@ -0,0 +1,114 @@
+/*
+ * 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 { act } from 'react-dom/test-utils';
+import { setup, SetupResult, getProcessorValue } from './processor.helpers';
+
+const CIRCLE_TYPE = 'circle';
+
+describe('Processor: Circle', () => {
+ let onUpdate: jest.Mock;
+ let testBed: SetupResult;
+
+ beforeAll(() => {
+ jest.useFakeTimers();
+ });
+
+ afterAll(() => {
+ jest.useRealTimers();
+ });
+
+ beforeEach(async () => {
+ onUpdate = jest.fn();
+
+ await act(async () => {
+ testBed = await setup({
+ value: {
+ processors: [],
+ },
+ onFlyoutOpen: jest.fn(),
+ onUpdate,
+ });
+ });
+ testBed.component.update();
+ const {
+ actions: { addProcessor, addProcessorType },
+ } = testBed;
+ // Open the processor flyout
+ addProcessor();
+
+ // Add type (the other fields are not visible until a type is selected)
+ await addProcessorType(CIRCLE_TYPE);
+ });
+
+ test('prevents form submission if required fields are not provided', async () => {
+ const {
+ actions: { saveNewProcessor },
+ form,
+ } = testBed;
+
+ // Click submit button with only the type defined
+ await saveNewProcessor();
+
+ // Expect form error as "field" and "shape_type" are required parameters
+ expect(form.getErrorsMessages()).toEqual([
+ 'A field value is required.',
+ 'A shape type value is required.',
+ ]);
+ });
+
+ test('saves with required parameter values', async () => {
+ const {
+ actions: { saveNewProcessor },
+ form,
+ } = testBed;
+
+ // Add "field" value (required)
+ form.setInputValue('fieldNameField.input', 'field_1');
+ // Save the field
+ form.setSelectValue('shapeSelectorField', 'shape');
+ // Set the error distance
+ form.setInputValue('errorDistanceField.input', '10');
+
+ await saveNewProcessor();
+
+ const processors = getProcessorValue(onUpdate, CIRCLE_TYPE);
+
+ expect(processors[0].circle).toEqual({
+ field: 'field_1',
+ error_distance: 10,
+ shape_type: 'shape',
+ });
+ });
+
+ test('allows optional parameters to be set', async () => {
+ const {
+ actions: { saveNewProcessor },
+ form,
+ } = testBed;
+
+ // Add "field" value (required)
+ form.setInputValue('fieldNameField.input', 'field_1');
+ // Select the shape
+ form.setSelectValue('shapeSelectorField', 'geo_shape');
+ // Add "target_field" value
+ form.setInputValue('targetField.input', 'target_field');
+
+ form.setInputValue('errorDistanceField.input', '10');
+
+ // Save the field with new changes
+ await saveNewProcessor();
+
+ const processors = getProcessorValue(onUpdate, CIRCLE_TYPE);
+ expect(processors[0].circle).toEqual({
+ field: 'field_1',
+ error_distance: 10,
+ shape_type: 'geo_shape',
+ target_field: 'target_field',
+ });
+ });
+});
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx
index c00f09b2d2b06..15e8c323b1308 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx
@@ -151,6 +151,8 @@ type TestSubject =
| 'keepOriginalField.input'
| 'removeIfSuccessfulField.input'
| 'targetFieldsField.input'
+ | 'shapeSelectorField'
+ | 'errorDistanceField.input'
| 'separatorValueField.input'
| 'quoteValueField.input'
| 'emptyValueField.input'
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/circle.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/circle.tsx
index acb480df6d35f..74a7f37d841ae 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/circle.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/circle.tsx
@@ -97,6 +97,7 @@ export const Circle: FunctionComponent = () => {
/>
{
{
if (!valid) {
return (
-
- }
- color="danger"
- iconType="help"
- >
- {message}{' '}
-
-
-
-
+
+
+
+
+ }
+ body={{message}
}
+ actions={[
+
+
+ ,
+ ]}
+ />
+
);
}
return (
diff --git a/x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx b/x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx
index ca05d390518f2..321b5c0e5e11b 100644
--- a/x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx
+++ b/x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx
@@ -25,7 +25,7 @@ export function getPageErrorCode(errorOrErrors: any) {
}
}
-export function PageError({ errorCode, id }: { errorCode?: any; id?: any }) {
+export function PageError({ errorCode, id }: { errorCode?: number; id?: string }) {
switch (errorCode) {
case 404:
return ;
diff --git a/x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx b/x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx
index c2e93c7f06600..56dc5c7dc22b5 100644
--- a/x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx
+++ b/x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx
@@ -13,8 +13,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
export function PageErrorForbidden() {
return (
-
+ {id ? (
+
+ ) : (
+
+ )}
}
/>
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx
index 8b5827fbd0fe0..80931c3f60c05 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx
@@ -7,15 +7,7 @@
import React, { useContext, useState } from 'react';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPageContent,
- EuiSpacer,
- EuiTab,
- EuiTabs,
- EuiTitle,
-} from '@elastic/eui';
+import { EuiPageHeader, EuiSpacer, EuiPageContentBody } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ExecuteDetails } from '../../../../models/execute_details';
import { getActionType } from '../../../../../../common/lib/get_action_type';
@@ -96,36 +88,31 @@ export const JsonWatchEdit = ({ pageTitle }: { pageTitle: string }) => {
const hasExecuteWatchErrors = !!Object.keys(executeWatchErrors).find(
(errorKey) => executeWatchErrors[errorKey].length >= 1
);
+
return (
-
-
-
-
- {pageTitle}
-
-
-
-
- {WATCH_TABS.map((tab, index) => (
- {
- setSelectedTab(tab.id);
- setExecuteDetails(
- new ExecuteDetails({
- ...executeDetails,
- actionModes: getActionModes(watchActions),
- })
- );
- }}
- isSelected={tab.id === selectedTab}
- key={index}
- data-test-subj="tab"
- >
- {tab.name}
-
- ))}
-
+
+ {pageTitle}}
+ bottomBorder
+ tabs={WATCH_TABS.map((tab, index) => ({
+ onClick: () => {
+ setSelectedTab(tab.id);
+ setExecuteDetails(
+ new ExecuteDetails({
+ ...executeDetails,
+ actionModes: getActionModes(watchActions),
+ })
+ );
+ },
+ isSelected: tab.id === selectedTab,
+ key: index,
+ 'data-test-subj': 'tab',
+ label: tab.name,
+ }))}
+ />
+
+
{selectedTab === WATCH_SIMULATE_TAB && (
{
watchActions={watchActions}
/>
)}
+
{selectedTab === WATCH_EDIT_TAB && }
-
+
);
};
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx
index 930c11340ce5e..b00e4dc310e27 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx
@@ -7,16 +7,7 @@
import React, { useContext } from 'react';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPageContent,
- EuiSpacer,
- EuiTitle,
- EuiCallOut,
- EuiText,
- EuiLink,
-} from '@elastic/eui';
+import { EuiPageContent, EuiEmptyPrompt, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { WatchContext } from '../../watch_context';
import { useAppContext } from '../../../../app_context';
@@ -27,46 +18,31 @@ export const MonitoringWatchEdit = ({ pageTitle }: { pageTitle: string }) => {
const { watch } = useContext(WatchContext);
const { history } = useAppContext();
- const systemWatchTitle = (
-
- );
-
const systemWatchMessage = (
-
-
- ),
}}
/>
);
return (
-
-
-
-
- {pageTitle}
-
-
-
-
-
-
- {systemWatchMessage}
-
-
+
+ {pageTitle}}
+ body={{systemWatchMessage}
}
+ actions={[
+
+
+ ,
+ ]}
+ />
);
};
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx
index 2f89a3bc2be64..6587974363a80 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx
@@ -18,13 +18,14 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiForm,
- EuiPageContent,
EuiPopover,
EuiPopoverTitle,
EuiSelect,
EuiSpacer,
EuiText,
EuiTitle,
+ EuiPageHeader,
+ EuiPageContentBody,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -236,19 +237,15 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => {
};
return (
-
-
-
-
- {pageTitle}
-
-
-
- {watch.titleDescription}
-
-
-
-
+
+ {pageTitle}}
+ description={watch.titleDescription}
+ bottomBorder
+ />
+
+
+
{serverError && (
@@ -957,6 +954,6 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => {
close={() => setIsRequestVisible(false)}
/>
) : null}
-
+
);
};
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx
index 525ae077df655..fa3c7e374f7b5 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx
@@ -10,19 +10,20 @@ import { isEqual } from 'lodash';
import { EuiPageContent } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-
import { FormattedMessage } from '@kbn/i18n/react';
-import { Watch } from '../../../models/watch';
+
import { WATCH_TYPES } from '../../../../../common/constants';
import { BaseWatch } from '../../../../../common/types/watch_types';
-import { getPageErrorCode, PageError, SectionLoading, SectionError } from '../../../components';
+import { getPageErrorCode, PageError, SectionLoading } from '../../../components';
import { loadWatch } from '../../../lib/api';
import { listBreadcrumb, editBreadcrumb, createBreadcrumb } from '../../../lib/breadcrumbs';
+import { useAppContext } from '../../../app_context';
+import { Watch } from '../../../models/watch';
+import { PageError as GenericPageError } from '../../../shared_imports';
+import { WatchContext } from '../watch_context';
import { JsonWatchEdit } from './json_watch_edit';
import { ThresholdWatchEdit } from './threshold_watch_edit';
import { MonitoringWatchEdit } from './monitoring_watch_edit';
-import { WatchContext } from '../watch_context';
-import { useAppContext } from '../../../app_context';
const getTitle = (watch: BaseWatch) => {
if (watch.isNew) {
@@ -115,7 +116,7 @@ export const WatchEdit = ({
const loadedWatch = await loadWatch(id);
dispatch({ command: 'setWatch', payload: loadedWatch });
} catch (error) {
- dispatch({ command: 'setError', payload: error });
+ dispatch({ command: 'setError', payload: error.body });
}
} else if (type) {
const WatchType = Watch.getWatchTypes()[type];
@@ -135,36 +136,34 @@ export const WatchEdit = ({
const errorCode = getPageErrorCode(loadError);
if (errorCode) {
return (
-
+
);
- }
-
- if (loadError) {
+ } else if (loadError) {
return (
-
-
- }
- error={loadError}
- />
-
+
+ }
+ error={loadError}
+ />
);
}
if (!watch) {
return (
-
-
-
+
+
+
+
+
);
}
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx b/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx
index 0e89871063507..31accef0b6369 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx
@@ -11,25 +11,25 @@ import {
CriteriaWithPagination,
EuiButton,
EuiButtonEmpty,
- EuiFlexGroup,
- EuiFlexItem,
EuiInMemoryTable,
EuiLink,
EuiPageContent,
EuiSpacer,
EuiText,
- EuiTitle,
EuiToolTip,
EuiEmptyPrompt,
EuiButtonIcon,
EuiPopover,
EuiContextMenuPanel,
EuiContextMenuItem,
+ EuiPageHeader,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { Moment } from 'moment';
+import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
+
import { REFRESH_INTERVALS, PAGINATION, WATCH_TYPES } from '../../../../../common/constants';
import { listBreadcrumb } from '../../../lib/breadcrumbs';
import {
@@ -37,15 +37,13 @@ import {
PageError,
DeleteWatchesModal,
WatchStatus,
- SectionError,
SectionLoading,
Error,
} from '../../../components';
import { useLoadWatches } from '../../../lib/api';
import { goToCreateThresholdAlert, goToCreateAdvancedWatch } from '../../../lib/navigation';
import { useAppContext } from '../../../app_context';
-
-import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
+import { PageError as GenericPageError } from '../../../shared_imports';
export const WatchList = () => {
// hooks
@@ -173,21 +171,36 @@ export const WatchList = () => {
if (isWatchesLoading) {
return (
-
-
-
+
+
+
+
+
);
}
- if (getPageErrorCode(error)) {
+ const errorCode = getPageErrorCode(error);
+ if (errorCode) {
return (
-
-
+
+
);
+ } else if (error) {
+ return (
+
+ }
+ error={(error as unknown) as Error}
+ />
+ );
}
if (availableWatches && availableWatches.length === 0) {
@@ -206,7 +219,7 @@ export const WatchList = () => {
);
return (
-
+
{
let content;
- if (error) {
- content = (
-
- }
- error={(error as unknown) as Error}
- />
- );
- } else if (availableWatches) {
+ if (availableWatches) {
const columns = [
{
field: 'id',
@@ -463,56 +464,46 @@ export const WatchList = () => {
);
}
- if (content) {
- return (
-
- {
- if (deleted) {
- setDeletedWatches([...deletedWatches, ...watchesToDelete]);
- }
- setWatchesToDelete([]);
- }}
- watchesToDelete={watchesToDelete}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {watcherDescriptionText}
-
+ return (
+ <>
+
+
+
+ }
+ bottomBorder
+ rightSideItems={[
+
+
+ ,
+ ]}
+ description={watcherDescriptionText}
+ />
+ {
+ if (deleted) {
+ setDeletedWatches([...deletedWatches, ...watchesToDelete]);
+ }
+ setWatchesToDelete([]);
+ }}
+ watchesToDelete={watchesToDelete}
+ />
-
+
- {content}
-
- );
- }
- return null;
+ {content}
+ >
+ );
};
diff --git a/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx
index 1e3548620339a..73400b9ccaaa7 100644
--- a/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx
+++ b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx
@@ -9,14 +9,10 @@ import React, { useEffect, useState } from 'react';
import {
EuiPageContent,
EuiSpacer,
- EuiTabs,
- EuiTab,
- EuiFlexGroup,
- EuiFlexItem,
- EuiTitle,
EuiToolTip,
EuiBadge,
EuiButtonEmpty,
+ EuiPageHeader,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -88,18 +84,20 @@ export const WatchStatus = ({
if (isWatchDetailLoading) {
return (
-
-
-
+
+
+
+
+
);
}
if (errorCode) {
return (
-
+
);
@@ -156,20 +154,11 @@ export const WatchStatus = ({
return (
-
- {
- if (deleted) {
- goToWatchList();
- }
- setWatchesToDelete([]);
- }}
- watchesToDelete={watchesToDelete}
- />
-
-
-
-
+ <>
+
+
-
-
-
- {isSystemWatch ? (
-
-
- }
- >
-
-
-
-
-
- ) : (
-
-
-
+
+ {isSystemWatch && (
+ <>
+ {' '}
+
+ }
+ >
+
+
+
+
+ >
+ )}
+ >
+ }
+ bottomBorder
+ rightSideItems={
+ isSystemWatch
+ ? []
+ : [
toggleWatchActivation()}
isLoading={isTogglingActivation}
>
{activationButtonText}
-
-
-
+ ,
{
@@ -223,30 +213,34 @@ export const WatchStatus = ({
id="xpack.watcher.sections.watchHistory.deleteWatchButtonLabel"
defaultMessage="Delete"
/>
-
-
-
-
- )}
-
-
-
- {WATCH_STATUS_TABS.map((tab, index) => (
- {
- setSelectedTab(tab.id);
- }}
- isSelected={tab.id === selectedTab}
- key={index}
- data-test-subj="tab"
- >
- {tab.name}
-
- ))}
-
+ ,
+ ]
+ }
+ tabs={WATCH_STATUS_TABS.map((tab, index) => ({
+ onClick: () => {
+ setSelectedTab(tab.id);
+ },
+ isSelected: tab.id === selectedTab,
+ key: index,
+ 'data-test-subj': 'tab',
+ label: tab.name,
+ }))}
+ />
+
+
{selectedTab === WATCH_ACTIONS_TAB ? : }
-
+
+ {
+ if (deleted) {
+ goToWatchList();
+ }
+ setWatchesToDelete([]);
+ }}
+ watchesToDelete={watchesToDelete}
+ />
+ >
);
}
diff --git a/x-pack/plugins/watcher/public/application/shared_imports.ts b/x-pack/plugins/watcher/public/application/shared_imports.ts
index e3eb11eda77b3..44bef3b0c4f5f 100644
--- a/x-pack/plugins/watcher/public/application/shared_imports.ts
+++ b/x-pack/plugins/watcher/public/application/shared_imports.ts
@@ -12,4 +12,5 @@ export {
sendRequest,
useRequest,
XJson,
+ PageError,
} from '../../../../../src/plugins/es_ui_shared/public';
diff --git a/yarn.lock b/yarn.lock
index 68d27e955aa12..61c5305821a05 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -20304,9 +20304,9 @@ normalize-url@^3.0.0:
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
normalize-url@^4.1.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
- integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
+ integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
now-and-later@^2.0.0:
version "2.0.0"