mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* [Watcher] New Platform (NP) Migration (#50908) * First iteration of watch public -> new platform Still need to switch to np ready version of use_request * - Switched to using np ready request - Some updates after API changes * First attempt at server shim * Rename file and re-enable react hooks linting * Fix some public types and react hooks lint rules * Fix types * More ES lint react hooks fixes * Migrated server lib -> ts. Part way done with migrating routes to NP router and TS * Big subset of routes to TS and NP router - almost there * Delete legacy error wrappers and moved last set of routes to TS and NP router * Remove @ts-ignore's and update route registration to use shim with http router * Added routes validations, fixes for hooks and fixes for types * Fix more types and finish testing API routes * Fix usage of feature catalogue and fix time buckets types * Fix error message shape [skip ci] * Split legacy from new platform dependencies server-side * Refactor: Seperate client legacy and NP dependencies * Add file: added types file * Fix UISettings client type import * Update license pre-routing factory spec * Update variable names, use of I18nContext (use NP) and docs * Use NP elasticsearchclient * Simplify is_es_error_factory * Fix types * Improve code legibility and remove second use of `useAppContext` * Use @kbn/config-schema (not validate: false) on routes! * Fix watch create JSON spec * Create threshold test working * Unskip watch_edit.test.ts * Unskip watch_list.test.ts * Done re-enabling component integration tests * TimeBuckets typo + remove unnecessary // @ts-ignore * Backport for "xPack:defaultAdminEmail" 7.x specific behaviour
This commit is contained in:
parent
9ed3fe0ccf
commit
85f55bc946
256 changed files with 2326 additions and 2223 deletions
|
@ -209,13 +209,6 @@ module.exports = {
|
|||
'react-hooks/rules-of-hooks': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['x-pack/legacy/plugins/watcher/**/*.{js,ts,tsx}'],
|
||||
rules: {
|
||||
'react-hooks/rules-of-hooks': 'off',
|
||||
'react-hooks/exhaustive-deps': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Prettier
|
||||
|
|
22
src/legacy/ui/public/time_buckets/index.d.ts
vendored
Normal file
22
src/legacy/ui/public/time_buckets/index.d.ts
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
declare module 'ui/time_buckets' {
|
||||
export const TimeBuckets: any;
|
||||
}
|
|
@ -19,11 +19,12 @@
|
|||
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
|
||||
import { HttpServiceBase } from '../../../../../src/core/public';
|
||||
import { HttpServiceBase, HttpFetchQuery } from '../../../../../src/core/public';
|
||||
|
||||
export interface SendRequestConfig {
|
||||
path: string;
|
||||
method: 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
||||
query?: HttpFetchQuery;
|
||||
body?: any;
|
||||
}
|
||||
|
||||
|
@ -48,10 +49,10 @@ export interface UseRequestResponse {
|
|||
|
||||
export const sendRequest = async (
|
||||
httpClient: HttpServiceBase,
|
||||
{ path, method, body }: SendRequestConfig
|
||||
{ path, method, body, query }: SendRequestConfig
|
||||
): Promise<SendRequestResponse> => {
|
||||
try {
|
||||
const response = await httpClient[method](path, { body });
|
||||
const response = await httpClient[method](path, { body, query });
|
||||
|
||||
return {
|
||||
data: response.data ? response.data : response,
|
||||
|
@ -70,6 +71,7 @@ export const useRequest = (
|
|||
{
|
||||
path,
|
||||
method,
|
||||
query,
|
||||
body,
|
||||
pollIntervalMs,
|
||||
initialData,
|
||||
|
@ -112,6 +114,7 @@ export const useRequest = (
|
|||
const requestBody = {
|
||||
path,
|
||||
method,
|
||||
query,
|
||||
body,
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) {
|
|||
'uiExports/(.*)': fileMockPath,
|
||||
'^src/core/(.*)': `${kibanaDirectory}/src/core/$1`,
|
||||
'^src/legacy/(.*)': `${kibanaDirectory}/src/legacy/$1`,
|
||||
'^plugins/watcher/models/(.*)': `${xPackKibanaDirectory}/legacy/plugins/watcher/public/models/$1`,
|
||||
'^plugins/watcher/np_ready/application/models/(.*)':
|
||||
`${xPackKibanaDirectory}/legacy/plugins/watcher/public/np_ready/application/models/$1`,
|
||||
'^plugins/([^/.]*)(.*)': `${kibanaDirectory}/src/legacy/core_plugins/$1/public$2`,
|
||||
'^plugins/xpack_main/(.*);': `${xPackKibanaDirectory}/legacy/plugins/xpack_main/public/$1`,
|
||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': fileMockPath,
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ComponentType } from 'enzyme';
|
||||
import {
|
||||
chromeServiceMock,
|
||||
docLinksServiceMock,
|
||||
uiSettingsServiceMock,
|
||||
notificationServiceMock,
|
||||
httpServiceMock,
|
||||
} from '../../../../../../../src/core/public/mocks';
|
||||
import { AppContextProvider } from '../../../public/np_ready/application/app_context';
|
||||
|
||||
export const mockContextValue = {
|
||||
docLinks: docLinksServiceMock.createStartContract(),
|
||||
chrome: chromeServiceMock.createStartContract(),
|
||||
legacy: {
|
||||
TimeBuckets: class MockTimeBuckets {
|
||||
setBounds(_domain: any) {
|
||||
return {};
|
||||
}
|
||||
getInterval() {
|
||||
return {
|
||||
expression: {},
|
||||
};
|
||||
}
|
||||
},
|
||||
MANAGEMENT_BREADCRUMB: { text: 'test' },
|
||||
licenseStatus: {},
|
||||
},
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
toasts: notificationServiceMock.createSetupContract().toasts,
|
||||
euiUtils: {
|
||||
useChartsTheme: jest.fn(),
|
||||
},
|
||||
// For our test harness, we don't use this mocked out http service
|
||||
http: httpServiceMock.createSetupContract(),
|
||||
};
|
||||
|
||||
export const withAppContext = (Component: ComponentType<any>) => (props: any) => {
|
||||
return (
|
||||
<AppContextProvider value={mockContextValue}>
|
||||
<Component {...props} />
|
||||
</AppContextProvider>
|
||||
);
|
||||
};
|
|
@ -4,4 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { registerFieldsRoutes } from './register_fields_routes';
|
||||
export const wrapBodyResponse = (obj: object) => JSON.stringify({ body: JSON.stringify(obj) });
|
||||
|
||||
export const unwrapBodyResponse = (string: string) => JSON.parse(JSON.parse(string).body);
|
|
@ -34,7 +34,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
|
|||
const defaultResponse = { watchHistoryItems: [] };
|
||||
server.respondWith(
|
||||
'GET',
|
||||
`${API_ROOT}/watch/:id/history?startTime=*`,
|
||||
`${API_ROOT}/watch/:id/history`,
|
||||
mockResponse(defaultResponse, response)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ import { setup as watchCreateThresholdSetup } from './watch_create_threshold.hel
|
|||
import { setup as watchEditSetup } from './watch_edit.helpers';
|
||||
|
||||
export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../../../../test_utils';
|
||||
|
||||
export { wrapBodyResponse, unwrapBodyResponse } from './body_response';
|
||||
export { setupEnvironment } from './setup_environment';
|
||||
|
||||
export const pageHelpers = {
|
||||
|
|
|
@ -7,9 +7,17 @@
|
|||
import axios from 'axios';
|
||||
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
||||
import { init as initHttpRequests } from './http_requests';
|
||||
import { setHttpClient, setSavedObjectsClient } from '../../../public/lib/api';
|
||||
import { setHttpClient, setSavedObjectsClient } from '../../../public/np_ready/application/lib/api';
|
||||
|
||||
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
|
||||
mockHttpClient.interceptors.response.use(
|
||||
res => {
|
||||
return res.data;
|
||||
},
|
||||
rej => {
|
||||
return Promise.reject(rej);
|
||||
}
|
||||
);
|
||||
|
||||
const mockSavedObjectsClient = () => {
|
||||
return {
|
||||
|
@ -23,7 +31,7 @@ export const setupEnvironment = () => {
|
|||
// @ts-ignore
|
||||
setHttpClient(mockHttpClient);
|
||||
|
||||
setSavedObjectsClient(mockSavedObjectsClient());
|
||||
setSavedObjectsClient(mockSavedObjectsClient() as any);
|
||||
|
||||
return {
|
||||
server,
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { withAppContext } from './app_context.mock';
|
||||
import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils';
|
||||
import { WatchEdit } from '../../../public/sections/watch_edit/components/watch_edit';
|
||||
import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit';
|
||||
import { ROUTES, WATCH_TYPES } from '../../../common/constants';
|
||||
import { registerRouter } from '../../../public/lib/navigation';
|
||||
import { registerRouter } from '../../../public/np_ready/application/lib/navigation';
|
||||
|
||||
const testBedConfig: TestBedConfig = {
|
||||
memoryRouter: {
|
||||
|
@ -17,7 +18,7 @@ const testBedConfig: TestBedConfig = {
|
|||
doMountAsync: true,
|
||||
};
|
||||
|
||||
const initTestBed = registerTestBed(WatchEdit, testBedConfig);
|
||||
const initTestBed = registerTestBed(withAppContext(WatchEdit), testBedConfig);
|
||||
|
||||
export interface WatchCreateJsonTestBed extends TestBed<WatchCreateJsonTestSubjects> {
|
||||
actions: {
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils';
|
||||
import { WatchEdit } from '../../../public/sections/watch_edit/components/watch_edit';
|
||||
import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit';
|
||||
import { ROUTES, WATCH_TYPES } from '../../../common/constants';
|
||||
import { registerRouter } from '../../../public/lib/navigation';
|
||||
import { registerRouter } from '../../../public/np_ready/application/lib/navigation';
|
||||
import { withAppContext } from './app_context.mock';
|
||||
|
||||
const testBedConfig: TestBedConfig = {
|
||||
memoryRouter: {
|
||||
|
@ -17,7 +18,7 @@ const testBedConfig: TestBedConfig = {
|
|||
doMountAsync: true,
|
||||
};
|
||||
|
||||
const initTestBed = registerTestBed(WatchEdit, testBedConfig);
|
||||
const initTestBed = registerTestBed(withAppContext(WatchEdit), testBedConfig);
|
||||
|
||||
export interface WatchCreateThresholdTestBed extends TestBed<WatchCreateThresholdTestSubjects> {
|
||||
actions: {
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils';
|
||||
import { WatchEdit } from '../../../public/sections/watch_edit/components/watch_edit';
|
||||
import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit';
|
||||
import { ROUTES } from '../../../common/constants';
|
||||
import { registerRouter } from '../../../public/lib/navigation';
|
||||
import { registerRouter } from '../../../public/np_ready/application/lib/navigation';
|
||||
import { WATCH_ID } from './constants';
|
||||
import { withAppContext } from './app_context.mock';
|
||||
|
||||
const testBedConfig: TestBedConfig = {
|
||||
memoryRouter: {
|
||||
|
@ -18,7 +19,7 @@ const testBedConfig: TestBedConfig = {
|
|||
doMountAsync: true,
|
||||
};
|
||||
|
||||
const initTestBed = registerTestBed(WatchEdit, testBedConfig);
|
||||
const initTestBed = registerTestBed(withAppContext(WatchEdit), testBedConfig);
|
||||
|
||||
export interface WatchEditTestBed extends TestBed<WatchEditSubjects> {
|
||||
actions: {
|
||||
|
|
|
@ -13,8 +13,9 @@ import {
|
|||
TestBedConfig,
|
||||
nextTick,
|
||||
} from '../../../../../../test_utils';
|
||||
import { WatchList } from '../../../public/sections/watch_list/components/watch_list';
|
||||
import { WatchList } from '../../../public/np_ready/application/sections/watch_list/components/watch_list';
|
||||
import { ROUTES } from '../../../common/constants';
|
||||
import { withAppContext } from './app_context.mock';
|
||||
|
||||
const testBedConfig: TestBedConfig = {
|
||||
memoryRouter: {
|
||||
|
@ -23,7 +24,7 @@ const testBedConfig: TestBedConfig = {
|
|||
doMountAsync: true,
|
||||
};
|
||||
|
||||
const initTestBed = registerTestBed(WatchList, testBedConfig);
|
||||
const initTestBed = registerTestBed(withAppContext(WatchList), testBedConfig);
|
||||
|
||||
export interface WatchListTestBed extends TestBed<WatchListTestSubjects> {
|
||||
actions: {
|
||||
|
|
|
@ -13,9 +13,10 @@ import {
|
|||
TestBedConfig,
|
||||
nextTick,
|
||||
} from '../../../../../../test_utils';
|
||||
import { WatchStatus } from '../../../public/sections/watch_status/components/watch_status';
|
||||
import { WatchStatus } from '../../../public/np_ready/application/sections/watch_status/components/watch_status';
|
||||
import { ROUTES } from '../../../common/constants';
|
||||
import { WATCH_ID } from './constants';
|
||||
import { withAppContext } from './app_context.mock';
|
||||
|
||||
const testBedConfig: TestBedConfig = {
|
||||
memoryRouter: {
|
||||
|
@ -25,7 +26,7 @@ const testBedConfig: TestBedConfig = {
|
|||
doMountAsync: true,
|
||||
};
|
||||
|
||||
const initTestBed = registerTestBed(WatchStatus, testBedConfig);
|
||||
const initTestBed = registerTestBed(withAppContext(WatchStatus), testBedConfig);
|
||||
|
||||
export interface WatchStatusTestBed extends TestBed<WatchStatusTestSubjects> {
|
||||
actions: {
|
||||
|
|
|
@ -4,22 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { setupEnvironment, pageHelpers, nextTick } from './helpers';
|
||||
import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers';
|
||||
import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers';
|
||||
import { WATCH } from './helpers/constants';
|
||||
import defaultWatchJson from '../../public/models/watch/default_watch.json';
|
||||
import defaultWatchJson from '../../public/np_ready/application/models/watch/default_watch.json';
|
||||
import { getExecuteDetails } from '../../test/fixtures';
|
||||
|
||||
jest.mock('ui/chrome', () => ({
|
||||
breadcrumbs: { set: () => {} },
|
||||
addBasePath: (path: string) => path || '/api/watcher',
|
||||
}));
|
||||
|
||||
jest.mock('ui/time_buckets', () => {});
|
||||
|
||||
const { setup } = pageHelpers.watchCreateJson;
|
||||
|
||||
describe.skip('<JsonWatchEdit /> create route', () => {
|
||||
describe('<JsonWatchEdit /> create route', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
let testBed: WatchCreateJsonTestBed;
|
||||
|
||||
|
@ -107,7 +100,7 @@ describe.skip('<JsonWatchEdit /> create route', () => {
|
|||
'There are {{ctx.payload.hits.total}} documents in your index. Threshold is 10.';
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
id: watch.id,
|
||||
name: watch.name,
|
||||
type: watch.type,
|
||||
|
@ -194,7 +187,7 @@ describe.skip('<JsonWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes,
|
||||
}),
|
||||
|
@ -258,7 +251,7 @@ describe.skip('<JsonWatchEdit /> create route', () => {
|
|||
const scheduledTime = `now+${SCHEDULED_TIME}s`;
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
triggerData: {
|
||||
triggeredTime,
|
||||
|
|
|
@ -7,7 +7,13 @@ import React from 'react';
|
|||
import { act } from 'react-dom/test-utils';
|
||||
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
||||
import axios from 'axios';
|
||||
import { setupEnvironment, pageHelpers, nextTick } from './helpers';
|
||||
import {
|
||||
setupEnvironment,
|
||||
pageHelpers,
|
||||
nextTick,
|
||||
wrapBodyResponse,
|
||||
unwrapBodyResponse,
|
||||
} from './helpers';
|
||||
import { WatchCreateThresholdTestBed } from './helpers/watch_create_threshold.helpers';
|
||||
import { getExecuteDetails } from '../../test/fixtures';
|
||||
import { WATCH_TYPES } from '../../common/constants';
|
||||
|
@ -42,31 +48,8 @@ const WATCH_VISUALIZE_DATA = {
|
|||
|
||||
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
|
||||
|
||||
jest.mock('ui/chrome', () => ({
|
||||
breadcrumbs: { set: () => {} },
|
||||
addBasePath: (path: string) => path || '/api/watcher',
|
||||
getUiSettingsClient: () => ({
|
||||
get: () => {},
|
||||
isDefault: () => true,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('ui/time_buckets', () => {
|
||||
class MockTimeBuckets {
|
||||
setBounds(_domain: any) {
|
||||
return {};
|
||||
}
|
||||
getInterval() {
|
||||
return {
|
||||
expression: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
return { TimeBuckets: MockTimeBuckets };
|
||||
});
|
||||
|
||||
jest.mock('../../public/lib/api', () => ({
|
||||
...jest.requireActual('../../public/lib/api'),
|
||||
jest.mock('../../public/np_ready/application/lib/api', () => ({
|
||||
...jest.requireActual('../../public/np_ready/application/lib/api'),
|
||||
loadIndexPatterns: async () => {
|
||||
const INDEX_PATTERNS = [
|
||||
{ attributes: { title: 'index1' } },
|
||||
|
@ -85,7 +68,7 @@ jest.mock('@elastic/eui', () => ({
|
|||
EuiComboBox: (props: any) => (
|
||||
<input
|
||||
data-test-subj="mockComboBox"
|
||||
onChange={async (syntheticEvent: any) => {
|
||||
onChange={(syntheticEvent: any) => {
|
||||
props.onChange([syntheticEvent['0']]);
|
||||
}}
|
||||
/>
|
||||
|
@ -94,7 +77,7 @@ jest.mock('@elastic/eui', () => ({
|
|||
|
||||
const { setup } = pageHelpers.watchCreateThreshold;
|
||||
|
||||
describe.skip('<ThresholdWatchEdit /> create route', () => {
|
||||
describe('<ThresholdWatchEdit /> create route', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
let testBed: WatchCreateThresholdTestBed;
|
||||
|
||||
|
@ -105,12 +88,9 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
describe('on component mount', () => {
|
||||
beforeEach(async () => {
|
||||
testBed = await setup();
|
||||
|
||||
await act(async () => {
|
||||
const { component } = testBed;
|
||||
await nextTick();
|
||||
component.update();
|
||||
});
|
||||
const { component } = testBed;
|
||||
await nextTick();
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('should set the correct page title', () => {
|
||||
|
@ -125,13 +105,6 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
httpRequestsMockHelpers.setLoadEsFieldsResponse({ fields: ES_FIELDS });
|
||||
httpRequestsMockHelpers.setLoadSettingsResponse(SETTINGS);
|
||||
httpRequestsMockHelpers.setLoadWatchVisualizeResponse(WATCH_VISUALIZE_DATA);
|
||||
|
||||
testBed = await setup();
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
testBed.component.update();
|
||||
});
|
||||
});
|
||||
|
||||
describe('form validation', () => {
|
||||
|
@ -173,7 +146,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
expect(find('saveWatchButton').props().disabled).toEqual(true);
|
||||
});
|
||||
|
||||
test('it should enable the Create button and render additonal content with valid fields', async () => {
|
||||
test('it should enable the Create button and render additional content with valid fields', async () => {
|
||||
const { form, find, component, exists } = testBed;
|
||||
|
||||
form.setInputValue('nameInput', 'my_test_watch');
|
||||
|
@ -192,39 +165,30 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
expect(exists('watchActionsPanel')).toBe(true);
|
||||
});
|
||||
|
||||
describe('watch conditions', () => {
|
||||
beforeEach(async () => {
|
||||
const { form, find, component } = testBed;
|
||||
// Looks like there is an issue with using 'mockComboBox'.
|
||||
describe.skip('watch conditions', () => {
|
||||
beforeEach(() => {
|
||||
const { form, find } = testBed;
|
||||
|
||||
// Name, index and time fields are required before the watch condition expression renders
|
||||
form.setInputValue('nameInput', 'my_test_watch');
|
||||
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
|
||||
form.setInputValue('watchTimeFieldSelect', '@timestamp');
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
component.update();
|
||||
act(() => {
|
||||
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
|
||||
});
|
||||
form.setInputValue('watchTimeFieldSelect', '@timestamp');
|
||||
});
|
||||
|
||||
test('should require a threshold value', async () => {
|
||||
const { form, find, component } = testBed;
|
||||
test('should require a threshold value', () => {
|
||||
const { form, find } = testBed;
|
||||
|
||||
find('watchThresholdButton').simulate('click');
|
||||
|
||||
// Provide invalid value
|
||||
form.setInputValue('watchThresholdInput', '');
|
||||
|
||||
expect(form.getErrorsMessages()).toContain('A value is required.');
|
||||
|
||||
// Provide valid value
|
||||
form.setInputValue('watchThresholdInput', '0');
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
component.update();
|
||||
act(() => {
|
||||
find('watchThresholdButton').simulate('click');
|
||||
// Provide invalid value
|
||||
form.setInputValue('watchThresholdInput', '');
|
||||
// Provide valid value
|
||||
form.setInputValue('watchThresholdInput', '0');
|
||||
});
|
||||
|
||||
expect(form.getErrorsMessages()).toContain('A value is required.');
|
||||
expect(form.getErrorsMessages().length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
@ -273,7 +237,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -300,7 +264,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
logging_1: 'force_execute',
|
||||
|
@ -341,7 +305,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -367,7 +331,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
index_1: 'force_execute',
|
||||
|
@ -401,7 +365,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -430,7 +394,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
slack_1: 'force_execute',
|
||||
|
@ -471,7 +435,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -504,7 +468,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
email_1: 'force_execute',
|
||||
|
@ -559,7 +523,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -594,7 +558,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
webhook_1: 'force_execute',
|
||||
|
@ -645,7 +609,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -682,7 +646,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
jira_1: 'force_execute',
|
||||
|
@ -723,7 +687,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).watch.id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -750,7 +714,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
executeDetails: getExecuteDetails({
|
||||
actionModes: {
|
||||
pagerduty_1: 'force_execute',
|
||||
|
@ -784,7 +748,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
|
||||
const thresholdWatch = {
|
||||
id: JSON.parse(latestRequest.requestBody).id, // watch ID is created dynamically
|
||||
id: unwrapBodyResponse(latestRequest.requestBody).id, // watch ID is created dynamically
|
||||
name: WATCH_NAME,
|
||||
type: WATCH_TYPES.THRESHOLD,
|
||||
isNew: true,
|
||||
|
@ -801,7 +765,7 @@ describe.skip('<ThresholdWatchEdit /> create route', () => {
|
|||
threshold: 1000,
|
||||
};
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(JSON.stringify(thresholdWatch));
|
||||
expect(latestRequest.requestBody).toEqual(wrapBodyResponse(thresholdWatch));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,36 +6,17 @@
|
|||
import { act } from 'react-dom/test-utils';
|
||||
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
||||
import axios from 'axios';
|
||||
import { setupEnvironment, pageHelpers, nextTick } from './helpers';
|
||||
import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers';
|
||||
import { WatchEditTestBed } from './helpers/watch_edit.helpers';
|
||||
import { WATCH } from './helpers/constants';
|
||||
import defaultWatchJson from '../../public/models/watch/default_watch.json';
|
||||
import defaultWatchJson from '../../public/np_ready/application/models/watch/default_watch.json';
|
||||
import { getWatch } from '../../test/fixtures';
|
||||
import { getRandomString } from '../../../../../test_utils';
|
||||
|
||||
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
|
||||
|
||||
jest.mock('ui/chrome', () => ({
|
||||
breadcrumbs: { set: () => {} },
|
||||
addBasePath: (path: string) => path || '/api/watcher',
|
||||
}));
|
||||
|
||||
jest.mock('ui/time_buckets', () => {
|
||||
class MockTimeBuckets {
|
||||
setBounds(_domain: any) {
|
||||
return {};
|
||||
}
|
||||
getInterval() {
|
||||
return {
|
||||
expression: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
return { TimeBuckets: MockTimeBuckets };
|
||||
});
|
||||
|
||||
jest.mock('../../public/lib/api', () => ({
|
||||
...jest.requireActual('../../public/lib/api'),
|
||||
jest.mock('../../public/np_ready/application/lib/api', () => ({
|
||||
...jest.requireActual('../../public/np_ready/application/lib/api'),
|
||||
loadIndexPatterns: async () => {
|
||||
const INDEX_PATTERNS = [
|
||||
{ attributes: { title: 'index1' } },
|
||||
|
@ -49,7 +30,7 @@ jest.mock('../../public/lib/api', () => ({
|
|||
|
||||
const { setup } = pageHelpers.watchEdit;
|
||||
|
||||
describe.skip('<WatchEdit />', () => {
|
||||
describe('<WatchEdit />', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
let testBed: WatchEditTestBed;
|
||||
|
||||
|
@ -110,7 +91,7 @@ describe.skip('<WatchEdit />', () => {
|
|||
'There are {{ctx.payload.hits.total}} documents in your index. Threshold is 10.';
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
id: watch.id,
|
||||
name: EDITED_WATCH_NAME,
|
||||
type: watch.type,
|
||||
|
@ -202,7 +183,7 @@ describe.skip('<WatchEdit />', () => {
|
|||
} = watch;
|
||||
|
||||
expect(latestRequest.requestBody).toEqual(
|
||||
JSON.stringify({
|
||||
wrapBodyResponse({
|
||||
id,
|
||||
name: EDITED_WATCH_NAME,
|
||||
type,
|
||||
|
|
|
@ -18,16 +18,9 @@ import { ROUTES } from '../../common/constants';
|
|||
|
||||
const { API_ROOT } = ROUTES;
|
||||
|
||||
jest.mock('ui/chrome', () => ({
|
||||
breadcrumbs: { set: () => {} },
|
||||
addBasePath: (path: string) => path || '/api/watcher',
|
||||
}));
|
||||
|
||||
jest.mock('ui/time_buckets', () => {});
|
||||
|
||||
const { setup } = pageHelpers.watchList;
|
||||
|
||||
describe.skip('<WatchList />', () => {
|
||||
describe('<WatchList />', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
let testBed: WatchListTestBed;
|
||||
|
||||
|
|
|
@ -14,13 +14,6 @@ import { WATCH_STATES, ACTION_STATES } from '../../common/constants';
|
|||
|
||||
const { API_ROOT } = ROUTES;
|
||||
|
||||
jest.mock('ui/chrome', () => ({
|
||||
breadcrumbs: { set: () => {} },
|
||||
addBasePath: (path: string) => path || '/api/watcher',
|
||||
}));
|
||||
|
||||
jest.mock('ui/time_buckets', () => {});
|
||||
|
||||
const { setup } = pageHelpers.watchStatus;
|
||||
|
||||
const watchHistory1 = getWatchHistory({ startTime: '2019-06-04T01:11:11.294' });
|
||||
|
@ -45,7 +38,7 @@ const watch = {
|
|||
},
|
||||
};
|
||||
|
||||
describe.skip('<WatchStatus />', () => {
|
||||
describe('<WatchStatus />', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
let testBed: WatchStatusTestBed;
|
||||
|
||||
|
|
9
x-pack/legacy/plugins/watcher/kibana.json
Normal file
9
x-pack/legacy/plugins/watcher/kibana.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"id": "watcher",
|
||||
"version": "kibana",
|
||||
"requiredPlugins": [
|
||||
"home"
|
||||
],
|
||||
"server": true,
|
||||
"ui": true
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { registerFieldsRoutes } from './server/routes/api/fields';
|
||||
import { registerSettingsRoutes } from './server/routes/api/settings';
|
||||
import { registerHistoryRoutes } from './server/routes/api/history';
|
||||
import { registerIndicesRoutes } from './server/routes/api/indices';
|
||||
import { registerLicenseRoutes } from './server/routes/api/license';
|
||||
import { registerWatchesRoutes } from './server/routes/api/watches';
|
||||
import { registerWatchRoutes } from './server/routes/api/watch';
|
||||
import { registerLicenseChecker } from '../../server/lib/register_license_checker';
|
||||
import { PLUGIN } from './common/constants';
|
||||
|
||||
export const pluginDefinition = {
|
||||
id: PLUGIN.ID,
|
||||
configPrefix: 'xpack.watcher',
|
||||
publicDir: resolve(__dirname, 'public'),
|
||||
require: ['kibana', 'elasticsearch', 'xpack_main'],
|
||||
uiExports: {
|
||||
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
|
||||
managementSections: ['plugins/watcher'],
|
||||
home: ['plugins/watcher/register_feature'],
|
||||
},
|
||||
init: function (server) {
|
||||
// Register license checker
|
||||
registerLicenseChecker(
|
||||
server,
|
||||
PLUGIN.ID,
|
||||
PLUGIN.getI18nName(i18n),
|
||||
PLUGIN.MINIMUM_LICENSE_REQUIRED
|
||||
);
|
||||
|
||||
registerFieldsRoutes(server);
|
||||
registerHistoryRoutes(server);
|
||||
registerIndicesRoutes(server);
|
||||
registerLicenseRoutes(server);
|
||||
registerSettingsRoutes(server);
|
||||
registerWatchesRoutes(server);
|
||||
registerWatchRoutes(server);
|
||||
},
|
||||
};
|
32
x-pack/legacy/plugins/watcher/plugin_definition.ts
Normal file
32
x-pack/legacy/plugins/watcher/plugin_definition.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { plugin } from './server/np_ready';
|
||||
import { PLUGIN } from './common/constants';
|
||||
|
||||
export const pluginDefinition = {
|
||||
id: PLUGIN.ID,
|
||||
configPrefix: 'xpack.watcher',
|
||||
publicDir: resolve(__dirname, 'public'),
|
||||
require: ['kibana', 'elasticsearch', 'xpack_main'],
|
||||
uiExports: {
|
||||
styleSheetPaths: resolve(__dirname, 'public/np_ready/application/index.scss'),
|
||||
managementSections: ['plugins/watcher/legacy'],
|
||||
home: ['plugins/watcher/register_feature'],
|
||||
},
|
||||
init(server: any) {
|
||||
plugin({} as any).setup(server.newPlatform.setup.core, {
|
||||
__LEGACY: {
|
||||
route: server.route.bind(server),
|
||||
plugins: {
|
||||
watcher: server.plugins[PLUGIN.ID],
|
||||
xpack_main: server.plugins.xpack_main,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
<kbn-management-app section="elasticsearch/watcher">
|
||||
<div id="watchReactRoot"></div>
|
||||
</kbn-management-app>
|
146
x-pack/legacy/plugins/watcher/public/legacy.ts
Normal file
146
x-pack/legacy/plugins/watcher/public/legacy.ts
Normal file
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { CoreSetup, App, AppUnmount } from 'src/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
/* Legacy UI imports */
|
||||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import routes from 'ui/routes';
|
||||
import { management, MANAGEMENT_BREADCRUMB } from 'ui/management';
|
||||
import { TimeBuckets } from 'ui/time_buckets';
|
||||
// @ts-ignore
|
||||
import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
|
||||
/* Legacy UI imports */
|
||||
|
||||
import { plugin } from './np_ready';
|
||||
import { PLUGIN } from '../common/constants';
|
||||
import { LICENSE_STATUS_INVALID, LICENSE_STATUS_UNAVAILABLE } from '../../../common/constants';
|
||||
import { manageAngularLifecycle } from './manage_angular_lifecycle';
|
||||
|
||||
const template = `<kbn-management-app section="elasticsearch/watcher">
|
||||
<div id="watchReactRoot"></div>
|
||||
</kbn-management-app>`;
|
||||
|
||||
let elem: HTMLElement;
|
||||
let mountApp: () => AppUnmount | Promise<AppUnmount>;
|
||||
let unmountApp: AppUnmount | Promise<AppUnmount>;
|
||||
routes.when('/management/elasticsearch/watcher/:param1?/:param2?/:param3?/:param4?', {
|
||||
template,
|
||||
controller: class WatcherController {
|
||||
constructor($injector: any, $scope: any) {
|
||||
const $route = $injector.get('$route');
|
||||
const licenseStatus = xpackInfo.get(`features.${PLUGIN.ID}`);
|
||||
const shimCore: CoreSetup = {
|
||||
...npSetup.core,
|
||||
application: {
|
||||
...npSetup.core.application,
|
||||
register(app: App): void {
|
||||
mountApp = () =>
|
||||
app.mount(npStart as any, {
|
||||
element: elem,
|
||||
appBasePath: '/management/elasticsearch/watcher/',
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// clean up previously rendered React app if one exists
|
||||
// this happens because of React Router redirects
|
||||
if (elem) {
|
||||
((unmountApp as unknown) as AppUnmount)();
|
||||
}
|
||||
|
||||
$scope.$$postDigest(() => {
|
||||
elem = document.getElementById('watchReactRoot')!;
|
||||
const instance = plugin();
|
||||
instance.setup(shimCore, {
|
||||
...(npSetup.plugins as typeof npSetup.plugins & { eui_utils: any }),
|
||||
__LEGACY: {
|
||||
MANAGEMENT_BREADCRUMB,
|
||||
TimeBuckets,
|
||||
licenseStatus,
|
||||
},
|
||||
});
|
||||
|
||||
instance.start(npStart.core, npStart.plugins);
|
||||
|
||||
(mountApp() as Promise<AppUnmount>).then(fn => (unmountApp = fn));
|
||||
|
||||
manageAngularLifecycle($scope, $route, elem);
|
||||
});
|
||||
}
|
||||
} as any,
|
||||
// @ts-ignore
|
||||
controllerAs: 'watchRoute',
|
||||
});
|
||||
|
||||
routes.defaults(/\/management/, {
|
||||
resolve: {
|
||||
watcherManagementSection: () => {
|
||||
const watchesSection = management.getSection('elasticsearch/watcher');
|
||||
const licenseStatus = xpackInfo.get(`features.${PLUGIN.ID}`);
|
||||
const { status } = licenseStatus;
|
||||
|
||||
if (status === LICENSE_STATUS_INVALID || status === LICENSE_STATUS_UNAVAILABLE) {
|
||||
return watchesSection.hide();
|
||||
}
|
||||
|
||||
watchesSection.show();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
management.getSection('elasticsearch').register('watcher', {
|
||||
display: i18n.translate('xpack.watcher.sections.watchList.managementSection.watcherDisplayName', {
|
||||
defaultMessage: 'Watcher',
|
||||
}),
|
||||
order: 6,
|
||||
url: '#/management/elasticsearch/watcher/',
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher').register('watches', {
|
||||
display: i18n.translate('xpack.watcher.sections.watchList.managementSection.watchesDisplayName', {
|
||||
defaultMessage: 'Watches',
|
||||
}),
|
||||
order: 1,
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher').register('watch', {
|
||||
visible: false,
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher/watch').register('status', {
|
||||
display: i18n.translate('xpack.watcher.sections.watchList.managementSection.statusDisplayName', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
order: 1,
|
||||
visible: false,
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher/watch').register('edit', {
|
||||
display: i18n.translate('xpack.watcher.sections.watchList.managementSection.editDisplayName', {
|
||||
defaultMessage: 'Edit',
|
||||
}),
|
||||
order: 2,
|
||||
visible: false,
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher/watch').register('new', {
|
||||
display: i18n.translate(
|
||||
'xpack.watcher.sections.watchList.managementSection.newWatchDisplayName',
|
||||
{
|
||||
defaultMessage: 'New Watch',
|
||||
}
|
||||
),
|
||||
order: 1,
|
||||
visible: false,
|
||||
} as any);
|
||||
|
||||
management.getSection('elasticsearch/watcher/watch').register('history-item', {
|
||||
order: 1,
|
||||
visible: false,
|
||||
} as any);
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
|
||||
import { ACTION_TYPES } from '../../../common/constants';
|
||||
|
||||
const elasticDocLinkBase = `${ELASTIC_WEBSITE_URL}guide/en/`;
|
||||
|
||||
const esBase = `${elasticDocLinkBase}elasticsearch/reference/${DOC_LINK_VERSION}`;
|
||||
const esStackBase = `${elasticDocLinkBase}elastic-stack-overview/${DOC_LINK_VERSION}`;
|
||||
const kibanaBase = `${elasticDocLinkBase}kibana/${DOC_LINK_VERSION}`;
|
||||
|
||||
export const putWatchApiUrl = `${esBase}/watcher-api-put-watch.html`;
|
||||
export const executeWatchApiUrl = `${esBase}/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode`;
|
||||
export const watcherGettingStartedUrl = `${kibanaBase}/watcher-ui.html`;
|
||||
|
||||
export const watchActionsConfigurationMap = {
|
||||
[ACTION_TYPES.SLACK]: `${esStackBase}/actions-slack.html#configuring-slack`,
|
||||
[ACTION_TYPES.PAGERDUTY]: `${esStackBase}/actions-pagerduty.html#configuring-pagerduty`,
|
||||
[ACTION_TYPES.JIRA]: `${esStackBase}/actions-jira.html#configuring-jira`,
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
export const manageAngularLifecycle = ($scope, $route, elem) => {
|
||||
export const manageAngularLifecycle = ($scope: any, $route: any, elem: HTMLElement) => {
|
||||
const lastRoute = $route.current;
|
||||
|
||||
const deregister = $scope.$on('$locationChangeSuccess', () => {
|
||||
|
@ -17,7 +17,12 @@ export const manageAngularLifecycle = ($scope, $route, elem) => {
|
|||
});
|
||||
|
||||
$scope.$on('$destroy', () => {
|
||||
deregister && deregister();
|
||||
elem && unmountComponentAtNode(elem);
|
||||
if (deregister) {
|
||||
deregister();
|
||||
}
|
||||
|
||||
if (elem) {
|
||||
unmountComponentAtNode(elem);
|
||||
}
|
||||
});
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
declare module 'plugins/watcher/models/visualize_options' {
|
||||
export const VisualizeOptions: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/watch' {
|
||||
export const Watch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/watch/threshold_watch' {
|
||||
export const ThresholdWatch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/watch/json_watch' {
|
||||
export const JsonWatch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/execute_details/execute_details' {
|
||||
export const ExecuteDetails: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/watch_history_item' {
|
||||
export const WatchHistoryItem: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/watch_status' {
|
||||
export const WatchStatus: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/models/settings' {
|
||||
export const Settings: any;
|
||||
}
|
||||
declare module 'plugins/watcher/models/action' {
|
||||
export const Action: any;
|
||||
}
|
||||
declare module 'ui/time_buckets' {
|
||||
export const TimeBuckets: any;
|
||||
}
|
|
@ -4,8 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { registerLoadRoute } from './register_load_route';
|
||||
let defaultEmailTo: string;
|
||||
|
||||
export function registerHistoryRoutes(server) {
|
||||
registerLoadRoute(server);
|
||||
}
|
||||
export const setDefaultEmailTo = (emailTo: string) => {
|
||||
defaultEmailTo = emailTo;
|
||||
};
|
||||
|
||||
export const getDefaultEmailTo = () => {
|
||||
return defaultEmailTo!;
|
||||
};
|
|
@ -4,54 +4,61 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { HashRouter, Switch, Route, Redirect } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import {
|
||||
ChromeStart,
|
||||
DocLinksStart,
|
||||
HttpSetup,
|
||||
ToastsSetup,
|
||||
IUiSettingsClient,
|
||||
} from 'src/core/public';
|
||||
|
||||
import { EuiCallOut, EuiLink } from '@elastic/eui';
|
||||
import {
|
||||
HashRouter,
|
||||
Switch,
|
||||
Route,
|
||||
Redirect,
|
||||
withRouter,
|
||||
RouteComponentProps,
|
||||
} from 'react-router-dom';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { WatchStatus } from './sections/watch_status/components/watch_status';
|
||||
import { WatchEdit } from './sections/watch_edit/components/watch_edit';
|
||||
import { WatchList } from './sections/watch_list/components/watch_list';
|
||||
import { registerRouter } from './lib/navigation';
|
||||
import { BASE_PATH } from './constants';
|
||||
import { LICENSE_STATUS_VALID } from '../../../common/constants';
|
||||
import { EuiCallOut, EuiLink } from '@elastic/eui';
|
||||
import { LICENSE_STATUS_VALID } from '../../../../../common/constants';
|
||||
import { AppContextProvider } from './app_context';
|
||||
import { LegacyDependencies } from '../types';
|
||||
|
||||
class ShareRouter extends Component {
|
||||
static contextTypes = {
|
||||
router: PropTypes.shape({
|
||||
history: PropTypes.shape({
|
||||
push: PropTypes.func.isRequired,
|
||||
createHref: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
}).isRequired
|
||||
}
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.registerRouter();
|
||||
}
|
||||
const ShareRouter = withRouter(({ children, history }: RouteComponentProps & { children: any }) => {
|
||||
registerRouter({ history });
|
||||
return children;
|
||||
});
|
||||
|
||||
registerRouter() {
|
||||
// Share the router with the app without requiring React or context.
|
||||
const { router } = this.context;
|
||||
registerRouter(router);
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
export interface AppDeps {
|
||||
chrome: ChromeStart;
|
||||
docLinks: DocLinksStart;
|
||||
toasts: ToastsSetup;
|
||||
http: HttpSetup;
|
||||
uiSettings: IUiSettingsClient;
|
||||
legacy: LegacyDependencies;
|
||||
euiUtils: any;
|
||||
}
|
||||
export const App = ({ licenseStatus }) => {
|
||||
const { status, message } = licenseStatus;
|
||||
|
||||
export const App = (deps: AppDeps) => {
|
||||
const { status, message } = deps.legacy.licenseStatus;
|
||||
|
||||
if (status !== LICENSE_STATUS_VALID) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
title={(
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.watcher.app.licenseErrorTitle"
|
||||
defaultMessage="License error"
|
||||
/>
|
||||
)}
|
||||
}
|
||||
color="warning"
|
||||
iconType="help"
|
||||
>
|
||||
|
@ -69,7 +76,9 @@ export const App = ({ licenseStatus }) => {
|
|||
return (
|
||||
<HashRouter>
|
||||
<ShareRouter>
|
||||
<AppWithoutRouter />
|
||||
<AppContextProvider value={deps}>
|
||||
<AppWithoutRouter />
|
||||
</AppContextProvider>
|
||||
</ShareRouter>
|
||||
</HashRouter>
|
||||
);
|
||||
|
@ -81,7 +90,11 @@ export const AppWithoutRouter = () => (
|
|||
<Route exact path={`${BASE_PATH}watches`} component={WatchList} />
|
||||
<Route exact path={`${BASE_PATH}watches/watch/:id/status`} component={WatchStatus} />
|
||||
<Route exact path={`${BASE_PATH}watches/watch/:id/edit`} component={WatchEdit} />
|
||||
<Route exact path={`${BASE_PATH}watches/new-watch/:type(json|threshold)`} component={WatchEdit} />
|
||||
<Route
|
||||
exact
|
||||
path={`${BASE_PATH}watches/new-watch/:type(json|threshold)`}
|
||||
component={WatchEdit}
|
||||
/>
|
||||
<Redirect from={BASE_PATH} to={`${BASE_PATH}watches`} />
|
||||
</Switch>
|
||||
);
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { DocLinksStart } from 'src/core/public';
|
||||
import { ACTION_TYPES } from '../../../common/constants';
|
||||
import { AppDeps } from './app';
|
||||
|
||||
interface ContextValue extends Omit<AppDeps, 'docLinks'> {
|
||||
links: ReturnType<typeof generateDocLinks>;
|
||||
}
|
||||
|
||||
const AppContext = createContext<ContextValue>(null as any);
|
||||
|
||||
const generateDocLinks = ({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }: DocLinksStart) => {
|
||||
const elasticDocLinkBase = `${ELASTIC_WEBSITE_URL}guide/en/`;
|
||||
const esBase = `${elasticDocLinkBase}elasticsearch/reference/${DOC_LINK_VERSION}`;
|
||||
const kibanaBase = `${elasticDocLinkBase}kibana/${DOC_LINK_VERSION}`;
|
||||
const putWatchApiUrl = `${esBase}/watcher-api-put-watch.html`;
|
||||
const executeWatchApiUrl = `${esBase}/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode`;
|
||||
const watcherGettingStartedUrl = `${kibanaBase}/watcher-ui.html`;
|
||||
const watchActionsConfigurationMap = {
|
||||
[ACTION_TYPES.SLACK]: `${esBase}/actions-slack.html#configuring-slack`,
|
||||
[ACTION_TYPES.PAGERDUTY]: `${esBase}/actions-pagerduty.html#configuring-pagerduty`,
|
||||
[ACTION_TYPES.JIRA]: `${esBase}/actions-jira.html#configuring-jira`,
|
||||
};
|
||||
|
||||
return {
|
||||
putWatchApiUrl,
|
||||
executeWatchApiUrl,
|
||||
watcherGettingStartedUrl,
|
||||
watchActionsConfigurationMap,
|
||||
};
|
||||
};
|
||||
|
||||
export const AppContextProvider = ({
|
||||
children,
|
||||
value,
|
||||
}: {
|
||||
value: AppDeps;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const { docLinks, ...rest } = value;
|
||||
return (
|
||||
<AppContext.Provider
|
||||
value={Object.freeze({
|
||||
...rest,
|
||||
links: generateDocLinks(docLinks),
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAppContext = () => {
|
||||
const ctx = useContext(AppContext);
|
||||
if (!ctx) {
|
||||
throw new Error('"useAppContext" can only be called inside of AppContext.Provider!');
|
||||
}
|
||||
return ctx;
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { SavedObjectsClientContract } from 'src/core/public';
|
||||
|
||||
import { App, AppDeps } from './app';
|
||||
import { setHttpClient, setSavedObjectsClient } from './lib/api';
|
||||
import { LegacyDependencies } from '../types';
|
||||
import { setDefaultEmailTo } from './7_x_only';
|
||||
|
||||
interface BootDeps extends AppDeps {
|
||||
element: HTMLElement;
|
||||
savedObjects: SavedObjectsClientContract;
|
||||
I18nContext: any;
|
||||
legacy: LegacyDependencies;
|
||||
}
|
||||
|
||||
export const boot = (bootDeps: BootDeps) => {
|
||||
const { I18nContext, element, legacy, savedObjects, ...appDeps } = bootDeps;
|
||||
|
||||
setDefaultEmailTo(bootDeps.uiSettings.get('xPack:defaultAdminEmail'));
|
||||
setHttpClient(appDeps.http);
|
||||
setSavedObjectsClient(savedObjects);
|
||||
|
||||
render(
|
||||
<I18nContext>
|
||||
<App {...appDeps} legacy={legacy} />
|
||||
</I18nContext>,
|
||||
element
|
||||
);
|
||||
return () => unmountComponentAtNode(element);
|
||||
};
|
|
@ -6,8 +6,8 @@
|
|||
import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { deleteWatches } from '../lib/api';
|
||||
import { useAppContext } from '../app_context';
|
||||
|
||||
export const DeleteWatchesModal = ({
|
||||
watchesToDelete,
|
||||
|
@ -16,6 +16,7 @@ export const DeleteWatchesModal = ({
|
|||
watchesToDelete: string[];
|
||||
callback: (deleted?: string[]) => void;
|
||||
}) => {
|
||||
const { toasts } = useAppContext();
|
||||
const numWatchesToDelete = watchesToDelete.length;
|
||||
if (!numWatchesToDelete) {
|
||||
return null;
|
||||
|
@ -54,7 +55,7 @@ export const DeleteWatchesModal = ({
|
|||
const numErrors = errors.length;
|
||||
callback(successes);
|
||||
if (numSuccesses > 0) {
|
||||
toastNotifications.addSuccess(
|
||||
toasts.addSuccess(
|
||||
i18n.translate(
|
||||
'xpack.watcher.sections.watchList.deleteSelectedWatchesSuccessNotification.descriptionText',
|
||||
{
|
||||
|
@ -67,7 +68,7 @@ export const DeleteWatchesModal = ({
|
|||
}
|
||||
|
||||
if (numErrors > 0) {
|
||||
toastNotifications.addDanger(
|
||||
toasts.addDanger(
|
||||
i18n.translate(
|
||||
'xpack.watcher.sections.watchList.deleteSelectedWatchesErrorNotification.descriptionText',
|
||||
{
|
|
@ -8,6 +8,18 @@ import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
|||
import React, { Fragment } from 'react';
|
||||
|
||||
export interface Error {
|
||||
error: string;
|
||||
|
||||
/**
|
||||
* wrapEsError() on the server adds a "cause" array
|
||||
*/
|
||||
cause?: string[];
|
||||
|
||||
message?: string;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
data: {
|
||||
error: string;
|
||||
cause?: string[];
|
||||
|
@ -21,11 +33,9 @@ interface Props {
|
|||
}
|
||||
|
||||
export const SectionError: React.FunctionComponent<Props> = ({ title, error, ...rest }) => {
|
||||
const {
|
||||
error: errorString,
|
||||
cause, // wrapEsError() on the server adds a "cause" array
|
||||
message,
|
||||
} = error.data;
|
||||
const data = error.data || error;
|
||||
|
||||
const { error: errorString, cause, message } = data;
|
||||
|
||||
return (
|
||||
<EuiCallOut title={title} color="danger" iconType="alert" {...rest}>
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { ACTION_STATES, WATCH_STATES } from '../../common/constants';
|
||||
import { ACTION_STATES, WATCH_STATES } from '../../../../common/constants';
|
||||
|
||||
function StatusIcon({ status }: { status: string }) {
|
||||
switch (status) {
|
|
@ -3,20 +3,20 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { Settings } from 'plugins/watcher/models/settings';
|
||||
import { Watch } from 'plugins/watcher/models/watch';
|
||||
import { WatchHistoryItem } from 'plugins/watcher/models/watch_history_item';
|
||||
import { WatchStatus } from 'plugins/watcher/models/watch_status';
|
||||
import { HttpSetup, SavedObjectsClientContract } from 'src/core/public';
|
||||
import { Settings } from 'plugins/watcher/np_ready/application/models/settings';
|
||||
import { Watch } from 'plugins/watcher/np_ready/application/models/watch';
|
||||
import { WatchHistoryItem } from 'plugins/watcher/np_ready/application/models/watch_history_item';
|
||||
import { WatchStatus } from 'plugins/watcher/np_ready/application/models/watch_status';
|
||||
|
||||
import { __await } from 'tslib';
|
||||
import chrome from 'ui/chrome';
|
||||
import { ROUTES } from '../../common/constants';
|
||||
import { BaseWatch, ExecutedWatchDetails } from '../../common/types/watch_types';
|
||||
import { BaseWatch, ExecutedWatchDetails } from '../../../../common/types/watch_types';
|
||||
import { useRequest, sendRequest } from './use_request';
|
||||
|
||||
let httpClient: ng.IHttpService;
|
||||
import { ROUTES } from '../../../../common/constants';
|
||||
|
||||
export const setHttpClient = (anHttpClient: ng.IHttpService) => {
|
||||
let httpClient: HttpSetup;
|
||||
|
||||
export const setHttpClient = (anHttpClient: HttpSetup) => {
|
||||
httpClient = anHttpClient;
|
||||
};
|
||||
|
||||
|
@ -24,19 +24,17 @@ export const getHttpClient = () => {
|
|||
return httpClient;
|
||||
};
|
||||
|
||||
let savedObjectsClient: any;
|
||||
let savedObjectsClient: SavedObjectsClientContract;
|
||||
|
||||
export const setSavedObjectsClient = (aSavedObjectsClient: any) => {
|
||||
export const setSavedObjectsClient = (aSavedObjectsClient: SavedObjectsClientContract) => {
|
||||
savedObjectsClient = aSavedObjectsClient;
|
||||
};
|
||||
|
||||
export const getSavedObjectsClient = () => {
|
||||
return savedObjectsClient;
|
||||
};
|
||||
export const getSavedObjectsClient = () => savedObjectsClient;
|
||||
|
||||
const basePath = chrome.addBasePath(ROUTES.API_ROOT);
|
||||
const basePath = ROUTES.API_ROOT;
|
||||
|
||||
export const loadWatches = (pollIntervalMs: number) => {
|
||||
export const useLoadWatches = (pollIntervalMs: number) => {
|
||||
return useRequest({
|
||||
path: `${basePath}/watches`,
|
||||
method: 'get',
|
||||
|
@ -47,7 +45,7 @@ export const loadWatches = (pollIntervalMs: number) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const loadWatchDetail = (id: string) => {
|
||||
export const useLoadWatchDetail = (id: string) => {
|
||||
return useRequest({
|
||||
path: `${basePath}/watch/${id}`,
|
||||
method: 'get',
|
||||
|
@ -55,15 +53,10 @@ export const loadWatchDetail = (id: string) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const loadWatchHistory = (id: string, startTime: string) => {
|
||||
let path = `${basePath}/watch/${id}/history`;
|
||||
|
||||
if (startTime) {
|
||||
path += `?startTime=${startTime}`;
|
||||
}
|
||||
|
||||
export const useLoadWatchHistory = (id: string, startTime: string) => {
|
||||
return useRequest({
|
||||
path,
|
||||
query: startTime ? { startTime } : undefined,
|
||||
path: `${basePath}/watch/${id}/history`,
|
||||
method: 'get',
|
||||
deserializer: ({ watchHistoryItems = [] }: { watchHistoryItems: any }) => {
|
||||
return watchHistoryItems.map((historyItem: any) =>
|
||||
|
@ -73,7 +66,7 @@ export const loadWatchHistory = (id: string, startTime: string) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const loadWatchHistoryDetail = (id: string | undefined) => {
|
||||
export const useLoadWatchHistoryDetail = (id: string | undefined) => {
|
||||
return useRequest({
|
||||
path: !id ? '' : `${basePath}/history/${id}`,
|
||||
method: 'get',
|
||||
|
@ -83,12 +76,10 @@ export const loadWatchHistoryDetail = (id: string | undefined) => {
|
|||
};
|
||||
|
||||
export const deleteWatches = async (watchIds: string[]) => {
|
||||
const body = {
|
||||
const body = JSON.stringify({
|
||||
watchIds,
|
||||
};
|
||||
const {
|
||||
data: { results },
|
||||
} = await getHttpClient().post(`${basePath}/watches/delete`, body);
|
||||
});
|
||||
const { results } = await getHttpClient().post(`${basePath}/watches/delete`, { body });
|
||||
return results;
|
||||
};
|
||||
|
||||
|
@ -107,8 +98,8 @@ export const activateWatch = async (id: string) => {
|
|||
};
|
||||
|
||||
export const loadWatch = async (id: string) => {
|
||||
const { data: watch } = await getHttpClient().get(`${basePath}/watch/${id}`);
|
||||
return Watch.fromUpstreamJson(watch.watch);
|
||||
const { watch } = await getHttpClient().get(`${basePath}/watch/${id}`);
|
||||
return Watch.fromUpstreamJson(watch);
|
||||
};
|
||||
|
||||
export const getMatchingIndices = async (pattern: string) => {
|
||||
|
@ -118,32 +109,32 @@ export const getMatchingIndices = async (pattern: string) => {
|
|||
if (!pattern.endsWith('*')) {
|
||||
pattern = `${pattern}*`;
|
||||
}
|
||||
const {
|
||||
data: { indices },
|
||||
} = await getHttpClient().post(`${basePath}/indices`, { pattern });
|
||||
const body = JSON.stringify({ pattern });
|
||||
const { indices } = await getHttpClient().post(`${basePath}/indices`, { body });
|
||||
return indices;
|
||||
};
|
||||
|
||||
export const fetchFields = async (indexes: string[]) => {
|
||||
const {
|
||||
data: { fields },
|
||||
} = await getHttpClient().post(`${basePath}/fields`, { indexes });
|
||||
const { fields } = await getHttpClient().post(`${basePath}/fields`, {
|
||||
body: JSON.stringify({ indexes }),
|
||||
});
|
||||
return fields;
|
||||
};
|
||||
|
||||
export const createWatch = async (watch: BaseWatch) => {
|
||||
const { data } = await getHttpClient().put(`${basePath}/watch/${watch.id}`, watch.upstreamJson);
|
||||
return data;
|
||||
return await getHttpClient().put(`${basePath}/watch/${watch.id}`, {
|
||||
body: JSON.stringify(watch.upstreamJson),
|
||||
});
|
||||
};
|
||||
|
||||
export const executeWatch = async (executeWatchDetails: ExecutedWatchDetails, watch: BaseWatch) => {
|
||||
return sendRequest({
|
||||
path: `${basePath}/watch/execute`,
|
||||
method: 'put',
|
||||
body: {
|
||||
body: JSON.stringify({
|
||||
executeDetails: executeWatchDetails.upstreamJson,
|
||||
watch: watch.upstreamJson,
|
||||
},
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -156,19 +147,19 @@ export const loadIndexPatterns = async () => {
|
|||
return savedObjects;
|
||||
};
|
||||
|
||||
export const getWatchVisualizationData = (watchModel: BaseWatch, visualizeOptions: any) => {
|
||||
export const useGetWatchVisualizationData = (watchModel: BaseWatch, visualizeOptions: any) => {
|
||||
return useRequest({
|
||||
path: `${basePath}/watch/visualize`,
|
||||
method: 'post',
|
||||
body: {
|
||||
body: JSON.stringify({
|
||||
watch: watchModel.upstreamJson,
|
||||
options: visualizeOptions.upstreamJson,
|
||||
},
|
||||
}),
|
||||
deserializer: ({ visualizeData }: { visualizeData: any }) => visualizeData,
|
||||
});
|
||||
};
|
||||
|
||||
export const loadSettings = () => {
|
||||
export const useLoadSettings = () => {
|
||||
return useRequest({
|
||||
path: `${basePath}/settings`,
|
||||
method: 'get',
|
||||
|
@ -183,11 +174,8 @@ export const loadSettings = () => {
|
|||
};
|
||||
|
||||
export const ackWatchAction = async (watchId: string, actionId: string) => {
|
||||
const {
|
||||
data: { watchStatus },
|
||||
} = await getHttpClient().put(
|
||||
`${basePath}/watch/${watchId}/action/${actionId}/acknowledge`,
|
||||
null
|
||||
const { watchStatus } = await getHttpClient().put(
|
||||
`${basePath}/watch/${watchId}/action/${actionId}/acknowledge`
|
||||
);
|
||||
return WatchStatus.fromUpstreamJson(watchStatus);
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { TIME_UNITS } from '../../common/constants';
|
||||
import { TIME_UNITS } from '../../../../common/constants';
|
||||
|
||||
export function getTimeUnitLabel(timeUnit = TIME_UNITS.SECOND, timeValue = '0') {
|
||||
switch (timeUnit) {
|
|
@ -11,6 +11,7 @@ import {
|
|||
sendRequest as _sendRequest,
|
||||
useRequest as _useRequest,
|
||||
} from '../shared_imports';
|
||||
|
||||
import { getHttpClient } from './api';
|
||||
|
||||
export const sendRequest = (config: SendRequestConfig): Promise<SendRequestResponse> => {
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { get, set } from 'lodash';
|
||||
import { ACTION_TYPES } from '../../../common/constants';
|
||||
import { ACTION_TYPES } from '../../../../../common/constants';
|
||||
import { EmailAction } from './email_action';
|
||||
import { LoggingAction } from './logging_action';
|
||||
import { SlackAction } from './slack_action';
|
|
@ -7,23 +7,21 @@
|
|||
import { get, isArray } from 'lodash';
|
||||
import { BaseAction } from './base_action';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import chrome from 'ui/chrome';
|
||||
import { getDefaultEmailTo } from '../../7_x_only';
|
||||
|
||||
export class EmailAction extends BaseAction {
|
||||
constructor(props = {}) {
|
||||
super(props);
|
||||
|
||||
const uiSettings = chrome.getUiSettingsClient();
|
||||
const defaultToEmail = uiSettings.get('xPack:defaultAdminEmail');
|
||||
const toArray = get(props, 'to', defaultToEmail);
|
||||
const toArray = get(props, 'to', getDefaultEmailTo());
|
||||
|
||||
this.to = isArray(toArray) ? toArray : toArray && [ toArray ];
|
||||
this.to = isArray(toArray) ? toArray : toArray && [toArray];
|
||||
|
||||
const defaultSubject = i18n.translate('xpack.watcher.models.emailAction.defaultSubjectText', {
|
||||
defaultMessage: 'Watch [{context}] has exceeded the threshold',
|
||||
values: {
|
||||
context: '{{ctx.metadata.name}}',
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.subject = get(props, 'subject', props.ignoreDefaults ? null : defaultSubject);
|
||||
|
@ -38,9 +36,12 @@ export class EmailAction extends BaseAction {
|
|||
|
||||
if (!this.to || !this.to.length) {
|
||||
errors.to.push(
|
||||
i18n.translate('xpack.watcher.watchActions.email.emailRecipientIsRequiredValidationMessage', {
|
||||
defaultMessage: '"To" email address is required.',
|
||||
})
|
||||
i18n.translate(
|
||||
'xpack.watcher.watchActions.email.emailRecipientIsRequiredValidationMessage',
|
||||
{
|
||||
defaultMessage: '"To" email address is required.',
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ export class EmailAction extends BaseAction {
|
|||
body: {
|
||||
text: this.body,
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
|
@ -71,8 +72,8 @@ export class EmailAction extends BaseAction {
|
|||
return i18n.translate('xpack.watcher.models.emailAction.simulateMessage', {
|
||||
defaultMessage: 'Sample email sent to {toList}',
|
||||
values: {
|
||||
toList
|
||||
}
|
||||
toList,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -81,8 +82,8 @@ export class EmailAction extends BaseAction {
|
|||
return i18n.translate('xpack.watcher.models.emailAction.simulateFailMessage', {
|
||||
defaultMessage: 'Failed to send email to {toList}.',
|
||||
values: {
|
||||
toList
|
||||
}
|
||||
toList,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -98,6 +99,6 @@ export class EmailAction extends BaseAction {
|
|||
defaultMessage: 'Send an email from your server.',
|
||||
});
|
||||
static simulatePrompt = i18n.translate('xpack.watcher.models.emailAction.simulateButtonLabel', {
|
||||
defaultMessage: 'Send test email'
|
||||
defaultMessage: 'Send test email',
|
||||
});
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import { getMoment } from '../../../common/lib/get_moment';
|
||||
import { getMoment } from '../../../../../common/lib/get_moment';
|
||||
|
||||
export class ActionStatus {
|
||||
constructor(props = {}) {
|
39
x-pack/legacy/plugins/watcher/public/np_ready/application/models/index.d.ts
vendored
Normal file
39
x-pack/legacy/plugins/watcher/public/np_ready/application/models/index.d.ts
vendored
Normal file
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
declare module 'plugins/watcher/np_ready/application/models/visualize_options' {
|
||||
export const VisualizeOptions: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/watch' {
|
||||
export const Watch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/watch/threshold_watch' {
|
||||
export const ThresholdWatch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/watch/json_watch' {
|
||||
export const JsonWatch: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/execute_details/execute_details' {
|
||||
export const ExecuteDetails: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/watch_history_item' {
|
||||
export const WatchHistoryItem: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/watch_status' {
|
||||
export const WatchStatus: any;
|
||||
}
|
||||
|
||||
declare module 'plugins/watcher/np_ready/application/models/settings' {
|
||||
export const Settings: any;
|
||||
}
|
||||
declare module 'plugins/watcher/np_ready/application/models/action' {
|
||||
export const Action: any;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AGG_TYPES } from '../../../common/constants';
|
||||
import { AGG_TYPES } from '../../../../../common/constants';
|
||||
|
||||
export interface AggType {
|
||||
text: string;
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { COMPARATORS } from '../../../common/constants';
|
||||
import { COMPARATORS } from '../../../../../common/constants';
|
||||
|
||||
export interface Comparator {
|
||||
text: string;
|
|
@ -7,7 +7,7 @@
|
|||
import uuid from 'uuid';
|
||||
import { get } from 'lodash';
|
||||
import { BaseWatch } from './base_watch';
|
||||
import { ACTION_TYPES, WATCH_TYPES } from '../../../common/constants';
|
||||
import { ACTION_TYPES, WATCH_TYPES } from '../../../../../common/constants';
|
||||
import defaultWatchJson from './default_watch.json';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { BaseWatch } from './base_watch';
|
||||
import { WATCH_TYPES } from '../../../common/constants';
|
||||
import { WATCH_TYPES } from '../../../../../common/constants';
|
||||
|
||||
/**
|
||||
* {@code MonitoringWatch} system defined watches created by the Monitoring plugin.
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { BaseWatch } from './base_watch';
|
||||
import uuid from 'uuid';
|
||||
import { WATCH_TYPES, SORT_ORDERS, COMPARATORS } from '../../../common/constants';
|
||||
import { WATCH_TYPES, SORT_ORDERS, COMPARATORS } from '../../../../../common/constants';
|
||||
import { getTimeUnitLabel } from '../../lib/get_time_unit_label';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { aggTypes } from './agg_types';
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { get, set } from 'lodash';
|
||||
import { WATCH_TYPES } from '../../../common/constants';
|
||||
import { WATCH_TYPES } from '../../../../../common/constants';
|
||||
import { JsonWatch } from './json_watch';
|
||||
import { ThresholdWatch } from './threshold_watch';
|
||||
import { MonitoringWatch } from './monitoring_watch';
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import 'moment-duration-format';
|
||||
import { get } from 'lodash';
|
||||
import { getMoment } from '../../../common/lib/get_moment';
|
||||
import { getMoment } from '../../../../../common/lib/get_moment';
|
||||
import { WatchStatus } from '../watch_status';
|
||||
|
||||
export class WatchHistoryItem {
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import { getMoment } from '../../../common/lib/get_moment';
|
||||
import { getMoment } from '../../../../../common/lib/get_moment';
|
||||
import { ActionStatus } from '../action_status';
|
||||
|
||||
export class WatchStatus {
|
|
@ -16,10 +16,10 @@ import {
|
|||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ExecuteDetails } from 'plugins/watcher/models/execute_details/execute_details';
|
||||
import { getActionType } from '../../../../../common/lib/get_action_type';
|
||||
import { BaseWatch, ExecutedWatchDetails } from '../../../../../common/types/watch_types';
|
||||
import { ACTION_MODES, TIME_UNITS } from '../../../../../common/constants';
|
||||
import { ExecuteDetails } from 'plugins/watcher/np_ready/application/models/execute_details/execute_details';
|
||||
import { getActionType } from '../../../../../../../common/lib/get_action_type';
|
||||
import { BaseWatch, ExecutedWatchDetails } from '../../../../../../../common/types/watch_types';
|
||||
import { ACTION_MODES, TIME_UNITS } from '../../../../../../../common/constants';
|
||||
import { JsonWatchEditForm } from './json_watch_edit_form';
|
||||
import { JsonWatchEditSimulate } from './json_watch_edit_simulate';
|
||||
import { WatchContext } from '../../watch_context';
|
|
@ -20,15 +20,20 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { serializeJsonWatch } from '../../../../../common/lib/serialization';
|
||||
import { ErrableFormRow, SectionError } from '../../../../components';
|
||||
import { putWatchApiUrl } from '../../../../lib/documentation_links';
|
||||
import { serializeJsonWatch } from '../../../../../../../common/lib/serialization';
|
||||
import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components';
|
||||
import { onWatchSave } from '../../watch_edit_actions';
|
||||
import { WatchContext } from '../../watch_context';
|
||||
import { goToWatchList } from '../../../../lib/navigation';
|
||||
import { RequestFlyout } from '../request_flyout';
|
||||
import { useAppContext } from '../../../../app_context';
|
||||
|
||||
export const JsonWatchEditForm = () => {
|
||||
const {
|
||||
links: { putWatchApiUrl },
|
||||
toasts,
|
||||
} = useAppContext();
|
||||
|
||||
const { watch, setWatchProperty } = useContext(WatchContext);
|
||||
|
||||
const { errors } = watch.validate();
|
||||
|
@ -37,9 +42,7 @@ export const JsonWatchEditForm = () => {
|
|||
const [validationError, setValidationError] = useState<string | null>(null);
|
||||
const [isRequestVisible, setIsRequestVisible] = useState<boolean>(false);
|
||||
|
||||
const [serverError, setServerError] = useState<{
|
||||
data: { nessage: string; error: string };
|
||||
} | null>(null);
|
||||
const [serverError, setServerError] = useState<ServerError | null>(null);
|
||||
|
||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||
|
||||
|
@ -192,7 +195,7 @@ export const JsonWatchEditForm = () => {
|
|||
isDisabled={hasErrors}
|
||||
onClick={async () => {
|
||||
setIsSaving(true);
|
||||
const savedWatch = await onWatchSave(watch);
|
||||
const savedWatch = await onWatchSave(watch, toasts);
|
||||
if (savedWatch && savedWatch.error) {
|
||||
const { data } = savedWatch.error;
|
||||
setIsSaving(false);
|
|
@ -24,19 +24,19 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { ExecuteDetails } from 'plugins/watcher/models/execute_details/execute_details';
|
||||
import { WatchHistoryItem } from 'plugins/watcher/models/watch_history_item';
|
||||
import { ACTION_MODES, TIME_UNITS } from '../../../../../common/constants';
|
||||
import { ExecuteDetails } from 'plugins/watcher/np_ready/application/models/execute_details/execute_details';
|
||||
import { WatchHistoryItem } from 'plugins/watcher/np_ready/application/models/watch_history_item';
|
||||
import { ACTION_MODES, TIME_UNITS } from '../../../../../../../common/constants';
|
||||
import {
|
||||
ExecutedWatchDetails,
|
||||
ExecutedWatchResults,
|
||||
} from '../../../../../common/types/watch_types';
|
||||
} from '../../../../../../../common/types/watch_types';
|
||||
import { ErrableFormRow } from '../../../../components/form_errors';
|
||||
import { executeWatch } from '../../../../lib/api';
|
||||
import { executeWatchApiUrl } from '../../../../lib/documentation_links';
|
||||
import { WatchContext } from '../../watch_context';
|
||||
import { JsonWatchEditSimulateResults } from './json_watch_edit_simulate_results';
|
||||
import { getTimeUnitLabel } from '../../../../lib/get_time_unit_label';
|
||||
import { useAppContext } from '../../../../app_context';
|
||||
|
||||
const actionModeOptions = Object.keys(ACTION_MODES).map(mode => ({
|
||||
text: ACTION_MODES[mode],
|
||||
|
@ -70,6 +70,9 @@ export const JsonWatchEditSimulate = ({
|
|||
type: string;
|
||||
}>;
|
||||
}) => {
|
||||
const {
|
||||
links: { executeWatchApiUrl },
|
||||
} = useAppContext();
|
||||
const { watch } = useContext(WatchContext);
|
||||
|
||||
// hooks
|
|
@ -21,7 +21,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import {
|
||||
ExecutedWatchDetails,
|
||||
ExecutedWatchResults,
|
||||
} from '../../../../../common/types/watch_types';
|
||||
} from '../../../../../../../common/types/watch_types';
|
||||
import { getTypeFromAction } from '../../watch_edit_actions';
|
||||
import { WatchContext } from '../../watch_context';
|
||||
import { WatchStatus, SectionError } from '../../../../components';
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue