'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Licensed Materials - Property of IBM * IBM Business Analytics (C) Copyright IBM Corp. 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /** * @class VisDnDColumnToSlotProvider * @hideconstructor * * @classdesc Handles drag and drop of metadata to slot to create a visualization. */ define(['underscore', '../../../../../lib/@waca/dashboard-common/dist/core/APIFactory', '../../../../../dataSources/utils/ShapingUIUtils', '../../VisMapColumnsToSlot', 'dashboard-analytics/apiHelpers/SlotAPIHelper', 'dashboard-analytics/widgets/livewidget/nls/StringResources'], function (_, APIFactory, ShapingUIUtils, VisMapColumnsToSlot, SlotAPIHelper, StringResources) { var MULTI_MEASURES_SERIES = '_multiMeasuresSeries'; return function () { function VisDnDColumnToSlotProvider() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, VisDnDColumnToSlotProvider); this.visDnDUtils = options.visDnDUtils; this.dashboardAPI = options.dashboardAPI; this.datasources = options.datasources; this.datasourcesMoser = options.datasourcesMoser; this.content = options.content; this.visualization = options.visualization; this.transaction = options.transaction; this.visMapColumnsToSlot = new VisMapColumnsToSlot({ content: this.content, visualization: this.visualization, transaction: this.transaction }); } VisDnDColumnToSlotProvider.prototype.destroy = function destroy() { this.dashboardAPI = null; this.content = null; this.visDnDUtils = null; this.datasources = null; this.datasourcesMoser = null; this.visualization = null; this.transaction = null; }; /** * @param {Object} source - the DndSource defined by whichever source starts the drag * @param {Object} target - the DnDTarget defined by the drop target which includes target specific information. * @param {String} target.el - the drop node. * @param {String} target.type - the type of the target (eg. slot.item) * @param {String} target.info - a target-specific function which includes information about that target. * @return {boolean} true if this provider supports the dndSource and target. */ VisDnDColumnToSlotProvider.prototype.supports = function supports(source, target) { return (target.type === 'slot.item' || target.info.type === 'slot.item') && source.type === 'A11YMetadataColumns' || (source.type === 'MODEL_ITEM' || source.type === 'GRID_HEADER_ITEM') && source.data.columns || this._isMetadataColumnArray(source); }; VisDnDColumnToSlotProvider.prototype._getA11YData = function _getA11YData(sourceId) { var module = sourceId && this.datasourcesMoser.getModule(sourceId); var copiedTreeItems = ShapingUIUtils.getCopiedTreeItems(module, this.dashboardAPI); return copiedTreeItems && copiedTreeItems.data && copiedTreeItems.data; }; VisDnDColumnToSlotProvider.prototype._clearA11YData = function _clearA11YData() { ShapingUIUtils.clearCopiedTreeItems(); this.dashboardAPI.triggerDashboardEvent('dataSourceGrid:clearSourceSelected'); }; VisDnDColumnToSlotProvider.prototype._isMetadataColumnArray = function _isMetadataColumnArray(sourceData) { return sourceData.type === 'metadataColumns' && Array.isArray(sourceData.data); }; //The ColumnToSlot provider accepts 3 forms of input //1) For a11y, a hint exists in the source that indicates we need to fetch it from shaping. //2) Columns as from drag&drop data (which we receive from an actual drag&drop) //3) metadataColumns as a simple array of metadataColumnAPI's (which we receive from type-in) VisDnDColumnToSlotProvider.prototype._getNormalizedMetadataColumnArray = function _getNormalizedMetadataColumnArray(source) { if (source.type === 'A11YMetadataColumns') { var a11YData = this._getA11YData(this.dashboardAPI.getActiveDataSourceId()); return a11YData && a11YData.columns; } else if (source.data && source.data.columns) { return source.data.columns; } else if (this._isMetadataColumnArray(source)) { return source.data.map(function (column) { return { metadataColumn: column }; }); } return null; //Its can't be normalized into valid input. }; VisDnDColumnToSlotProvider.prototype.accepts = function accepts(source, target) { if (source.data && source.data.utils && source.data.utils.isValid()) { return this._acceptsMetadataColumns(source, target); } return false; }; VisDnDColumnToSlotProvider.prototype.onDrop = function onDrop(source, target) { var droppedColumns = this._getNormalizedMetadataColumnArray(source); if (!this.visDnDUtils.validateSupportsOLAP(droppedColumns.map(function (c) { return c.metadataColumn; }))) { this.dashboardAPI.getFeature('Notification').setMessage(StringResources.get('visualizationDoesNotSupportOLAP')); return false; } var addAfter = target.info.addAfter; var position = addAfter ? target.info.indexInSlot + 1 : target.info.indexInSlot; var transactionToken = this.transaction.startTransaction(); var options = { bReplace: addAfter || position < 0 ? false : true, position: position, canSetLocalFilters: this._isMetadataColumnArray(source) ? false : true, //TODO: Not sure about this. Looks like its for member DnD. activeDataSourceId: this.dashboardAPI.getActiveDataSourceId() }; this.visMapColumnsToSlot.mapColumns(target.info.slot.getId(), droppedColumns, options, transactionToken); if (source.type === 'A11YMetadataColumns') { this._clearA11YData(); } this.transaction.endTransaction(transactionToken); }; //Can this slotDataItem accept these items from the metadata tree or shaping grid? (aka metadataColumns) VisDnDColumnToSlotProvider.prototype._acceptsMetadataColumns = function _acceptsMetadataColumns(source, target) { var sourceData = source.data; var metadataColumns = sourceData; var metadataColumnsWithMembers = {}; if (sourceData && sourceData.columns) { metadataColumns = _.map(sourceData.columns, function (column) { return column.metadataColumn; }); metadataColumnsWithMembers = sourceData.utils && sourceData.utils.getColumnsWithMembers(); } if (!metadataColumns.length) { return false; } //You CAN'T drop metadataColumns if any columns don't match the sourceId of this widget. var currentSourceId = this.getDatasourceId(); var isDifferentSourceColumn = function isDifferentSourceColumn(metadataColumn) { /* needed to handle both metadataColumnApi and metadataColumn */ var columnSourceId = metadataColumn.getSourceId ? metadataColumn.getSourceId() : metadataColumn.sourceId; return currentSourceId && currentSourceId !== columnSourceId; }; if (metadataColumns.some(isDifferentSourceColumn)) { return false; } //You CAN'T drop metadatacolumns that have certain taxonomy characteristics if (!this._itemsSupported(metadataColumns, target.info.slot)) { return false; } // //You CAN'T drop on top of the placeholder dataItem 'Measure Group (n)' from the metadata tree. You CAN drop after it. if (!target.info.addAfter && this.isMeasureGroupItem(target.info.slot, target.info.indexInSlot)) { return false; } //You CAN'T drop a filter if (metadataColumns.some(function (metadataColumn) { return metadataColumn.getObjectType() === 'Filter'; })) { return false; } //Check what hierarchies (if any) the dropped columns belong to. //Don't allow drop if any are in a hierarchy that is already being used in the visualization. var oHierarchyMap = {}; if (ShapingUIUtils.isInvalidDragObject(metadataColumns, oHierarchyMap, metadataColumnsWithMembers, false /* metadataColumnsExist */) || this._isRestrictedForMembersOfSameHierarchy(metadataColumns, metadataColumnsWithMembers, target.info.slot.getId()) || ShapingUIUtils.isInvalidDragObject(this._getUsedMetadataColumns(), oHierarchyMap, metadataColumnsWithMembers, true /* metadataColumnsExist */)) { return false; } //You CAN'T drop more items than the slot can allow. var countItems = this._getCountItemsInDropData(metadataColumnsWithMembers, target.info.slot); return this._acceptsCommon(source, target, countItems, target.info.addAfter); }; VisDnDColumnToSlotProvider.prototype.getDatasourceId = function getDatasourceId() { var dataSource = this.visualization.getDataSource(); if (dataSource) { return dataSource.getId(); } return null; }; VisDnDColumnToSlotProvider.prototype.isMeasureGroupItem = function isMeasureGroupItem(slot, indexInSlot) { if (SlotAPIHelper.isMultiMeasuresSeriesSlot(slot)) { var thisDataItem = slot.getDataItemList()[indexInSlot]; return thisDataItem && thisDataItem.getColumnId() === '_multiMeasuresSeries'; } return false; }; // Restrict to drop members of same hierarchy or namedSet in different slots VisDnDColumnToSlotProvider.prototype._isRestrictedForMembersOfSameHierarchy = function _isRestrictedForMembersOfSameHierarchy(metadataColumns, metadataColumnsWithMembers, slotId) { if (_.isEmpty(metadataColumnsWithMembers)) { return false; } // Get items from dropped columns that are hierarchy or namedSet var droppedColumnsWithMembers = []; metadataColumns.forEach(function (column) { if (column.isHierarchy() || column.isNamedSet()) { droppedColumnsWithMembers.push(column.getId()); } }); if (!droppedColumnsWithMembers.length) { return false; } // Get all items from other slots that are hierarchy or namedSet var itemsFromOtherSlots = this._getColumnsFromHierarchyOrNamedSetOfOtherSlots(slotId); if (!itemsFromOtherSlots.length) { return false; } if (!_.intersection(droppedColumnsWithMembers, itemsFromOtherSlots).length) { return false; } return true; }; VisDnDColumnToSlotProvider.prototype._getColumnsFromHierarchyOrNamedSetOfOtherSlots = function _getColumnsFromHierarchyOrNamedSetOfOtherSlots(targetSlotId) { var itemsFromOtherSlots = []; this.visualization.getSlots().getSlotList().forEach(function (slot) { if (slot.getDefinition().getId() !== targetSlotId) { slot.getDataItemList().forEach(function (dataItem) { var column = dataItem.getMetadataColumn && dataItem.getMetadataColumn(); if (column && (column.isHierarchy() || column.isNamedSet())) { itemsFromOtherSlots.push(column.getId()); } }); } }); return itemsFromOtherSlots; }; /** * return a list of metadataColumns all the projected dataItems except MultiMeasure item. */ VisDnDColumnToSlotProvider.prototype._getUsedMetadataColumns = function _getUsedMetadataColumns() { var dataItemList = this.visualization.getSlots().getDataItemList(); return dataItemList.filter(function (dataItem) { return dataItem.getColumnId() !== MULTI_MEASURES_SERIES; }).map(function (dataItem) { return dataItem.getMetadataColumn(); }); }; VisDnDColumnToSlotProvider.prototype._getMappedItemsOfTargetSlot = function _getMappedItemsOfTargetSlot(slot) { var mappedItems = []; slot.getDataItemList().forEach(function (dataItem) { if (dataItem.getMetadataColumn) { mappedItems.push(dataItem.getMetadataColumn().getId()); } }); return mappedItems; }; VisDnDColumnToSlotProvider.prototype._itemsSupported = function _itemsSupported(metadataColumns, slot) { //convert to new metadataColumn api var sourceId = metadataColumns[0].getSourceId(); var dataSource = sourceId && this.datasources.getDataSource(sourceId); if (dataSource) { var newMetadataColumnAPIs = metadataColumns.map(function (metadataColumn) { return dataSource.getMetadataColumn(metadataColumn.getId()); }); return slot.supportsColumns(newMetadataColumnAPIs); } return false; }; // We count only columns that are not already in the slot VisDnDColumnToSlotProvider.prototype._getCountItemsInDropData = function _getCountItemsInDropData(metadataColumnsWithMembers, slot) { var _ref; if (!metadataColumnsWithMembers) { return 1; } var memberParentIds = Object.keys(metadataColumnsWithMembers); var members = Object.values(metadataColumnsWithMembers); var flattenedMembers = (_ref = []).concat.apply(_ref, members); if (!flattenedMembers.length) { // dropped columns are not members, count all return memberParentIds.length; } var mappedItemIds = this._getMappedItemsOfTargetSlot(slot); // do not count items that already exist in the slot var diffs = memberParentIds.filter(function (id) { return mappedItemIds.indexOf(id) === -1; }); return diffs.length; }; VisDnDColumnToSlotProvider.prototype._acceptsCommon = function _acceptsCommon(source, target, countOfItemsToDrop, addAfter) { //IF this definition contains (or could contain) a multiMeasuresSeries item, //You CAN drop on or after in a values slot (even though values has maxItems of 1 => multi-items go where 'Measure Group (n)' is) if (target.info.slot.getId() === 'values' && SlotAPIHelper.isMultiMeasuresSeriesSlot(target.info.slot) || target.info.slot.getDefinition().isMultiMeasureSupported()) { return true; } //{ targetSlotId, sourceSlotId, indexInSourceSlot, sourceColumns, indexInTargetSlot, isReplace } var params = { targetSlotId: target.info.slot.getId(), sourceSlotId: undefined, indexInSourceSlot: undefined, sourceColumns: _.map(source.data.columns, function (column) { return column.metadataColumn; }), indexInTargetSlot: target.info.addAfter ? target.info.indexInSlot + 1 : target.info.indexInSlot, isReplace: !target.info.addAfter }; var expandCollapseFeatureFlag = !this.dashboardAPI.getGlassCoreSvc('.FeatureChecker').checkValue('dashboard', 'expandCollapse', 'disabled'); if (expandCollapseFeatureFlag && this.visualization.getType() === 'Crosstab') { if (!this.visDnDUtils.acceptsOlapV2(params)) { return false; } } //You CAN'T drop more items than the slot can allow. return !this.visDnDUtils.exceedsItemsLimit(countOfItemsToDrop, target.info.indexInSlot, addAfter, target.info.slot); }; return VisDnDColumnToSlotProvider; }(); }); //# sourceMappingURL=VisDnDColumnToSlotProvider.js.map