123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- 'use strict';
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: Dashboard
- * (C) Copyright IBM Corp. 2016, 2020
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define(['../../../widgets/livewidget/nls/StringResources', '../../../util/DashboardFormatter', '../../../util/ArrayUtils', './GridEdgeIterator', './Summary', '../../../extensions/client-summaries/content-features/SummaryTypes', '../../../widgets/livewidget/query/QueryResultDataUtils'], function (StringResources, Formatter, ArrayUtils, GridEdgeIterator, Summary, SummaryTypes, QueryResultDataUtils) {
- 'use strict';
- var SUMMARY_ID = StringResources.get('summaryCaption');
- var NOT_AVAILABLE = StringResources.get('value_is_not_available');
- var UNDEFINED = 'undefined';
- var NONE = 'none';
- var OBJECT = 'object';
- var OVERALL = 'overall';
- var getUseValue = function getUseValue(oValue) {
- return oValue && _typeof(oValue.value) !== UNDEFINED ? oValue.value : oValue;
- };
- var getKeys = function getKeys(aData, bData) {
- var aKeys = [];
- if (Array.isArray(aData)) {
- for (var i = 0; i < aData.length; i++) {
- aKeys.push(getUseValue(aData[i]));
- }
- }
- if ((typeof bData === 'undefined' ? 'undefined' : _typeof(bData)) !== UNDEFINED) {
- aKeys.push(getUseValue(bData));
- }
- return aKeys.toString();
- };
- /**
- * !!! PERFORMANCE WARNING !!!
- * This class manipulates potentially very large amounts of data on the client. Any line of code may be
- * executed millions of times to render a single visualization, so should be as optimized as possible.
- */
- var GridDataProcessor = function () {
- function GridDataProcessor(options) {
- var _this = this;
- _classCallCheck(this, GridDataProcessor);
- this._queryResult = options.queryResult;
- this._numberOfColumns = options.numberOfColumns || 0;
- this._lastGroupedColumnIndex = options.lastGroupedColumnIndex || 0;
- this._ungroupedColumnsInfo = [];
- this._rankDataItems = options.rankDataItems || [];
- this._columnSlot = options.columnSlot;
- this._columnDataItems = options.columnDataItems || [];
- this._getRankFormat = options.getRankFormat;
- this._getRealColumnIndex = options.getRealColumnIndex;
- this._valuesMap = {};
- this._exceedsColumnThreshold = options.exceedsColumnThreshold || false;
- this._numberOfAttributeColumns = this._numberOfColumns - (options.factColumnIndices ? options.factColumnIndices.length : 0);
- this._doSummary = options.doSummary;
- this.summaryAPI = options.summaryFeature;
- this.summaryNotSupported = this.summaryAPI && this.summaryAPI.isNotSupported();
- this._onCellDataChange = options.onCellDataChange;
- this._summaryValuePromises = [];
- this._factColumnsMap = {};
- Array.isArray(options.factColumnIndices) && options.factColumnIndices.forEach(function (index) {
- return _this._factColumnsMap[index] = true;
- });
- }
- /**
- * onCellDataChange callback wrapper for formatted values
- * @param {number} row row index
- * @param {number} col column index
- * @param {string} value cell value
- * @param {object} formatSpec format specification for formatting the value
- */
- GridDataProcessor.prototype.onCellDataChange = function onCellDataChange(row, col, value, formatSpec) {
- // CADBLOC-1398: summary value should show N/A when it is not available
- var rawValue = value && value.u ? value.u : value || NOT_AVAILABLE;
- this._onCellDataChange(row, col, Formatter.format(rawValue, formatSpec || null), rawValue);
- };
- GridDataProcessor.prototype._setUngroupedColumnsInfo = function _setUngroupedColumnsInfo() {
- for (var columnIndex = this._lastGroupedColumnIndex; columnIndex < this._numberOfColumns; columnIndex++) {
- var dataItem = this._columnDataItems[columnIndex];
- var isRankDataItem = dataItem.isRank && dataItem.isRank();
- var info = {
- 'dataItemUniqueId': dataItem.getId(),
- 'formatSpec': this._getSlotFormat(columnIndex),
- 'id': dataItem.getId(),
- 'index': columnIndex,
- 'aggregationType': dataItem.getAggregation(),
- 'addSummary': !isRankDataItem && this._columnSlot.getDataItemList()[this._getRealColumnIndex(columnIndex)].getAggregation() !== NONE
- };
- this._ungroupedColumnsInfo.push(info);
- }
- };
- GridDataProcessor.prototype._getSlotFormat = function _getSlotFormat(index) {
- var formatSpec = void 0;
- var dataItemList = this._columnSlot.getDataItemList();
- if (this._rankDataItems.length) {
- if (this._columnDataItems[index].isRank) {
- formatSpec = this._getRankFormat();
- } else {
- formatSpec = dataItemList[index - this._rankDataItems.length].getFormat();
- }
- } else {
- formatSpec = dataItemList[index].getFormat();
- }
- return formatSpec;
- };
- GridDataProcessor.prototype._generateNewDataTableWithOrder = function _generateNewDataTableWithOrder() {
- if (this._doSummary) {
- return this._preProcessedData.length ? this._preProcessedData : this._rawData;
- }
- for (var index = 0; index < this._rawData.length; index++) {
- var queryDataRow = this._rawData[index];
- var matchingIndex = -1;
- for (var i = 0; i < this._preProcessedData.length; i++) {
- var preProcessedDataRow = this._preProcessedData[i];
- if (!preProcessedDataRow) {
- continue;
- }
- if (this._rankDataItems.length > 0) {
- // in this scenario, only comparing edge rank value is sufficient since column index does not change and rank info is unique
- var preProcessedDataRowEdgeValue = preProcessedDataRow[0] && preProcessedDataRow[0].value;
- if (!preProcessedDataRowEdgeValue) {
- continue;
- }
- var queryDataRowEdgetRank = queryDataRow[0].value;
- if (!queryDataRowEdgetRank) {
- continue;
- }
- var preProcessedDataRowEdgeRank = preProcessedDataRowEdgeValue.deco && preProcessedDataRowEdgeValue.deco.rank;
- if (!preProcessedDataRowEdgeRank) {
- continue;
- }
- if (preProcessedDataRowEdgeRank === queryDataRowEdgetRank) {
- matchingIndex = i;
- break;
- }
- } else {
- // in this scenario, we need to compare the dataPoint value
- var preProcessedDataRowValue = preProcessedDataRow.map(function (item) {
- return item.value && _typeof(item.value.value) !== UNDEFINED ? item.value.value : item.value;
- });
- var queryDataRowValue = [];
- for (var j = 0; j < queryDataRow.length; j++) {
- var row = queryDataRow[j];
- if (Array.isArray(row)) {
- for (var k = 0; k < row.length; k++) {
- if (_typeof(row[k].value) !== UNDEFINED) {
- queryDataRowValue.push(row[k].value);
- }
- }
- } else if (_typeof(row.value) !== UNDEFINED) {
- queryDataRowValue.push(row.value);
- }
- }
- if (ArrayUtils.isArrayInArray(queryDataRowValue, preProcessedDataRowValue)) {
- matchingIndex = i;
- break;
- }
- }
- }
- if (matchingIndex !== -1) {
- this._rawData[index] = this._preProcessedData[matchingIndex];
- this._preProcessedData[matchingIndex] = null;
- }
- }
- return this._rawData;
- };
- GridDataProcessor.prototype.getData = function getData() {
- this._rawData = QueryResultDataUtils.getResolvedDataRows(this._queryResult);
- if (this._exceedsColumnThreshold) {
- // if ranking is applied or summary is disabled, we should respect the sort order of the query result
- return Promise.resolve(this._rawData);
- } else {
- // Promise-ifying this as a chain to allow time between the expensive steps for
- // the rest of the UI to react. Long-running
- return Promise.resolve().then(this._setUngroupedColumnsInfo.bind(this)).then(this._generateIntermediateObjects.bind(this)).then(this._generateNewDataTableWithSummaries.bind(this)).then(this._generateNewDataTableWithOrder.bind(this));
- }
- };
- /*
- * Generates grouped columns traversal object and a values map containing summaries.
- */
- GridDataProcessor.prototype._generateIntermediateObjects = function _generateIntermediateObjects() {
- //an intermediate object which the iterator will traverse to get grouped column and summaries info
- //used to generate the keys for indexing into the values map.
- var dataRowCount = this._queryResult.getRowCount();
- var container = {};
- var attributeRowValues = void 0;
- for (var rowIdx = 0; rowIdx < dataRowCount; rowIdx++) {
- attributeRowValues = this._getAttributeValuesInTheRow(rowIdx);
- this._addRowValuesToGroupedItemsContainer(container, attributeRowValues, rowIdx);
- this._generateIntermediateObjectsForUngroupedColumns(attributeRowValues, rowIdx);
- }
- return this._addSortKeysToContainer(container);
- };
- GridDataProcessor.prototype._generateIntermediateObjectsForUngroupedColumns = function _generateIntermediateObjectsForUngroupedColumns(attributeRowValues, rowIdx) {
- var ungroupedColumnInfo = void 0,
- value = void 0,
- rowValue = void 0,
- cellIdx = void 0,
- key = void 0,
- useValue = void 0,
- end = void 0,
- summaryKey = void 0,
- currentSummaryValue = void 0;
- for (var idx = 0, j = this._lastGroupedColumnIndex; j < this._numberOfColumns; j++, idx++) {
- ungroupedColumnInfo = this._ungroupedColumnsInfo[idx];
- value = this._getCellValue(rowIdx, j);
- cellIdx = rowIdx + ':' + j;
- if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) !== UNDEFINED) {
- useValue = getUseValue(value);
- if ((typeof useValue === 'undefined' ? 'undefined' : _typeof(useValue)) !== UNDEFINED && useValue !== null) {
- rowValue = attributeRowValues.concat(ungroupedColumnInfo.dataItemUniqueId);
- key = getKeys(rowValue);
- this._valuesMap[key] = { value: value, cellIdx: cellIdx };
- if (ungroupedColumnInfo.addSummary && ungroupedColumnInfo.aggregationType) {
- var keyUIds = {
- summaryKeys: [],
- oCategoryAndTupleUIds: {},
- isLocalSummary: this._isLocalSummary(ungroupedColumnInfo.aggregationType)
- };
- // groups not including the last attribute and measure
- end = rowValue.length - 2;
- for (; end >= 0; --end) {
- rowValue[end] = SUMMARY_ID;
- summaryKey = getKeys(rowValue);
- keyUIds.summaryKeys.push(summaryKey);
- var categoryAndTupleUId = {
- categoryUIds: [],
- tupleUIds: []
- };
- if (!(keyUIds.isLocalSummary || this.summaryNotSupported || keyUIds.oCategoryAndTupleUIds[summaryKey])) {
- for (var i = 0; i < this._columnDataItems.length; i++) {
- if (_typeof(rowValue[i]) === OBJECT) {
- categoryAndTupleUId.categoryUIds.push(this._columnDataItems[i].getId());
- categoryAndTupleUId.tupleUIds.push(rowValue[i].value);
- }
- }
- }
- keyUIds.oCategoryAndTupleUIds[summaryKey] = categoryAndTupleUId;
- currentSummaryValue = this._valuesMap[summaryKey];
- if (!currentSummaryValue && ungroupedColumnInfo) {
- currentSummaryValue = new Summary(ungroupedColumnInfo, keyUIds.isLocalSummary);
- if (!this.summaryNotSupported && !keyUIds.isLocalSummary) {
- // Add call back context to update values once resolved
- currentSummaryValue.addCallBackContext({
- categoryUIds: keyUIds.oCategoryAndTupleUIds[summaryKey].categoryUIds,
- tupleUIds: keyUIds.oCategoryAndTupleUIds[summaryKey].tupleUIds,
- cbOnCellDataChange: this.onCellDataChange.bind(this),
- cbGetSummary: this.summaryAPI ? this.summaryAPI.getSummary.bind(this.summaryAPI) : undefined,
- cbAddSummaryValuePromise: this.cacheSummaryValuePromise.bind(this)
- });
- }
- }
- if (currentSummaryValue) {
- currentSummaryValue.addValue(useValue);
- }
- this._valuesMap[summaryKey] = currentSummaryValue;
- }
- }
- }
- }
- }
- };
- /**
- * Retrieve a cell value for grid
- *
- * @param {number} rowIdx - the row index value
- * @param {number} columnIdx - the column index value
- *
- * @return {object} the cell value object
- */
- GridDataProcessor.prototype._getCellValue = function _getCellValue(rowIdx, columnIdx) {
- var value = this._queryResult.getValue(rowIdx, columnIdx);
- return value instanceof Array && !!value.length ? value[0] : value;
- };
- GridDataProcessor.prototype._getAttributeValuesInTheRow = function _getAttributeValuesInTheRow(rowIdx) {
- var attributeRowValues = [];
- for (var colIdx = 0; colIdx < this._numberOfColumns; colIdx++) {
- if (!this._factColumnsMap[colIdx]) {
- attributeRowValues.push(this._getCellValue(rowIdx, colIdx));
- }
- }
- return attributeRowValues;
- };
- /**
- * Returns a new object with Summary as the last item to be used for iterating
- */
- GridDataProcessor.prototype._addSortKeysToContainer = function _addSortKeysToContainer(edge) {
- var hasSummary = false;
- var newEdgeObject = {
- edge: edge,
- sortedKeys: []
- };
- for (var key in edge) {
- if (edge.hasOwnProperty(key)) {
- if (key === SUMMARY_ID) {
- hasSummary = true;
- } else {
- newEdgeObject.sortedKeys.push(key);
- var nestedEdges = edge[key].nestedEdges;
- if (nestedEdges) {
- edge[key].nestedEdges = this._addSortKeysToContainer(nestedEdges);
- }
- }
- }
- }
- if (hasSummary) {
- newEdgeObject.sortedKeys.push(SUMMARY_ID);
- var _nestedEdges = edge[SUMMARY_ID].nestedEdges;
- if (_nestedEdges) {
- edge[SUMMARY_ID].nestedEdges = this._addSortKeysToContainer(_nestedEdges);
- }
- }
- return newEdgeObject;
- };
- GridDataProcessor.prototype._addRowValuesToGroupedItemsContainer = function _addRowValuesToGroupedItemsContainer(container, attributeRowValues, rowIndex, columnIndex, ancestor) {
- var attributeRowValueIndex = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
- columnIndex = columnIndex || 0;
- if (attributeRowValues && attributeRowValues.length > 0) {
- var rowValue = attributeRowValues[attributeRowValueIndex].value;
- if (!container[rowValue]) {
- container[rowValue] = {
- value: attributeRowValues[attributeRowValueIndex],
- level: columnIndex,
- cellIdx: rowIndex + ':' + columnIndex
- };
- if (this._doSummary) {
- this._addSummaryToGroupedItemsContainer(container, columnIndex, ancestor);
- }
- }
- var nextAttributeRowValueIndex = attributeRowValueIndex + 1;
- if (nextAttributeRowValueIndex < attributeRowValues.length) {
- if (!container[rowValue].nestedEdges) {
- container[rowValue].nestedEdges = {};
- }
- this._addRowValuesToGroupedItemsContainer(container[rowValue].nestedEdges, attributeRowValues, rowIndex, columnIndex + 1, rowValue, nextAttributeRowValueIndex);
- }
- }
- };
- GridDataProcessor.prototype._addSummaryToGroupedItemsContainer = function _addSummaryToGroupedItemsContainer(container, columnIndex, ancestor, bIsOverallSummary) {
- var isOverallSummary = bIsOverallSummary || columnIndex === 0;
- if (columnIndex < this._numberOfAttributeColumns) {
- var summaryNode = {
- isSummary: true,
- level: columnIndex,
- isOverallSummary: isOverallSummary,
- summaryOf: isOverallSummary ? OVERALL : ancestor
- };
- container[SUMMARY_ID] = summaryNode;
- if (columnIndex < this._numberOfAttributeColumns - 1) {
- //special handling for overall summary in order for the crosstab to render the summary column correctly
- //need to add as many summary as nested levels
- summaryNode.nestedEdges = {};
- this._addSummaryToGroupedItemsContainer(summaryNode.nestedEdges, columnIndex + 1, ancestor, isOverallSummary);
- }
- }
- };
- /**
- * caching the summary value promise
- *
- * @param {object} summary value promise; when resolved the summary value is available
- */
- GridDataProcessor.prototype.cacheSummaryValuePromise = function cacheSummaryValuePromise(promise) {
- this._summaryValuePromises.push(promise);
- };
- /**
- * Returns a promise indicating whether all summaries get in the grid
- */
- GridDataProcessor.prototype.whenAllSummaryValuesAreReady = function whenAllSummaryValuesAreReady() {
- return Promise.all(this._summaryValuePromises);
- };
- GridDataProcessor.prototype._getSummaryKeys = function _getSummaryKeys(attributeRowValues) {
- var summaryKeys = {};
- //rowStart/rowEnd indicates starting/ending position in the originalDimension array that contains row info
- var rowEnd = this._numberOfAttributeColumns - 1;
- for (var rowStart = 0; rowEnd >= rowStart; --rowEnd) {
- attributeRowValues[rowEnd] = SUMMARY_ID;
- summaryKeys[getKeys(attributeRowValues)] = true;
- }
- return Object.keys(summaryKeys);
- };
- GridDataProcessor.prototype._generateNewDataTableWithSummaries = function _generateNewDataTableWithSummaries(groupedColumnsTraversalObject) {
- var dataWithSummary = [];
- var nextGroupedItem = void 0;
- var dataTableRow = void 0;
- var rowIndex = 0;
- var groupedColumnsRowIterator = new GridEdgeIterator(groupedColumnsTraversalObject, undefined);
- while (nextGroupedItem = groupedColumnsRowIterator.next()) {
- dataTableRow = [];
- this._addGroupedItemsToRow(dataTableRow, nextGroupedItem);
- this._addValuesToRow(dataTableRow, nextGroupedItem, ++rowIndex);
- dataWithSummary.push(dataTableRow);
- }
- this._preProcessedData = dataWithSummary;
- };
- GridDataProcessor.prototype._addGroupedItemsToRow = function _addGroupedItemsToRow(dataTableRow, firstGroupedItem) {
- var nextColumn = firstGroupedItem;
- var columnIndex = 0;
- while (nextColumn && columnIndex < this._lastGroupedColumnIndex) {
- dataTableRow.push(nextColumn);
- nextColumn = nextColumn.subCategory;
- columnIndex++;
- }
- };
- /*
- * This function adds fact value or attribute value which is not grouped.
- */
- GridDataProcessor.prototype._addValuesToRow = function _addValuesToRow(dataTableRow, firstGroupedItem, rowIndex) {
- for (var columnIndex = 0; columnIndex < this._ungroupedColumnsInfo.length; columnIndex++) {
- var nextColumn = this._ungroupedColumnsInfo[columnIndex];
- var key = getKeys(firstGroupedItem.descendant_or_self, nextColumn.dataItemUniqueId);
- var valueObj = this._valuesMap[key] || null;
- var data = null;
- var rawValue = null;
- if (valueObj) {
- if (valueObj.getSummarizedValue) {
- if (!valueObj._isLocalSummary) {
- data = valueObj.getSummarizedValue(rowIndex, nextColumn.index);
- } else if (valueObj.getValue() !== null) {
- rawValue = valueObj.getValue();
- data = Formatter.formatNull(rawValue, valueObj._formatSpec || null);
- } else {
- data = valueObj.value;
- }
- } else {
- data = valueObj.value;
- }
- }
- var result = data;
- if (!result) {
- //for summary of attribute column which is ungrouped
- if (firstGroupedItem.isSummary && !nextColumn.aggregationType) {
- result = ' ';
- }
- }
- dataTableRow.push({
- isSummary: firstGroupedItem.isSummary,
- value: result,
- rawValue: rawValue,
- key: key,
- cellIdx: valueObj ? valueObj.cellIdx : null,
- isOverallSummary: firstGroupedItem.isOverallSummary
- });
- }
- };
- GridDataProcessor.prototype._isLocalSummary = function _isLocalSummary(aggregationType) {
- return SummaryTypes.indexOf(aggregationType) === -1;
- };
- return GridDataProcessor;
- }();
- return GridDataProcessor;
- });
- //# sourceMappingURL=GridDataProcessor.js.map
|