"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.convertToSerializedVis = exports.convertFromSerializedVis = exports.SAVED_VIS_TYPE = void 0; exports.findListItems = findListItems; exports.getFullPath = getFullPath; exports.getSavedVisualization = getSavedVisualization; exports.mapHitSource = mapHitSource; exports.saveVisualization = saveVisualization; exports.shouldShowMissedDataViewError = void 0; exports.urlFor = urlFor; var _lodash = _interopRequireDefault(require("lodash")); var _public = require("@kbn/kibana-utils-plugin/public"); var _public2 = require("@kbn/data-plugin/public"); var _saved_objects_utils = require("./saved_objects_utils"); var _vis_update_state = require("../legacy/vis_update_state"); var _saved_visualization_references = require("./saved_visualization_references"); var _constants = require("./saved_objects_utils/constants"); var _content_management = require("../content_management"); /* * 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 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ // @ts-ignore const SAVED_VIS_TYPE = 'visualization'; exports.SAVED_VIS_TYPE = SAVED_VIS_TYPE; const getDefaults = opts => ({ title: '', visState: !opts.type ? null : { type: opts.type }, uiStateJSON: '{}', description: '', savedSearchId: opts.savedSearchId, version: 1 }); function getFullPath(id) { return `/app/visualize#/edit/${id}`; } function urlFor(id) { return `#/edit/${encodeURIComponent(id)}`; } function mapHitSource(visTypes, { attributes, id, references, updatedAt }) { var _newAttributes$type, _newAttributes$type2, _newAttributes$type3, _visTypes$get; const newAttributes = { id, references, url: urlFor(id), updatedAt, ...attributes }; let typeName = attributes.typeName; if (attributes.visState) { try { typeName = JSON.parse(String(attributes.visState)).type; } catch (e) { /* missing typename handled below */ } } if (!typeName || !visTypes.get(typeName)) { newAttributes.error = 'Unknown visualization type'; return newAttributes; } newAttributes.type = visTypes.get(typeName); newAttributes.savedObjectType = 'visualization'; newAttributes.icon = (_newAttributes$type = newAttributes.type) === null || _newAttributes$type === void 0 ? void 0 : _newAttributes$type.icon; newAttributes.image = (_newAttributes$type2 = newAttributes.type) === null || _newAttributes$type2 === void 0 ? void 0 : _newAttributes$type2.image; newAttributes.typeTitle = (_newAttributes$type3 = newAttributes.type) === null || _newAttributes$type3 === void 0 ? void 0 : _newAttributes$type3.title; newAttributes.editUrl = `/edit/${id}`; newAttributes.readOnly = Boolean((_visTypes$get = visTypes.get(typeName)) === null || _visTypes$get === void 0 ? void 0 : _visTypes$get.disableEdit); return newAttributes; } const convertToSerializedVis = savedVis => { const { id, title, description, visState, uiStateJSON, searchSourceFields } = savedVis; const aggs = searchSourceFields && searchSourceFields.index ? visState.aggs || [] : visState.aggs; return { id, title, type: visState.type, description, params: visState.params, uiState: JSON.parse(uiStateJSON || '{}'), data: { aggs, searchSource: searchSourceFields, savedSearchId: savedVis.savedSearchId } }; }; exports.convertToSerializedVis = convertToSerializedVis; const convertFromSerializedVis = vis => { return { id: vis.id, title: vis.title, description: vis.description, visState: { title: vis.title, type: vis.type, aggs: vis.data.aggs, params: vis.params }, uiStateJSON: JSON.stringify(vis.uiState), searchSourceFields: vis.data.searchSource, savedSearchId: vis.data.savedSearchId }; }; exports.convertFromSerializedVis = convertFromSerializedVis; async function findListItems(visTypes, search, size, references, referencesToExclude) { const visAliases = visTypes.getAliases(); const extensions = visAliases.map(v => { var _v$appExtensions; return (_v$appExtensions = v.appExtensions) === null || _v$appExtensions === void 0 ? void 0 : _v$appExtensions.visualizations; }).filter(Boolean); const extensionByType = extensions.reduce((acc, m) => { return m.docTypes.reduce((_acc, type) => { acc[type] = m; return acc; }, acc); }, {}); const searchOption = (field, ...defaults) => (0, _lodash.default)(extensions).map(field).concat(defaults).compact().flatten().uniq().value(); const { hits: savedObjects, pagination: { total } } = await _content_management.visualizationsClient.search({ text: search ? `${search}*` : undefined, limit: size, tags: { included: references === null || references === void 0 ? void 0 : references.map(r => r.id), excluded: referencesToExclude === null || referencesToExclude === void 0 ? void 0 : referencesToExclude.map(r => r.id) } }, { types: searchOption('docTypes', 'visualization'), searchFields: searchOption('searchFields', 'title^3', 'description') }); return { total, hits: savedObjects.map(savedObject => { const config = extensionByType[savedObject.type]; if (config) { return { ...config.toListItem(savedObject), references: savedObject.references }; } else { return mapHitSource(visTypes, savedObject); } }) }; } async function getSavedVisualization(services, opts) { if (typeof opts !== 'object') { opts = { id: opts }; } const id = opts.id || ''; const savedObject = { id, migrationVersion: opts.migrationVersion, displayName: SAVED_VIS_TYPE, getEsType: () => SAVED_VIS_TYPE, getDisplayName: () => SAVED_VIS_TYPE, searchSource: opts.searchSource ? services.search.searchSource.createEmpty() : undefined }; const defaultsProps = getDefaults(opts); if (!id) { Object.assign(savedObject, defaultsProps); return savedObject; } const { item: resp, meta: { outcome, aliasTargetId, aliasPurpose } } = await _content_management.visualizationsClient.get(id); if (!resp.id) { throw new _public.SavedObjectNotFound(SAVED_VIS_TYPE, id || ''); } const attributes = _lodash.default.cloneDeep(resp.attributes); if (attributes.visState && typeof attributes.visState === 'string') { attributes.visState = JSON.parse(attributes.visState); } // assign the defaults to the response _lodash.default.defaults(attributes, defaultsProps); Object.assign(savedObject, attributes); savedObject.lastSavedTitle = savedObject.title; savedObject.sharingSavedObjectProps = { aliasTargetId, outcome, aliasPurpose, errorJSON: outcome === 'conflict' && services.spaces ? JSON.stringify({ targetType: SAVED_VIS_TYPE, sourceId: id, targetSpace: (await services.spaces.getActiveSpace()).id }) : undefined }; const meta = attributes.kibanaSavedObjectMeta; if (meta && meta.searchSourceJSON) { try { let searchSourceValues = (0, _public2.parseSearchSourceJSON)(meta.searchSourceJSON); if (opts.searchSource) { searchSourceValues = (0, _public2.injectSearchSourceReferences)(searchSourceValues, resp.references); savedObject.searchSource = await services.search.searchSource.create(searchSourceValues); } else { savedObject.searchSourceFields = searchSourceValues; } } catch (error) { throw error; } } if (resp.references && resp.references.length > 0) { (0, _saved_visualization_references.injectReferences)(savedObject, resp.references); } if (services.savedObjectsTagging) { savedObject.tags = services.savedObjectsTagging.ui.getTagIdsFromReferences(resp.references); } savedObject.visState = await (0, _vis_update_state.updateOldState)(savedObject.visState); return savedObject; } async function saveVisualization(savedObject, { confirmOverwrite = false, isTitleDuplicateConfirmed = false, onTitleDuplicate, copyOnSave = false }, services) { // Save the original id in case the save fails. const originalId = savedObject.id; // Read https://github.com/elastic/kibana/issues/9056 and // https://github.com/elastic/kibana/issues/9012 for some background into why this copyOnSave variable // exists. // The goal is to move towards a better rename flow, but since our users have been conditioned // to expect a 'save as' flow during a rename, we are keeping the logic the same until a better // UI/UX can be worked out. if (copyOnSave) { delete savedObject.id; } const attributes = { visState: JSON.stringify(savedObject.visState), title: savedObject.title, uiStateJSON: savedObject.uiStateJSON, description: savedObject.description, savedSearchId: savedObject.savedSearchId, version: savedObject.version, kibanaSavedObjectMeta: {} }; let references = []; if (savedObject.searchSource) { const { searchSourceJSON, references: searchSourceReferences } = savedObject.searchSource.serialize(); attributes.kibanaSavedObjectMeta = { searchSourceJSON }; references.push(...searchSourceReferences); } if (savedObject.searchSourceFields) { const [searchSourceFields, searchSourceReferences] = (0, _public2.extractSearchSourceReferences)(savedObject.searchSourceFields); const searchSourceJSON = JSON.stringify(searchSourceFields); attributes.kibanaSavedObjectMeta = { searchSourceJSON }; references.push(...searchSourceReferences); } if (services.savedObjectsTagging) { references = services.savedObjectsTagging.ui.updateTagsReferences(references, savedObject.tags || []); } const extractedRefs = (0, _saved_visualization_references.extractReferences)({ attributes, references }); if (!extractedRefs.references) { throw new Error('References not returned from extractReferences'); } try { await (0, _saved_objects_utils.checkForDuplicateTitle)(savedObject, copyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate, services); const createOpt = { migrationVersion: savedObject.migrationVersion, references: extractedRefs.references }; const resp = confirmOverwrite ? await (0, _saved_objects_utils.saveWithConfirmation)(attributes, savedObject, createOpt, services) : savedObject.id ? await _content_management.visualizationsClient.update({ id: savedObject.id, data: { ...extractedRefs.attributes }, options: { overwrite: true, references: extractedRefs.references } }) : await _content_management.visualizationsClient.create({ data: { ...extractedRefs.attributes }, options: { overwrite: true, references: extractedRefs.references } }); savedObject.id = resp.item.id; savedObject.lastSavedTitle = savedObject.title; return savedObject.id; } catch (err) { savedObject.id = originalId; if (err && [_constants.OVERWRITE_REJECTED, _constants.SAVE_DUPLICATE_REJECTED].includes(err.message)) { return ''; } return Promise.reject(err); } } const shouldShowMissedDataViewError = error => error instanceof _public.SavedObjectNotFound && error.savedObjectType === 'data view'; exports.shouldShowMissedDataViewError = shouldShowMissedDataViewError;