123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- 'use strict';
- var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
- 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, 2020
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define(['./DataItem', '../../api/DataItemAPI', '../../visualizations/interactions/BinningActionsUtils', '../../util/TransactionUtil', '../../apiHelpers/SlotAPIHelper'], function (DataItem, DataItemAPI, BinningActionsUtils, TransactionUtil, SlotAPIHelper) {
- var MappedDataItem = function (_DataItem) {
- _inherits(MappedDataItem, _DataItem);
- function MappedDataItem(filterSupport, dataItemModel, slot, dataSource, transaction, locale, visualizationImpl, slotsImpl) {
- _classCallCheck(this, MappedDataItem);
- var _this = _possibleConstructorReturn(this, _DataItem.call(this, dataItemModel, dataSource, transaction, locale));
- _this.visualizationImpl = visualizationImpl;
- _this.slotsImpl = slotsImpl;
- _this.localFilters = filterSupport.getLocalFilters();
- _this.filterSupport = filterSupport;
- _this.slot = slot;
- /*
- The originalCustomGroupItemId (ie group sourceColumn) is required for driling so it needs to be persisted for module load consumption
- Since the public DataItem API no longer supports this method, we set it for now via the oldDataItemAPI
- TODO: ReEnvision custom groups architecture so this interim solution is no longer necessary.
- TODO: persist the original columnIds as part of the data source spec instead. This does not belong in the dataitem.
- TODO: AVOID calling getFeature('DataSources.moser')
- */
- var shaping = _this.visualizationImpl.dashboardAPI.getFeature('DataSources.moser');
- if (shaping && shaping.isConsumerGroupColumn) {
- var sourceId = _this.dataSourceAPI.getId();
- var columnId = _this.getColumnId();
- if (shaping.isConsumerGroupColumn(sourceId, columnId)) {
- var customGroup = shaping.getCustomGroupData(sourceId, columnId);
- if (customGroup && customGroup.basedOnMoserObjectId) {
- _this.dataItemModel.originalCustomGroupItemId = customGroup.basedOnMoserObjectId;
- }
- }
- }
- return _this;
- }
- MappedDataItem.prototype.getSlot = function getSlot() {
- return this.slot;
- };
- MappedDataItem.prototype.destroy = function destroy() {
- _DataItem.prototype.destroy.call(this);
- this.visualizationImpl = null;
- this.slotsImpl = null;
- this.localFilters = null;
- this.filterSupport = null;
- };
- MappedDataItem.prototype.setSlot = function setSlot(slot, transactionToken) {
- this.slot = slot;
- if (slot && this.getBinning()) {
- var canApplyBinning = this.visualizationImpl.getDefinition().getProperty('canApplyBinning');
- if (!canApplyBinning || !SlotAPIHelper.doesDataItemSupportBinning(slot, this.getAPI())) {
- this.getAPI().setBinning(null, transactionToken);
- }
- }
- };
- MappedDataItem.prototype.getType = function getType() {
- var slotType = void 0;
- if (this.slot) {
- var def = this.slot.getDefinition();
- if (def.getSubType() === 'latitude' || def.getSubType() === 'longitude') {
- slotType = 'category';
- } else if (def.getType() === 'any') {
- if (SlotAPIHelper.isMultiMeasuresSeriesSlot(this.slot)) {
- slotType = 'category';
- } else if (this.getBinning()) {
- slotType = 'category';
- } else {
- var metadata = this.getMetadataColumn();
- if (metadata && metadata.getType() === 'attribute') {
- if (this.getAggregation() === DataItemAPI.AGGREGATION_TYPE.none) {
- slotType = 'category';
- } else {
- slotType = 'ordinal';
- }
- } else if (metadata && metadata.getType() === 'fact') {
- /**
- * - If one of the items in an 'any' slot is a measure, and we have more than one items,
- * then simply consider slot type to be category.
- * This prevents issues described in defect #255087
- */
- if (this.slot.getDataItemList().length > 1 && !this.slot.getDefinition().getProperty('repeats')) {
- slotType = 'category';
- } else {
- slotType = 'ordinal';
- }
- }
- }
- }
- if (!slotType) {
- slotType = def.getType();
- }
- }
- return slotType && (slotType === 'ordinal' ? 'fact' : 'attribute');
- };
- MappedDataItem.prototype.setAggregation = function setAggregation(aggregationType, transactionToken) {
- if (!this.slot) {
- _DataItem.prototype.setAggregation.call(this, aggregationType, transactionToken);
- } else {
- var subTransaction = this.transaction.startTransaction(transactionToken);
- if (this.getType() === 'fact') {
- var currentAggregationType = this.getAggregation();
- var localFilters = this.localFilters;
- var rangeFilterOnOldAggregationType = localFilters.getFilterEntry(localFilters.getOrdinalFilterKey(this.getColumnId(), currentAggregationType));
- if (rangeFilterOnOldAggregationType) {
- var itemContext = {
- uniqueId: this.getId(),
- itemId: this.getColumnId(),
- itemName: this.getLabel(),
- dataType: this.getDataType(),
- sourceId: this.visualizationImpl.getDataSource().getId(),
- aggregationType: currentAggregationType
- };
- this.visualizationImpl.getLocalFilters().removeFilter(itemContext, subTransaction);
- }
- }
- _DataItem.prototype.setAggregation.call(this, aggregationType, subTransaction);
- this.transaction.endTransaction(subTransaction);
- }
- };
- MappedDataItem.prototype.getAggregation = function getAggregation() {
- if (!this.slot) {
- return _DataItem.prototype.getAggregation.call(this);
- }
- var mdColumn = this.getMetadataColumn();
- if (!mdColumn) {
- return null;
- }
- var type = this.dataItemModel.aggregate;
- if (!type) {
- // TODO -- livewidget_cleanup --- apply this old code in here (used to be in visDataSlotsManager)
- // Basically if the category is in both measure and category slot, set the default aggregation to Count.. instead of
- var mappedSlots = this.slotsImpl.getMappedSlotList();
- // Check to see if we have the same column in both the aggregations and dimensions, if so, default to aggType of 'count'
- if (this.slot.getDefinition().getType() === 'ordinal' && this.getMetadataColumn().getType() === 'attribute') {
- var itemId = this.getColumnId();
- for (var i = 0; i < mappedSlots.length; i++) {
- var slotAPI = mappedSlots[i];
- var slotDef = slotAPI.getDefinition();
- if (slotDef.getType() === 'category' || slotDef.getType() === 'any') {
- var dataItemAPIs = slotAPI.getDataItemList();
- for (var j = 0; j < dataItemAPIs.length; j++) {
- if (dataItemAPIs[j].getColumnId() === itemId) {
- type = 'count';
- break;
- }
- }
- }
- // Stop once aggType is set.
- if (type) {
- break;
- }
- }
- }
- if (!type) {
- var _mdColumn = this.getMetadataColumn();
- type = _mdColumn ? _mdColumn.getDefaultAggregation() : null;
- }
- }
- var def = this.slot.getDefinition();
- if (def.getType() === 'any') {
- if (_DataItem.prototype.getType.call(this) === 'attribute') {
- if (!_DataItem.prototype.hasDefaultAggregation.call(this)) {
- return type;
- } else {
- type = DataItemAPI.AGGREGATION_TYPE.none;
- }
- }
- // fact assigned to a category slot should not aggregate
- } else if (def.getType() === 'category') {
- type = DataItemAPI.AGGREGATION_TYPE.none;
- // when an attribute is used in an ordinal slot, aggregation none doesn't make sense...consider it a count
- } else if (def.getType() === 'ordinal' && _DataItem.prototype.getType.call(this) === 'attribute' && type === DataItemAPI.AGGREGATION_TYPE.none) {
- var defaultAggrType = _DataItem.prototype.getMetadataColumn.call(this).getDefaultAggregation();
- type = defaultAggrType === DataItemAPI.AGGREGATION_TYPE.none ? DataItemAPI.AGGREGATION_TYPE.countDistinct : defaultAggrType;
- }
- return type;
- };
- /**
- * @function MappedDataItem#getFormat
- * @description Retrieve the format for the mapped data item.
- * @return {Object} An object containing format related properties.
- */
- MappedDataItem.prototype.getFormat = function getFormat() {
- if (!this.slot) {
- return _DataItem.prototype.getFormat.call(this);
- }
- var widgetModel = this.visualizationImpl.widgetModel;
- // this comes from an upgraded dashboard where we want to change the KPI format. see SummaryKPIUpgrade.js
- var useSlotDefinitionFormat = widgetModel.enableSlotDefinitionFormat === false ? false : true;
- var slotDefinitionFormat = this._getDefinitionFormat();
- var format = _DataItem.prototype.getFormat.call(this);
- if (useSlotDefinitionFormat && !format) {
- format = slotDefinitionFormat;
- }
- if (!format && (this.getMetadataColumn().getType() !== 'attribute' || _DataItem.prototype.isDateOrTimeType.call(this))) {
- // Default format
- format = {
- 'selectedFormat': 'none', // This property does not appear to be used anymore, it may be replaced with dateStyle
- 'maximumFractionDigits': 2,
- 'formatLength': 'short' // This property is only applicable for dates
- };
- if (_DataItem.prototype.isDateOrTimeType.call(this)) {
- format.type = this.getMetadataColumn().getDataType();
- }
- }
- // resolve the proper format when have an invalid format
- var metadataColumn = this.getMetadataColumn();
- if (format && metadataColumn) {
- var dataType = metadataColumn.getDataType();
- var isDateOrTimeType = dataType === 'date' || dataType === 'datetime' || dataType === 'time' || dataType === 'year' ? true : false;
- if (isDateOrTimeType) {
- isDateOrTimeType = this.getType() !== 'ordinal';
- }
- var formatType = format && format.type;
- var invalidDateFormatting = isDateOrTimeType && metadataColumn.getType() !== 'attribute' && ['date', 'time', 'datetime'].indexOf(formatType) === -1;
- var invalidBinningFormatting = this.getBinning() && (formatType === 'currency' || formatType === 'percent');
- if (invalidDateFormatting || invalidBinningFormatting || !isDateOrTimeType && ['date', 'time', 'datetime'].indexOf(formatType) > -1) {
- format = {
- 'selectedFormat': 'none',
- 'maximumFractionDigits': 2,
- 'formatLength': 'short',
- 'locale': this.locale
- };
- if (invalidDateFormatting || invalidBinningFormatting) {
- format.type = metadataColumn.getDataType();
- }
- }
- }
- // Overwrite the format type to be number if the dataItem is fact and doesn't already have a number format spec set
- if (this.getType() === 'fact') {
- if (_DataItem.prototype.isDateOrTimeType.call(this) && format && format.type !== 'number') {
- // Default format
- return {
- 'selectedFormat': 'none',
- 'maximumFractionDigits': 2,
- 'formatLength': 'short',
- 'type': 'number',
- 'locale': this.locale
- };
- } else if (!format && (_DataItem.prototype.getAggregation.call(this) === 'count' || _DataItem.prototype.getAggregation.call(this) === 'countdistinct')) {
- //If the item is assigned to an ordinal slot and it has aggregation type count or countdistinct and no format specified,
- //return a default (1 decimal number)
- //this should be changed back to 0 when implementation of VIDA story for using tickInterval is finished. See story 228160
- return {
- 'selectedFormat': 'none',
- 'maximumFractionDigits': 1,
- 'formatLength': 'short',
- 'type': 'number',
- 'locale': this.locale
- };
- }
- }
- // TODO -- livewidget_cleanup - we should not add .selectedFormat to set the ui to auto. We should simply call the hasDefaultFormat() API
- // ensure use auto if using default format
- if (format && _DataItem.prototype.hasDefaultFormat.call(this)) {
- format.selectedFormat = 'none';
- }
- if (format && !format.locale) {
- format.locale = this.locale;
- }
- return format;
- };
- MappedDataItem.prototype._getDefinitionFormat = function _getDefinitionFormat() {
- var definitionFormat = null;
- var format = this.slot.getDefinition().getFormat();
- if (format) {
- definitionFormat = Object.assign({ locale: this.locale }, format);
- }
- return definitionFormat;
- };
- /**
- * Updates the priority field on any sort entries on all slots, such that they enforce priority order as implied by the slot definition order.
- * This is done before a new sort is added, and the events are silent, as the sort addition will send a non-silent event to trigger render.
- * @param {string} slotId - the id of the slot having sort added
- * @param {string} dataItemId - the id of the data item having sort added
- * @param {number} explicitPriority (optional) - the priority explicitly given to the data item.
- * If omitted, the priority will be assigned automatically based on the existing data item sorts
- * @param {object} options
- */
- MappedDataItem.prototype._setSortPriorities = function _setSortPriorities(slotId, dataItemId, explicitPriority) {
- var _this2 = this;
- var isExplicitPriority = typeof explicitPriority !== 'undefined' && explicitPriority !== null;
- var priority = 0,
- newPriority = void 0;
- var mappedSlotList = this.slotsImpl.getMappedSlotList();
- mappedSlotList.forEach(function (slot) {
- var currentSlotId = slot.getId();
- var dataItemList = slot.getDataItemList();
- dataItemList.forEach(function (dataItem) {
- if (slotId === currentSlotId && dataItem.getId() === dataItemId) {
- //This is the item which will have its sort set - record the priority it's at
- newPriority = isExplicitPriority ? explicitPriority : priority++;
- } else if (dataItem.getSort()) {
- //Existing item - adjust its priority
- var shift = isExplicitPriority && priority >= explicitPriority;
- if (!dataItem.hasDefaultSort()) {
- var sort = dataItem.getSort();
- sort.priority = shift ? ++priority : priority++;
- _this2.slotsImpl.getDataItemImpl(dataItem.getId())._setSortWithoutAdjustingPriority(sort);
- }
- }
- });
- });
- return newPriority;
- };
- MappedDataItem.prototype._setSortWithoutAdjustingPriority = function _setSortWithoutAdjustingPriority(params, transactionToken) {
- return _DataItem.prototype.setSort.call(this, params, transactionToken);
- };
- MappedDataItem.prototype.setSort = function setSort(params, transactionToken) {
- var sortSpec = params ? JSON.parse(JSON.stringify(params)) : {};
- if (!this.slot) {
- return _DataItem.prototype.setSort.call(this, sortSpec, transactionToken);
- }
- if (sortSpec) {
- // TODO - make the the setSortPriorities is abble to reset to previous prioroties if the sortSpec is not defined (i.e. clearing the sort)
- //Adjust priority setting on existing sorts prior to setting actual sort
- sortSpec.priority = this._setSortPriorities(this.slot.getId(), this.getId(), sortSpec.priority);
- }
- return _DataItem.prototype.setSort.call(this, sortSpec, transactionToken);
- };
- MappedDataItem.prototype.hasModelSort = function hasModelSort() {
- return !!this._getDefaultSort();
- };
- MappedDataItem.prototype._getDefaultSort = function _getDefaultSort() {
- var _this3 = this;
- var mdColumn = this.getMetadataColumn();
- var sortType = mdColumn ? mdColumn.getDefaultSortType() : null;
- if (sortType) {
- // model sort found.
- // Calculate sort priority for model sort.
- var dataItemSortPriority = 0;
- var modelSortItemIdx = 0;
- var modelSortItemFound = false;
- this.slotsImpl.getDataItemImplList().forEach(function (dataItem) {
- var sortObj = dataItem._getUserSort();
- if (sortObj) {
- // User defined sort is set/saved with dataitems with highest priority.
- // Priorty numbers are in ascending order with 0 been the highest priority.
- // Find the lowest priority for user defined sort.
- if (dataItemSortPriority < sortObj.priority) {
- dataItemSortPriority = sortObj.priority;
- }
- } else if (!modelSortItemFound) {
- // Find the index of the model sort data item over all dataitems with model sort but without user defned sort.
- var currentItemId = dataItem.getColumnId();
- var currentItemMdColumn = dataItem.getMetadataColumn();
- var modelSortType = currentItemMdColumn ? currentItemMdColumn.getDefaultSortType() : null;
- if (modelSortType) {
- modelSortItemIdx++;
- modelSortItemFound = currentItemId === _this3.getColumnId();
- }
- }
- });
- return {
- type: sortType,
- by: 'caption',
- // The current model sort priority should be the highest user defined sort priorty number plus
- // the index of the model sort data item over all dataitems with model sort but without user defned sort.
- priority: dataItemSortPriority + modelSortItemIdx
- };
- }
- return null;
- };
- MappedDataItem.prototype.getSort = function getSort() {
- if (!this.slot) {
- return _DataItem.prototype.getSort.call(this);
- }
- var dataItemSort = _DataItem.prototype.getSort.call(this);
- if (!dataItemSort) {
- dataItemSort = this._getDefaultSort();
- }
- if (!dataItemSort || !dataItemSort.type) {
- var metadataColumn = this.getMetadataColumn();
- var defaultSort = metadataColumn && !metadataColumn.isOlapColumn() && !metadataColumn.isNamedSet() && this.slot.getDefinition().getSort();
- if (defaultSort) {
- dataItemSort = dataItemSort && dataItemSort.custom ? _extends({}, dataItemSort, { type: defaultSort }) : { type: defaultSort };
- }
- }
- if (dataItemSort && dataItemSort.rankSort) {
- delete dataItemSort.rankSort;
- }
- return dataItemSort;
- };
- //Crurrently AutobinDialog listens on BA-UI-TOOLKIT NumberInput's onChange event
- //However, there are cases that it is not the change of the number input's value that
- //caused the onChange event but just a blur or focus on number input
- //Currently onChange event that executs auto bin action, therefore, to avoid unecssary
- //auto bin action, we compare the incoming state's value with the dataitem's existing
- //binning state, we only execute auto bin action for new values
- MappedDataItem.prototype._isSameNumberOfBins = function _isSameNumberOfBins(binningSpec) {
- if (!binningSpec) {
- return false;
- }
- var binningInfo = this.getBinning();
- if (!binningInfo) {
- return false;
- }
- if (binningInfo.bins !== binningSpec.bins) {
- return false;
- }
- return true;
- };
- MappedDataItem.prototype.setBinning = function setBinning(binningSpec, transactionToken) {
- if (!this.slot) {
- _DataItem.prototype.setBinning.call(this, binningSpec, transactionToken);
- } else if (!this._isSameNumberOfBins(binningSpec)) {
- var options = TransactionUtil.transactionTokenToOptions(transactionToken);
- this.filterSupport.clearSelectionsByDataItemIds([this.getColumnId()]);
- BinningActionsUtils.removeCompoundFilters(this.slot, this.localFilters, options);
- var binningFilters = BinningActionsUtils.getBinningFilters(this.localFilters, this);
- if (binningFilters) {
- BinningActionsUtils.removeLocalBinnedFilterEntries(this.localFilters, binningFilters, options);
- }
- _DataItem.prototype.setBinning.call(this, binningSpec, transactionToken);
- }
- };
- MappedDataItem.prototype.setFormat = function setFormat(spec, transactionToken) {
- var formatSpec = JSON.parse(JSON.stringify(spec));
- if (!this.slot) {
- return _DataItem.prototype.setFormat.call(this, formatSpec, transactionToken);
- }
- var binningFilters = void 0;
- var options = TransactionUtil.transactionTokenToOptions(transactionToken);
- if (_DataItem.prototype.getBinning.call(this)) {
- //for any changes in binning we need clear all selection filters, it will not be part of undo/redo
- this.filterSupport.clearSelectionsByDataItemIds([_DataItem.prototype.getColumnId.call(this)]);
- BinningActionsUtils.removeCompoundFilters(this.slot, this.localFilters, options);
- binningFilters = formatSpec ? BinningActionsUtils.getBinningFilterForFormatedItem(formatSpec, this.localFilters, this) : null;
- }
- var clientSideDataFormatting = binningFilters ? false : true;
- if (binningFilters) {
- BinningActionsUtils.removeLocalBinnedFilterEntries(this.localFilters, binningFilters, options);
- }
- if (clientSideDataFormatting) {
- //Only re-send the query if needed since formatting is done on the client side so set dataIfQueryChanged to true.
- //Reasons why binned has to be formatted on the server side due to how the values are returned. Examples of binned values returned from DSS:
- //'less than 202.309000, '202.309000 to < 404.608000', '404.608000 to < 606.907000'
- //So the client side cannot format such values
- if (!options.payloadData) {
- options.payloadData = {};
- }
- options.payloadData.dataIfQueryChanged = true;
- }
- // TODO livewidget_cleanup --- should be passing a transction token and not options !!
- _DataItem.prototype.setFormat.call(this, formatSpec, options);
- };
- return MappedDataItem;
- }(DataItem);
- return MappedDataItem;
- });
- //# sourceMappingURL=MappedDataItem.js.map
|