UNPKG

igniteui-webcomponents-datasources

Version:

Reference custom data providers for the Ignite UI Web Components data source.

765 lines (764 loc) 34.2 kB
import { AsyncVirtualDataSourceProviderWorker } from "igniteui-webcomponents-core"; import { SortDescriptionCollection } from "igniteui-webcomponents-core"; import { RestVirtualDataSourceProviderTaskDataHolder } from "./RestVirtualDataSourceProviderTaskDataHolder"; import { AsyncDataSourcePageTaskHolder } from "igniteui-webcomponents-core"; import { AsyncVirtualDataTask } from "igniteui-webcomponents-core"; import { RestVirtualDataSourcePage } from "./RestVirtualDataSourcePage"; import { DefaultSectionInformation } from "igniteui-webcomponents-core"; import { Convert } from "igniteui-webcomponents-core"; import { ODataDataSourceFilterExpressionVisitor } from "igniteui-webcomponents-core"; import { ListSortDirection } from "igniteui-webcomponents-core"; import { stringIsNullOrEmpty } from "igniteui-webcomponents-core"; import { DataSourceSummaryOperand } from "igniteui-webcomponents-core"; import { DataSourceSummaryScope } from "igniteui-webcomponents-core"; import { DefaultSummaryResult } from "igniteui-webcomponents-core"; import { LocalDataSource } from "igniteui-webcomponents-core"; import { DefaultDataSourceSchema } from "igniteui-webcomponents-core"; export let RestVirtualDataSourceDataProviderWorker = /*@__PURE__*/ (() => { class RestVirtualDataSourceDataProviderWorker extends AsyncVirtualDataSourceProviderWorker { get sortDescriptions() { return this._sortDescriptions; } get filterExpressions() { return this._filterExpressions; } get desiredProperties() { return this._desiredPropeties; } initialize() { super.initialize(); } getTaskDataHolder() { let holder = new RestVirtualDataSourceProviderTaskDataHolder(); return holder; } getCompletedTaskData(holder, completed) { super.getCompletedTaskData(holder, completed); } removeCompletedTaskData(holder, completed) { super.removeCompletedTaskData(holder, completed); } getTasksData(holder) { super.getTasksData(holder); } *iter(coll) { for (let i = 0; i < coll.size(); i++) { yield coll.get(i); } } *iterFilter(coll) { for (let i = 0; i < coll.size(); i++) { yield coll.get(i); } } *iterSummaries(summaries) { for (let i = 0; i < summaries.size(); i++) { yield summaries.get(i); } } constructor(settings) { super(settings); this._baseUri = null; this._entitySet = null; this._sortDescriptions = null; this._groupDescriptions = null; this._filterExpressions = null; this._summaryDescriptions = null; this._desiredPropeties = null; this._schemaIncludedProperties = null; this._enableJsonp = true; this._isAggregationSupported = false; this._provideFullCount = null; this._provideOrderByParameter = null; this._provideFilterParameter = null; this._provideAggregationParameter = null; this._provideAggregatedCount = null; this._providePagingParameter = null; this._provideDesiredPropertiesParameter = null; this._provideUri = null; this._performFetch = null; this._fixedFullCount = -1; this._groupInformation = null; this._summaryInformation = null; this._filterString = null; this._selectedString = null; this.doWork = this.doWork.bind(this); this._baseUri = settings.baseUri; this._entitySet = settings.entitySet; this._sortDescriptions = settings.sortDescriptions; this._groupDescriptions = settings.groupDescriptions; if (this._groupDescriptions != null && this._groupDescriptions.size() > 0) { this._sortDescriptions = new SortDescriptionCollection(); for (let sd of this.iter(settings.sortDescriptions)) { this._sortDescriptions.add(sd); } for (let i = 0; i < this._groupDescriptions.size(); i++) { this._sortDescriptions.insert(i, this._groupDescriptions.get(i)); } } this._filterExpressions = settings.filterExpressions; this._desiredPropeties = settings.propertiesRequested; if (settings.schemaIncludedProperties != null) { this._schemaIncludedProperties = new Set(); for (let i = 0; i < settings.schemaIncludedProperties.length; i++) { this._schemaIncludedProperties.add(settings.schemaIncludedProperties[i]); } } this._summaryDescriptions = settings.summaryDescriptions; this._fixedFullCount = settings.fixedFullCount; this._summaryScope = settings.summaryScope; this._enableJsonp = settings.enableJsonp; this._provideFullCount = settings.provideFullCount; this._performFetch = settings.performFetch; this._provideAggregationParameter = settings.provideAggregationParameter; this._provideFilterParameter = settings.provideFilterParameter; this._provideOrderByParameter = settings.provideOrderByParameter; this._provideUri = settings.provideUri; this._providePagingParameter = settings.providePagingParameter; this._provideDesiredPropertiesParameter = settings.provideDesiredPropertiesParameter; this._provideItems = settings.provideItems; this._provideAggregatedCount = settings.provideAggregatedCount; if (!this._provideItems) { this._provideItems = (res) => { return res ? res.items : null; }; } if (!this._provideFullCount) { this._provideFullCount = (p) => { if (p.fullCount) { return p.fullCount; } else { return this._fixedFullCount >= 0 ? this._fixedFullCount : 0; } }; } if (!this._provideOrderByParameter) { this._provideOrderByParameter = (args, orderByString, orderBy) => { args.push({ name: "orderBy", value: encodeURIComponent(orderByString) }); }; } if (!this._providePagingParameter) { this._providePagingParameter = (args, skip, take) => { args.push({ name: "skip", value: skip }); args.push({ name: "take", value: take }); }; } if (!this._provideAggregationParameter) { this._provideAggregationParameter = (args, fetchCountOnly, groupByString, groupBy, summaryString, summary) => { args.push({ name: "groupBy", value: groupByString }); args.push({ name: "aggregate", value: "count" }); }; } if (!this._provideUri) { this._provideUri = (baseUri, entitySet, args) => { let requestUri = baseUri; requestUri += "/" + entitySet; if (args.length > 0) { requestUri += "?"; } let argsString = ""; for (var i = 0; i < args.length; i++) { if (i > 0) { argsString += "&"; } argsString += args[i].name + "=" + args[i].value; } return requestUri + argsString; }; } this._isAggregationSupported = settings.isAggregationSupported; window.setTimeout(this.doWork, 100); } processCompletedTask(completedTask, currentDelay, pageIndex, taskDataHolder) { let h = taskDataHolder; let schema = null; let result = null; let schemaFetchCount = -1; let task = completedTask.task; try { if (task.hasErrors) { this.retryIndex(pageIndex, currentDelay); return; } if (pageIndex == RestVirtualDataSourceDataProviderWorker.schemaRequestIndex) { result = task.result; schemaFetchCount = (this._provideFullCount(result)); } else { result = task.result; } } catch (e) { this.retryIndex(pageIndex, currentDelay); return; } if (schemaFetchCount >= 0) { this.actualCount = schemaFetchCount; } else { this.actualCount = (this._provideFullCount(result)); } schema = this.actualSchema; if (schema == null) { let requests = 0; this.resolveSchema((s) => { // resolveSchema success callback this.actualSchema = s; if (this._isAggregationSupported && (this._groupDescriptions.size() !== 0 || this._summaryDescriptions.size() !== 0)) { if (this._groupDescriptions.size() > 0) { requests++; this.resolveGroupInformation((g) => { // group info success requests--; if (requests === 0) { this.finishProcessingCompletedTask(task, pageIndex, s, result); } }, () => { // group info failure this.retryIndex(pageIndex, currentDelay); return; }); } if (this._summaryDescriptions.size() > 0) { requests++; this.resolveSummaryInformation((g) => { // summary info success requests--; if (requests === 0) { this.finishProcessingCompletedTask(task, pageIndex, s, result); } }, () => { // summary info failure this.retryIndex(pageIndex, currentDelay); return; }); } } else { this.finishProcessingCompletedTask(task, pageIndex, s, result); } }, () => { // resolveSchema failure callback this.retryIndex(pageIndex, currentDelay); return; }); return; } this.finishProcessingCompletedTask(task, pageIndex, schema, result); } finishProcessingCompletedTask(task, pageIndex, schema, result) { let executionContext; let pageLoaded; let groupInformation; let summaryInformation; this.actualSchema = schema; executionContext = this.executionContext; groupInformation = this._groupInformation; summaryInformation = this._summaryInformation; pageLoaded = this.pageLoaded; let page = null; if (result != null) { page = new RestVirtualDataSourcePage(result, schema, groupInformation, summaryInformation, pageIndex); if (!this.isLastPage(pageIndex) && page.count() > 0 && !this.populatedActualPageSize) { this.populatedActualPageSize = true; this.actualPageSize = page.count(); } } else { page = new RestVirtualDataSourcePage(null, schema, groupInformation, summaryInformation, pageIndex); } if (this.pageLoaded != null) { if (this.executionContext != null) { if (executionContext == null || pageLoaded == null) { this.shutdown(); return; } executionContext.execute(() => pageLoaded(page, this.actualCount, this.actualPageSize)); } else { if (pageLoaded == null) { this.shutdown(); return; } pageLoaded(page, this.actualCount, this.actualPageSize); } } } resolveGroupInformation(finishAction, failureAction) { if (this._groupInformation != null) { finishAction(this._groupInformation); return; } let orderBy = ""; let groupBy = ""; let filter = null; let summary = ""; if (this._groupDescriptions == null || this._groupDescriptions.size() == 0) { finishAction(null); return; } if (this._provideAggregationParameter == null) { finishAction(null); return; } filter = this._filterString; this.updateFilterString(); if (this._groupDescriptions != null) { let first1 = true; for (let group of this.iter(this._groupDescriptions)) { if (first1) { first1 = false; } else { orderBy += ", "; groupBy += ", "; } groupBy += group.propertyName; if (group.direction === ListSortDirection.Descending) { orderBy += group.propertyName + " desc"; } else { orderBy += group.propertyName + " asc"; } } } if (this._summaryScope === DataSourceSummaryScope.Both || this._summaryScope === DataSourceSummaryScope.Groups) { let summaryParameters = this.getSummaryQueryParameters(true); if (!stringIsNullOrEmpty(summaryParameters)) { summary = ", " + summaryParameters; } } let args = []; if (this._provideOrderByParameter) { this._provideOrderByParameter(args, orderBy, this._groupDescriptions); } if (this._provideFilterParameter && filter != null) { this._provideFilterParameter(args, filter, this._filterExpressions); } if (this._provideAggregationParameter) { this._provideAggregationParameter(args, true, groupBy, this._groupDescriptions, summary, this._summaryDescriptions); } var uri = this._provideUri(this._baseUri, this._entitySet, args); try { let groupInformation = []; let success_ = (data, response) => this.groupSuccess(data, response, finishAction, failureAction, groupInformation); let failure_ = (err) => this.groupError(err, finishAction, failureAction, groupInformation); let run_ = null; var headers = { 'Content-Type': 'application/json', Accept: 'application/json' }; var request = { requestUri: uri, enableJsonpCallback: this._enableJsonp, method: 'GET', headers: headers, data: null }; run_ = () => { this.fetchUri(request, success_, failure_); }; run_(); } catch (e) { failureAction(); } } fetchUri(request, success, failure) { if (this._performFetch) { this._performFetch(request, success, failure); } else { fetch(request.requestUri, { method: request.method, headers: request.headers, }).then((res) => { res.json().then((j) => { success(j, res); }); }).catch((e) => { failure(e); }); } } groupError(err, finishAction, failureAction, groupInformation) { this._groupInformation = null; } groupSuccess(data, response, finishAction, failureAction, groupInformation) { let groupNames = []; for (let group of this.iter(this._groupDescriptions)) { groupNames.push(group.propertyName); } let groupNamesArray = groupNames; let items = this._provideItems(data); if (items && items.length > 0) { let currentIndex = 0; for (let i = 0; i < items.length; i++) { this.addGroup(groupInformation, groupNames, groupNames, currentIndex, items[i]); } } this._groupInformation = groupInformation; finishAction(this._groupInformation); } addGroup(groupInformation, groupNames, groupNamesArray, currentIndex, group) { let groupValues = []; for (let name of groupNames) { if (group[name]) { groupValues.push(group[name]); } } let groupCount = 0; //todo: make this customizable if (this._provideAggregatedCount) { let ct = this._provideAggregatedCount(group); } else { if (group["aggregatedCount"]) { groupCount = Convert.toInt321(group["aggregatedCount"]); } } let summaryResults = null; if (this._summaryScope == DataSourceSummaryScope.Both || this._summaryScope == DataSourceSummaryScope.Groups) { summaryResults = this.createSummaryResults(group); } let groupInfo = new DefaultSectionInformation(currentIndex, currentIndex + (groupCount - 1), groupNamesArray, groupValues, summaryResults); groupInformation.push(groupInfo); } resolveSummaryInformation(finishAction, failureAction) { if (this._summaryInformation != null) { finishAction(this._summaryInformation); return; } let filter = null; let summary = null; if (this._summaryDescriptions == null || this._summaryDescriptions.size() == 0 || this._summaryScope == DataSourceSummaryScope.Groups || this._summaryScope == DataSourceSummaryScope.None) { finishAction(null); return; } filter = this._filterString; this.updateFilterString(); summary = this.getSummaryQueryParameters(false); let args = []; // if (this._provideOrderByParameter) { // args.push({ name: "orderBy", value: this._provideOrderByParameter(orderBy, this._sortDescriptions) }); // } if (this._provideFilterParameter && filter != null) { this._provideFilterParameter(args, filter, this._filterExpressions); } if (this._provideAggregationParameter) { this._provideAggregationParameter(args, true, null, null, summary, this._summaryDescriptions); } var uri = this._provideUri(this._baseUri, this._entitySet, args); // let commandText = this._entitySet + "?$apply="; // if (!stringIsNullOrEmpty(filter)) { // commandText += "filter(" + filter + ")/"; // } // commandText += "aggregate(" + summary + ")"; try { let summaryInformation = []; let success_ = (data, response) => this.summarySuccess(data, response, finishAction, failureAction, summaryInformation); let failure_ = (err) => this.summaryError(err, finishAction, failureAction, summaryInformation); let run_ = null; var headers = { 'Content-Type': 'application/json', Accept: 'application/json' }; var request = { requestUri: uri, enableJsonpCallback: this._enableJsonp, method: 'GET', headers: headers, data: null }; run_ = () => { this.fetchUri(request, success_, failure_); }; run_(); } catch (e) { failureAction(); } } summarySuccess(data, response, finishAction, failureAction, summaryInformation) { if (data && data.value && data.value.length > 0) { summaryInformation = this.createSummaryResults(data.value[0]); } this._summaryInformation = summaryInformation; finishAction(this._summaryInformation); } summaryError(err, finishAction, failureAction, summaryInformation) { this._summaryInformation = null; } getSummaryQueryParameters(ignoreCount) { let result = ""; if (this._summaryDescriptions != null) { let first = true; let countExists = false; for (let summary of this.iterSummaries(this._summaryDescriptions)) { if (summary.operand == DataSourceSummaryOperand.Count && (ignoreCount || countExists)) { continue; } if (!first) { result += ", "; } switch (summary.operand) { case DataSourceSummaryOperand.Average: result += summary.propertyName + " with average as " + summary.propertyName + "Average"; break; case DataSourceSummaryOperand.Min: result += summary.propertyName + " with min as " + summary.propertyName + "Min"; break; case DataSourceSummaryOperand.Max: result += summary.propertyName + " with max as " + summary.propertyName + "Max"; break; case DataSourceSummaryOperand.Sum: result += summary.propertyName + " with sum as " + summary.propertyName + "Sum"; break; case DataSourceSummaryOperand.Count: result += "$count as $__count"; countExists = true; break; } first = false; } } return result; } createSummaryResults(data) { let summaryResults = []; for (let summary of this.iterSummaries(this._summaryDescriptions)) { let summaryName = summary.propertyName; switch (summary.operand) { case DataSourceSummaryOperand.Average: summaryName += "Average"; break; case DataSourceSummaryOperand.Min: summaryName += "Min"; break; case DataSourceSummaryOperand.Max: summaryName += "Max"; break; case DataSourceSummaryOperand.Sum: summaryName += "Sum"; break; case DataSourceSummaryOperand.Count: summaryName = "$__count"; break; } let summaryValue = null; if (data && data[summaryName]) { summaryValue = data[summaryName]; } let summaryResult = new DefaultSummaryResult(summary.propertyName, summary.operand, summaryValue); summaryResults.push(summaryResult); } return summaryResults; } resolveSchemaFromItems(items) { let lds = new LocalDataSource(); lds.dataSource = items; lds.flushAutoRefresh(); return lds.actualSchema; } resolveSchema(finishAction, failureAction) { if (!this._provideItems || !this._providePagingParameter) { failureAction("required providers for items and paging are not specified"); return; } let success_ = (res) => { let items = this._provideItems(res); if (items && items.length > 0) { let schema = this.resolveSchemaFromItems(items); if (this._schemaIncludedProperties != null) { let propertyNames = []; let propertyTypes = []; for (let i = 0; i < schema.propertyNames.length; i++) { if (!this._schemaIncludedProperties.has(schema.propertyNames[i])) { continue; } propertyNames.push(schema.propertyNames[i]); propertyTypes.push(schema.propertyTypes[i]); } schema = new DefaultDataSourceSchema(propertyNames, propertyTypes, schema.primaryKey, schema.propertyDataIntents, schema.subSchemas); } finishAction(schema); } else { failureAction("could not find items to resolve schema"); } }; let failure_ = (e) => failureAction(e); let args = []; if (this._providePagingParameter) { this._providePagingParameter(args, 0, this.actualPageSize); } let uri = this._provideUri(this._baseUri, this._entitySet, args); try { let run_ = null; var headers = { 'Content-Type': 'application/json', Accept: 'application/json' }; var request = { requestUri: uri, enableJsonpCallback: this._enableJsonp, method: 'GET', headers: headers, data: null }; run_ = () => { this.fetchUri(request, success_, failure_); }; run_(); } catch (e) { failureAction(e); } } makeTaskForRequest(request, retryDelay) { let args = []; // if (this._provideAggregationParameter) { // args.push({ name: "apply", value: this._provideAggregationParameter(true, groupBy, this._groupDescriptions, summary, this._summaryDescriptions) }); // } let actualPageSize = 0; let sortDescriptions = null; actualPageSize = this.actualPageSize; sortDescriptions = this.sortDescriptions; //let requestUrl: string = this._baseUri; //requestUrl += "/" + this._entitySet; let queryStarted = false; this.updateFilterString(); if (this._filterString != null) { if (this._provideFilterParameter) { this._provideFilterParameter(args, this._filterString, this._filterExpressions); } } if (this.sortDescriptions != null) { let sortString = null; for (let sort of this.iter(this.sortDescriptions)) { if (sortString == null) { sortString = ""; } else { sortString += ", "; } if (sort.direction == ListSortDirection.Descending) { sortString += sort.propertyName + " desc"; } else { sortString += sort.propertyName; } } if (sortString != null) { if (this._provideOrderByParameter) { this._provideOrderByParameter(args, sortString, this._sortDescriptions); } } } if (this.desiredProperties != null && this.desiredProperties.length > 0) { let selectString = ""; let first = true; let $t = this.desiredProperties; for (let i = 0; i < $t.length; i++) { let select = $t[i]; if (first) { first = false; } else { selectString += ", "; } selectString += select; } if (this._provideDesiredPropertiesParameter) { this._provideDesiredPropertiesParameter(args, selectString, this._desiredPropeties); } } if (this._providePagingParameter) { if (request.index == RestVirtualDataSourceDataProviderWorker.schemaRequestIndex) { this._providePagingParameter(args, 0, actualPageSize); } else { this._providePagingParameter(args, request.index * actualPageSize, actualPageSize); } } let task = new AsyncVirtualDataTask(); let uri = this._provideUri(this._baseUri, this._entitySet, args); if (request.index == RestVirtualDataSourceDataProviderWorker.schemaRequestIndex) { this.executeRequest(uri, queryStarted, 0, actualPageSize, task); } else { this.executeRequest(uri, queryStarted, request.index * actualPageSize, actualPageSize, task); } request.taskHolder = new AsyncDataSourcePageTaskHolder(); request.taskHolder.task = task; this.tasks.add(request); } updateFilterString() { if (this.filterExpressions != null && this.filterExpressions.size() > 0 && this._filterString == null) { let sb = ""; let first = true; for (let expr of this.iterFilter(this.filterExpressions)) { if (first) { first = false; } else { sb += " AND "; } let visitor = new ODataDataSourceFilterExpressionVisitor(0); visitor.visit(expr); let txt = visitor.toString(); if (this.filterExpressions.size() > 1) { txt = "(" + txt + ")"; } sb += (txt); } this._filterString = sb; } } executeRequest(requestUrl, queryStarted, skip, top, task) { // if (!queryStarted) { // queryStarted = true; // requestUrl += "?"; // } else { // requestUrl += "&"; // } // requestUrl += "$skip=" + skip + "&$top=" + top + "&$count=true"; let requestUrl_ = requestUrl; let self_ = this; let success_ = (data, response) => this.success(task, data, response); let failure_ = (err) => this.error(task, err); let run_ = null; var headers = { 'Content-Type': 'application/json', Accept: 'application/json' }; var request = { requestUri: requestUrl_, enableJsonpCallback: this._enableJsonp, method: 'GET', headers: headers, data: null }; run_ = () => { this.fetchUri(request, success_, failure_); }; task.run = run_; } success(t, data, response) { t.result = data; t.isCompleted = true; } error(t, result) { t.isCompleted = true; t.hasErrors = true; } createBatchRequest(changes) { //TODO: updates } getRequestUriWithKey(key) { let result = ""; const keys = Object.keys(key); for (let i = 0; i < keys.length; i++) { if (i > 0) { result += ","; } result += `${keys[i]}=${key[keys[i]]}`; } return `${this._entitySet}(${result})`; } } RestVirtualDataSourceDataProviderWorker.schemaRequestIndex = -1; return RestVirtualDataSourceDataProviderWorker; })();