123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- 'use strict';
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: Dashboard
- * (C) Copyright IBM Corp. 2018, 2021
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define(['underscore', '../../lib/@waca/dashboard-common/dist/core/APIFactory', './SlotAPISpec', '../SlotAPI', '../../visualizations/interactions/BinningActionsUtils', '../../apiHelpers/SlotAPIHelper', '../../widgets/livewidget/nls/StringResources', '../../util/TransactionUtil'], function (_, APIFactory, SlotAPISpec, SlotAPI, BinningActionsUtils, SlotAPIHelper, StringResources, TransactionUtil) {
- var SlotImpl = function (_SlotAPISpec) {
- _inherits(SlotImpl, _SlotAPISpec);
- function SlotImpl(slotDefinitionAPI, filterSupport, slotsImpl, transaction, locale, visualizationImpl, dataModel, slotMappingModel) {
- _classCallCheck(this, SlotImpl);
- // @todo remove localFilters, slotDfn (for now used in creating MappedDataItem) plus SlotAPI
- var _this = _possibleConstructorReturn(this, _SlotAPISpec.call(this));
- _this.slotDefinitionAPI = slotDefinitionAPI;
- // @todo need to revise by using events
- _this.filterSupport = filterSupport;
- _this.metadataManager = filterSupport.getMetadata();
- _this.transaction = transaction;
- _this.locale = locale;
- _this.slotsImpl = slotsImpl;
- _this.visualizationImpl = visualizationImpl;
- _this.dataModel = dataModel;
- _this.slotMappingModel = slotMappingModel;
- _this.api = APIFactory.createAPI(_this, [SlotAPI]);
- return _this;
- }
- SlotImpl.prototype.setDefinition = function setDefinition(slotDefinitionAPI) {
- this.slotDefinitionAPI = slotDefinitionAPI;
- };
- SlotImpl.prototype.destroy = function destroy() {
- this.slotDefinitionAPI = null;
- this.filterSupport = null;
- this.metadataManager = null;
- this.transaction = null;
- this.locale = null;
- this.slotsImpl = null;
- this.visualizationImpl = null;
- this.dataModel = null;
- this.slotMappingModel = null;
- this.api = null;
- };
- SlotImpl.prototype.getAPI = function getAPI() {
- return this.api;
- };
- SlotImpl.prototype.getId = function getId() {
- return this.getDefinition().getId();
- };
- SlotImpl.prototype.getLocalFilters = function getLocalFilters() {
- return this.filterSupport.getLocalFilters();
- };
- SlotImpl.prototype.getDataSource = function getDataSource() {
- return this.slotsImpl.getDataSource();
- };
- SlotImpl.prototype.resolveDataViewId = function resolveDataViewId() {
- var viewId = void 0;
- // step 1 : check the first item (if any) that belongs to this slot
- var dataItemList = this.getDataItemList();
- if (dataItemList.length > 0) {
- viewId = this.dataModel.getDataViewIdForDataItem(dataItemList[0].getId());
- }
- // Step 2: If we have no mapped dataitem, search the slots that belong to the same dataset
- if (!viewId) {
- var slot = void 0;
- var slotDefinition = this.getDefinition();
- var slotDefinitionList = this.visualizationImpl.getDefinition().getSlotList();
- for (var i = 0; i < slotDefinitionList.length; i++) {
- if (slotDefinition.getId() !== slotDefinitionList[i].getId() && slotDefinition.getDatasetIdList()[0] === slotDefinitionList[i].getDatasetIdList()[0]) {
- // the slots are part of the same dataset
- // see if it has mapped dataitems.. then use the same view
- slot = this.slotsImpl.getSlot(slotDefinitionList[i].getId());
- dataItemList = slot.getDataItemList();
- if (dataItemList.length > 0) {
- viewId = this.dataModel.getDataViewIdForDataItem(dataItemList[0].getId());
- break;
- }
- }
- }
- }
- if (!viewId) {
- // we could not find a view.. we create a new one
- var dataView = this.dataModel.createDataView();
- var dataSource = this.visualizationImpl.getDataSource();
- // default the modelRef if we have other views
- if (dataSource) {
- this.dataModel.setModelRefInAllViews(dataSource.getId());
- }
- viewId = dataView.id;
- }
- return viewId;
- };
- /**
- * Return the slotImpl associated with the multi-measure series. We use the implementation so that
- * any operations are considered inernal and no events will be generated.
- */
- SlotImpl.prototype.getMultiMeasuresSeriesSlot = function getMultiMeasuresSeriesSlot() {
- var multiMeasureSlot = void 0;
- var dataset = this.getDefinition().getDatasetIdList()[0];
- var customMultiMeasureSlotId = this.slotMappingModel.getMultiMeasureSlotId(dataset);
- if (customMultiMeasureSlotId) {
- // slot may not exist, e.g changing visualization from one with slot series to one with color.
- multiMeasureSlot = this.slotsImpl.getSlotImpl(customMultiMeasureSlotId);
- }
- if (!multiMeasureSlot) {
- var defaultMultiMeasureSlot = SlotAPIHelper.getMultiMeasureSeriesSlot(this.visualizationImpl.getAPI(), dataset).getId();
- multiMeasureSlot = this.slotsImpl.getSlotImpl(defaultMultiMeasureSlot);
- }
- return multiMeasureSlot;
- };
- SlotImpl.prototype.getMultiMeasureSeriesPosition = function getMultiMeasureSeriesPosition() {
- var dataset = this.getDefinition().getDatasetIdList()[0];
- return this.slotMappingModel.getMultiMeasurePosition(dataset);
- };
- /**
- * Check how many measure we have in the slot and decide if we need to add, remove or update the measure series slot
- */
- SlotImpl.prototype._processMultiMeasure = function _processMultiMeasure() {
- if (!this.getDefinition().getProperty('multiMeasure')) {
- return;
- }
- var targetSlot = this.getMultiMeasuresSeriesSlot();
- if (targetSlot) {
- var currentDataItemList = this.getDataItemList();
- var multiMeasuresLabel = StringResources.get('MeasuresGroupCaption', {
- count: currentDataItemList.length
- });
- var multiMeasureDataItemId = SlotAPIHelper.MULTI_MEASURES_SERIES + '_' + targetSlot.getDefinition().getDatasetIdList()[0];
- var multiMeasureRequired = currentDataItemList.length > 1;
- var multiMeasureDataItem = this.slotsImpl.getDataItemImpl(multiMeasureDataItemId);
- var createMultiMeasureDataItem = function () {
- // Use the implementation to keep the actions internal (i.e. no events)
- this.slotsImpl.createDataItems([{
- id: multiMeasureDataItemId,
- columnId: SlotAPIHelper.MULTI_MEASURES_SERIES,
- itemLabel: multiMeasuresLabel
- }]);
- targetSlot.addDataItemsMapping([multiMeasureDataItemId], this.getMultiMeasureSeriesPosition());
- }.bind(this);
- var deleteMultiMeasureDataItem = function () {
- // Use the implementation to keep the actions internal (i.e. no events)
- this.slotsImpl.deleteDataItems([multiMeasureDataItemId]);
- targetSlot.removeDataItemsMapping([multiMeasureDataItemId]);
- }.bind(this);
- var updateMultiMeasureDataItem = function () {
- // Use the implementation to keep the actions internal (i.e. no events)
- this.slotsImpl.getDataItemImpl(multiMeasureDataItem.getId()).setLabel(multiMeasuresLabel);
- }.bind(this);
- if (multiMeasureRequired && multiMeasureDataItem) {
- updateMultiMeasureDataItem();
- } else if (multiMeasureRequired && !multiMeasureDataItem) {
- createMultiMeasureDataItem();
- } else if (!multiMeasureRequired && multiMeasureDataItem) {
- deleteMultiMeasureDataItem();
- }
- }
- };
- SlotImpl.prototype.getDataItemIndex = function getDataItemIndex(id) {
- var slotModel = this.slotMappingModel.getSlot(this.getId());
- return slotModel.dataItems.indexOf(id);
- };
- // Return the actual instance and not just the API interface
- SlotImpl.prototype.getDataItemImpl = function getDataItemImpl(dataItemId) {
- var impl = void 0;
- // Search the mapping model
- var slotModel = this.slotMappingModel.getMappedSlot(dataItemId);
- if (slotModel && slotModel.name === this.getId()) {
- // the dataItem is mapped to this slot
- impl = this.slotsImpl.getDataItemImpl(dataItemId);
- }
- return impl;
- };
- SlotImpl.prototype.getDataItem = function getDataItem(dataItemId) {
- var impl = this.getDataItemImpl(dataItemId);
- return impl ? impl.getAPI() : null;
- };
- SlotImpl.prototype.addDataItems = function addDataItems(dataItemSpecList, position, transactionToken) {
- var subTransaction = this.transaction.startTransaction(transactionToken);
- // Use the API to trigger the event
- var dataItemList = this.slotsImpl.getAPI().createDataItems(dataItemSpecList, subTransaction);
- this.getAPI().addDataItemsMapping(dataItemList.map(function (dataItem) {
- return dataItem.getId();
- }), position, subTransaction);
- this.transaction.endTransaction(subTransaction);
- return dataItemList;
- };
- SlotImpl.prototype.removeDataItems = function removeDataItems(dataItemIdList, transactionToken) {
- var _this2 = this;
- var subTransaction = this.transaction.startTransaction(transactionToken);
- this._removeSelectionsOnUnusedDataItems(dataItemIdList, subTransaction);
- this._removedUnmappedOrdinalSlotsWithFilters(dataItemIdList.map(function (id) {
- var dataItem = _this2.slotsImpl.getDataItemImpl(id);
- if (dataItem) {
- return {
- columnId: dataItem.getColumnId(),
- aggregationType: dataItem.getAggregation()
- };
- }
- }), subTransaction);
- this.getAPI().removeDataItemsMapping(dataItemIdList, subTransaction);
- // Use the API to trigger the event
- this.slotsImpl.getAPI().deleteDataItems(dataItemIdList, subTransaction);
- this.transaction.endTransaction(subTransaction);
- };
- SlotImpl.prototype._removeSelectionsOnUnusedDataItems = function _removeSelectionsOnUnusedDataItems(dataItemIdList, transactionToken) {
- var _this3 = this;
- var columnIdList = dataItemIdList.map(function (id) {
- return _this3.getDataItemImpl(id).getColumnId();
- });
- this.filterSupport.clearSelectionsByDataItemIds(columnIdList, TransactionUtil.transactionTokenToOptions(transactionToken));
- };
- SlotImpl.prototype._removedUnmappedOrdinalSlotsWithFilters = function _removedUnmappedOrdinalSlotsWithFilters(unusedFilterRef, transactionToken) {
- var localFilters = this.getLocalFilters();
- var filterEntryToRemove = _.find(localFilters.models, function (filterEntry) {
- if (filterEntry.isMissing) {
- return _.findWhere(unusedFilterRef, _.pick(filterEntry, 'columnId'));
- } else if (filterEntry.aggregationType) {
- /* Remove obsolete ordinal filter when there is no match for both column id and aggregation type.
- 1. when the data item is not projected anymore
- - eg. projected data in the slot but no aggregation type matching
- - eg. projected data items with ids 'col1' (sum), 'col1' (count), col2' but the filter was set on 'col1' (avg) */
- return _.findWhere(unusedFilterRef, _.pick(filterEntry, 'columnId', 'aggregationType'));
- } else {
- return _.findWhere(unusedFilterRef, _.pick(filterEntry, 'columnId'));
- }
- });
- if (filterEntryToRemove) {
- localFilters.removeFilterEntry(filterEntryToRemove);
- localFilters.allFilterModificationComplete(TransactionUtil.transactionTokenToOptions(transactionToken));
- }
- };
- SlotImpl.prototype.removeDataItemsMapping = function removeDataItemsMapping(dataItemIds) {
- var _this4 = this;
- var result = [];
- _.each(dataItemIds, function (dataItemId) {
- var dataItem = _this4.getDataItemImpl(dataItemId);
- if (dataItem) {
- _this4.slotMappingModel.unmapDataItemsFromSlots([dataItemId]);
- dataItem.setSlot(null);
- result.push(dataItem);
- } else {
- result.push(null);
- }
- });
- this._processMultiMeasure();
- return result;
- };
- SlotImpl.prototype.addDataItemsMapping = function addDataItemsMapping(dataItemIdList) {
- var _this5 = this;
- var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
- var transactionToken = arguments[2];
- dataItemIdList.forEach(function (id, index) {
- var dataItem = _this5.slotsImpl.getDataItemImpl(id);
- // When dataItem is empty, we remove it from dataItemIdList, here is an example:
- // e.g. we now have this slots mapping
- // Length
- // - measure1
- // - measure2
- // Color
- // - Measures Group(2)
- //
- // now we move measure2 into `Color` and put it before `Measures Group(2)`, `setDataItems()` will be called with a
- // `dataItemIdList` including measure2's dataItemId and a multimeasure dataItemId, inside `setDataItems`, measure2 will be removed from original
- // slot(ie, Length) first, removing it will remove the related multimeasure data item(see _processMultiMeasure), then
- // `addDataItemsMappingthen` is called with the `dataItemIdList`, in this case, `dataItemIdList` contains the id of the deleted
- // multimeasure data item, so getDataItemImpl(id) will return null for the multimeasure data item.
- if (!dataItem) {
- dataItemIdList.splice(index, 1);
- return;
- }
- if (dataItem.getSlot()) {
- throw new Error('Cannot map an already mapped data item, it must to be unmapped first. The dataitem with id "' + id + '" is mapped to slot "' + dataItem.getSlot().getId() + '"');
- }
- });
- var actualPosition = position === -1 ? this.getDataItemList().length : position;
- this.dataModel.moveDataItemsToView(dataItemIdList, this.resolveDataViewId());
- this.slotMappingModel.mapDataItemsToSlot(dataItemIdList, this.getId(), position);
- dataItemIdList.forEach(function (id, index) {
- // If one of the dataitems is a measure series, then mark this slot as the preferred measure series slot.
- if (id.indexOf(SlotAPIHelper.MULTI_MEASURES_SERIES) > -1) {
- var dataset = _this5.getDefinition().getDatasetIdList()[0];
- _this5.slotMappingModel.setMultiMeasureSlotId(dataset, _this5.getId());
- _this5.slotMappingModel.setMultiMeasurePosition(dataset, actualPosition + index);
- }
- _this5.slotsImpl.getDataItemImpl(id).setSlot(_this5.getAPI(), transactionToken);
- });
- this._processMultiMeasure();
- };
- SlotImpl.prototype.getDataItemList = function getDataItemList() {
- var ignoreDefaultDataItemMapping = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- return this._getDataItemListWithOptions(ignoreDefaultDataItemMapping);
- };
- SlotImpl.prototype._getDataItemListWithOptions = function _getDataItemListWithOptions(ignoreDefaultDataItemMapping) {
- var _this6 = this;
- // TODO - livewidget cleanup - cache and free the list for performance
- var idList = this.slotMappingModel.getMappedDataItemIdList(this.getId());
- var list = idList.map(function (id) {
- var dataItem = _this6.slotsImpl.getDataItem(id);
- if (!dataItem) {
- throw new Error('The referenced data item \'' + id + '\' is not found in the widget.');
- }
- return dataItem;
- });
- if (list.length === 0 && !ignoreDefaultDataItemMapping) {
- var defaultFromSlot = this.getDefinition().getDefaultFromSlot();
- if (defaultFromSlot && defaultFromSlot.id) {
- var slot = this.slotsImpl.getSlot(defaultFromSlot.id);
- if (slot) {
- list = slot.getDataItemList();
- }
- }
- }
- return list;
- };
- SlotImpl.prototype.supportsColumns = function supportsColumns(metadataColumnList) {
- return !this.itemsNotSupported(metadataColumnList);
- };
- /**
- * @param metadata either an array of metadatacolumns or a single dataitemapi which both have access to their taxonomy(the class and family of the data column)
- * @returns a boolean whether the slot supports the taxonomy or datatype of the metadata item(s).
- * This method will check to make sure that the columns being dropped into the slots have the correct taxonomy class and family as per these rules:
- * 1) If the slot has no taxonomy defined, then it accepts all data columns
- * 2) If the slot is a lot/long, then it can accept columns that are also lat/long or if they do not have a taxonomy defined, then the slot will also accept numbers
- * 3) If the slot has a taxonomy defined which is not lat/long then it accepts everything except for lat/long columns
- */
- //jshint maxdepth:4
- SlotImpl.prototype.itemsNotSupported = function itemsNotSupported(metadata) {
- var slot = this.getDefinition();
- if (slot.getSubType()) {
- if (_.isArray(metadata)) {
- if (this._itemsNotSupportedFromTree(metadata)) {
- return true;
- }
- } else {
- if (this._itemsNotSupportedFromSlots(metadata)) {
- return true;
- }
- }
- }
- return false;
- };
- SlotImpl.prototype._isLatLong = function _isLatLong() {
- var slot = this.getDefinition();
- return slot.getSubType() === 'latitude' || slot.getSubType() === 'longitude';
- };
- SlotImpl.prototype._itemsNotSupportedFromTree = function _itemsNotSupportedFromTree(metadata) {
- var i;
- for (i = 0; i < metadata.length; i++) {
- var metadataItem = metadata[i];
- if (this._itemsNotSupportedHelper(metadataItem)) {
- return true;
- }
- }
- };
- //this block handles cases where you are swapping slots
- SlotImpl.prototype._itemsNotSupportedFromSlots = function _itemsNotSupportedFromSlots(metadata) {
- if (this._itemsNotSupportedHelper(metadata)) {
- return true;
- }
- };
- SlotImpl.prototype._itemsNotSupportedHelper = function _itemsNotSupportedHelper(metadataItem) {
- var slot = this.getDefinition();
- var taxonomy = metadataItem.getTaxonomyList() ? metadataItem.getTaxonomyList()[0] : null;
- if (this._isLatLong()) {
- if (taxonomy) {
- if (!(taxonomy.getFamily() === 'cLatitude' && slot.getSubType() === 'latitude' || taxonomy.getFamily() === 'cLongitude' && slot.getSubType() === 'longitude')) {
- return true;
- }
- } else if (!this._isSupportedDataType(metadataItem.getDataType())) {
- return true;
- }
- } else {
- if (taxonomy && (taxonomy.getFamily() === 'cLatitude' || taxonomy.getFamily() === 'cLongitude')) {
- return true;
- }
- }
- };
- SlotImpl.prototype._isSupportedDataType = function _isSupportedDataType(datatype) {
- if (this._isLatLong()) {
- return ['integer', 'decimal', 'double', 'float'].indexOf(datatype) > -1;
- }
- return true;
- };
- SlotImpl.prototype.getDefinition = function getDefinition() {
- return this.slotDefinitionAPI;
- };
- SlotImpl.prototype.isStacked = function isStacked() {
- var mappedDataItems = this.slotMappingModel.getMappedDataItemIdList(this.getId());
- return !!(mappedDataItems.length > 1 && this.getDefinition().isStackItems());
- };
- SlotImpl.prototype.hasUnavailableMetadataColumns = function hasUnavailableMetadataColumns() {
- var unavailableColumn = _.find(this.getDataItemList(), function (dataItem) {
- return dataItem.isColumnUnavailable();
- });
- return !!unavailableColumn;
- };
- SlotImpl.prototype._convertTransactionTokenToLegacyOptions = function _convertTransactionTokenToLegacyOptions(transactionToken) {
- var oldOptions = {};
- if (transactionToken) {
- oldOptions.payloadData = {
- transactionToken: transactionToken
- };
- if (transactionToken.transactionId) {
- oldOptions.payloadData.undoRedoTransactionId = transactionToken.transactionId;
- }
- }
- return oldOptions;
- };
- return SlotImpl;
- }(SlotAPISpec);
- return SlotImpl;
- });
- //# sourceMappingURL=Slot.js.map
|