From 4d790f01ce8c1dcb2b7215fd0b8c702ecd8105f6 Mon Sep 17 00:00:00 2001 From: Andrey Ignatovskiy <43685423+LazyLahtak@users.noreply.github.com> Date: Mon, 27 Jan 2020 11:01:09 +0300 Subject: [PATCH] Renovation: Data Source refactoring (#11479) --- js/bundles/modules/data.js | 2 +- js/data/data_source/data_source.js | 484 ++++++------------ js/data/data_source/operation_manager.js | 34 ++ js/data/data_source/utils.js | 124 +++++ js/data_helper.js | 2 +- js/ui/collection/ui.collection_widget.edit.js | 3 +- .../ui.grid_core.columns_controller.js | 3 +- .../ui.grid_core.filter_custom_operations.js | 4 +- js/ui/grid_core/ui.grid_core.header_filter.js | 2 +- js/ui/pivot_grid/data_source.js | 2 +- .../ui.scheduler.resource_manager.js | 9 +- js/ui/shared/ui.editor_factory_mixin.js | 2 +- js/ui/tag_box.js | 2 +- .../common.markup.tests.js | 18 +- .../chart.part1.tests.js | 6 +- .../DevExpress.viz.charts/chart.tests.js | 14 +- .../common.part1.tests.js | 8 +- .../common.part3.tests.js | 4 +- .../sparkline.tests.js | 8 +- .../mapLayer.tests.js | 8 +- .../mapLayer_new.tests.js | 4 +- 21 files changed, 363 insertions(+), 380 deletions(-) create mode 100644 js/data/data_source/operation_manager.js create mode 100644 js/data/data_source/utils.js diff --git a/js/bundles/modules/data.js b/js/bundles/modules/data.js index cc96eda4fb2c..c2a4800d0f84 100644 --- a/js/bundles/modules/data.js +++ b/js/bundles/modules/data.js @@ -56,4 +56,4 @@ DevExpress.data.utils.toComparable = require('../../core/utils/data').toComparab DevExpress.data.utils.multiLevelGroup = require('../../data/store_helper').multiLevelGroup; DevExpress.data.utils.arrangeSortingInfo = require('../../data/store_helper').arrangeSortingInfo; -DevExpress.data.utils.normalizeDataSourceOptions = require('../../data/data_source/data_source').normalizeDataSourceOptions; +DevExpress.data.utils.normalizeDataSourceOptions = require('../../data/data_source/utils').normalizeDataSourceOptions; diff --git a/js/data/data_source/data_source.js b/js/data/data_source/data_source.js index e7de6461f2a6..e618b2acdd26 100644 --- a/js/data/data_source/data_source.js +++ b/js/data/data_source/data_source.js @@ -1,194 +1,27 @@ -const Class = require('../../core/class'); -const extend = require('../../core/utils/extend').extend; -const commonUtils = require('../../core/utils/common'); -const iteratorUtils = require('../../core/utils/iterator'); -const ajax = require('../../core/utils/ajax'); -const typeUtils = require('../../core/utils/type'); -const dataUtils = require('../utils'); -const arrayUtils = require('../array_utils'); -const Store = require('../abstract_store'); -const ArrayStore = require('../array_store'); -const CustomStore = require('../custom_store'); -const EventsStrategy = require('../../core/events_strategy').EventsStrategy; -const errors = require('../errors').errors; -const array = require('../../core/utils/array'); -const queue = require('../../core/utils/queue'); -const deferredUtils = require('../../core/utils/deferred'); -const when = deferredUtils.when; -const Deferred = deferredUtils.Deferred; - -const __isString = typeUtils.isString; -const __isNumber = typeUtils.isNumeric; -const __isBoolean = typeUtils.isBoolean; -const __isDefined = typeUtils.isDefined; - -const 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 deferred.state() === 'pending'; -} - -function normalizeDataSourceOptions(options, normalizationOptions) { - let store; - - function createCustomStoreFromLoadFunc() { - const 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) { - const 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(typeof options === 'string') { - options = { - paginate: false, - store: createCustomStoreFromUrl(options) - }; - } - - if(options === undefined) { - options = []; - } - - if(Array.isArray(options) || options instanceof Store) { - options = { store: options }; - } else { - options = extend({}, options); - } - - if(options.store === undefined) { - 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 undefined; - case 1: - return originalArguments[0]; - } - return [].slice.call(originalArguments); -} - -function generateStoreLoadOptionAccessor(optionName) { - return function() { - const args = normalizeStoreLoadOptionAccessorArguments(arguments); - if(args === undefined) { - 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) { - const 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, - extra - }; -} - -const DataSource = Class.inherit({ +import Class from '../../core/class'; +import { extend } from '../../core/utils/extend'; +import commonUtils from '../../core/utils/common'; +import { each } from '../../core/utils/iterator'; +import { isString, isNumeric, isBoolean, isDefined, isPlainObject } from '../../core/utils/type'; +import { throttleChanges } from '../utils'; +import arrayUtils from '../array_utils'; +import CustomStore from '../custom_store'; +import { EventsStrategy } from '../../core/events_strategy'; +import { errors } from '../errors'; +import array from '../../core/utils/array'; +import queue from '../../core/utils/queue'; +import { Deferred, when } from '../../core/utils/deferred'; +import OperationManager from './operation_manager'; +import { + normalizeDataSourceOptions, + normalizeStoreLoadOptionAccessorArguments, + CANCELED_TOKEN, + isPending, + normalizeLoadResult, + mapDataRespectingGrouping +} from './utils'; + +export const DataSource = Class.inherit({ /** * @name DataSourceMethods.ctor * @publicName ctor(url) @@ -213,8 +46,7 @@ const DataSource = Class.inherit({ * @param1 options:CustomStoreOptions|DataSourceOptions * @hidden */ - ctor: function(options) { - const that = this; + ctor(options) { options = normalizeDataSourceOptions(options); this._eventsStrategy = new EventsStrategy(this); @@ -224,12 +56,11 @@ const DataSource = Class.inherit({ */ const onPushHandler = options.pushAggregationTimeout !== 0 - ? dataUtils.throttleChanges(this._onPush, function() { - if(options.pushAggregationTimeout === undefined) { - return that._changedTime * 5; - } - return options.pushAggregationTimeout; - }) + ? throttleChanges(this._onPush, () => + options.pushAggregationTimeout === undefined + ? this._changedTime * 5 + : options.pushAggregationTimeout + ) : this._onPush; this._changedTime = 0; @@ -263,9 +94,9 @@ const DataSource = Class.inherit({ this._paginate = options.paginate; - this._reshapeOnPush = __isDefined(options.reshapeOnPush) ? options.reshapeOnPush : false; + this._reshapeOnPush = options.reshapeOnPush ?? false; - iteratorUtils.each( + each( [ 'onChanged', @@ -276,9 +107,9 @@ const DataSource = Class.inherit({ 'onCustomizeLoadResult', 'onCustomizeStoreLoadOptions' ], - function(_, optionName) { + (_, optionName) => { if(optionName in options) { - that.on(optionName.substr(2, 1).toLowerCase() + optionName.substr(3), options[optionName]); + this.on(optionName.substr(2, 1).toLowerCase() + optionName.substr(3), options[optionName]); } }); @@ -286,36 +117,34 @@ const DataSource = Class.inherit({ this._init(); }, - _init: function() { + _init() { this._items = []; this._userData = {}; this._totalCount = -1; this._isLoaded = false; - if(!__isDefined(this._paginate)) { + if(!isDefined(this._paginate)) { this._paginate = !this.group(); } this._isLastPage = !this._paginate; }, - dispose: function() { + dispose() { this._store.off('push', this._onPushHandler); this._eventsStrategy.dispose(); clearTimeout(this._aggregationTimeoutId); delete this._store; - if(this._delayedLoadTask) { - this._delayedLoadTask.abort(); - } + this._delayedLoadTask?.abort(); this._operationManager.cancelAll(); this._disposed = true; }, - _extractLoadOptions: function(options) { + _extractLoadOptions(options) { const result = {}; let names = ['sort', 'filter', 'select', 'group', 'requireTotalCount']; const customNames = this._store._customLoadOptions(); @@ -324,22 +153,22 @@ const DataSource = Class.inherit({ names = names.concat(customNames); } - iteratorUtils.each(names, function() { + each(names, function() { result[this] = options[this]; }); return result; }, - loadOptions: function() { + loadOptions() { return this._storeLoadOptions; }, - items: function() { + items() { return this._items; }, - pageIndex: function(newIndex) { - if(!__isNumber(newIndex)) { + pageIndex(newIndex) { + if(!isNumeric(newIndex)) { return this._pageIndex; } @@ -347,8 +176,8 @@ const DataSource = Class.inherit({ this._isLastPage = !this._paginate; }, - paginate: function(value) { - if(!__isBoolean(value)) { + paginate(value) { + if(!isBoolean(value)) { return this._paginate; } @@ -358,21 +187,34 @@ const DataSource = Class.inherit({ } }, - pageSize: function(value) { - if(!__isNumber(value)) { + pageSize(value) { + if(!isNumeric(value)) { return this._pageSize; } this._pageSize = value; }, - isLastPage: function() { + isLastPage() { return this._isLastPage; }, - sort: generateStoreLoadOptionAccessor('sort'), + generateStoreLoadOptionAccessor(optionName) { + return (args) => { + const normalizedArgs = normalizeStoreLoadOptionAccessorArguments(args); + if(normalizedArgs === undefined) { + return this._storeLoadOptions[optionName]; + } + + this._storeLoadOptions[optionName] = normalizedArgs; + }; + }, - filter: function() { + sort(...args) { + return this.generateStoreLoadOptionAccessor('sort')(args); + }, + + filter() { const newFilter = normalizeStoreLoadOptionAccessorArguments(arguments); if(newFilter === undefined) { return this._storeLoadOptions.filter; @@ -382,19 +224,23 @@ const DataSource = Class.inherit({ this.pageIndex(0); }, - group: generateStoreLoadOptionAccessor('group'), + group(...args) { + return this.generateStoreLoadOptionAccessor('group')(args); + }, - select: generateStoreLoadOptionAccessor('select'), + select(...args) { + return this.generateStoreLoadOptionAccessor('select')(args); + }, - requireTotalCount: function(value) { - if(!__isBoolean(value)) { + requireTotalCount(value) { + if(!isBoolean(value)) { return this._storeLoadOptions.requireTotalCount; } this._storeLoadOptions.requireTotalCount = value; }, - searchValue: function(value) { + searchValue(value) { if(arguments.length < 1) { return this._searchValue; } @@ -403,8 +249,8 @@ const DataSource = Class.inherit({ this.pageIndex(0); }, - searchOperation: function(op) { - if(!__isString(op)) { + searchOperation(op) { + if(!isString(op)) { return this._searchOperation; } @@ -412,7 +258,7 @@ const DataSource = Class.inherit({ this.pageIndex(0); }, - searchExpr: function(expr) { + searchExpr(expr) { const argc = arguments.length; if(argc === 0) { @@ -427,39 +273,39 @@ const DataSource = Class.inherit({ this.pageIndex(0); }, - store: function() { + store() { return this._store; }, - key: function() { - return this._store && this._store.key(); + key() { + return this._store?.key(); }, - totalCount: function() { + totalCount() { return this._totalCount; }, - isLoaded: function() { + isLoaded() { return this._isLoaded; }, - isLoading: function() { + isLoading() { return this._loadingCount > 0; }, - beginLoading: function() { + beginLoading() { this._changeLoadingCount(1); }, - endLoading: function() { + endLoading() { this._changeLoadingCount(-1); }, - _createLoadQueue: function() { + _createLoadQueue() { return queue.create(); }, - _changeLoadingCount: function(increment) { + _changeLoadingCount(increment) { const oldLoading = this.isLoading(); this._loadingCount += increment; @@ -470,55 +316,47 @@ const DataSource = Class.inherit({ } }, - _scheduleLoadCallbacks: function(deferred) { - const that = this; - - that.beginLoading(); + _scheduleLoadCallbacks(deferred) { + this.beginLoading(); - deferred.always(function() { - that.endLoading(); + deferred.always(() => { + this.endLoading(); }); }, - _scheduleFailCallbacks: function(deferred) { - const that = this; - - deferred.fail(function() { - if(arguments[0] === CANCELED_TOKEN) { + _scheduleFailCallbacks(deferred) { + deferred.fail((...args) => { + if(args[0] === CANCELED_TOKEN) { return; } - that._eventsStrategy.fireEvent('loadError', arguments); + this._eventsStrategy.fireEvent('loadError', args); }); }, - _fireChanged: function(args) { + _fireChanged(args) { const date = new Date(); this._eventsStrategy.fireEvent('changed', args); this._changedTime = new Date() - date; }, - _scheduleChangedCallbacks: function(deferred) { - deferred.done(() => { - this._fireChanged(); - }); + _scheduleChangedCallbacks(deferred) { + deferred.done(() => this._fireChanged()); }, - loadSingle: function(propName, propValue) { - const that = this; - + loadSingle(propName, propValue) { const d = new Deferred(); const key = this.key(); const store = this._store; const options = this._createStoreLoadOptions(); - const handleDone = function(data) { - if(!__isDefined(data) || array.isEmpty(data)) { + const handleDone = (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]); + d.resolve(this._applyMapFunction(data)[0]); } }; @@ -535,11 +373,9 @@ const DataSource = Class.inherit({ delete options.pageIndex; delete options.searchString; - function shouldForceByKey() { - return (store instanceof CustomStore) && !store._byKeyViaLoad(); - } + const shouldForceByKey = () => (store instanceof CustomStore) && !store._byKeyViaLoad(); - (function() { + (() => { // NOTE for CustomStore always using byKey for backward compatibility with "old user datasource" if(propName === key || shouldForceByKey()) { @@ -558,12 +394,11 @@ const DataSource = Class.inherit({ return d.promise(); }, - load: function() { - const that = this; + load() { const d = new Deferred(); - function loadTask() { - if(that._disposed) { + const loadTask = () => { + if(this._disposed) { return undefined; } @@ -571,8 +406,8 @@ const DataSource = Class.inherit({ return; } - return that._loadFromStore(loadOperation, d); - } + return this._loadFromStore(loadOperation, d); + }; this._scheduleLoadCallbacks(d); this._scheduleFailCallbacks(d); @@ -582,9 +417,9 @@ const DataSource = Class.inherit({ this._eventsStrategy.fireEvent('customizeStoreLoadOptions', [loadOperation]); - this._loadQueue.add(function() { + this._loadQueue.add(() => { if(typeof loadOperation.delay === 'number') { - that._delayedLoadTask = commonUtils.executeAsync(loadTask, loadOperation.delay); + this._delayedLoadTask = commonUtils.executeAsync(loadTask, loadOperation.delay); } else { loadTask(); } @@ -596,11 +431,11 @@ const DataSource = Class.inherit({ }); }, - _onPush: function(changes) { + _onPush(changes) { if(this._reshapeOnPush) { this.load(); } else { - this._eventsStrategy.fireEvent('changing', [{ changes: changes }]); + this._eventsStrategy.fireEvent('changing', [{ changes }]); const group = this.group(); const items = this.items(); @@ -624,21 +459,19 @@ const DataSource = Class.inherit({ } }, - _createLoadOperation: function(deferred) { - const id = this._operationManager.add(deferred); - const options = this._createStoreLoadOptions(); + _createLoadOperation(deferred) { + const operationId = this._operationManager.add(deferred); + const storeLoadOptions = this._createStoreLoadOptions(); - deferred.always(function() { - this._operationManager.remove(id); - }.bind(this)); + deferred.always(() => this._operationManager.remove(operationId)); return { - operationId: id, - storeLoadOptions: options + operationId, + storeLoadOptions }; }, - reload: function() { + reload() { const store = this.store(); if(store instanceof CustomStore) { store.clearRawDataCache(); @@ -648,15 +481,15 @@ const DataSource = Class.inherit({ return this.load(); }, - cancel: function(operationId) { + cancel(operationId) { return this._operationManager.cancel(operationId); }, - cancelAll: function() { + cancelAll() { return this._operationManager.cancelAll(); }, - _addSearchOptions: function(storeLoadOptions) { + _addSearchOptions(storeLoadOptions) { if(this._disposed) { return; } @@ -670,7 +503,7 @@ const DataSource = Class.inherit({ } }, - _createStoreLoadOptions: function() { + _createStoreLoadOptions() { const result = extend({}, this._storeLoadOptions); this._addSearchOptions(result); @@ -686,7 +519,7 @@ const DataSource = Class.inherit({ return result; }, - _addSearchFilter: function(storeLoadOptions) { + _addSearchFilter(storeLoadOptions) { const value = this._searchValue; const op = this._searchOperation; let selector = this._searchExpr; @@ -706,7 +539,7 @@ const DataSource = Class.inherit({ // TODO optimize for byKey case - iteratorUtils.each(selector, function(i, item) { + each(selector, function(i, item) { if(searchFilter.length) { searchFilter.push('or'); } @@ -721,21 +554,9 @@ const DataSource = Class.inherit({ } }, - _loadFromStore: function(loadOptions, pendingDeferred) { - const that = this; - - function handleSuccess(data, extra) { - function processResult() { - const loadResult = extend(normalizeLoadResult(data, extra), loadOptions); - - that._eventsStrategy.fireEvent('customizeLoadResult', [loadResult]); - when(loadResult.data).done(function(data) { - loadResult.data = data; - that._processStoreLoadResult(loadResult, pendingDeferred); - }).fail(pendingDeferred.reject); - } - - if(that._disposed) { + _loadFromStore(loadOptions, pendingDeferred) { + const handleSuccess = (data, extra) => { + if(this._disposed) { return; } @@ -743,8 +564,15 @@ const DataSource = Class.inherit({ return; } - processResult(); - } + // Process result + const loadResult = extend(normalizeLoadResult(data, extra), loadOptions); + + this._eventsStrategy.fireEvent('customizeLoadResult', [loadResult]); + when(loadResult.data).done((data) => { + loadResult.data = data; + this._processStoreLoadResult(loadResult, pendingDeferred); + }).fail(pendingDeferred.reject); + }; if(loadOptions.data) { return new Deferred().resolve(loadOptions.data).done(handleSuccess); @@ -755,44 +583,42 @@ const DataSource = Class.inherit({ .fail(pendingDeferred.reject); }, - _processStoreLoadResult: function(loadResult, pendingDeferred) { - const that = this; + _processStoreLoadResult(loadResult, pendingDeferred) { let data = loadResult.data; let extra = loadResult.extra; const storeLoadOptions = loadResult.storeLoadOptions; - function resolvePendingDeferred() { - that._isLoaded = true; - that._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1; + const resolvePendingDeferred = () => { + this._isLoaded = true; + this._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1; return pendingDeferred.resolve(data, extra); - } - - function proceedLoadingTotalCount() { + }; - that.store().totalCount(storeLoadOptions) + const proceedLoadingTotalCount = () => { + this.store().totalCount(storeLoadOptions) .done(function(count) { extra.totalCount = count; resolvePendingDeferred(); }) .fail(pendingDeferred.reject); - } + }; - if(that._disposed) { + if(this._disposed) { return; } // todo: if operation is canceled there is no need to do data transformation - data = that._applyPostProcessFunction(that._applyMapFunction(data)); + data = this._applyPostProcessFunction(this._applyMapFunction(data)); - if(!typeUtils.isPlainObject(extra)) { + if(!isPlainObject(extra)) { extra = {}; } - that._items = data; + this._items = data; - if(!data.length || !that._paginate || (that._pageSize && (data.length < that._pageSize))) { - that._isLastPage = true; + if(!data.length || !this._paginate || (this._pageSize && (data.length < this._pageSize))) { + this._isLastPage = true; } if(storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount)) { @@ -802,7 +628,7 @@ const DataSource = Class.inherit({ } }, - _applyMapFunction: function(data) { + _applyMapFunction(data) { if(this._mapFunc) { return mapDataRespectingGrouping(data, this._mapFunc, this.group()); } @@ -810,7 +636,7 @@ const DataSource = Class.inherit({ return data; }, - _applyPostProcessFunction: function(data) { + _applyPostProcessFunction(data) { if(this._postProcessFunc) { return this._postProcessFunc(data); } @@ -828,7 +654,3 @@ const DataSource = Class.inherit({ return this; }, }); - -exports.DataSource = DataSource; -exports.normalizeDataSourceOptions = normalizeDataSourceOptions; -exports.normalizeLoadResult = normalizeLoadResult; diff --git a/js/data/data_source/operation_manager.js b/js/data/data_source/operation_manager.js new file mode 100644 index 000000000000..210055ffb5a6 --- /dev/null +++ b/js/data/data_source/operation_manager.js @@ -0,0 +1,34 @@ +import { CANCELED_TOKEN } from './utils'; + +export default class OperationManager { + constructor() { + this._counter = -1; + this._deferreds = {}; + } + + add(deferred) { + this._counter++; + this._deferreds[this._counter] = deferred; + return this._counter; + } + + remove(operationId) { + return delete this._deferreds[operationId]; + } + + cancel(operationId) { + if(operationId in this._deferreds) { + this._deferreds[operationId].reject(CANCELED_TOKEN); + return true; + } + + return false; + } + + cancelAll() { + while(this._counter > -1) { + this.cancel(this._counter); + this._counter--; + } + } +} diff --git a/js/data/data_source/utils.js b/js/data/data_source/utils.js new file mode 100644 index 000000000000..426eb6607c8e --- /dev/null +++ b/js/data/data_source/utils.js @@ -0,0 +1,124 @@ +import { sendRequest } from '../../core/utils/ajax'; +import Store from '../abstract_store'; +import ArrayStore from '../array_store'; +import { each, map } from '../../core/utils/iterator'; +import CustomStore from '../custom_store'; +import { extend } from '../../core/utils/extend'; +import { isPlainObject } from '../../core/utils/type'; +import { normalizeSortingInfo } from '../utils'; + +export const CANCELED_TOKEN = 'canceled'; + +export const isPending = deferred => deferred.state() === 'pending'; + +export const normalizeStoreLoadOptionAccessorArguments = (originalArguments) => { + switch(originalArguments.length) { + case 0: + return undefined; + case 1: + return originalArguments[0]; + } + return [].slice.call(originalArguments); +}; + +const mapGroup = (group, level, mapper) => map(group, item => { + const result = { + key: item.key, + items: mapRecursive(item.items, level - 1, mapper) + }; + if('aggregates' in item) { + result.aggregates = item.aggregates; + } + return result; +}); + +const mapRecursive = (items, level, mapper) => { + if(!Array.isArray(items)) return items; + return level ? mapGroup(items, level, mapper) : map(items, mapper); +}; + +export const mapDataRespectingGrouping = (items, mapper, groupInfo) => { + const level = groupInfo ? normalizeSortingInfo(groupInfo).length : 0; + + return mapRecursive(items, level, mapper); +}; + +export const normalizeLoadResult = (data, extra) => { + if(data?.data) { + extra = data; + data = data.data; + } + + if(!Array.isArray(data)) { + data = [data]; + } + + return { + data, + extra + }; +}; + +const createCustomStoreFromLoadFunc = (options) => { + const storeConfig = {}; + + each(['useDefaultSearch', 'key', 'load', 'loadMode', 'cacheRawData', 'byKey', 'lookup', 'totalCount', 'insert', 'update', 'remove'], function() { + storeConfig[this] = options[this]; + delete options[this]; + }); + + return new CustomStore(storeConfig); +}; + +const createStoreFromConfig = (storeConfig) => { + const alias = storeConfig.type; + + delete storeConfig.type; + + return Store.create(alias, storeConfig); +}; + +const createCustomStoreFromUrl = (url, normalizationOptions) => + new CustomStore({ + load: () => sendRequest({ url, dataType: 'json' }), + loadMode: normalizationOptions?.fromUrlLoadMode + }); + +export const normalizeDataSourceOptions = (options, normalizationOptions) => { + let store; + + if(typeof options === 'string') { + options = { + paginate: false, + store: createCustomStoreFromUrl(options, normalizationOptions) + }; + } + + if(options === undefined) { + options = []; + } + + if(Array.isArray(options) || options instanceof Store) { + options = { store: options }; + } else { + options = extend({}, options); + } + + if(options.store === undefined) { + options.store = []; + } + + store = options.store; + + if('load' in options) { + store = createCustomStoreFromLoadFunc(options); + } else if(Array.isArray(store)) { + store = new ArrayStore(store); + } else if(isPlainObject(store)) { + store = createStoreFromConfig(extend({}, store)); + } + + options.store = store; + + return options; +}; diff --git a/js/data_helper.js b/js/data_helper.js index 4a918574b048..a61ec486e174 100644 --- a/js/data_helper.js +++ b/js/data_helper.js @@ -1,6 +1,6 @@ const DataSource = require('./data/data_source/data_source').DataSource; const extend = require('./core/utils/extend').extend; -const normalizeDataSourceOptions = require('./data/data_source/data_source').normalizeDataSourceOptions; +const normalizeDataSourceOptions = require('./data/data_source/utils').normalizeDataSourceOptions; const DATA_SOURCE_OPTIONS_METHOD = '_dataSourceOptions'; const DATA_SOURCE_CHANGED_METHOD = '_dataSourceChangedHandler'; diff --git a/js/ui/collection/ui.collection_widget.edit.js b/js/ui/collection/ui.collection_widget.edit.js index ef21df6115cf..42a4bb83a37e 100644 --- a/js/ui/collection/ui.collection_widget.edit.js +++ b/js/ui/collection/ui.collection_widget.edit.js @@ -8,7 +8,8 @@ import { noop } from '../../core/utils/common'; import { isDefined } from '../../core/utils/type'; import PlainEditStrategy from './ui.collection_widget.edit.strategy.plain'; import { compileGetter } from '../../core/utils/data'; -import { DataSource, normalizeLoadResult } from '../../data/data_source/data_source'; +import { DataSource } from '../../data/data_source/data_source'; +import { normalizeLoadResult } from '../../data/data_source/utils'; import Selection from '../selection/selection'; import { when, Deferred, fromPromise } from '../../core/utils/deferred'; diff --git a/js/ui/grid_core/ui.grid_core.columns_controller.js b/js/ui/grid_core/ui.grid_core.columns_controller.js index 47f8093a6dea..12520778d3f8 100644 --- a/js/ui/grid_core/ui.grid_core.columns_controller.js +++ b/js/ui/grid_core/ui.grid_core.columns_controller.js @@ -21,7 +21,8 @@ import dateLocalization from '../../localization/date'; import messageLocalization from '../../localization/message'; import { when, Deferred } from '../../core/utils/deferred'; import Store from '../../data/abstract_store'; -import { DataSource, normalizeDataSourceOptions } from '../../data/data_source/data_source'; +import { DataSource } from '../../data/data_source/data_source'; +import { normalizeDataSourceOptions } from '../../data/data_source/utils'; import filterUtils from '../shared/filtering'; const USER_STATE_FIELD_NAMES_15_1 = ['filterValues', 'filterType', 'fixed', 'fixedPosition']; diff --git a/js/ui/grid_core/ui.grid_core.filter_custom_operations.js b/js/ui/grid_core/ui.grid_core.filter_custom_operations.js index 4de8bd625ee7..4b8075c113c7 100644 --- a/js/ui/grid_core/ui.grid_core.filter_custom_operations.js +++ b/js/ui/grid_core/ui.grid_core.filter_custom_operations.js @@ -3,7 +3,7 @@ import { renderValueText } from '../filter_builder/filter_builder'; const $ = require('../../core/renderer'); const messageLocalization = require('../../localization/message'); const extend = require('../../core/utils/extend').extend; -const DataSourceModule = require('../../data/data_source/data_source'); +const DataSource = require('../../data/data_source/data_source').DataSource; const deferredUtils = require('../../core/utils/deferred'); const utils = require('../filter_builder/utils'); @@ -57,7 +57,7 @@ function baseOperation(grid) { if(!headerFilterDataSource && lookup.items) { dataSourceOptions.store = lookup.items; } - const dataSource = new DataSourceModule.DataSource(dataSourceOptions); + const dataSource = new DataSource(dataSourceOptions); const result = new deferredUtils.Deferred(); dataSource.load().done(items => { diff --git a/js/ui/grid_core/ui.grid_core.header_filter.js b/js/ui/grid_core/ui.grid_core.header_filter.js index 52b3ccc13899..79135dee0867 100644 --- a/js/ui/grid_core/ui.grid_core.header_filter.js +++ b/js/ui/grid_core/ui.grid_core.header_filter.js @@ -10,7 +10,7 @@ import { each } from '../../core/utils/iterator'; import { isDefined, isObject, isFunction } from '../../core/utils/type'; import { getDefaultAlignment } from '../../core/utils/position'; import { extend } from '../../core/utils/extend'; -import { normalizeDataSourceOptions } from '../../data/data_source/data_source'; +import { normalizeDataSourceOptions } from '../../data/data_source/utils'; import dateLocalization from '../../localization/date'; import { isWrapped } from '../../core/utils/variable_wrapper'; import { Deferred } from '../../core/utils/deferred'; diff --git a/js/ui/pivot_grid/data_source.js b/js/ui/pivot_grid/data_source.js index 111132fd04b4..65d4c9821ad0 100644 --- a/js/ui/pivot_grid/data_source.js +++ b/js/ui/pivot_grid/data_source.js @@ -1,4 +1,4 @@ -import { normalizeDataSourceOptions } from '../../data/data_source/data_source'; +import { normalizeDataSourceOptions } from '../../data/data_source/utils'; import Store from '../../data/abstract_store'; import { executeAsync } from '../../core/utils/common'; import { isFunction, isNumeric, isDefined, isString, isPlainObject } from '../../core/utils/type'; diff --git a/js/ui/scheduler/ui.scheduler.resource_manager.js b/js/ui/scheduler/ui.scheduler.resource_manager.js index 21d98e81aad0..a7f085b2295a 100644 --- a/js/ui/scheduler/ui.scheduler.resource_manager.js +++ b/js/ui/scheduler/ui.scheduler.resource_manager.js @@ -7,8 +7,9 @@ import { extend } from '../../core/utils/extend'; import { inArray } from '../../core/utils/array'; import query from '../../data/query'; import dataCoreUtils from '../../core/utils/data'; -import DataSourceModule from '../../data/data_source/data_source'; +import { DataSource } from '../../data/data_source/data_source'; import { when, Deferred } from '../../core/utils/deferred'; +import { normalizeDataSourceOptions } from '../../data/data_source/utils'; const getValueExpr = resource => resource.valueExpr || 'id'; const getDisplayExpr = resource => resource.displayExpr || 'text'; @@ -20,11 +21,11 @@ export default class ResourceManager { } _wrapDataSource(dataSource) { - if(dataSource instanceof DataSourceModule.DataSource) { + if(dataSource instanceof DataSource) { return dataSource; } else { - return new DataSourceModule.DataSource({ - store: DataSourceModule.normalizeDataSourceOptions(dataSource).store, + return new DataSource({ + store: normalizeDataSourceOptions(dataSource).store, pageSize: 0 }); } diff --git a/js/ui/shared/ui.editor_factory_mixin.js b/js/ui/shared/ui.editor_factory_mixin.js index 91c29e127444..e92aa1367ff7 100644 --- a/js/ui/shared/ui.editor_factory_mixin.js +++ b/js/ui/shared/ui.editor_factory_mixin.js @@ -8,7 +8,7 @@ const browser = require('../../core/utils/browser'); const extend = require('../../core/utils/extend').extend; const devices = require('../../core/devices'); const getPublicElement = require('../../core/utils/dom').getPublicElement; -const normalizeDataSourceOptions = require('../../data/data_source/data_source').normalizeDataSourceOptions; +const normalizeDataSourceOptions = require('../../data/data_source/utils').normalizeDataSourceOptions; const normalizeKeyName = require('../../events/utils').normalizeKeyName; require('../text_box'); diff --git a/js/ui/tag_box.js b/js/ui/tag_box.js index e32e3d39cf89..12725b0d0014 100644 --- a/js/ui/tag_box.js +++ b/js/ui/tag_box.js @@ -17,7 +17,7 @@ import messageLocalization from '../localization/message'; import { addNamespace, normalizeKeyName } from '../events/utils'; import { name as clickEvent } from '../events/click'; import caret from './text_box/utils.caret'; -import { normalizeLoadResult } from '../data/data_source/data_source'; +import { normalizeLoadResult } from '../data/data_source/utils'; import SelectBox from './select_box'; import { BindableTemplate } from '../core/templates/bindable_template'; diff --git a/testing/tests/DevExpress.ui.widgets.scheduler/common.markup.tests.js b/testing/tests/DevExpress.ui.widgets.scheduler/common.markup.tests.js index 48ca67a39631..ae99dcabdb4a 100644 --- a/testing/tests/DevExpress.ui.widgets.scheduler/common.markup.tests.js +++ b/testing/tests/DevExpress.ui.widgets.scheduler/common.markup.tests.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import fx from 'animation/fx'; import dxScheduler from 'ui/scheduler/ui.scheduler'; -import DataSource from 'data/data_source/data_source'; +import { DataSource } from 'data/data_source/data_source'; import dateUtils from 'core/utils/date'; import dxSchedulerAppointmentModel from 'ui/scheduler/ui.scheduler.appointment_model'; @@ -54,7 +54,7 @@ QUnit.module('Scheduler markup', moduleConfig, () => { }); QUnit.test('Scheduler should not fail when dataSource is set', function(assert) { - const data = new DataSource.DataSource({ + const data = new DataSource({ store: this.tasks }); @@ -66,11 +66,11 @@ QUnit.module('Scheduler markup', moduleConfig, () => { }).dxScheduler('instance'); assert.ok(instance._appointmentModel instanceof dxSchedulerAppointmentModel, 'Task model is initialized on scheduler init'); - assert.ok(instance._appointmentModel._dataSource instanceof DataSource.DataSource, 'Task model has data source instance'); + assert.ok(instance._appointmentModel._dataSource instanceof DataSource, 'Task model has data source instance'); }); QUnit.test('Scheduler should not fail when dataSource is set, timelineView', function(assert) { - const data = new DataSource.DataSource({ + const data = new DataSource({ store: this.tasks }); @@ -82,11 +82,11 @@ QUnit.module('Scheduler markup', moduleConfig, () => { }).dxScheduler('instance'); assert.ok(instance._appointmentModel instanceof dxSchedulerAppointmentModel, 'Task model is initialized on scheduler init'); - assert.ok(instance._appointmentModel._dataSource instanceof DataSource.DataSource, 'Task model has data source instance'); + assert.ok(instance._appointmentModel._dataSource instanceof DataSource, 'Task model has data source instance'); }); QUnit.test('Scheduler should not fail when dataSource is set, timelineWeek', function(assert) { - const data = new DataSource.DataSource({ + const data = new DataSource({ store: this.tasks }); @@ -98,11 +98,11 @@ QUnit.module('Scheduler markup', moduleConfig, () => { }).dxScheduler('instance'); assert.ok(instance._appointmentModel instanceof dxSchedulerAppointmentModel, 'Task model is initialized on scheduler init'); - assert.ok(instance._appointmentModel._dataSource instanceof DataSource.DataSource, 'Task model has data source instance'); + assert.ok(instance._appointmentModel._dataSource instanceof DataSource, 'Task model has data source instance'); }); QUnit.test('Scheduler should not fail when dataSource is set, agenda', function(assert) { - const data = new DataSource.DataSource({ + const data = new DataSource({ store: this.tasks }); @@ -114,7 +114,7 @@ QUnit.module('Scheduler markup', moduleConfig, () => { }).dxScheduler('instance'); assert.ok(instance._appointmentModel instanceof dxSchedulerAppointmentModel, 'Task model is initialized on scheduler init'); - assert.ok(instance._appointmentModel._dataSource instanceof DataSource.DataSource, 'Task model has data source instance'); + assert.ok(instance._appointmentModel._dataSource instanceof DataSource, 'Task model has data source instance'); }); QUnit.test('Header & work space currentDate should not contain information about hours, minutes, seconds', function(assert) { diff --git a/testing/tests/DevExpress.viz.charts/chart.part1.tests.js b/testing/tests/DevExpress.viz.charts/chart.part1.tests.js index 68fa823799d2..33316ca46a6e 100644 --- a/testing/tests/DevExpress.viz.charts/chart.part1.tests.js +++ b/testing/tests/DevExpress.viz.charts/chart.part1.tests.js @@ -2,7 +2,7 @@ const $ = require('jquery'); const noop = require('core/utils/common').noop; const vizMocks = require('../../helpers/vizMocks.js'); const commons = require('./chartParts/commons.js'); -const dataSourceModule = require('data/data_source/data_source'); +const DataSource = require('data/data_source/data_source').DataSource; const BaseChart = require('viz/chart_components/base_chart').BaseChart; const rendererModule = require('viz/core/renderers/renderer'); const layoutManagerModule = require('viz/chart_components/layout_manager'); @@ -460,7 +460,7 @@ QUnit.test('hide on reinit', function(assert) { QUnit.test('not hide on reinit, when dataSource is not loaded', function(assert) { // arrange - const ds = new dataSourceModule.DataSource(); + const ds = new DataSource(); const chart = this.createChart({ dataSource: ds }); @@ -976,7 +976,7 @@ QUnit.module('isReady', $.extend({}, commons.environment, { })); QUnit.test('isReady with not loaded dataSource', function(assert) { - const ds = new dataSourceModule.DataSource(); + const ds = new DataSource(); ds.isLoaded = sinon.stub().returns(false); const chart = this.createChart({ dataSource: ds }); diff --git a/testing/tests/DevExpress.viz.charts/chart.tests.js b/testing/tests/DevExpress.viz.charts/chart.tests.js index d666fa9458ce..82a03f4cf0f3 100644 --- a/testing/tests/DevExpress.viz.charts/chart.tests.js +++ b/testing/tests/DevExpress.viz.charts/chart.tests.js @@ -14,8 +14,8 @@ const Legend = vizMocks.Legend; const ChartTitle = vizMocks.Title; const Axis = vizMocks.stubClass(axisModule.Axis); const Range = vizMocks.stubClass(rangeModule.Range); -const dataSourceModule = require('data/data_source/data_source'); -const DataSource = vizMocks.stubClass(dataSourceModule.DataSource); +const DataSource = require('data/data_source/data_source').DataSource; +const DataSourceMock = vizMocks.stubClass(DataSource); require('viz/chart'); @@ -184,7 +184,7 @@ QUnit.test('Creation dataSource', function(assert) { this.options = { dataSource: [{}], series: [{}] }; const chart = this.createChart(); - assert.ok(chart.getDataSource() instanceof dataSourceModule.DataSource, 'dataSource created'); + assert.ok(chart.getDataSource() instanceof DataSource, 'dataSource created'); }); QUnit.test('Loading dataSource', function(assert) { @@ -197,7 +197,7 @@ QUnit.test('Loading dataSource', function(assert) { }); QUnit.test('dataSource instance', function(assert) { - const dataSource = new DataSource(); + const dataSource = new DataSourceMock(); this.options = { dataSource: dataSource, series: [{}] }; const chart = this.createChart(); @@ -255,7 +255,7 @@ QUnit.test('update with null dataSource', function(assert) { }); QUnit.test('changed event', function(assert) { - const dataSource = new DataSource(); + const dataSource = new DataSourceMock(); this.options = { dataSource: dataSource, series: [{}] }; this.createChart(); @@ -266,7 +266,7 @@ QUnit.test('changed event', function(assert) { }); QUnit.test('loadError event', function(assert) { - const dataSource = new DataSource(); + const dataSource = new DataSourceMock(); this.options = { dataSource: dataSource, series: [{}] }; this.createChart(); @@ -277,7 +277,7 @@ QUnit.test('loadError event', function(assert) { }); QUnit.test('disposing', function(assert) { - const dataSource = new DataSource(); + const dataSource = new DataSourceMock(); this.options = { dataSource: dataSource, series: [{}] }; const chart = this.createChart(); diff --git a/testing/tests/DevExpress.viz.rangeSelector/common.part1.tests.js b/testing/tests/DevExpress.viz.rangeSelector/common.part1.tests.js index d03e5fdcc44c..8f67f9e2a78a 100644 --- a/testing/tests/DevExpress.viz.rangeSelector/common.part1.tests.js +++ b/testing/tests/DevExpress.viz.rangeSelector/common.part1.tests.js @@ -1,6 +1,6 @@ const $ = require('jquery'); const trackerModule = require('viz/range_selector/tracker'); -const dataSourceModule = require('data/data_source/data_source'); +const DataSource = require('data/data_source/data_source').DataSource; const seriesDataSourceModule = require('viz/range_selector/series_data_source'); const commons = require('./rangeSelectorParts/commons.js'); @@ -223,7 +223,7 @@ QUnit.test('Creation', function(assert) { const widget = this.createWidget({ dataSource: [1, 2, 3] }); const ds = widget.getDataSource(); - assert.ok(ds instanceof dataSourceModule.DataSource); + assert.ok(ds instanceof DataSource); assert.deepEqual(ds.items(), [1, 2, 3]); }); @@ -239,7 +239,7 @@ QUnit.module('isReady', $.extend({}, commons.environment, { })); QUnit.test('dataSource is not loaded', function(assert) { - const ds = new dataSourceModule.DataSource(); + const ds = new DataSource(); ds.isLoaded = sinon.stub().returns(false); const rangeSelector = this.createWidget({ dataSource: ds }); @@ -248,7 +248,7 @@ QUnit.test('dataSource is not loaded', function(assert) { }); QUnit.test('dataSource is loaded', function(assert) { - const ds = new dataSourceModule.DataSource(); + const ds = new DataSource(); ds.isLoaded = sinon.stub().returns(true); const rangeSelector = this.createWidget({ dataSource: ds }); diff --git a/testing/tests/DevExpress.viz.rangeSelector/common.part3.tests.js b/testing/tests/DevExpress.viz.rangeSelector/common.part3.tests.js index 9fe11c729f59..6753d4b50870 100644 --- a/testing/tests/DevExpress.viz.rangeSelector/common.part3.tests.js +++ b/testing/tests/DevExpress.viz.rangeSelector/common.part3.tests.js @@ -3,7 +3,7 @@ import baseWidgetModule from 'viz/core/base_widget'; import commons from './rangeSelectorParts/commons.js'; import slidersControllerModule from 'viz/range_selector/sliders_controller'; import seriesDataSourceModule from 'viz/range_selector/series_data_source'; -import dataSourceModule from 'data/data_source/data_source'; +import { DataSource } from 'data/data_source/data_source'; import dateLocalization from 'localization/date'; import axisModule from 'viz/axes/base_axis'; @@ -1660,7 +1660,7 @@ QUnit.test('dataSource creation', function(assert) { }); const ds = widget.getDataSource(); - assert.ok(ds instanceof dataSourceModule.DataSource); + assert.ok(ds instanceof DataSource); assert.ok(ds.isLoaded()); assert.deepEqual(ds.items(), [{}]); }); diff --git a/testing/tests/DevExpress.viz.sparklines/sparkline.tests.js b/testing/tests/DevExpress.viz.sparklines/sparkline.tests.js index af56cf628ff3..9aa99843bfa0 100644 --- a/testing/tests/DevExpress.viz.sparklines/sparkline.tests.js +++ b/testing/tests/DevExpress.viz.sparklines/sparkline.tests.js @@ -8,7 +8,7 @@ const rendererModule = require('viz/core/renderers/renderer'); const dataValidatorModule = require('viz/components/data_validator'); const translator2DModule = require('viz/translators/translator2d'); const seriesModule = require('viz/series/base_series'); -const dataSourceModule = require('data/data_source/data_source'); +const DataSource = require('data/data_source/data_source').DataSource; require('viz/sparkline'); @@ -2082,7 +2082,7 @@ QUnit.begin(function() { beforeEach: function() { environment.beforeEach.call(this); sinon.stub(BaseWidget.prototype, '_drawn', sinon.spy()); - this.data = new dataSourceModule.DataSource(); + this.data = new DataSource(); this.isLoadedStub = sinon.stub(this.data, 'isLoaded'); }, afterEach: function() { @@ -2127,7 +2127,7 @@ QUnit.begin(function() { }); QUnit.test('isReady with not loaded dataSource', function(assert) { - const data = new dataSourceModule.DataSource(); + const data = new DataSource(); sinon.stub(data, 'isLoaded', function() { return false; }); const sparkline = this.createSparkline({ dataSource: data }); @@ -2158,7 +2158,7 @@ QUnit.begin(function() { const widget = this.createSparkline({ dataSource: [1, 2, 3] }); const ds = widget.getDataSource(); - assert.ok(ds instanceof dataSourceModule.DataSource); + assert.ok(ds instanceof DataSource); assert.ok(ds.isLoaded()); assert.deepEqual(ds.items(), [1, 2, 3]); }); diff --git a/testing/tests/DevExpress.viz.vectorMap/mapLayer.tests.js b/testing/tests/DevExpress.viz.vectorMap/mapLayer.tests.js index bb709a013b05..8853ab1e5209 100644 --- a/testing/tests/DevExpress.viz.vectorMap/mapLayer.tests.js +++ b/testing/tests/DevExpress.viz.vectorMap/mapLayer.tests.js @@ -11,7 +11,7 @@ let stubSelectStrategy; let StubMapLayerElement; let StubProxy; const projectionModule = require('viz/vector_map/projection.main'); -const dataSourceModule = require('data/data_source/data_source'); +const DataSource = require('data/data_source/data_source').DataSource; const baseThemeManagerModule = require('viz/core/base_theme_manager'); const vizMocks = require('../../helpers/vizMocks.js'); @@ -140,7 +140,7 @@ QUnit.test('dataSource creation', function(assert) { this.layer.setOptions({ dataSource: [{}] }); assert.ok(this.layer.getDataSource(), 'getDataSource method is work'); - assert.ok(this.layer.getDataSource() instanceof dataSourceModule.DataSource); + assert.ok(this.layer.getDataSource() instanceof DataSource); assert.deepEqual(this.layer.getDataSource().items(), [{}], 'data source items'); }); @@ -225,8 +225,8 @@ QUnit.test('Set options with data, load error', function(assert) { const labelRoot = this.context.labelRoot = new vizMocks.Element(); this.context.grouping = { g1: 1, g2: 2 }; - const DataSource = vizMocks.stubClass(dataSourceModule.DataSource); - const ds = new DataSource(); + const DataSourceMock = vizMocks.stubClass(DataSource); + const ds = new DataSourceMock(); this.layer.setOptions({ dataSource: ds diff --git a/testing/tests/DevExpress.viz.vectorMap/mapLayer_new.tests.js b/testing/tests/DevExpress.viz.vectorMap/mapLayer_new.tests.js index c6d0c5976bef..60dc1161df2a 100644 --- a/testing/tests/DevExpress.viz.vectorMap/mapLayer_new.tests.js +++ b/testing/tests/DevExpress.viz.vectorMap/mapLayer_new.tests.js @@ -7,7 +7,7 @@ const controlBarModule = require('viz/vector_map/control_bar'); const legendModule = require('viz/vector_map/legend'); const tooltipModule = require('viz/core/tooltip'); const tooltipViewerModule = require('viz/vector_map/tooltip_viewer'); -const dataSourceModule = require('data/data_source/data_source'); +const DataSource = require('data/data_source/data_source').DataSource; const exportMenuModule = require('viz/core/export'); // TODO maybe if you test layer - you should create exact layer? const rendererModule = require('viz/core/renderers/renderer'); @@ -567,7 +567,7 @@ QUnit.test('getDataSource method', function(assert) { ]) }); - assert.ok(map.getLayers()[0].getDataSource() instanceof dataSourceModule.DataSource); + assert.ok(map.getLayers()[0].getDataSource() instanceof DataSource); }); QUnit.test('Bounds calculation', function(assert) {