"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.explorerRouteFactory = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireWildcard(require("react")); var _useObservable = _interopRequireDefault(require("react-use/lib/useObservable")); var _i18n = require("@kbn/i18n"); var _eui = require("@elastic/eui"); var _common = require("@kbn/kibana-react-plugin/common"); var _mlUrlState = require("@kbn/ml-url-state"); var _mlDatePicker = require("@kbn/ml-date-picker"); var _mlAnomalyUtils = require("@kbn/ml-anomaly-utils"); var _resolvers = require("../resolvers"); var _locator = require("../../../locator"); var _kibana = require("../../contexts/kibana"); var _router = require("../router"); var _use_refresh = require("../use_refresh"); var _use_resolver = require("../use_resolver"); var _explorer = require("../../explorer"); var _job_service = require("../../services/job_service"); var _ml_api_service = require("../../services/ml_api_service"); var _actions = require("../../explorer/actions"); var _explorer_dashboard_service = require("../../explorer/explorer_dashboard_service"); var _explorer_utils = require("../../explorer/explorer_utils"); var _use_job_selection = require("../../components/job_selector/use_job_selection"); var _select_interval = require("../../components/controls/select_interval"); var _select_severity = require("../../components/controls/select_severity"); var _breadcrumbs = require("../breadcrumbs"); var _ml_annotation_updates_context = require("../../contexts/ml/ml_annotation_updates_context"); var _annotations_service = require("../../services/annotations_service"); var _use_time_buckets = require("../../components/custom_hooks/use_time_buckets"); var _page_header = require("../../components/page_header"); var _page_title = require("../../components/page_title"); var _anomaly_results_view_selector = require("../../components/anomaly_results_view_selector"); var _anomaly_detection_empty_state = require("../../jobs/jobs_list/components/anomaly_detection_empty_state"); var _anomaly_explorer_context = require("../../explorer/anomaly_explorer_context"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const explorerRouteFactory = (navigateToPath, basePath) => ({ id: 'explorer', path: (0, _router.createPath)(_locator.ML_PAGES.ANOMALY_EXPLORER), title: _i18n.i18n.translate('xpack.ml.anomalyDetection.anomalyExplorer.docTitle', { defaultMessage: 'Anomaly Explorer' }), render: (props, deps) => /*#__PURE__*/_react.default.createElement(PageWrapper, (0, _extends2.default)({}, props, { deps: deps })), breadcrumbs: [(0, _breadcrumbs.getBreadcrumbWithUrlForApp)('ML_BREADCRUMB', navigateToPath, basePath), (0, _breadcrumbs.getBreadcrumbWithUrlForApp)('ANOMALY_DETECTION_BREADCRUMB', navigateToPath, basePath), { text: _i18n.i18n.translate('xpack.ml.anomalyDetection.anomalyExplorerLabel', { defaultMessage: 'Anomaly Explorer' }) }], enableDatePicker: true, 'data-test-subj': 'mlPageAnomalyExplorer' }); exports.explorerRouteFactory = explorerRouteFactory; const PageWrapper = () => { const { services: { mlServices: { mlApiServices } } } = (0, _kibana.useMlKibana)(); const { context, results } = (0, _use_resolver.useRouteResolver)('full', ['canGetJobs'], { ...(0, _resolvers.basicResolvers)(), jobs: _job_service.mlJobService.loadJobsWrapper, jobsWithTimeRange: () => mlApiServices.jobs.jobsWithTimerange((0, _explorer_utils.getDateFormatTz)()) }); const annotationUpdatesService = (0, _react.useMemo)(() => new _annotations_service.AnnotationUpdatesService(), []); return /*#__PURE__*/_react.default.createElement(_router.PageLoader, { context: context }, /*#__PURE__*/_react.default.createElement(_ml_annotation_updates_context.MlAnnotationUpdatesContext.Provider, { value: annotationUpdatesService }, /*#__PURE__*/_react.default.createElement(_anomaly_explorer_context.AnomalyExplorerContextProvider, null, results ? /*#__PURE__*/_react.default.createElement(ExplorerUrlStateManager, { jobsWithTimeRange: results.jobsWithTimeRange.jobs }) : null))); }; const ExplorerUrlStateManager = ({ jobsWithTimeRange }) => { var _refresh$lastRefresh, _globalState$time, _globalState$time2, _globalState$time3, _cases$ui$getCasesCon; const { services: { cases } } = (0, _kibana.useMlKibana)(); const [globalState] = (0, _mlUrlState.useUrlState)('_g'); const [stoppedPartitions, setStoppedPartitions] = (0, _react.useState)(); const [invalidTimeRangeError, setInValidTimeRangeError] = (0, _react.useState)(false); const timeBuckets = (0, _use_time_buckets.useTimeBuckets)(); const timefilter = (0, _mlDatePicker.useTimefilter)({ timeRangeSelector: true, autoRefreshSelector: true }); const { jobIds } = (0, _use_job_selection.useJobSelection)(jobsWithTimeRange); const selectedJobsRunning = jobsWithTimeRange.some(job => jobIds.includes(job.id) && job.isRunning === true); const explorerState = (0, _useObservable.default)(_explorer_dashboard_service.explorerService.state$); const anomalyExplorerContext = (0, _anomaly_explorer_context.useAnomalyExplorerContext)(); const refresh = (0, _use_refresh.useRefresh)(); const lastRefresh = (_refresh$lastRefresh = refresh === null || refresh === void 0 ? void 0 : refresh.lastRefresh) !== null && _refresh$lastRefresh !== void 0 ? _refresh$lastRefresh : 0; // We cannot simply infer bounds from the globalState's `time` attribute // with `moment` since it can contain custom strings such as `now-15m`. // So when globalState's `time` changes, we update the timefilter and use // `timefilter.getBounds()` to update `bounds` in this component's state. (0, _react.useEffect)(() => { if ((globalState === null || globalState === void 0 ? void 0 : globalState.time) !== undefined) { if (globalState.time.mode === 'invalid') { setInValidTimeRangeError(true); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [globalState === null || globalState === void 0 ? void 0 : (_globalState$time = globalState.time) === null || _globalState$time === void 0 ? void 0 : _globalState$time.from, globalState === null || globalState === void 0 ? void 0 : (_globalState$time2 = globalState.time) === null || _globalState$time2 === void 0 ? void 0 : _globalState$time2.to, globalState === null || globalState === void 0 ? void 0 : (_globalState$time3 = globalState.time) === null || _globalState$time3 === void 0 ? void 0 : _globalState$time3.ts]); const getJobsWithStoppedPartitions = (0, _react.useCallback)(async selectedJobIds => { try { const fetchedStoppedPartitions = await _ml_api_service.ml.results.getCategoryStoppedPartitions(selectedJobIds, _mlAnomalyUtils.ML_JOB_ID); if (fetchedStoppedPartitions && Array.isArray(fetchedStoppedPartitions.jobs) && fetchedStoppedPartitions.jobs.length > 0) { setStoppedPartitions(fetchedStoppedPartitions.jobs); } else { setStoppedPartitions(undefined); } } catch (error) { // eslint-disable-next-line no-console console.error(error); } }, []); (0, _react.useEffect)(function handleJobSelection() { if (jobIds.length > 0) { _explorer_dashboard_service.explorerService.updateJobSelection(jobIds); getJobsWithStoppedPartitions(jobIds); } else { _explorer_dashboard_service.explorerService.clearJobs(); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(jobIds)]); (0, _react.useEffect)(() => { return () => { // upon component unmounting // clear any data to prevent next page from rendering old charts _explorer_dashboard_service.explorerService.clearExplorerData(); }; }, []); const [explorerData, loadExplorerData] = (0, _actions.useExplorerData)(); (0, _react.useEffect)(() => { if (explorerData !== undefined && Object.keys(explorerData).length > 0) { _explorer_dashboard_service.explorerService.setExplorerData(explorerData); } }, [explorerData]); const [tableInterval] = (0, _select_interval.useTableInterval)(); const [tableSeverity] = (0, _select_severity.useTableSeverity)(); const showCharts = (0, _useObservable.default)(anomalyExplorerContext.chartsStateService.getShowCharts$(), anomalyExplorerContext.chartsStateService.getShowCharts()); const selectedCells = (0, _useObservable.default)(anomalyExplorerContext.anomalyTimelineStateService.getSelectedCells$(), anomalyExplorerContext.anomalyTimelineStateService.getSelectedCells()); const viewByFieldName = (0, _useObservable.default)(anomalyExplorerContext.anomalyTimelineStateService.getViewBySwimlaneFieldName$()); const swimLaneSeverity = (0, _useObservable.default)(anomalyExplorerContext.anomalyTimelineStateService.getSwimLaneSeverity$(), anomalyExplorerContext.anomalyTimelineStateService.getSwimLaneSeverity()); const influencersFilterQuery = (0, _useObservable.default)(anomalyExplorerContext.anomalyExplorerCommonStateService.getInfluencerFilterQuery$()); const loadExplorerDataConfig = explorerState !== undefined ? { lastRefresh, influencersFilterQuery, noInfluencersConfigured: explorerState.noInfluencersConfigured, selectedCells, selectedJobs: explorerState.selectedJobs, tableInterval: tableInterval.val, tableSeverity: tableSeverity.val, viewBySwimlaneFieldName: viewByFieldName } : undefined; (0, _react.useEffect)(function updateAnomalyExplorerCommonState() { anomalyExplorerContext.anomalyExplorerCommonStateService.setSelectedJobs(loadExplorerDataConfig === null || loadExplorerDataConfig === void 0 ? void 0 : loadExplorerDataConfig.selectedJobs); }, // eslint-disable-next-line react-hooks/exhaustive-deps [loadExplorerDataConfig]); (0, _react.useEffect)(() => { if (!loadExplorerDataConfig || (loadExplorerDataConfig === null || loadExplorerDataConfig === void 0 ? void 0 : loadExplorerDataConfig.selectedCells) === undefined) return; loadExplorerData(loadExplorerDataConfig); // eslint-disable-next-line react-hooks/exhaustive-deps }, [JSON.stringify(loadExplorerDataConfig)]); const overallSwimlaneData = (0, _useObservable.default)(anomalyExplorerContext.anomalyTimelineStateService.getOverallSwimLaneData$(), null); if (explorerState === undefined || refresh === undefined) { return null; } const CasesContext = (_cases$ui$getCasesCon = cases === null || cases === void 0 ? void 0 : cases.ui.getCasesContext()) !== null && _cases$ui$getCasesCon !== void 0 ? _cases$ui$getCasesCon : _react.default.Fragment; const casesPermissions = cases === null || cases === void 0 ? void 0 : cases.helpers.canUseCases(); return /*#__PURE__*/_react.default.createElement("div", { className: "ml-explorer" }, /*#__PURE__*/_react.default.createElement(_page_header.MlPageHeader, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { alignItems: "center", gutterSize: "s" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_anomaly_results_view_selector.AnomalyResultsViewSelector, { viewId: "explorer", selectedJobs: explorerState.selectedJobs })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_page_title.PageTitle, { title: _i18n.i18n.translate('xpack.ml.explorer.pageTitle', { defaultMessage: 'Anomaly Explorer' }) })))), /*#__PURE__*/_react.default.createElement(_common.EuiThemeProvider, null, /*#__PURE__*/_react.default.createElement(CasesContext, { owner: [], permissions: casesPermissions }, jobsWithTimeRange.length === 0 ? /*#__PURE__*/_react.default.createElement(_anomaly_detection_empty_state.AnomalyDetectionEmptyState, null) : /*#__PURE__*/_react.default.createElement(_explorer.Explorer, { explorerState, overallSwimlaneData, showCharts, severity: tableSeverity.val, stoppedPartitions, invalidTimeRangeError, selectedJobsRunning, timeBuckets, timefilter, selectedCells, swimLaneSeverity })))); };