'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. 2019, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /** * @classdesc helper class that is used to deal with OLAP */ define([], function () { var OlapHelperV2 = function () { function OlapHelperV2(dashboard, visualization) { _classCallCheck(this, OlapHelperV2); this.dashboard = dashboard; this.visualization = visualization; } /** * @desc Accepts olap column on slot * @param {String} targetSlotId - target slot id * @param {String} sourceSlotId - source slot id, it is undefined if dnd from metadata tree * @param {Number} indexInSourceSlot - slot item index in source slot, it is undefined if dnd from metadata tree * @param {Array} sourceColumns - metadata columns to be added into target slot * @param {Number} indexInTargetSlot - position to add * @param {Boolean} isReplace - if it is to replace the column in the position * @return {Boolean} return True if the two lists of columns can be in the same slot */ OlapHelperV2.prototype.acceptsOlapV2 = function acceptsOlapV2(_ref) { var targetSlotId = _ref.targetSlotId, sourceSlotId = _ref.sourceSlotId, indexInSourceSlot = _ref.indexInSourceSlot, sourceColumns = _ref.sourceColumns, indexInTargetSlot = _ref.indexInTargetSlot, isReplace = _ref.isReplace; var expandCollapseFeatureFlag = !this.dashboard.getGlassCoreSvc('.FeatureChecker').checkValue('dashboard', 'expandCollapse', 'disabled'); // There are no restrictions on OLAP columns on non-crosstab visualizations if (!expandCollapseFeatureFlag || this.visualization.getType() !== 'Crosstab') { return true; } var slotsAPI = this.visualization.getSlots(); var targetSlotAPI = slotsAPI.getSlot(targetSlotId); var sourceSlotAPI = sourceSlotId ? slotsAPI.getSlot(sourceSlotId) : undefined; var sourceMetadataColumns = sourceSlotAPI ? sourceSlotAPI.getDataItemList().slice(indexInSourceSlot, indexInSourceSlot + 1).map(function (item) { return item.getMetadataColumn(); }) : sourceColumns; if (targetSlotAPI.getDefinition().getType() !== 'category' && (!sourceSlotAPI || sourceSlotAPI.getDefinition().getType() !== 'category')) { // OLAP restrictions only apply to categorical slots return true; } var hasOlapColumn = false; var olapMeasureColumn = sourceMetadataColumns.find(function (col) { var isOlapColumn = col.isOlapColumn(); hasOlapColumn = hasOlapColumn || isOlapColumn; return isOlapColumn && col.getType() === 'fact'; }); if (olapMeasureColumn) { // OLAP measure column is not allowed to be dropped to category slot. Aggregation over measure sets is not supported. return false; } if (!hasOlapColumn) { // Need at least one OLAP column for OLAP restrictions to apply return true; } var accepts = void 0; if (sourceSlotAPI) { accepts = this._acceptsSlotItem({ slotsAPI: slotsAPI, targetSlotAPI: targetSlotAPI, sourceSlotAPI: sourceSlotAPI, sourceMetadataColumns: sourceMetadataColumns, isReplace: isReplace, indexInTargetSlot: indexInTargetSlot, indexInSourceSlot: indexInSourceSlot }); } else { accepts = this._acceptsMetadataColumns({ slotsAPI: slotsAPI, targetSlotAPI: targetSlotAPI, sourceMetadataColumns: sourceMetadataColumns }); } var targetMetadataColumns = targetSlotAPI.getDataItemList().map(function (dataItem) { return dataItem.getMetadataColumn(); }); var isSameSlot = targetSlotId === sourceSlotId; return accepts && this._acceptsColumnsInSlot({ targetMetadataColumns: targetMetadataColumns, sourceMetadataColumns: sourceMetadataColumns, indexInTargetSlot: indexInTargetSlot, isReplace: isReplace, isSameSlot: isSameSlot, indexInSourceSlot: indexInSourceSlot }); }; /** * Gets OLAP hierarchy by a metadata column * @param {Object} metadata column * @return {Object} olap metadata hierarchy, return null if metadata column is not olap */ OlapHelperV2.prototype._getHierarchy = function _getHierarchy(metadataColumn) { if (metadataColumn.isOlapColumn()) { if (metadataColumn.isHierarchy()) { return metadataColumn; } else if (metadataColumn.isLevel()) { return metadataColumn.getParent(); } else if (metadataColumn.isProperty()) { var grandparent = metadataColumn.getParent().getParent(); return grandparent && grandparent.isHierarchy() && grandparent; } } return null; }; /** * Check if two olap metadata columns are in the same hierarchy * @param {Object} metadata column 1 * @param {Object} metadata column 2 * @return {Boolean} return true if the two metadata column are in the same hierarchy */ OlapHelperV2.prototype._inSameHierarchy = function _inSameHierarchy(metadataColumn1, metadataColumn2) { if (metadataColumn1.isOlapColumn() && metadataColumn2.isOlapColumn()) { var h1 = this._getHierarchy(metadataColumn1); var h2 = this._getHierarchy(metadataColumn2); return h1 && h2 && h1.getId() === h2.getId(); } return false; }; OlapHelperV2.prototype._getHierarchies = function _getHierarchies(metadataColumns) { var _this = this; var hierarchies = []; metadataColumns.forEach(function (col) { var hier = col && _this._getHierarchy(col); if (hier) { if (!hierarchies.find(function (id) { return id === hier.getId(); })) { hierarchies.push(hier.getId()); } } }); return hierarchies; }; /** * @desc accepts a slot item * @param {Object} slotsAPI - slots api * @param {Object} targetSlotAPI - target slot api * @param {Object} sourceSlotAPI - source slot api * @param {Array} sourceMetadataColumns - metadata columns to be added into target slot * @param {Number} indexInSourceSlot - slot item index in source slot, it is undefined if dnd from metadata tree * @param {Number} indexInTargetSlot - position to add * @param {Boolean} isReplace - if it is to replace the column in the position * @return {Boolean} return True if a hierarchy is not on both col and row */ OlapHelperV2.prototype._acceptsSlotItem = function _acceptsSlotItem(_ref2) { var _this2 = this; var slotsAPI = _ref2.slotsAPI, targetSlotAPI = _ref2.targetSlotAPI, sourceSlotAPI = _ref2.sourceSlotAPI, sourceMetadataColumns = _ref2.sourceMetadataColumns, isReplace = _ref2.isReplace, indexInTargetSlot = _ref2.indexInTargetSlot, indexInSourceSlot = _ref2.indexInSourceSlot; var metadataColumnsTargetSlot = targetSlotAPI.getDataItemList().map(function (dataItem) { return dataItem.getMetadataColumn(); }); var metadataColumnsSourceSlot = sourceSlotAPI.getDataItemList().map(function (dataItem) { return dataItem.getMetadataColumn(); }); var sourceMetadataColumn = sourceMetadataColumns[0]; //can only drag one slot item at a time if (isReplace) { var swapTarget = metadataColumnsTargetSlot[indexInTargetSlot]; metadataColumnsTargetSlot[indexInTargetSlot] = sourceMetadataColumn; metadataColumnsSourceSlot[indexInSourceSlot] = swapTarget; } else { metadataColumnsTargetSlot.splice(indexInTargetSlot, 0, sourceMetadataColumn); metadataColumnsSourceSlot.splice(indexInSourceSlot, 1); } //get rest of category slot IDs var restSlotIDs = slotsAPI.getSlotList().filter(function (slot) { return slot.getDefinition().getId() !== targetSlotAPI.getDefinition().getId() && slot.getDefinition().getId() !== sourceSlotAPI.getDefinition().getId() && slot.getDefinition().getType() === 'category'; }).map(function (s) { return s.getDefinition().getId(); }); var slotsColumns = restSlotIDs.map(function (id) { return slotsAPI.getSlot(id).getDataItemList().map(function (dataItem) { return dataItem.getMetadataColumn(); }); }); var hierarchies = []; var isSameSlot = targetSlotAPI.getDefinition().getId() === sourceSlotAPI.getDefinition().getId(); if (!isSameSlot) { if (targetSlotAPI.getDefinition().getType() === 'category') { slotsColumns.push(metadataColumnsTargetSlot); } if (sourceSlotAPI.getDefinition().getType() === 'category') { slotsColumns.push(metadataColumnsSourceSlot); } } return slotsColumns.every(function (columns) { var hierList = _this2._getHierarchies(columns); if (hierarchies.some(function (h) { return hierList.indexOf(h) !== -1; })) { return false; } hierarchies.push.apply(hierarchies, hierList); return true; }); }; /** * @desc accepts a list of metadata columns from metadata tree * @param {Object} slotsAPI - slots api * @param {Object} targetSlotAPI - target slot api * @param {Array} sourceMetadataColumns - metadata columns to be added into target slot * @return {Boolean} return True if a hierarchy is not on both col and row */ OlapHelperV2.prototype._acceptsMetadataColumns = function _acceptsMetadataColumns(_ref3) { var _this3 = this; var slotsAPI = _ref3.slotsAPI, targetSlotAPI = _ref3.targetSlotAPI, sourceMetadataColumns = _ref3.sourceMetadataColumns; var categorySlots = slotsAPI.getSlotList().filter(function (slot) { return slot.getDefinition().getType() === 'category'; }); var dataItemList = []; categorySlots.forEach(function (slot) { var items = slot.getDataItemList().filter(function (dataItem) { return dataItem.getColumnId() !== '_multiMeasuresSeries'; }); dataItemList.push.apply(dataItemList, items); }); var projectedMetadataColumns = dataItemList.map(function (dataItem) { return dataItem.getMetadataColumn(); }); var targetSlotDataItemList = targetSlotAPI.getDataItemList(); var targetSlotMetadataColumnIds = targetSlotDataItemList.filter(function (dataItem) { return dataItem.getColumnId() !== '_multiMeasuresSeries'; }).map(function (dataItem) { return dataItem.getColumnId(); }); var columnsNotInTargetSlot = projectedMetadataColumns.filter(function (column) { return targetSlotMetadataColumnIds.indexOf(column.getId()) === -1; }); var hierarchyNotInTargetSlot = columnsNotInTargetSlot.some(function (column) { return sourceMetadataColumns.some(function (dragColumn) { return _this3._inSameHierarchy(dragColumn, column); }); }); // Find any columns which will be in different slots from the target slot, // and which are in the same hierarchy as the source columns if (hierarchyNotInTargetSlot) { return false; } return true; }; /** * @desc Check if a list of metadata columns can be added into another list of columns in the same slot * @param {Array} targetMetadataColumns - metadata columns in target slot * @param {Array} sourceMetadataColumns - metadata columns to be added into target slot * @param {Number} indexInTargetSlot - index in target slot to add * @param {Number} indexInSourceSlot - slot item index in source slot, it is undefined if dnd from metadata tree * @param {Boolean} isReplace - if it is to replace the column in the position * @param {Boolean} IsSameSlot - if it is drag and drop in the same slot * @return {Boolean} return True if the two lists of columns can be in the same slot */ OlapHelperV2.prototype._acceptsColumnsInSlot = function _acceptsColumnsInSlot(_ref4) { var targetMetadataColumns = _ref4.targetMetadataColumns, sourceMetadataColumns = _ref4.sourceMetadataColumns, indexInTargetSlot = _ref4.indexInTargetSlot, isReplace = _ref4.isReplace, isSameSlot = _ref4.isSameSlot, indexInSourceSlot = _ref4.indexInSourceSlot; //check if OLAP columns are in natural order and consecutive in slot if (!targetMetadataColumns || !sourceMetadataColumns || indexInTargetSlot === undefined || isReplace === undefined) { return false; } var targetSlotMetadataColumns = [].concat(targetMetadataColumns); if (indexInTargetSlot < 0) { indexInTargetSlot = targetSlotMetadataColumns.length; } if (isReplace) { if (isSameSlot) { //swap //can only drag one slot item, so actually sourceMetadataColumns.length is 1 var items = targetSlotMetadataColumns.splice.apply(targetSlotMetadataColumns, [indexInTargetSlot, 1].concat(sourceMetadataColumns)); targetSlotMetadataColumns.splice.apply(targetSlotMetadataColumns, [indexInSourceSlot, 1].concat(items)); } else { targetSlotMetadataColumns.splice.apply(targetSlotMetadataColumns, [indexInTargetSlot, 1].concat(sourceMetadataColumns)); } } else { if (isSameSlot) { //if dnd in the same slot, remove dragged item from target slot columns targetSlotMetadataColumns.splice(indexInSourceSlot, 1); if (indexInSourceSlot < indexInTargetSlot) { indexInTargetSlot--; } } targetSlotMetadataColumns.splice.apply(targetSlotMetadataColumns, [indexInTargetSlot, 0].concat(sourceMetadataColumns)); } return this._isColumnOrderValidInSlot(targetSlotMetadataColumns); }; OlapHelperV2.prototype._isColumnOrderValidInSlot = function _isColumnOrderValidInSlot(metadataColumns) { var _this4 = this; var hierarchyMap = {}; metadataColumns.forEach(function (col, index) { var hierarchy = _this4._getHierarchy(col); if (hierarchy) { if (hierarchyMap[hierarchy.getId()]) { hierarchyMap[hierarchy.getId()].metadataColumns.push({ metadataColumn: col, index: index }); } else { hierarchyMap[hierarchy.getId()] = { metadataColumns: [{ metadataColumn: col, index: index }], hierarchy: hierarchy }; } } }); return this._isHierarchyInNaturalOrderAndConsecutiveNestingLevels(hierarchyMap); }; OlapHelperV2.prototype._isHierarchyInNaturalOrderAndConsecutiveNestingLevels = function _isHierarchyInNaturalOrderAndConsecutiveNestingLevels(hierarchyMap) { var _this5 = this; var hierarchies = Object.values(hierarchyMap); return !hierarchies.some(function (hierarchy) { var hierarchyItemIds = hierarchy.hierarchy.getHierarchyLevelIds(); // Find natural order index for the column in each position var indexes = hierarchy.metadataColumns.map(function (col) { var metadataColumn = col.metadataColumn; if (metadataColumn.isHierarchy()) { return -1; } else if (metadataColumn.isProperty()) { metadataColumn = metadataColumn.getParent(); } return hierarchyItemIds.findIndex(function (id) { return metadataColumn.getId() === id; }); }); if (!_this5._isDescSorted(indexes)) { return true; } indexes = hierarchy.metadataColumns.map(function (col) { return col.index; }); if (!_this5._isHierarchyInConsecutiveNestingLevels(indexes)) { return true; } }); }; OlapHelperV2.prototype._isHierarchyInConsecutiveNestingLevels = function _isHierarchyInConsecutiveNestingLevels(indexes) { var consecutive = true; for (var i = 0; i <= indexes.length - 2; i++) { if (indexes[i] + 1 !== indexes[i + 1]) { consecutive = false; break; } } return consecutive; }; OlapHelperV2.prototype._isDescSorted = function _isDescSorted(indexes) { var sorted = true; for (var i = 0; i < indexes.length - 1; i++) { if (indexes[i] > indexes[i + 1]) { sorted = false; break; } } return sorted; }; return OlapHelperV2; }(); return OlapHelperV2; }); //# sourceMappingURL=OlapHelper.v2.js.map