"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.SAVE_STATE = exports.Page = void 0; var _react = _interopRequireWildcard(require("react")); var _i18nReact = require("@kbn/i18n-react"); var _i18n = require("@kbn/i18n"); var _eui = require("@elastic/eui"); var _lodash = require("lodash"); var _moment = _interopRequireDefault(require("moment")); var _mlIsPopulatedObject = require("@kbn/ml-is-populated-object"); var _mlQueryUtils = require("@kbn/ml-query-utils"); var _mlDateUtils = require("@kbn/ml-date-utils"); var _ml = require("../../../contexts/ml"); var _kibana = require("../../../contexts/kibana"); var _create_result_callout = require("./components/create_result_callout"); var _kibana_objects = require("./components/kibana_objects"); var _module_jobs = require("./components/module_jobs"); var _job_settings_form = require("./components/job_settings_form"); var _locator = require("../../../../../common/constants/locator"); var _jobs_awaiting_node_warning = require("../../../components/jobs_awaiting_node_warning"); var _page_header = require("../../../components/page_header"); 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. */ let SAVE_STATE; exports.SAVE_STATE = SAVE_STATE; (function (SAVE_STATE) { SAVE_STATE[SAVE_STATE["NOT_SAVED"] = 0] = "NOT_SAVED"; SAVE_STATE[SAVE_STATE["SAVING"] = 1] = "SAVING"; SAVE_STATE[SAVE_STATE["SAVED"] = 2] = "SAVED"; SAVE_STATE[SAVE_STATE["FAILED"] = 3] = "FAILED"; SAVE_STATE[SAVE_STATE["PARTIAL_FAILURE"] = 4] = "PARTIAL_FAILURE"; })(SAVE_STATE || (exports.SAVE_STATE = SAVE_STATE = {})); const Page = ({ moduleId, existingGroupIds }) => { var _selectedSavedSearch$; const { services: { notifications, mlServices: { mlApiServices: { getTimeFieldRange, setupDataRecognizerConfig, getDataRecognizerModule } } } } = (0, _kibana.useMlKibana)(); const locator = (0, _kibana.useMlLocator)(); // #region State const [jobPrefix, setJobPrefix] = (0, _react.useState)(''); const [jobs, setJobs] = (0, _react.useState)([]); const [jobOverrides, setJobOverrides] = (0, _react.useState)({}); const [kibanaObjects, setKibanaObjects] = (0, _react.useState)({}); const [saveState, setSaveState] = (0, _react.useState)(SAVE_STATE.NOT_SAVED); const [resultsUrl, setResultsUrl] = (0, _react.useState)(''); const [existingGroups, setExistingGroups] = (0, _react.useState)(existingGroupIds); const [jobsAwaitingNodeCount, setJobsAwaitingNodeCount] = (0, _react.useState)(0); // #endregion const { selectedSavedSearch, selectedDataView: dataView, combinedQuery } = (0, _ml.useDataSource)(); const pageTitle = selectedSavedSearch ? _i18n.i18n.translate('xpack.ml.newJob.recognize.savedSearchPageTitle', { defaultMessage: 'saved search {savedSearchTitle}', values: { savedSearchTitle: (_selectedSavedSearch$ = selectedSavedSearch.title) !== null && _selectedSavedSearch$ !== void 0 ? _selectedSavedSearch$ : '' } }) : _i18n.i18n.translate('xpack.ml.newJob.recognize.dataViewPageTitle', { defaultMessage: 'data view {dataViewName}', values: { dataViewName: dataView.getName() } }); const displayQueryWarning = selectedSavedSearch !== null; const tempQuery = selectedSavedSearch === null ? undefined : combinedQuery; /** * Loads recognizer module configuration. */ const loadModule = (0, _react.useCallback)(async () => { try { const response = await getDataRecognizerModule({ moduleId }); setJobs(response.jobs); setSaveState(SAVE_STATE.NOT_SAVED); // mix existing groups from the server with the groups used across all jobs in the module. const moduleGroups = [...response.jobs.map(j => j.config.groups || [])].flat(); const newGroups = [...new Set([...existingGroups, ...moduleGroups])].sort(); if (!(0, _lodash.isEqual)(newGroups, existingGroups)) { setExistingGroups(newGroups); } } catch (e) { // eslint-disable-next-line no-console console.error(e); } }, [existingGroups, getDataRecognizerModule, moduleId]); const getTimeRange = (0, _react.useCallback)(async (useFullIndexData, timeRange) => { if (useFullIndexData) { const runtimeMappings = dataView.getComputedFields().runtimeFields; const { start, end } = await getTimeFieldRange({ index: dataView.getIndexPattern(), timeFieldName: dataView.timeFieldName, // By default we want to use full non-frozen time range query: (0, _mlQueryUtils.addExcludeFrozenToQuery)(combinedQuery), ...((0, _mlIsPopulatedObject.isPopulatedObject)(runtimeMappings) ? { runtimeMappings } : {}) }); return { start, end }; } else { return Promise.resolve(timeRange); } }, [combinedQuery, dataView, getTimeFieldRange]); (0, _react.useEffect)(() => { loadModule(); }, [loadModule]); /** * Sets up recognizer module configuration. */ const save = (0, _react.useCallback)(async formValues => { setSaveState(SAVE_STATE.SAVING); const { jobPrefix: resultJobPrefix, startDatafeedAfterSave, useDedicatedIndex, useFullIndexData, timeRange } = formValues; const resultTimeRange = await getTimeRange(useFullIndexData, timeRange); try { let jobOverridesPayload = Object.values(jobOverrides); jobOverridesPayload = jobOverridesPayload.length > 0 ? jobOverridesPayload : null; const response = await setupDataRecognizerConfig({ moduleId, prefix: resultJobPrefix, query: tempQuery, indexPatternName: dataView.getIndexPattern(), useDedicatedIndex, startDatafeed: startDatafeedAfterSave, ...(jobOverridesPayload !== null ? { jobOverrides: jobOverridesPayload } : {}), ...resultTimeRange }); const { datafeeds: datafeedsResponse, jobs: jobsResponse, kibana: kibanaResponse } = response; setJobs(jobs.map(job => { return { ...job, datafeedResult: datafeedsResponse.find(({ id }) => id.endsWith(job.id)), setupResult: jobsResponse.find(({ id }) => id === resultJobPrefix + job.id) }; })); setKibanaObjects((0, _lodash.merge)(kibanaObjects, kibanaResponse)); if (locator) { const url = await locator.getUrl({ page: _locator.ML_PAGES.ANOMALY_EXPLORER, pageState: { jobIds: jobsResponse.filter(({ success }) => success).map(({ id }) => id), timeRange: { from: (0, _moment.default)(resultTimeRange.start).format(_mlDateUtils.TIME_FORMAT), to: (0, _moment.default)(resultTimeRange.end).format(_mlDateUtils.TIME_FORMAT), mode: 'absolute' } } }); setResultsUrl(url); } const failedJobsCount = jobsResponse.reduce((count, { success }) => success ? count : count + 1, 0); const lazyJobsCount = datafeedsResponse.reduce((count, { awaitingMlNodeAllocation }) => awaitingMlNodeAllocation === true ? count + 1 : count, 0); setJobsAwaitingNodeCount(lazyJobsCount); setSaveState(failedJobsCount === 0 ? SAVE_STATE.SAVED : failedJobsCount === jobs.length ? SAVE_STATE.FAILED : SAVE_STATE.PARTIAL_FAILURE); } catch (e) { setSaveState(SAVE_STATE.FAILED); // eslint-disable-next-line no-console console.error('Error setting up module', e); const { toasts } = notifications; toasts.addDanger({ title: _i18n.i18n.translate('xpack.ml.newJob.recognize.moduleSetupFailedWarningTitle', { defaultMessage: 'Error setting up module {moduleId}', values: { moduleId } }), text: _i18n.i18n.translate('xpack.ml.newJob.recognize.moduleSetupFailedWarningDescription', { defaultMessage: 'An error occurred trying to create the {count, plural, one {job} other {jobs}} in the module.', values: { count: jobs.length } }) }); } }, [dataView, getTimeRange, jobOverrides, jobs, kibanaObjects, locator, moduleId, notifications, setupDataRecognizerConfig, tempQuery]); const onJobOverridesChange = job => { setJobOverrides({ ...jobOverrides, [job.job_id]: job }); if (job.groups !== undefined) { // add newly added jobs to the list of existing groups // for use when editing other jobs in the module const groups = [...new Set([...existingGroups, ...job.groups])]; setExistingGroups(groups); } }; const isFormVisible = [SAVE_STATE.NOT_SAVED, SAVE_STATE.SAVING].includes(saveState); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_page_header.MlPageHeader, null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.newJob.recognize.newJobFromTitle", defaultMessage: "New job from {pageTitle}", values: { pageTitle } })), displayQueryWarning && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, { title: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.newJob.recognize.searchWillBeOverwrittenLabel", defaultMessage: "Search will be overwritten" }), color: "warning", iconType: "warning" }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "s" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.newJob.recognize.usingSavedSearchDescription", defaultMessage: "Using a saved search will mean the query used in the datafeeds will be different from the default ones we supply in the {moduleId} module.", values: { moduleId } }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "l" })), jobsAwaitingNodeCount > 0 && /*#__PURE__*/_react.default.createElement(_jobs_awaiting_node_warning.JobsAwaitingNodeWarning, { jobCount: jobsAwaitingNodeCount }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { wrap: true, gutterSize: "m", "data-test-subj": "mlPageJobWizard recognizer" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: 1 }, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { grow: false, hasShadow: false, hasBorder: true }, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "s" }, /*#__PURE__*/_react.default.createElement("h4", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.newJob.recognize.jobSettingsTitle", defaultMessage: "Job settings" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "m" }), isFormVisible && /*#__PURE__*/_react.default.createElement(_job_settings_form.JobSettingsForm, { onSubmit: save, onJobPrefixChange: setJobPrefix, saveState: saveState, jobs: jobs }), /*#__PURE__*/_react.default.createElement(_create_result_callout.CreateResultCallout, { saveState: saveState, resultsUrl: resultsUrl, onReset: loadModule }))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: 2 }, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { grow: false, hasShadow: false, hasBorder: true }, /*#__PURE__*/_react.default.createElement(_module_jobs.ModuleJobs, { jobs: jobs, jobPrefix: jobPrefix, saveState: saveState, existingGroupIds: existingGroups, jobOverrides: jobOverrides, onJobOverridesChange: onJobOverridesChange })), Object.keys(kibanaObjects).length > 0 && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "m" }), /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { grow: false, hasShadow: false, hasBorder: true }, Object.keys(kibanaObjects).map((objectType, i) => /*#__PURE__*/_react.default.createElement(_react.Fragment, { key: objectType }, /*#__PURE__*/_react.default.createElement(_kibana_objects.KibanaObjects, { objectType: objectType, kibanaObjects: kibanaObjects[objectType], isSaving: saveState === SAVE_STATE.SAVING }), i < Object.keys(kibanaObjects).length - 1 && /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "s" }))))))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "l" })); }; exports.Page = Page;