salix/client/core/src/components/rest-model/crud-model.js

237 lines
5.4 KiB
JavaScript
Raw Normal View History

import ngModule from '../../module';
import ModelProxy from '../model-proxy/model-proxy';
export default class CrudModel extends ModelProxy {
constructor($http, $q) {
super();
this.$http = $http;
this.$q = $q;
this.primaryKey = 'id';
this.autoLoad = true;
}
get isLoading() {
return this.canceler != null;
}
$onInit() {
if (this.autoLoad)
this.refresh();
}
2018-07-06 14:32:23 +00:00
refresh(usFilter) {
if (!this.url) return;
let myFilter = {
fields: this.fields,
where: mergeWhere(this.link, this.where),
include: this.include,
order: this.order,
2018-07-09 16:06:25 +00:00
limit: this.limit
};
let filter = this.filter;
filter = mergeFilters(myFilter, filter);
filter = mergeFilters(usFilter, filter);
return this.sendRequest(filter);
}
cancelRequest() {
if (this.canceler) {
this.canceler.resolve();
this.canceler = null;
}
}
sendRequest(filter, append) {
this.cancelRequest();
this.canceler = this.$q.defer();
2018-07-06 14:32:23 +00:00
let options = {
timeout: this.canceler.promise,
params: {filter: filter}
};
if (this.userParams instanceof Object)
Object.assign(options.params, this.userParams);
return this.$http.get(this.url, options).then(
json => this.onRemoteDone(json, filter, append),
json => this.onRemoteError(json)
);
}
onRemoteDone(json, filter, append) {
let data = json.data;
if (append)
this.orgData = this.orgData.concat(data);
else
this.orgData = data;
this.currentFilter = filter;
this.moreRows = filter.limit && data.length == filter.limit;
this.onRequestEnd();
this.dataChanged();
}
onRemoteError(err) {
this.onRequestEnd();
throw err;
}
onRequestEnd() {
this.canceler = null;
}
loadMore() {
if (this.moreRows) {
let filter = Object.assign({}, this.currentFilter);
filter.skip = (filter.skip || 0) + filter.limit;
this.sendRequest(filter, true);
}
}
getChanges() {
let create = [];
let update = [];
let remove = [];
for (let row of this.removed)
remove.push(row.$data[this.primaryKey]);
for (let row of this._data) {
if (row.$isNew)
create.push(row.$data);
else if (row.$oldData)
update.push(row.$data);
}
let isChanged =
create.length > 0 ||
update.length > 0 ||
remove.length > 0;
if (!isChanged)
return null;
let changes = {
create: create,
update: update,
delete: remove
};
return changes;
}
2018-07-06 14:32:23 +00:00
save() {
let changes = this.getChanges();
if (!changes)
return this.$q.resolve();
let url = this.saveUrl ? this.saveUrl : `${this.url}/crud`;
return this.$http.post(url, changes)
.then(() => this.resetChanges);
}
}
CrudModel.$inject = ['$http', '$q'];
ngModule.component('vnCrudModel', {
controller: CrudModel,
bindings: {
orgData: '<?',
data: '=?',
2018-07-02 09:52:50 +00:00
onDataChange: '&?',
fields: '<?',
link: '<?',
url: '@?',
saveUrl: '@?',
where: '<?',
include: '<?',
order: '@?',
limit: '<?',
filter: '<?',
2018-07-09 16:06:25 +00:00
userParams: '<?',
primaryKey: '@?',
autoLoad: '<?'
}
});
/**
* Passes a loopback fields filter to an object.
*
* @param {Object} fields The fields object or array
* @return {Object} The fields as object
*/
function fieldsToObject(fields) {
let fieldsObj = {};
if (Array.isArray(fields))
for (let field of fields)
fieldsObj[field] = true;
else if (typeof fields == 'object')
for (let field in fields)
if (fields[field])
fieldsObj[field] = true;
return fieldsObj;
}
/**
* Merges two loopback fields filters.
*
* @param {Object|Array} src The source fields
* @param {Object|Array} dst The destination fields
* @return {Array} The merged fields as an array
*/
function mergeFields(src, dst) {
let fields = {};
Object.assign(fields,
fieldsToObject(src),
fieldsToObject(dst)
);
return Object.keys(fields);
}
/**
* Merges two loopback where filters.
*
* @param {Object|Array} src The source where
* @param {Object|Array} dst The destination where
* @return {Array} The merged wheres
*/
function mergeWhere(src, dst) {
let and = [];
if (src) and.push(src);
if (dst) and.push(dst);
return and.length > 1 ? {and} : and[0];
}
/**
* Merges two loopback filters returning the merged filter.
*
* @param {Object} src The source filter
* @param {Object} dst The destination filter
* @return {Object} The result filter
*/
function mergeFilters(src, dst) {
let res = Object.assign({}, dst);
if (!src)
return res;
if (src.fields)
res.fields = mergeFields(src.fields, res.fields);
if (src.where)
res.where = mergeWhere(res.where, src.where);
if (src.include)
res.include = src.include;
if (src.order)
res.order = src.order;
if (src.limit)
res.limit = src.limit;
return res;
}