From 042892696d9f01b5b29d71da61d559aea21bda77 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Thu, 20 Sep 2018 11:46:24 +0100 Subject: [PATCH] [ML] Moves custom URL editor Add button and form to top of flyout (#23326) * [ML] Moves custom URL editor Add button and form to top of flyout * [ML] Edits to custom URL editor class name --- .../__snapshots__/editor.test.js.snap | 883 ++++++++++++++++++ .../__snapshots__/list.test.js.snap | 387 ++++++++ .../components/custom_url_editor/editor.js | 6 +- .../custom_url_editor/editor.test.js | 166 ++++ .../components/custom_url_editor/list.test.js | 70 ++ .../custom_url_editor/styles/main.less | 2 +- .../edit_job_flyout/edit_job_flyout.js | 2 + .../edit_job_flyout/styles/main.less | 8 + .../edit_job_flyout/tabs/custom_urls.js | 40 +- 9 files changed, 1547 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/editor.test.js.snap create mode 100644 x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/list.test.js.snap create mode 100644 x-pack/plugins/ml/public/jobs/components/custom_url_editor/editor.test.js create mode 100644 x-pack/plugins/ml/public/jobs/components/custom_url_editor/list.test.js diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/editor.test.js.snap b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/editor.test.js.snap new file mode 100644 index 00000000000000..d4c1003a218857 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/editor.test.js.snap @@ -0,0 +1,883 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CustomUrlEditor renders the editor for a dashboard type URL with a label 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + + + + + + + + + + + +
+`; + +exports[`CustomUrlEditor renders the editor for a discover type URL with an entity and empty time range interval 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+`; + +exports[`CustomUrlEditor renders the editor for a discover type URL with valid time range interval 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+`; + +exports[`CustomUrlEditor renders the editor for a new dashboard type URL with no label 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + + + + + + + + + + + +
+`; + +exports[`CustomUrlEditor renders the editor for other type of URL with duplicate label 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + +
+`; + +exports[`CustomUrlEditor renders the editor for other type of URL with unique label 1`] = ` + + +

+ Create new custom URL +

+
+ + + + + + + + + + + + +
+`; diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/list.test.js.snap b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/list.test.js.snap new file mode 100644 index 00000000000000..2ba3152f918068 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/__snapshots__/list.test.js.snap @@ -0,0 +1,387 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CustomUrlList renders a list of custom URLs 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/editor.js b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/editor.js index 84f0890ce7ed81..863887ac8ddb71 100644 --- a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/editor.js +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/editor.js @@ -175,9 +175,9 @@ export class CustomUrlEditor extends Component { }); const entityOptions = queryEntityFieldNames.map(fieldName => ({ label: fieldName })); - const queryFieldNames = kibanaSettings.queryFieldNames; let selectedEntityOptions = []; - if (queryFieldNames !== undefined) { + if (kibanaSettings !== undefined && kibanaSettings.queryFieldNames !== undefined) { + const queryFieldNames = kibanaSettings.queryFieldNames; selectedEntityOptions = queryFieldNames.map(fieldName => ({ label: fieldName })); } @@ -197,7 +197,7 @@ export class CustomUrlEditor extends Component {

Create new custom URL

- + 'mlJobService'); + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { CustomUrlEditor } from './editor'; +import { + TIME_RANGE_TYPE, + URL_TYPE +} from './constants'; + +function prepareTest(customUrl, setEditCustomUrlFn) { + + const savedCustomUrls = [ + { + url_name: 'Show data', + time_range: 'auto', + url_value: 'kibana#/discover?_g=(time:(from:\'$earliest$\',mode:absolute,to:\'$latest$\'))&_a=' + + '(index:e532ba80-b76f-11e8-a9dc-37914a458883,query:(language:lucene,query:\'airline:"$airline$"\'))' + }, + { + url_name: 'Show dashboard', + time_range: '1h', + url_value: 'kibana#/dashboard/52ea8840-bbef-11e8-a04d-b1701b2b977e?_g=' + + '(time:(from:\'$earliest$\',mode:absolute,to:\'$latest$\'))&' + + '_a=(filters:!(),query:(language:lucene,query:\'airline:"$airline$"\'))' + }, + { + url_name: 'Show airline', + time_range: 'auto', + url_value: 'http://airlinecodes.info/airline-code-$airline$' + }, + + ]; + + const dashboards = [ + { id: 'dash1', title: 'Dashboard 1' }, + { id: 'dash2', title: 'Dashboard 2' }, + ]; + + const indexPatterns = [ + { id: 'pattern1', title: 'Index Pattern 1' }, + { id: 'pattern2', title: 'Index Pattern 2' }, + ]; + + const queryEntityFieldNames = ['airline']; + + const props = { + customUrl, + setEditCustomUrl: setEditCustomUrlFn, + savedCustomUrls, + dashboards, + indexPatterns, + queryEntityFieldNames, + }; + + const wrapper = shallow( + + ); + + return wrapper; +} + + +describe('CustomUrlEditor', () => { + + const setEditCustomUrl = jest.fn(() => {}); + const dashboardUrl = { + label: '', + timeRange: { + type: TIME_RANGE_TYPE.AUTO, + interval: '' + }, + type: URL_TYPE.KIBANA_DASHBOARD, + kibanaSettings: { + queryFieldNames: [], + dashboardId: 'dash1', + }, + }; + + const discoverUrl = { + label: 'Open Discover', + timeRange: { + type: TIME_RANGE_TYPE.INTERVAL, + interval: '' + }, + type: URL_TYPE.KIBANA_DISCOVER, + kibanaSettings: { + queryFieldNames: ['airline'], + discoverIndexPatternId: 'pattern1', + }, + }; + + const otherUrl = { + label: 'Show airline', + timeRange: { + type: TIME_RANGE_TYPE.AUTO, + interval: '' + }, + type: URL_TYPE.OTHER, + otherUrlSettings: { + urlValue: 'https://www.google.co.uk/search?q=airline+code+$airline$' + } + }; + + test('renders the editor for a new dashboard type URL with no label', () => { + const wrapper = prepareTest(dashboardUrl, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the editor for a dashboard type URL with a label', () => { + const dashboardUrlEdit = { + ...dashboardUrl, + label: 'Open Dashboard 1' + }; + const wrapper = prepareTest(dashboardUrlEdit, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the editor for a discover type URL with an entity and empty time range interval', () => { + const wrapper = prepareTest(discoverUrl, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the editor for a discover type URL with valid time range interval', () => { + const discoverUrlEdit = { + ...discoverUrl, + timeRange: { + type: TIME_RANGE_TYPE.INTERVAL, + interval: '1h' + } + }; + const wrapper = prepareTest(discoverUrlEdit, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the editor for other type of URL with duplicate label', () => { + const wrapper = prepareTest(otherUrl, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the editor for other type of URL with unique label', () => { + const otherUrlEdit = { + ...otherUrl, + label: 'View airline' + }; + const wrapper = prepareTest(otherUrlEdit, setEditCustomUrl); + expect(wrapper).toMatchSnapshot(); + }); + + test('calls setEditCustomUrl on updating a custom URL field', () => { + const wrapper = prepareTest(dashboardUrl, setEditCustomUrl); + const labelInput = wrapper.find('EuiFieldText').first(); + labelInput.simulate('change', { target: { value: 'Edit' } }); + wrapper.update(); + expect(setEditCustomUrl).toHaveBeenCalled(); + }); + +}); diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/list.test.js b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/list.test.js new file mode 100644 index 00000000000000..f831c84078728b --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/list.test.js @@ -0,0 +1,70 @@ +/* + * 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. + */ + +// Mock the mlJobService that is used for testing custom URLs. +jest.mock('../../../services/job_service.js', () => 'mlJobService'); + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { CustomUrlList } from './list'; + +function prepareTest(setCustomUrlsFn) { + + const customUrls = [ + { + url_name: 'Show data', + time_range: 'auto', + url_value: 'kibana#/discover?_g=(time:(from:\'$earliest$\',mode:absolute,to:\'$latest$\'))&_a=' + + '(index:e532ba80-b76f-11e8-a9dc-37914a458883,query:(language:lucene,query:\'airline:"$airline$"\'))' + }, + { + url_name: 'Show dashboard', + time_range: '1h', + url_value: 'kibana#/dashboard/52ea8840-bbef-11e8-a04d-b1701b2b977e?_g=' + + '(time:(from:\'$earliest$\',mode:absolute,to:\'$latest$\'))&' + + '_a=(filters:!(),query:(language:lucene,query:\'airline:"$airline$"\'))' + }, + { + url_name: 'Show airline', + time_range: 'auto', + url_value: 'http://airlinecodes.info/airline-code-$airline$' + }, + + ]; + + const props = { + job: {}, + customUrls, + setCustomUrls: setCustomUrlsFn, + }; + + const wrapper = shallow( + + ); + + return wrapper; +} + + +describe('CustomUrlList', () => { + + const setCustomUrls = jest.fn(() => {}); + + test('renders a list of custom URLs', () => { + const wrapper = prepareTest(setCustomUrls); + expect(wrapper).toMatchSnapshot(); + }); + + test('calls setCustomUrls on updating a custom URL field', () => { + const wrapper = prepareTest(setCustomUrls); + const url1LabelInput = wrapper.find('EuiFieldText').first(); + url1LabelInput.simulate('change', { target: { value: 'Edit' } }); + wrapper.update(); + expect(setCustomUrls).toHaveBeenCalled(); + }); + +}); diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/styles/main.less b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/styles/main.less index d29cda20d779f4..0a853ce2bfc1e9 100644 --- a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/styles/main.less @@ -1,4 +1,4 @@ -.ml-custom-url-editor { +.ml-edit-url-form { .url-label { width: 250px; } diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js index a0bba700b21b32..b4acd33e57b7a8 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js @@ -23,6 +23,8 @@ import { EuiTabbedContent, } from '@elastic/eui'; +import './styles/main.less'; + import { JobDetails, Detectors, Datafeed, CustomUrls } from './tabs'; import { saveJob } from './edit_utils'; import { loadFullJob } from '../utils'; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/styles/main.less b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/styles/main.less index e69de29bb2d1d6..38343aed2985c4 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/styles/main.less @@ -0,0 +1,8 @@ +.edit-custom-url-panel { + .close-editor-button { + position: relative; + float: right; + top: -5px; + right: 0px; + } +} diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js index 5d7895281ee6ac..ec732c6ae8300d 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js @@ -12,6 +12,7 @@ import React, { import { EuiButton, EuiButtonEmpty, + EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiPanel, @@ -135,6 +136,10 @@ export class CustomUrls extends Component { }); } + closeEditor = () => { + this.setState({ editorOpen: false }); + } + render() { const { customUrls, @@ -151,22 +156,25 @@ export class CustomUrls extends Component { return ( - - {editorOpen === false ? ( - this.editNewCustomUrl()} - > - Add custom URL - + + this.editNewCustomUrl()} + > + Add custom URL + + ) : ( - - + + this.closeEditor()} + iconType="cross" + aria-label="Close custom URL editor" + className="close-editor-button" + /> )} + + );