From 01d8f93c76f6e8365449ebc03616caf6b3c2c0cf Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 15 Jul 2019 13:16:17 -0400 Subject: [PATCH] [ML] NavMenu conversion to React follow-up (#41054) * remove old nav_menu direcory * Bit of cleanup of types and in datavis controller * replace angular service with importable observable * wrap tabs in links --- .../ml/public/components/nav_menu/_index.scss | 1 - .../public/components/nav_menu/_nav_menu.scss | 4 -- .../public/components/nav_menu/nav_menu.html | 51 ---------------- .../ml/public/components/nav_menu/nav_menu.js | 44 -------------- ...navigation_menu_react_wrapper_directive.js | 11 ++-- .../components/navigation_menu/tabs.tsx | 59 ++++++++++--------- .../navigation_menu/top_nav/top_nav.tsx | 9 ++- .../datavisualizer_controller.js | 16 +++-- .../ml/public/explorer/explorer_controller.js | 4 +- .../timefilter_refresh_service.tsx} | 4 +- .../timeseriesexplorer_controller.js | 4 +- 11 files changed, 58 insertions(+), 149 deletions(-) delete mode 100644 x-pack/legacy/plugins/ml/public/components/nav_menu/_index.scss delete mode 100644 x-pack/legacy/plugins/ml/public/components/nav_menu/_nav_menu.scss delete mode 100644 x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.html delete mode 100644 x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.js rename x-pack/legacy/plugins/ml/public/{components/nav_menu/index.js => services/timefilter_refresh_service.tsx} (74%) diff --git a/x-pack/legacy/plugins/ml/public/components/nav_menu/_index.scss b/x-pack/legacy/plugins/ml/public/components/nav_menu/_index.scss deleted file mode 100644 index a5981e1022e15..0000000000000 --- a/x-pack/legacy/plugins/ml/public/components/nav_menu/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'nav_menu' diff --git a/x-pack/legacy/plugins/ml/public/components/nav_menu/_nav_menu.scss b/x-pack/legacy/plugins/ml/public/components/nav_menu/_nav_menu.scss deleted file mode 100644 index 6b1be3c238390..0000000000000 --- a/x-pack/legacy/plugins/ml/public/components/nav_menu/_nav_menu.scss +++ /dev/null @@ -1,4 +0,0 @@ -.disabled-nav-link { - color: $euiColorMediumShade; - pointer-events: none; -} diff --git a/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.html b/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.html deleted file mode 100644 index 73befd0e149ad..0000000000000 --- a/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.html +++ /dev/null @@ -1,51 +0,0 @@ - -
- -
- -
-
-
diff --git a/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.js b/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.js deleted file mode 100644 index 97abaa3589cf4..0000000000000 --- a/x-pack/legacy/plugins/ml/public/components/nav_menu/nav_menu.js +++ /dev/null @@ -1,44 +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 template from './nav_menu.html'; -import { isFullLicense } from '../../license/check_license'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -import 'ui/directives/kbn_href'; - -module.directive('mlNavMenu', function () { - return { - restrict: 'E', - transclude: true, - template, - link: function (scope, el, attrs) { - - // Tabs - scope.name = attrs.name; - - scope.showTabs = false; - if (scope.name === 'jobs' || - scope.name === 'settings' || - scope.name === 'data_frame' || - scope.name === 'datavisualizer' || - scope.name === 'filedatavisualizer' || - scope.name === 'timeseriesexplorer' || - scope.name === 'access-denied' || - scope.name === 'explorer') { - scope.showTabs = true; - } - scope.isActiveTab = function (path) { - return scope.name === path; - }; - - scope.disableLinks = (isFullLicense() === false); - } - }; -}); diff --git a/x-pack/legacy/plugins/ml/public/components/navigation_menu/navigation_menu_react_wrapper_directive.js b/x-pack/legacy/plugins/ml/public/components/navigation_menu/navigation_menu_react_wrapper_directive.js index ea075ee504b2d..b9853967c64db 100644 --- a/x-pack/legacy/plugins/ml/public/components/navigation_menu/navigation_menu_react_wrapper_directive.js +++ b/x-pack/legacy/plugins/ml/public/components/navigation_menu/navigation_menu_react_wrapper_directive.js @@ -12,13 +12,13 @@ import { isFullLicense } from '../../license/check_license'; import { timeHistory } from 'ui/timefilter/time_history'; import { uiModules } from 'ui/modules'; import { timefilter } from 'ui/timefilter'; -import { Subject } from 'rxjs'; const module = uiModules.get('apps/ml'); +import { mlTimefilterRefresh$ } from '../../services/timefilter_refresh_service'; import 'ui/directives/kbn_href'; -module.directive('mlNavMenu', function (config, mlTimefilterRefreshService) { +module.directive('mlNavMenu', function (config) { return { restrict: 'E', transclude: true, @@ -44,7 +44,7 @@ module.directive('mlNavMenu', function (config, mlTimefilterRefreshService) { tabId: name, timeHistory, timefilter, - forceRefresh: () => mlTimefilterRefreshService.next() + forceRefresh: () => mlTimefilterRefresh$.next() }; ReactDOM.render(React.createElement(NavigationMenu, props), @@ -57,7 +57,4 @@ module.directive('mlNavMenu', function (config, mlTimefilterRefreshService) { }); } }; -}) - .service('mlTimefilterRefreshService', function () { - return new Subject(); - }); +}); diff --git a/x-pack/legacy/plugins/ml/public/components/navigation_menu/tabs.tsx b/x-pack/legacy/plugins/ml/public/components/navigation_menu/tabs.tsx index 9323a4c55861a..f95ad02d9bd3a 100644 --- a/x-pack/legacy/plugins/ml/public/components/navigation_menu/tabs.tsx +++ b/x-pack/legacy/plugins/ml/public/components/navigation_menu/tabs.tsx @@ -5,7 +5,7 @@ */ import React, { FC, useState } from 'react'; -import { EuiTabs, EuiTab } from '@elastic/eui'; +import { EuiTabs, EuiTab, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; @@ -15,10 +15,6 @@ interface Tab { disabled: boolean; } -interface TestSubjMap { - [key: string]: string; -} - interface Props { disableLinks: boolean; tabId: string; @@ -71,23 +67,20 @@ function getTabs(disableLinks: boolean): Tab[] { ]; } -const TAB_TEST_SUBJ_MAP: TestSubjMap = { - jobs: 'mlTabJobManagement', - explorer: 'mlTabAnomalyExplorer', - timeseriesexplorer: 'mlTabSingleMetricViewer', - data_frames: 'mlTabDataFrames', - datavisualizer: 'mlTabDataVisualizer', - settings: 'mlTabSettings', -}; - -function moveToSelectedTab(selectedTabId: string) { - window.location.href = `${chrome.getBasePath()}/app/ml#/${selectedTabId}`; +enum TAB_TEST_SUBJECT { + jobs = 'mlTabJobManagement', + explorer = 'mlTabAnomalyExplorer', + timeseriesexplorer = 'mlTabSingleMetricViewer', + data_frames = 'mlTabDataFrames', // eslint-disable-line + datavisualizer = 'mlTabDataVisualizer', + settings = 'mlTabSettings', } +type TAB_TEST_SUBJECTS = keyof typeof TAB_TEST_SUBJECT; + export const Tabs: FC = ({ tabId, disableLinks }) => { const [selectedTabId, setSelectedTabId] = useState(tabId); function onSelectedTabChanged(id: string) { - moveToSelectedTab(id); setSelectedTabId(id); } @@ -95,18 +88,26 @@ export const Tabs: FC = ({ tabId, disableLinks }) => { return ( - {tabs.map((tab: Tab) => ( - onSelectedTabChanged(tab.id)} - isSelected={tab.id === selectedTabId} - disabled={tab.disabled} - key={`${tab.id}-key`} - data-test-subj={TAB_TEST_SUBJ_MAP[tab.id]} - > - {tab.name} - - ))} + {tabs.map((tab: Tab) => { + const id = tab.id; + return ( + + onSelectedTabChanged(id)} + isSelected={id === selectedTabId} + disabled={tab.disabled} + > + {tab.name} + + + ); + })} ); }; diff --git a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/top_nav.tsx b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/top_nav.tsx index 6103623b90ab6..7da5668f08129 100644 --- a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/top_nav.tsx +++ b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/top_nav.tsx @@ -16,7 +16,12 @@ interface Props { timefilter: Timefilter; } -function getRecentlyUsedRanges(timeHistory: TimeHistory): Array<{ start: string; end: string }> { +interface Duration { + start: string; + end: string; +} + +function getRecentlyUsedRanges(timeHistory: TimeHistory): Duration[] { return timeHistory.get().map(({ from, to }: TimeRange) => { return { start: from, @@ -60,7 +65,7 @@ export const TopNav: FC = ({ dateFormat, forceRefresh, timeHistory, timef setIsTimeRangeSelectorEnabled(timefilter.isTimeRangeSelectorEnabled); } - function updateFilter({ start, end }: { start: string; end: string }) { + function updateFilter({ start, end }: Duration) { const newTime = { from: start, to: end }; // Update timefilter for controllers listening for changes timefilter.setTime(newTime); diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/datavisualizer_controller.js b/x-pack/legacy/plugins/ml/public/datavisualizer/datavisualizer_controller.js index b5d174a12019a..0efce7aed7d54 100644 --- a/x-pack/legacy/plugins/ml/public/datavisualizer/datavisualizer_controller.js +++ b/x-pack/legacy/plugins/ml/public/datavisualizer/datavisualizer_controller.js @@ -33,6 +33,7 @@ import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { ml } from 'plugins/ml/services/ml_api_service'; import template from './datavisualizer.html'; +import { mlTimefilterRefresh$ } from '../services/timefilter_refresh_service'; uiRoutes .when('/jobs/new_job/datavisualizer', { @@ -52,11 +53,16 @@ import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); module - .controller('MlDataVisualizerViewFields', function ($injector, $scope, $timeout, $window, Private, AppState, config) { + .controller('MlDataVisualizerViewFields', function ( + $scope, + $timeout, + $window, + Private, + AppState, + config) { timefilter.enableTimeRangeSelector(); timefilter.enableAutoRefreshSelector(); - const mlTimefilterRefreshService = $injector.get('mlTimefilterRefreshService'); const createSearchItems = Private(SearchItemsProvider); const { @@ -152,11 +158,9 @@ module } // Refresh the data when the time range is altered. - $scope.$listenAndDigestAsync(timefilter, 'fetch', function () { - refresh(); - }); + $scope.$listenAndDigestAsync(timefilter, 'fetch', refresh); - const timefilterRefreshServiceSub = mlTimefilterRefreshService.subscribe(refresh); + const timefilterRefreshServiceSub = mlTimefilterRefresh$.subscribe(refresh); $scope.$on('$destroy', () => { timefilterRefreshServiceSub.unsubscribe(); diff --git a/x-pack/legacy/plugins/ml/public/explorer/explorer_controller.js b/x-pack/legacy/plugins/ml/public/explorer/explorer_controller.js index 00767fd65e3ce..04b67cf92b743 100644 --- a/x-pack/legacy/plugins/ml/public/explorer/explorer_controller.js +++ b/x-pack/legacy/plugins/ml/public/explorer/explorer_controller.js @@ -30,6 +30,7 @@ import { checkGetJobsPrivilege } from '../privilege/check_privilege'; import { getIndexPatterns, loadIndexPatterns } from '../util/index_utils'; import { MlTimeBuckets } from 'plugins/ml/util/ml_time_buckets'; import { explorer$ } from './explorer_dashboard_service'; +import { mlTimefilterRefresh$ } from '../services/timefilter_refresh_service'; import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; import { mlJobService } from '../services/job_service'; import { refreshIntervalWatcher } from '../util/refresh_interval_watcher'; @@ -71,7 +72,6 @@ module.controller('MlExplorerController', function ( $injector.get('mlSelectSeverityService'); const mlJobSelectService = $injector.get('mlJobSelectService'); - const mlTimefilterRefreshService = $injector.get('mlTimefilterRefreshService'); // $scope should only contain what's actually still necessary for the angular part. // For the moment that's the job selector and the (hidden) filter bar. @@ -204,7 +204,7 @@ module.controller('MlExplorerController', function ( } }); - const timefilterRefreshServiceSub = mlTimefilterRefreshService.subscribe(() => { + const timefilterRefreshServiceSub = mlTimefilterRefresh$.subscribe(() => { if ($scope.jobSelectionUpdateInProgress === false) { explorer$.next({ action: EXPLORER_ACTION.RELOAD }); } diff --git a/x-pack/legacy/plugins/ml/public/components/nav_menu/index.js b/x-pack/legacy/plugins/ml/public/services/timefilter_refresh_service.tsx similarity index 74% rename from x-pack/legacy/plugins/ml/public/components/nav_menu/index.js rename to x-pack/legacy/plugins/ml/public/services/timefilter_refresh_service.tsx index d775c32c9d9f8..2085c2a5dc77f 100644 --- a/x-pack/legacy/plugins/ml/public/components/nav_menu/index.js +++ b/x-pack/legacy/plugins/ml/public/services/timefilter_refresh_service.tsx @@ -4,4 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import './nav_menu'; +import { Subject } from 'rxjs'; + +export const mlTimefilterRefresh$ = new Subject(); diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js index 53b34a9158d7c..1043936350b63 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js @@ -60,6 +60,7 @@ import { annotationsRefresh$ } from '../services/annotations_service'; import { interval$ } from '../components/controls/select_interval/select_interval'; import { severity$ } from '../components/controls/select_severity/select_severity'; import { setGlobalState, getSelectedJobIds } from '../components/job_selector/job_select_service_utils'; +import { mlTimefilterRefresh$ } from '../services/timefilter_refresh_service'; import chrome from 'ui/chrome'; @@ -93,7 +94,6 @@ module.controller('MlTimeSeriesExplorerController', function ( $injector.get('mlSelectIntervalService'); $injector.get('mlSelectSeverityService'); const mlJobSelectService = $injector.get('mlJobSelectService'); - const mlTimefilterRefreshService = $injector.get('mlTimefilterRefreshService'); $scope.timeFieldName = 'timestamp'; timefilter.enableTimeRangeSelector(); @@ -712,7 +712,7 @@ module.controller('MlTimeSeriesExplorerController', function ( } }); - const timefilterRefreshServiceSub = mlTimefilterRefreshService.subscribe($scope.refresh); + const timefilterRefreshServiceSub = mlTimefilterRefresh$.subscribe($scope.refresh); $scope.$on('$destroy', () => { refreshWatcher.cancel();