| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636 |
- /**
- * DevExtreme (data/data_source/data_source.js)
- * Version: 19.1.16
- * Build date: Tue Oct 18 2022
- *
- * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
- * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
- */
- "use strict";
- var Class = require("../../core/class");
- var extend = require("../../core/utils/extend").extend;
- var commonUtils = require("../../core/utils/common");
- var iteratorUtils = require("../../core/utils/iterator");
- var ajax = require("../../core/utils/ajax");
- var typeUtils = require("../../core/utils/type");
- var dataUtils = require("../utils");
- var arrayUtils = require("../array_utils");
- var Store = require("../abstract_store");
- var ArrayStore = require("../array_store");
- var CustomStore = require("../custom_store");
- var EventsMixin = require("../../core/events_mixin");
- var errors = require("../errors").errors;
- var array = require("../../core/utils/array");
- var queue = require("../../core/utils/queue");
- var deferredUtils = require("../../core/utils/deferred");
- var when = deferredUtils.when;
- var Deferred = deferredUtils.Deferred;
- var __isString = typeUtils.isString;
- var __isNumber = typeUtils.isNumeric;
- var __isBoolean = typeUtils.isBoolean;
- var __isDefined = typeUtils.isDefined;
- var CANCELED_TOKEN = "canceled";
- function OperationManager() {
- this._counter = -1;
- this._deferreds = {}
- }
- OperationManager.prototype.constructor = OperationManager;
- OperationManager.prototype.add = function(deferred) {
- this._counter += 1;
- this._deferreds[this._counter] = deferred;
- return this._counter
- };
- OperationManager.prototype.remove = function(operationId) {
- return delete this._deferreds[operationId]
- };
- OperationManager.prototype.cancel = function(operationId) {
- if (operationId in this._deferreds) {
- this._deferreds[operationId].reject(CANCELED_TOKEN);
- return true
- }
- return false
- };
- OperationManager.prototype.cancelAll = function() {
- while (this._counter > -1) {
- this.cancel(this._counter);
- this._counter--
- }
- };
- function isPending(deferred) {
- return "pending" === deferred.state()
- }
- function normalizeDataSourceOptions(options, normalizationOptions) {
- var store;
- function createCustomStoreFromLoadFunc() {
- var storeConfig = {};
- iteratorUtils.each(["useDefaultSearch", "key", "load", "loadMode", "cacheRawData", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() {
- storeConfig[this] = options[this];
- delete options[this]
- });
- return new CustomStore(storeConfig)
- }
- function createStoreFromConfig(storeConfig) {
- var alias = storeConfig.type;
- delete storeConfig.type;
- return Store.create(alias, storeConfig)
- }
- function createCustomStoreFromUrl(url) {
- return new CustomStore({
- load: function() {
- return ajax.sendRequest({
- url: url,
- dataType: "json"
- })
- },
- loadMode: normalizationOptions && normalizationOptions.fromUrlLoadMode
- })
- }
- if ("string" === typeof options) {
- options = {
- paginate: false,
- store: createCustomStoreFromUrl(options)
- }
- }
- if (void 0 === options) {
- options = []
- }
- if (Array.isArray(options) || options instanceof Store) {
- options = {
- store: options
- }
- } else {
- options = extend({}, options)
- }
- if (void 0 === options.store) {
- options.store = []
- }
- store = options.store;
- if ("load" in options) {
- store = createCustomStoreFromLoadFunc()
- } else {
- if (Array.isArray(store)) {
- store = new ArrayStore(store)
- } else {
- if (typeUtils.isPlainObject(store)) {
- store = createStoreFromConfig(extend({}, store))
- }
- }
- }
- options.store = store;
- return options
- }
- function normalizeStoreLoadOptionAccessorArguments(originalArguments) {
- switch (originalArguments.length) {
- case 0:
- return;
- case 1:
- return originalArguments[0]
- }
- return [].slice.call(originalArguments)
- }
- function generateStoreLoadOptionAccessor(optionName) {
- return function() {
- var args = normalizeStoreLoadOptionAccessorArguments(arguments);
- if (void 0 === args) {
- return this._storeLoadOptions[optionName]
- }
- this._storeLoadOptions[optionName] = args
- }
- }
- function mapDataRespectingGrouping(items, mapper, groupInfo) {
- function mapRecursive(items, level) {
- if (!Array.isArray(items)) {
- return items
- }
- return level ? mapGroup(items, level) : iteratorUtils.map(items, mapper)
- }
- function mapGroup(group, level) {
- return iteratorUtils.map(group, function(item) {
- var result = {
- key: item.key,
- items: mapRecursive(item.items, level - 1)
- };
- if ("aggregates" in item) {
- result.aggregates = item.aggregates
- }
- return result
- })
- }
- return mapRecursive(items, groupInfo ? dataUtils.normalizeSortingInfo(groupInfo).length : 0)
- }
- function normalizeLoadResult(data, extra) {
- if (data && !Array.isArray(data) && data.data) {
- extra = data;
- data = data.data
- }
- if (!Array.isArray(data)) {
- data = [data]
- }
- return {
- data: data,
- extra: extra
- }
- }
- var DataSource = Class.inherit({
- ctor: function(options) {
- var _this = this;
- var that = this;
- options = normalizeDataSourceOptions(options);
- var onPushHandler = 0 !== options.pushAggregationTimeout ? dataUtils.throttleChanges(this._onPush, function() {
- if (void 0 === options.pushAggregationTimeout) {
- return 5 * that._changedTime
- }
- return options.pushAggregationTimeout
- }) : this._onPush;
- this._changedTime = 0;
- this._onPushHandler = function(changes) {
- _this._aggregationTimeoutId = onPushHandler.call(_this, changes)
- };
- this._store = options.store;
- this._store.on("push", this._onPushHandler);
- this._storeLoadOptions = this._extractLoadOptions(options);
- this._mapFunc = options.map;
- this._postProcessFunc = options.postProcess;
- this._pageIndex = void 0 !== options.pageIndex ? options.pageIndex : 0;
- this._pageSize = void 0 !== options.pageSize ? options.pageSize : 20;
- this._loadingCount = 0;
- this._loadQueue = this._createLoadQueue();
- this._searchValue = "searchValue" in options ? options.searchValue : null;
- this._searchOperation = options.searchOperation || "contains";
- this._searchExpr = options.searchExpr;
- this._paginate = options.paginate;
- this._reshapeOnPush = __isDefined(options.reshapeOnPush) ? options.reshapeOnPush : false;
- iteratorUtils.each(["onChanged", "onLoadError", "onLoadingChanged", "onCustomizeLoadResult", "onCustomizeStoreLoadOptions"], function(_, optionName) {
- if (optionName in options) {
- that.on(optionName.substr(2, 1).toLowerCase() + optionName.substr(3), options[optionName])
- }
- });
- this._operationManager = new OperationManager;
- this._init()
- },
- _init: function() {
- this._items = [];
- this._userData = {};
- this._totalCount = -1;
- this._isLoaded = false;
- if (!__isDefined(this._paginate)) {
- this._paginate = !this.group()
- }
- this._isLastPage = !this._paginate
- },
- dispose: function() {
- this._store.off("push", this._onPushHandler);
- this._disposeEvents();
- clearTimeout(this._aggregationTimeoutId);
- delete this._store;
- if (this._delayedLoadTask) {
- this._delayedLoadTask.abort()
- }
- this._operationManager.cancelAll();
- this._disposed = true
- },
- _extractLoadOptions: function(options) {
- var result = {};
- var names = ["sort", "filter", "select", "group", "requireTotalCount"];
- var customNames = this._store._customLoadOptions();
- if (customNames) {
- names = names.concat(customNames)
- }
- iteratorUtils.each(names, function() {
- result[this] = options[this]
- });
- return result
- },
- loadOptions: function() {
- return this._storeLoadOptions
- },
- items: function() {
- return this._items
- },
- pageIndex: function(newIndex) {
- if (!__isNumber(newIndex)) {
- return this._pageIndex
- }
- this._pageIndex = newIndex;
- this._isLastPage = !this._paginate
- },
- paginate: function(value) {
- if (!__isBoolean(value)) {
- return this._paginate
- }
- if (this._paginate !== value) {
- this._paginate = value;
- this.pageIndex(0)
- }
- },
- pageSize: function(value) {
- if (!__isNumber(value)) {
- return this._pageSize
- }
- this._pageSize = value
- },
- isLastPage: function() {
- return this._isLastPage
- },
- sort: generateStoreLoadOptionAccessor("sort"),
- filter: function() {
- var newFilter = normalizeStoreLoadOptionAccessorArguments(arguments);
- if (void 0 === newFilter) {
- return this._storeLoadOptions.filter
- }
- this._storeLoadOptions.filter = newFilter;
- this.pageIndex(0)
- },
- group: generateStoreLoadOptionAccessor("group"),
- select: generateStoreLoadOptionAccessor("select"),
- requireTotalCount: function(value) {
- if (!__isBoolean(value)) {
- return this._storeLoadOptions.requireTotalCount
- }
- this._storeLoadOptions.requireTotalCount = value
- },
- searchValue: function(value) {
- if (arguments.length < 1) {
- return this._searchValue
- }
- this._searchValue = value;
- this.pageIndex(0)
- },
- searchOperation: function(op) {
- if (!__isString(op)) {
- return this._searchOperation
- }
- this._searchOperation = op;
- this.pageIndex(0)
- },
- searchExpr: function(expr) {
- var argc = arguments.length;
- if (0 === argc) {
- return this._searchExpr
- }
- if (argc > 1) {
- expr = [].slice.call(arguments)
- }
- this._searchExpr = expr;
- this.pageIndex(0)
- },
- store: function() {
- return this._store
- },
- key: function() {
- return this._store && this._store.key()
- },
- totalCount: function() {
- return this._totalCount
- },
- isLoaded: function() {
- return this._isLoaded
- },
- isLoading: function() {
- return this._loadingCount > 0
- },
- beginLoading: function() {
- this._changeLoadingCount(1)
- },
- endLoading: function() {
- this._changeLoadingCount(-1)
- },
- _createLoadQueue: function() {
- return queue.create()
- },
- _changeLoadingCount: function(increment) {
- var oldLoading = this.isLoading();
- this._loadingCount += increment;
- var newLoading = this.isLoading();
- if (oldLoading ^ newLoading) {
- this.fireEvent("loadingChanged", [newLoading])
- }
- },
- _scheduleLoadCallbacks: function(deferred) {
- var that = this;
- that.beginLoading();
- deferred.always(function() {
- that.endLoading()
- })
- },
- _scheduleFailCallbacks: function(deferred) {
- var that = this;
- deferred.fail(function() {
- if (arguments[0] === CANCELED_TOKEN) {
- return
- }
- that.fireEvent("loadError", arguments)
- })
- },
- _fireChanged: function(args) {
- var date = new Date;
- this.fireEvent("changed", args);
- this._changedTime = new Date - date
- },
- _scheduleChangedCallbacks: function(deferred) {
- var _this2 = this;
- deferred.done(function() {
- _this2._fireChanged()
- })
- },
- loadSingle: function(propName, propValue) {
- var that = this;
- var d = new Deferred;
- var key = this.key();
- var store = this._store;
- var options = this._createStoreLoadOptions();
- var handleDone = function(data) {
- if (!__isDefined(data) || array.isEmpty(data)) {
- d.reject(new errors.Error("E4009"))
- } else {
- if (!Array.isArray(data)) {
- data = [data]
- }
- d.resolve(that._applyMapFunction(data)[0])
- }
- };
- this._scheduleFailCallbacks(d);
- if (arguments.length < 2) {
- propValue = propName;
- propName = key
- }
- delete options.skip;
- delete options.group;
- delete options.refresh;
- delete options.pageIndex;
- delete options.searchString;
- function shouldForceByKey() {
- return store instanceof CustomStore && !store._byKeyViaLoad()
- }(function() {
- if (propName === key || shouldForceByKey()) {
- return store.byKey(propValue, options)
- }
- options.take = 1;
- options.filter = options.filter ? [options.filter, [propName, propValue]] : [propName, propValue];
- return store.load(options)
- })().fail(d.reject).done(handleDone);
- return d.promise()
- },
- load: function() {
- var that = this;
- var d = new Deferred;
- function loadTask() {
- if (that._disposed) {
- return
- }
- if (!isPending(d)) {
- return
- }
- return that._loadFromStore(loadOperation, d)
- }
- this._scheduleLoadCallbacks(d);
- this._scheduleFailCallbacks(d);
- this._scheduleChangedCallbacks(d);
- var loadOperation = this._createLoadOperation(d);
- this.fireEvent("customizeStoreLoadOptions", [loadOperation]);
- this._loadQueue.add(function() {
- if ("number" === typeof loadOperation.delay) {
- that._delayedLoadTask = commonUtils.executeAsync(loadTask, loadOperation.delay)
- } else {
- loadTask()
- }
- return d.promise()
- });
- return d.promise({
- operationId: loadOperation.operationId
- })
- },
- _onPush: function(changes) {
- var _this3 = this;
- if (this._reshapeOnPush) {
- this.load()
- } else {
- this.fireEvent("changing", [{
- changes: changes
- }]);
- var group = this.group();
- var items = this.items();
- var groupLevel = 0;
- var dataSourceChanges = this.paginate() || group ? changes.filter(function(item) {
- return "update" === item.type
- }) : changes;
- if (group) {
- groupLevel = Array.isArray(group) ? group.length : 1
- }
- if (this._mapFunc) {
- dataSourceChanges.forEach(function(item) {
- if ("insert" === item.type) {
- item.data = _this3._mapFunc(item.data)
- }
- })
- }
- arrayUtils.applyBatch(this.store(), items, dataSourceChanges, groupLevel, true);
- this._fireChanged([{
- changes: changes
- }])
- }
- },
- _createLoadOperation: function(deferred) {
- var id = this._operationManager.add(deferred);
- var options = this._createStoreLoadOptions();
- deferred.always(function() {
- this._operationManager.remove(id)
- }.bind(this));
- return {
- operationId: id,
- storeLoadOptions: options
- }
- },
- reload: function() {
- var store = this.store();
- if (store instanceof CustomStore) {
- store.clearRawDataCache()
- }
- this._init();
- return this.load()
- },
- cancel: function(operationId) {
- return this._operationManager.cancel(operationId)
- },
- cancelAll: function() {
- return this._operationManager.cancelAll()
- },
- _addSearchOptions: function(storeLoadOptions) {
- if (this._disposed) {
- return
- }
- if (this.store()._useDefaultSearch) {
- this._addSearchFilter(storeLoadOptions)
- } else {
- storeLoadOptions.searchOperation = this._searchOperation;
- storeLoadOptions.searchValue = this._searchValue;
- storeLoadOptions.searchExpr = this._searchExpr
- }
- },
- _createStoreLoadOptions: function() {
- var result = extend({}, this._storeLoadOptions);
- this._addSearchOptions(result);
- if (this._paginate) {
- if (this._pageSize) {
- result.skip = this._pageIndex * this._pageSize;
- result.take = this._pageSize
- }
- }
- result.userData = this._userData;
- return result
- },
- _addSearchFilter: function(storeLoadOptions) {
- var value = this._searchValue;
- var op = this._searchOperation;
- var selector = this._searchExpr;
- var searchFilter = [];
- if (!value) {
- return
- }
- if (!selector) {
- selector = "this"
- }
- if (!Array.isArray(selector)) {
- selector = [selector]
- }
- iteratorUtils.each(selector, function(i, item) {
- if (searchFilter.length) {
- searchFilter.push("or")
- }
- searchFilter.push([item, op, value])
- });
- if (storeLoadOptions.filter) {
- storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter]
- } else {
- storeLoadOptions.filter = searchFilter
- }
- },
- _loadFromStore: function(loadOptions, pendingDeferred) {
- var that = this;
- function handleSuccess(data, extra) {
- function processResult() {
- var loadResult = extend(normalizeLoadResult(data, extra), loadOptions);
- that.fireEvent("customizeLoadResult", [loadResult]);
- when(loadResult.data).done(function(data) {
- loadResult.data = data;
- that._processStoreLoadResult(loadResult, pendingDeferred)
- }).fail(pendingDeferred.reject)
- }
- if (that._disposed) {
- return
- }
- if (!isPending(pendingDeferred)) {
- return
- }
- processResult()
- }
- if (loadOptions.data) {
- return (new Deferred).resolve(loadOptions.data).done(handleSuccess)
- }
- return this.store().load(loadOptions.storeLoadOptions).done(handleSuccess).fail(pendingDeferred.reject)
- },
- _processStoreLoadResult: function(loadResult, pendingDeferred) {
- var that = this;
- var data = loadResult.data;
- var extra = loadResult.extra;
- var storeLoadOptions = loadResult.storeLoadOptions;
- function resolvePendingDeferred() {
- that._isLoaded = true;
- that._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1;
- return pendingDeferred.resolve(data, extra)
- }
- function proceedLoadingTotalCount() {
- that.store().totalCount(storeLoadOptions).done(function(count) {
- extra.totalCount = count;
- resolvePendingDeferred()
- }).fail(pendingDeferred.reject)
- }
- if (that._disposed) {
- return
- }
- data = that._applyPostProcessFunction(that._applyMapFunction(data));
- if (!typeUtils.isPlainObject(extra)) {
- extra = {}
- }
- that._items = data;
- if (!data.length || !that._paginate || that._pageSize && data.length < that._pageSize) {
- that._isLastPage = true
- }
- if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount)) {
- proceedLoadingTotalCount()
- } else {
- resolvePendingDeferred()
- }
- },
- _applyMapFunction: function(data) {
- if (this._mapFunc) {
- return mapDataRespectingGrouping(data, this._mapFunc, this.group())
- }
- return data
- },
- _applyPostProcessFunction: function(data) {
- if (this._postProcessFunc) {
- return this._postProcessFunc(data)
- }
- return data
- }
- }).include(EventsMixin);
- exports.DataSource = DataSource;
- exports.normalizeDataSourceOptions = normalizeDataSourceOptions;
- exports.normalizeLoadResult = normalizeLoadResult;
|