devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
540 lines (511 loc) • 21.9 kB
JavaScript
/**
* DevExtreme (ui/pivot_grid/remote_store.js)
* Version: 20.1.7
* Build date: Tue Aug 25 2020
*
* Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
;
var _type = require("../../core/utils/type");
var _class = require("../../core/class");
var _class2 = _interopRequireDefault(_class);
var _extend = require("../../core/utils/extend");
var _iterator = require("../../core/utils/iterator");
var _data_source = require("../../data/data_source/data_source");
var _deferred = require("../../core/utils/deferred");
var _uiPivot_grid = require("./ui.pivot_grid.utils");
var _date_serialization = require("../../core/utils/date_serialization");
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
"default": obj
}
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread()
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) {
return
}
if ("string" === typeof o) {
return _arrayLikeToArray(o, minLen)
}
var n = Object.prototype.toString.call(o).slice(8, -1);
if ("Object" === n && o.constructor) {
n = o.constructor.name
}
if ("Map" === n || "Set" === n) {
return Array.from(o)
}
if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) {
return _arrayLikeToArray(o, minLen)
}
}
function _iterableToArray(iter) {
if ("undefined" !== typeof Symbol && Symbol.iterator in Object(iter)) {
return Array.from(iter)
}
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) {
return _arrayLikeToArray(arr)
}
}
function _arrayLikeToArray(arr, len) {
if (null == len || len > arr.length) {
len = arr.length
}
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i]
}
return arr2
}
function createGroupingOptions(dimensionOptions, useSortOrder) {
var groupingOptions = [];
(0, _iterator.each)(dimensionOptions, function(index, dimensionOption) {
groupingOptions.push({
selector: dimensionOption.dataField,
groupInterval: dimensionOption.groupInterval,
desc: useSortOrder && "desc" === dimensionOption.sortOrder,
isExpanded: index < dimensionOptions.length - 1
})
});
return groupingOptions
}
function getFieldFilterSelector(field) {
var selector = field.dataField;
var groupInterval = field.groupInterval;
if ("date" === field.dataType && "string" === typeof groupInterval) {
if ("quarter" === groupInterval.toLowerCase()) {
groupInterval = "Month"
}
selector = selector + "." + (0, _uiPivot_grid.capitalizeFirstLetter)(groupInterval)
}
return selector
}
function getIntervalFilterExpression(selector, numericInterval, numericValue, isExcludedFilterType) {
var startFilterValue = [selector, isExcludedFilterType ? "<" : ">=", numericValue];
var endFilterValue = [selector, isExcludedFilterType ? ">=" : "<", numericValue + numericInterval];
return [startFilterValue, isExcludedFilterType ? "or" : "and", endFilterValue]
}
function getFilterExpressionForFilterValue(field, filterValue) {
var selector = getFieldFilterSelector(field);
var isExcludedFilterType = "exclude" === field.filterType;
var expression = [selector, isExcludedFilterType ? "<>" : "=", filterValue];
if ((0, _type.isDefined)(field.groupInterval)) {
if ("string" === typeof field.groupInterval && "quarter" === field.groupInterval.toLowerCase()) {
expression = getIntervalFilterExpression(selector, 3, 3 * (filterValue - 1) + 1, isExcludedFilterType)
} else {
if ("number" === typeof field.groupInterval && "date" !== field.dataType) {
expression = getIntervalFilterExpression(selector, field.groupInterval, filterValue, isExcludedFilterType)
}
}
}
return expression
}
function createFieldFilterExpressions(field, operation) {
var fieldFilterExpressions = [];
if (field.searchValue) {
return [field.dataField, "contains", field.searchValue]
}
if ("exclude" === field.filterType) {
operation = operation || "and"
} else {
operation = operation || "or"
}(0, _iterator.each)(field.filterValues, function(index, filterValue) {
var currentExpression = [];
if (Array.isArray(filterValue)) {
var parseLevelsRecursive = field.levels && field.levels.length;
if (parseLevelsRecursive) {
currentExpression = createFieldFilterExpressions({
filterValues: filterValue,
filterType: field.filterType,
levels: field.levels
}, "and")
}
} else {
var currentField = field.levels ? field.levels[index] : field;
currentExpression = getFilterExpressionForFilterValue(currentField, filterValue)
}
if (!currentExpression.length) {
return
}
if (fieldFilterExpressions.length) {
fieldFilterExpressions.push(operation)
}
fieldFilterExpressions.push(currentExpression)
});
return fieldFilterExpressions
}
function createFilterExpressions(fields) {
var filterExpressions = [];
(0, _iterator.each)(fields, function(_, field) {
var fieldExpressions = createFieldFilterExpressions(field);
if (!fieldExpressions.length) {
return []
}
if (filterExpressions.length) {
filterExpressions.push("and")
}
filterExpressions.push(fieldExpressions)
});
if (1 === filterExpressions.length) {
filterExpressions = filterExpressions[0]
}
return filterExpressions
}
function mergeFilters(filter1, filter2) {
var mergedFilter;
var notEmpty = function(filter) {
return filter && filter.length
};
if (notEmpty(filter1) && notEmpty(filter2)) {
mergedFilter = [filter1, "and", filter2]
} else {
mergedFilter = notEmpty(filter1) ? filter1 : filter2
}
return mergedFilter
}
function createLoadOptions(options, externalFilterExpr, hasRows) {
var filterExpressions = createFilterExpressions(options.filters);
var groupingOptions = createGroupingOptions(options.rows, options.rowTake).concat(createGroupingOptions(options.columns, options.columnTake));
var loadOptions = {
groupSummary: [],
totalSummary: [],
group: groupingOptions.length ? groupingOptions : void 0,
take: groupingOptions.length ? void 0 : 1
};
if (options.rows.length && options.rowTake) {
loadOptions.skip = options.rowSkip;
loadOptions.take = options.rowTake;
loadOptions.requireGroupCount = true
} else {
if (options.columns.length && options.columnTake && !hasRows) {
loadOptions.skip = options.columnSkip;
loadOptions.take = options.columnTake;
loadOptions.requireGroupCount = true
}
}
if (externalFilterExpr) {
filterExpressions = mergeFilters(filterExpressions, externalFilterExpr)
}
if (filterExpressions.length) {
loadOptions.filter = filterExpressions
}(0, _iterator.each)(options.values, function(_, value) {
var summaryOption = {
selector: value.dataField,
summaryType: value.summaryType || "count"
};
loadOptions.groupSummary.push(summaryOption);
options.includeTotalSummary && loadOptions.totalSummary.push(summaryOption)
});
return loadOptions
}
function forEachGroup(data, callback, level) {
data = data || [];
level = level || 0;
for (var i = 0; i < data.length; i++) {
var group = data[i];
callback(group, level);
if (group && group.items && group.items.length) {
forEachGroup(group.items, callback, level + 1)
}
}
}
function setValue(valuesArray, value, rowIndex, columnIndex, dataIndex) {
valuesArray[rowIndex] = valuesArray[rowIndex] || [];
valuesArray[rowIndex][columnIndex] = valuesArray[rowIndex][columnIndex] || [];
if (!(0, _type.isDefined)(valuesArray[rowIndex][columnIndex][dataIndex])) {
valuesArray[rowIndex][columnIndex][dataIndex] = value
}
}
function parseValue(value, field) {
if (field && "number" === field.dataType && (0, _type.isString)(value)) {
return Number(value)
}
if (field && "date" === field.dataType && !field.groupInterval && !(value instanceof Date)) {
return (0, _date_serialization.deserializeDate)(value)
}
return value
}
function parseResult(data, total, descriptions, result) {
var rowPath = [];
var columnPath = [];
var rowHash = result.rowHash;
var columnHash = result.columnHash;
if (total && total.summary) {
(0, _iterator.each)(total.summary, function(index, summary) {
setValue(result.values, summary, result.grandTotalRowIndex, result.grandTotalColumnIndex, index)
})
}
if (total && total.groupCount >= 0) {
var skip = descriptions.rows.length ? descriptions.rowSkip : descriptions.columnSkip;
data = _toConsumableArray(Array(skip)).concat(data);
data.length = total.groupCount
}
function getItem(dataItem, dimensionName, path, level, field) {
var dimensionHash = result[dimensionName + "Hash"];
var parentItem;
var parentItemChildren;
var item;
var pathValue = path.slice(0, level + 1).join("/");
var parentPathValue;
if (void 0 !== dimensionHash[pathValue]) {
item = dimensionHash[pathValue]
} else {
item = {
value: parseValue(dataItem.key, field),
index: result[dimensionName + "Index"]++
};
parentPathValue = path.slice(0, level).join("/");
if (level > 0 && void 0 !== dimensionHash[parentPathValue]) {
parentItem = dimensionHash[parentPathValue];
parentItemChildren = parentItem.children = parentItem.children || []
} else {
parentItemChildren = result[dimensionName + "s"]
}
parentItemChildren.push(item);
dimensionHash[pathValue] = item
}
return item
}
forEachGroup(data, function(item, level) {
var rowLevel = level >= descriptions.rows.length ? descriptions.rows.length : level;
var columnLevel = level >= descriptions.rows.length ? level - descriptions.rows.length : 0;
var columnItem;
var rowItem;
if (level >= descriptions.rows.length && columnLevel >= descriptions.columns.length) {
return
}
if (level < descriptions.rows.length) {
columnPath = []
}
if (level >= descriptions.rows.length) {
if (item) {
columnPath[columnLevel] = item.key + "";
columnItem = getItem(item, "column", columnPath, columnLevel, descriptions.columns[columnLevel]);
rowItem = rowHash[rowPath.slice(0, rowLevel + 1).join("/")]
} else {
result.columns.push({})
}
} else {
if (item) {
rowPath[rowLevel] = item.key + "";
rowItem = getItem(item, "row", rowPath, rowLevel, descriptions.rows[rowLevel]);
columnItem = columnHash[columnPath.slice(0, columnLevel + 1).join("/")]
} else {
result.rows.push({})
}
}
var currentRowIndex = rowItem && rowItem.index || result.grandTotalRowIndex;
var currentColumnIndex = columnItem && columnItem.index || result.grandTotalColumnIndex;
(0, _iterator.each)(item && item.summary || [], function(i, summary) {
setValue(result.values, summary, currentRowIndex, currentColumnIndex, i)
})
});
return result
}
function getFiltersForDimension(fields) {
return (fields || []).filter(function(f) {
return f.filterValues && f.filterValues.length || f.searchValue
})
}
function getExpandedIndex(options, axis) {
if (options.headerName) {
if (axis === options.headerName) {
return options.path.length
} else {
if (options.oppositePath) {
return options.oppositePath.length
}
}
}
return 0
}
function getFiltersForExpandedDimension(options) {
return (0, _uiPivot_grid.getFiltersByPath)(options[options.headerName], options.path).concat((0, _uiPivot_grid.getFiltersByPath)(options["rows" === options.headerName ? "columns" : "rows"], options.oppositePath || []))
}
function getExpandedPathSliceFilter(options, dimensionName, level, firstCollapsedFieldIndex) {
var result = [];
var startSliceIndex = level > firstCollapsedFieldIndex ? 0 : firstCollapsedFieldIndex;
var fields = options.headerName !== dimensionName ? options[dimensionName].slice(startSliceIndex, level) : [];
var paths = "rows" === dimensionName ? options.rowExpandedPaths : options.columnExpandedPaths;
(0, _iterator.each)(fields, function(index, field) {
var filterValues = [];
(0, _iterator.each)(paths, function(_, path) {
path = path.slice(startSliceIndex, level);
if (index < path.length) {
var filterValue = path[index];
if (filterValues.indexOf(filterValue) === -1) {
filterValues.push(filterValue)
}
}
});
if (filterValues.length) {
result.push((0, _extend.extend)({}, field, {
filterType: "include",
filterValues: filterValues
}))
}
});
return result
}
function getGrandTotalRequest(options, dimensionName, expandedIndex, expandedLevel, commonFilters, firstCollapsedFieldIndex) {
var expandedPaths = ("columns" === dimensionName ? options.columnExpandedPaths : options.rowExpandedPaths) || [];
var oppositeDimensionName = "columns" === dimensionName ? "rows" : "columns";
var fields = options[dimensionName];
var result = [];
var newOptions;
if (expandedPaths.length) {
for (var i = expandedIndex; i < expandedLevel + 1; i++) {
newOptions = {
filters: commonFilters.concat(getExpandedPathSliceFilter(options, dimensionName, i, firstCollapsedFieldIndex))
};
newOptions[dimensionName] = fields.slice(expandedIndex, i + 1);
newOptions[oppositeDimensionName] = [];
result.push((0, _extend.extend)({}, options, newOptions))
}
} else {
newOptions = {
filters: commonFilters
};
newOptions[dimensionName] = fields.slice(expandedIndex, expandedLevel + 1);
newOptions[oppositeDimensionName] = [];
result.push((0, _extend.extend)({}, options, newOptions))
}
result[0].includeTotalSummary = true;
return result
}
function getFirstCollapsedIndex(fields) {
var firstCollapsedIndex = 0;
(0, _iterator.each)(fields, function(index, field) {
if (!field.expanded) {
firstCollapsedIndex = index;
return false
}
});
return firstCollapsedIndex
}
function getRequestsData(options) {
var rowExpandedLevel = (0, _uiPivot_grid.getExpandedLevel)(options, "rows");
var columnExpandedLevel = (0, _uiPivot_grid.getExpandedLevel)(options, "columns");
var filters = options.filters || [];
var columnExpandedIndex = getExpandedIndex(options, "columns");
var firstCollapsedColumnIndex = getFirstCollapsedIndex(options.columns);
var firstCollapsedRowIndex = getFirstCollapsedIndex(options.rows);
var rowExpandedIndex = getExpandedIndex(options, "rows");
var data = [];
filters = filters.concat(getFiltersForDimension(options.rows)).concat(getFiltersForDimension(options.columns)).concat(getFiltersForExpandedDimension(options));
var columnTotalsOptions = getGrandTotalRequest(options, "columns", columnExpandedIndex, columnExpandedLevel, filters, firstCollapsedColumnIndex);
if (options.rows.length && options.columns.length) {
if ("rows" !== options.headerName) {
data = data.concat(columnTotalsOptions)
}
for (var i = rowExpandedIndex; i < rowExpandedLevel + 1; i++) {
var rows = options.rows.slice(rowExpandedIndex, i + 1);
var rowFilterByExpandedPaths = getExpandedPathSliceFilter(options, "rows", i, firstCollapsedRowIndex);
for (var j = columnExpandedIndex; j < columnExpandedLevel + 1; j++) {
var preparedOptions = (0, _extend.extend)({}, options, {
columns: options.columns.slice(columnExpandedIndex, j + 1),
rows: rows,
filters: filters.concat(getExpandedPathSliceFilter(options, "columns", j, firstCollapsedColumnIndex)).concat(rowFilterByExpandedPaths)
});
data.push(preparedOptions)
}
}
} else {
data = options.columns.length ? columnTotalsOptions : getGrandTotalRequest(options, "rows", rowExpandedIndex, rowExpandedLevel, filters, firstCollapsedRowIndex)
}
return data
}
function prepareFields(fields) {
(0, _iterator.each)(fields || [], function(_, field) {
var levels = field.levels;
if (levels) {
prepareFields(levels)
}(0, _uiPivot_grid.setDefaultFieldValueFormatting)(field)
})
}
module.exports = _class2.default.inherit(function() {
return {
ctor: function(options) {
this._dataSource = new _data_source.DataSource(options);
this._store = this._dataSource.store()
},
getFields: function(fields) {
var d = new _deferred.Deferred;
this._store.load({
skip: 0,
take: 20
}).done(function(data) {
d.resolve((0, _uiPivot_grid.discoverObjectFields)(data, fields))
}).fail(d.reject);
return d
},
key: function() {
return this._store.key()
},
load: function(options) {
var that = this;
var d = new _deferred.Deferred;
var result = {
rows: [],
columns: [],
values: [],
grandTotalRowIndex: 0,
grandTotalColumnIndex: 0,
rowHash: {},
columnHash: {},
rowIndex: 1,
columnIndex: 1
};
var requestsData = getRequestsData(options);
var deferreds = [];
prepareFields(options.rows);
prepareFields(options.columns);
prepareFields(options.filters);
(0, _iterator.each)(requestsData, function(_, dataItem) {
deferreds.push(that._store.load(createLoadOptions(dataItem, that.filter(), options.rows.length)))
});
_deferred.when.apply(null, deferreds).done(function() {
var args = deferreds.length > 1 ? arguments : [arguments];
(0, _iterator.each)(args, function(index, argument) {
parseResult(argument[0], argument[1], requestsData[index], result)
});
d.resolve({
rows: result.rows,
columns: result.columns,
values: result.values,
grandTotalRowIndex: result.grandTotalRowIndex,
grandTotalColumnIndex: result.grandTotalColumnIndex
})
}).fail(d.reject);
return d
},
filter: function() {
return this._dataSource.filter.apply(this._dataSource, arguments)
},
supportPaging: function() {
return false
},
createDrillDownDataSource: function(loadOptions, params) {
loadOptions = loadOptions || {};
params = params || {};
var store = this._store;
var filters = (0, _uiPivot_grid.getFiltersByPath)(loadOptions.rows, params.rowPath).concat((0, _uiPivot_grid.getFiltersByPath)(loadOptions.columns, params.columnPath)).concat(getFiltersForDimension(loadOptions.rows)).concat(loadOptions.filters || []).concat(getFiltersForDimension(loadOptions.columns));
var filterExp = createFilterExpressions(filters);
return new _data_source.DataSource({
load: function(loadOptions) {
return store.load((0, _extend.extend)({}, loadOptions, {
filter: mergeFilters(filterExp, loadOptions.filter),
select: params.customColumns
}))
}
})
}
}
}());