2018-05-31 09:52:39 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-06-07 21:47:19 +00:00
|
|
|
get isLoading() {
|
|
|
|
return this.canceler != null;
|
|
|
|
}
|
|
|
|
|
2018-05-31 09:52:39 +00:00
|
|
|
$onInit() {
|
|
|
|
if (this.autoLoad)
|
|
|
|
this.refresh();
|
|
|
|
}
|
|
|
|
|
2018-07-06 14:32:23 +00:00
|
|
|
refresh(usFilter) {
|
2018-05-31 09:52:39 +00:00
|
|
|
if (!this.url) return;
|
|
|
|
|
2018-06-07 21:47:19 +00:00
|
|
|
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
|
2018-06-07 21:47:19 +00:00
|
|
|
};
|
|
|
|
|
2018-05-31 09:52:39 +00:00
|
|
|
let filter = this.filter;
|
2018-06-07 21:47:19 +00:00
|
|
|
filter = mergeFilters(myFilter, filter);
|
|
|
|
filter = mergeFilters(usFilter, filter);
|
|
|
|
return this.sendRequest(filter);
|
|
|
|
}
|
2018-05-31 09:52:39 +00:00
|
|
|
|
2018-06-07 21:47:19 +00:00
|
|
|
cancelRequest() {
|
|
|
|
if (this.canceler) {
|
|
|
|
this.canceler.resolve();
|
|
|
|
this.canceler = null;
|
2018-05-31 09:52:39 +00:00
|
|
|
}
|
2018-06-07 21:47:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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(
|
2018-06-07 21:47:19 +00:00
|
|
|
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();
|
|
|
|
}
|
2018-05-31 09:52:39 +00:00
|
|
|
|
2018-06-07 21:47:19 +00:00
|
|
|
onRemoteError(err) {
|
|
|
|
this.onRequestEnd();
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
onRequestEnd() {
|
|
|
|
this.canceler = null;
|
|
|
|
}
|
2018-05-31 09:52:39 +00:00
|
|
|
|
2018-06-07 21:47:19 +00:00
|
|
|
loadMore() {
|
|
|
|
if (this.moreRows) {
|
|
|
|
let filter = Object.assign({}, this.currentFilter);
|
|
|
|
filter.skip = (filter.skip || 0) + filter.limit;
|
|
|
|
this.sendRequest(filter, true);
|
|
|
|
}
|
2018-05-31 09:52:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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() {
|
2018-05-31 09:52:39 +00:00
|
|
|
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: '&?',
|
2018-05-31 09:52:39 +00:00
|
|
|
fields: '<?',
|
|
|
|
link: '<?',
|
|
|
|
url: '@?',
|
|
|
|
saveUrl: '@?',
|
|
|
|
where: '<?',
|
|
|
|
include: '<?',
|
|
|
|
order: '@?',
|
|
|
|
limit: '<?',
|
|
|
|
filter: '<?',
|
2018-07-09 16:06:25 +00:00
|
|
|
userParams: '<?',
|
2018-05-31 09:52:39 +00:00
|
|
|
primaryKey: '@?',
|
|
|
|
autoLoad: '<?'
|
|
|
|
}
|
|
|
|
});
|
2018-06-07 21:47:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|