1068 lines
28 KiB
JavaScript
1068 lines
28 KiB
JavaScript
/*
|
|
* Axelor Business Solutions
|
|
*
|
|
* Copyright (C) 2005-2019 Axelor (<http://axelor.com>).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
(function() {
|
|
|
|
"use strict";
|
|
|
|
var extend = angular.extend,
|
|
isArray = angular.isArray,
|
|
isObject = angular.isObject,
|
|
forEach = angular.forEach,
|
|
push = [].push;
|
|
|
|
var ds = angular.module('axelor.ds');
|
|
|
|
ds.factory('DataSource', ['$injector', '$rootScope', '$http', '$q', '$exceptionHandler', function($injector, $rootScope, $http, $q, $exceptionHandler) {
|
|
|
|
function DataSource(model, options) {
|
|
|
|
var opts = extend({
|
|
limit : DataSource.DEFAULT_LIMIT,
|
|
domain : null,
|
|
context : null
|
|
}, options);
|
|
|
|
this._model = model;
|
|
this._domain = opts.domain;
|
|
this._context = opts.context;
|
|
|
|
this._filter = null;
|
|
this._sortBy = null;
|
|
this._lastDomain = null;
|
|
this._lastContext = null;
|
|
this._lastAction = null;
|
|
this._showArchived = opts.archived;
|
|
|
|
if (opts.archived === undefined && _.has(opts.params || {}, 'showArchived')) {
|
|
this._showArchived = opts.params.showArchived;
|
|
}
|
|
|
|
this._data = [];
|
|
|
|
this._page = {
|
|
index : 0,
|
|
from : 0,
|
|
to : 0,
|
|
size : 0,
|
|
total : 0,
|
|
limit : opts.limit
|
|
};
|
|
|
|
this._listeners = {};
|
|
}
|
|
|
|
DataSource.DEFAULT_LIMIT = 40;
|
|
|
|
DataSource.prototype = {
|
|
|
|
constructor: DataSource,
|
|
|
|
_http: $http,
|
|
|
|
_request: function(action, id) {
|
|
var url = 'ws/rest/' + this._model;
|
|
if (id) url += '/' + id;
|
|
if (action) url += '/' + action;
|
|
|
|
return {
|
|
get: function(data, config) {
|
|
return $http.get(url, data, config);
|
|
},
|
|
post: function(data, config) {
|
|
return $http.post(url, data, config);
|
|
},
|
|
send: function (config) {
|
|
return $http(_.extend({}, config, {
|
|
url: url
|
|
}));
|
|
}
|
|
};
|
|
},
|
|
|
|
_new: function(model, options) {
|
|
return new DataSource(model, options);
|
|
},
|
|
|
|
on: function(name, listener) {
|
|
var listeners = this._listeners[name];
|
|
if(!listeners){
|
|
this._listeners[name] = listeners = [];
|
|
}
|
|
listeners.push(listener);
|
|
return function() {
|
|
var index = listeners.indexOf(listener);
|
|
if (index >= 0)
|
|
listeners.splice(index, 1);
|
|
return listener;
|
|
};
|
|
},
|
|
|
|
trigger: function(name) {
|
|
var listeners = this._listeners[name] || [],
|
|
event = {
|
|
name : name,
|
|
target: this
|
|
},
|
|
listenerArgs = [event];
|
|
listenerArgs = listenerArgs.concat([].slice.call(arguments, 1));
|
|
|
|
forEach(listeners, function(listener) {
|
|
try {
|
|
listener.apply(null, listenerArgs);
|
|
} catch (e) {
|
|
$exceptionHandler(e);
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Check whether two objects are equal.
|
|
*
|
|
* It compares relational field values by it's id if version property
|
|
* is missing (assuming, they are not modified).
|
|
*
|
|
*/
|
|
equals: function(a, b) {
|
|
if (a === b) return true;
|
|
if (a === null || b === null) return false;
|
|
if (a !== a && b !== b) return true; // NaN === NaN
|
|
|
|
function isWindow(obj) {
|
|
return obj && obj.document && obj.location && obj.alert && obj.setInterval;
|
|
}
|
|
|
|
function isScope(obj) {
|
|
return obj && obj.$evalAsync && obj.$watch;
|
|
}
|
|
|
|
function compact(obj) {
|
|
if (!obj || !_.isObject(obj)) return obj;
|
|
if (isScope(obj) || isWindow(obj)) return obj;
|
|
if (_.isArray(obj)) return _.map(obj, compact).sort();
|
|
if (_.isDate(obj)) return obj;
|
|
if (obj.id > 0 && !obj.$dirty && !_.has(obj, "version")) {
|
|
return obj.id;
|
|
}
|
|
var res = {};
|
|
_.each(obj, function(v, k) {
|
|
if (k.substring(0, 2) === '__') return;
|
|
if (k === 'selected') return; // selected is transient field
|
|
res[k] = compact(v);
|
|
});
|
|
res.id = res.id || res.$id; // make sure to use dummy id
|
|
return res;
|
|
}
|
|
return angular.equals(compact(a), compact(b));
|
|
},
|
|
|
|
/**
|
|
* Return the difference between two records.
|
|
*
|
|
* The relational fields are compared by it's id if version
|
|
* property is missing (assuming, the are not modified).
|
|
*
|
|
* @param {Object} a - source record
|
|
* @param {Object} b - original record
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
diff: function(a, b) {
|
|
if (a === b) return a;
|
|
if (a === null || b === null) return a;
|
|
if (!a && !b) return a;
|
|
if (!a.id || a.id < 1) return a;
|
|
var result = _.pick(a, 'id', 'version'),
|
|
that = this;
|
|
|
|
_.each(a, function (value, key) {
|
|
if (!that.equals(value, b[key])) {
|
|
result[key] = value;
|
|
}
|
|
});
|
|
|
|
return result;
|
|
},
|
|
|
|
rpc: function(method, options) {
|
|
|
|
var params = _.extend({
|
|
model: this._model,
|
|
domain: this._domain,
|
|
context: this._lastContext
|
|
}, options);
|
|
|
|
var promise = $http.post('ws/action/' + method, {
|
|
model : this._model,
|
|
data : params
|
|
});
|
|
|
|
promise.success = function(fn){
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
|
|
promise.error = function(fn){
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
// if search count is less than current page boundary, adjust the page and do search again
|
|
fixPage: function () {
|
|
var page = this._page;
|
|
if (page.from != 0 && page.total != 0 && page.from >= page.total) {
|
|
page.from = page.total - (page.total % page.limit);
|
|
page.from = page.from === page.total ? page.from - page.limit : page.from;
|
|
page.from = Math.max(0, page.from);
|
|
page.to = Math.min(page.from + page.limit, page.total);
|
|
return this.search();
|
|
}
|
|
},
|
|
|
|
search: function(options) {
|
|
|
|
var opts = _.extend({
|
|
store: true
|
|
}, options);
|
|
|
|
var limit = opts.limit === undefined ? this._page.limit : opts.limit;
|
|
var offset = opts.offset === undefined ? this._page.from : opts.offset;
|
|
var domain = opts.domain === undefined ? (this._lastDomain || this._domain) : opts.domain;
|
|
var context = opts.context === undefined ? (this._lastContext || this._context) : opts.context;
|
|
var action = opts.action === undefined ? this._lastAction : opts.action;
|
|
var archived = opts.archived === undefined ? this._showArchived : opts.archived;
|
|
|
|
var fields = _.isEmpty(opts.fields) ? null : opts.fields;
|
|
var filter = opts.filter || this._filter;
|
|
var sortBy = opts.sortBy || this._sortBy;
|
|
|
|
if (opts.store) {
|
|
this._filter = filter;
|
|
this._sortBy = sortBy;
|
|
this._lastDomain = domain;
|
|
this._lastContext = context;
|
|
this._lastAction = action;
|
|
|
|
if (opts.archived !== undefined) {
|
|
this._showArchived = opts.archived;
|
|
}
|
|
}
|
|
|
|
offset = offset || 0;
|
|
context = _.extend({}, this._context, context);
|
|
|
|
//sophal
|
|
if(context._model != undefined){
|
|
if(context._model =='com.axelor.apps.suppliermanagement.db.PurchaseOrderSupplierLine'){
|
|
var limit = null ;
|
|
}
|
|
}
|
|
//sophal
|
|
|
|
var query = extend({
|
|
_domain: domain,
|
|
_domainContext: context,
|
|
_domainAction: action || undefined,
|
|
_archived: archived
|
|
}, filter);
|
|
|
|
var that = this,
|
|
page = this._page,
|
|
records = this._data,
|
|
params = {
|
|
fields: fields,
|
|
sortBy: sortBy,
|
|
data: query,
|
|
limit: limit,
|
|
offset: offset,
|
|
parent: opts.parent
|
|
};
|
|
|
|
var promise = this._request('search').post(params);
|
|
|
|
promise = promise.then(function(response){
|
|
var res = response.data;
|
|
var length = (res.data||[]).length;
|
|
res.offset = offset;
|
|
res.data = _.unique(res.data, function (a) { return a.id; });
|
|
|
|
if (opts.store) {
|
|
that._accept(res);
|
|
page.index = -1;
|
|
} else {
|
|
records = res.data || [];
|
|
page = that._pageInfo(res);
|
|
}
|
|
|
|
if (length !== page.size) {
|
|
page.total -= (length - page.size);
|
|
}
|
|
});
|
|
promise.success = function(fn){
|
|
promise.then(function(res){
|
|
fn(records, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn){
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
at: function(index) {
|
|
return this._data[index];
|
|
},
|
|
|
|
get: function(id) {
|
|
for (var i = 0; i < this._data.length; i++) {
|
|
if (this._data[i].id === id) {
|
|
return this._data[i];
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Read the object with the given id.
|
|
*
|
|
* If options are provided then POST request is used otherwise GET is used.
|
|
* @param id record id
|
|
* @param options request options
|
|
* @returns promise
|
|
*/
|
|
read: function(id, options) {
|
|
var promise, record;
|
|
if (options) {
|
|
promise = this._request('fetch', id).post({
|
|
fields: options.fields,
|
|
related: options.related
|
|
});
|
|
} else {
|
|
promise = this._request(null, id).get();
|
|
}
|
|
|
|
promise.then(function(response){
|
|
var res = response.data;
|
|
record = res.data;
|
|
if (isArray(record)) {
|
|
record = record[0];
|
|
}
|
|
});
|
|
|
|
promise.success = function(fn){
|
|
promise.then(function(response){
|
|
fn(record);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
// find followers of the given record
|
|
followers: function (id) {
|
|
var promise = this._request('followers', id).get();
|
|
promise.success = function(fn) {
|
|
promise.then(function(res) {
|
|
fn(res.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
// find messages for the given record
|
|
messages: function (options) {
|
|
|
|
var opts = _.extend({}, options);
|
|
var promise = this._request('messages').send({
|
|
method: 'GET',
|
|
params: opts,
|
|
silent: opts.count ? true : undefined,
|
|
transformRequest: opts.count ? [] : undefined
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response) {
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
messageCount: function (options) {
|
|
var opts = _.extend({}, options, {
|
|
count: true
|
|
});
|
|
return this.messages(opts);
|
|
},
|
|
|
|
messagePost: function (id, text, options) {
|
|
|
|
var opts = _.extend({}, options);
|
|
var data = _.extend({
|
|
body : text,
|
|
subject: opts.subject,
|
|
type: opts.type,
|
|
parent: opts.parent,
|
|
files: opts.files,
|
|
recipients: opts.recipients
|
|
});
|
|
|
|
var promise = this._request('message', id).post({
|
|
data: data
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
messageFollow: function (id, options) {
|
|
var opts = _.extend({}, options);
|
|
var promise = this._request('follow', id).post({
|
|
data: opts.email
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
messageUnfollow: function (id, options) {
|
|
var opts = _.extend({}, options);
|
|
var promise = this._request('unfollow', id).post({
|
|
records: opts.records
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
isPermitted: function(action, values) {
|
|
|
|
var data = _.extend({}, {
|
|
id: values && values.id,
|
|
action: action
|
|
});
|
|
var promise = this._request("perms").get({
|
|
params: data
|
|
});
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
verify: function(values) {
|
|
var promise = this._request("verify").post({
|
|
data: values
|
|
});
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
upload: function(values, field, file) {
|
|
var that = this,
|
|
page = this._page,
|
|
record = null,
|
|
deferred = $q.defer(),
|
|
promise = deferred.promise;
|
|
|
|
var indicator = $injector.get('httpIndicator');
|
|
promise = promise.then(indicator.response, indicator.responseError);
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
var data = new FormData();
|
|
var progress_cb = angular.noop;
|
|
|
|
promise.then(function(response) {
|
|
var res = response.data;
|
|
res.data = res.data[0];
|
|
record = that._accept(res);
|
|
});
|
|
promise.progress = function(fn) {
|
|
progress_cb = fn;
|
|
return promise;
|
|
};
|
|
promise.success = function(fn) {
|
|
promise.then(function(response) {
|
|
fn(record, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, function(response){
|
|
fn(response.data);
|
|
});
|
|
return promise;
|
|
};
|
|
|
|
var request = {
|
|
data: values
|
|
};
|
|
|
|
data.append("file", file);
|
|
data.append("field", field);
|
|
data.append("request", angular.toJson(request));
|
|
|
|
xhr.upload.addEventListener("progress", function(e) {
|
|
var complete = Math.round(e.loaded * 100 / e.total);
|
|
progress_cb(complete);
|
|
}, false);
|
|
|
|
_.each($http.defaults.transformRequest, function(tr) {
|
|
tr(data);
|
|
});
|
|
|
|
xhr.onerror = deferred.reject;
|
|
xhr.onabort = deferred.reject;
|
|
xhr.onload = function () {
|
|
var data = angular.fromJson(xhr.response || xhr.responseText);
|
|
var response = {
|
|
data: data,
|
|
status: xhr.status
|
|
};
|
|
if (xhr.status == 200) {
|
|
deferred.resolve(response);
|
|
} else {
|
|
deferred.reject(response);
|
|
}
|
|
$rootScope.$applyAsync();
|
|
};
|
|
|
|
xhr.open("POST", "ws/rest/" + this._model + "/upload", true);
|
|
xhr.send(data);
|
|
|
|
return promise;
|
|
},
|
|
|
|
save: function(values) {
|
|
|
|
var that = this,
|
|
page = this._page,
|
|
record, promise;
|
|
|
|
if (values && values.$upload) {
|
|
var upload = values.$upload;
|
|
return this.upload(values, upload.field, upload.file);
|
|
}
|
|
|
|
promise = this._request().post({
|
|
data: values
|
|
});
|
|
|
|
promise.then(function(response){
|
|
var res = response.data;
|
|
res.data = res.data[0];
|
|
record = that._accept(res);
|
|
that.trigger('on:save', [values]);
|
|
$rootScope.$broadcast('ds:saved', that);
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(record, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
saveAll: function(items, fields) {
|
|
|
|
var that = this,
|
|
page = this._page,
|
|
records = this._data,
|
|
promise = this._request().post({
|
|
fields: fields,
|
|
records: items
|
|
});
|
|
|
|
promise.then(function(response){
|
|
var res = response.data;
|
|
_.each(res.data || [], function(item){
|
|
var found = _.find(records, function(rec){
|
|
if (rec.id === item.id) {
|
|
angular.copy(item, rec);
|
|
return true;
|
|
}
|
|
});
|
|
if (!found) {
|
|
records.push(item);
|
|
page.total += 1;
|
|
page.size += 1;
|
|
}
|
|
});
|
|
|
|
var i = 0;
|
|
while(i < records.length) {
|
|
var rec = records[i];
|
|
if (rec.id === 0) {
|
|
records.splice(i, 1);
|
|
break;
|
|
}
|
|
i ++;
|
|
}
|
|
|
|
that.trigger('change', records, page);
|
|
that.trigger('on:save', items);
|
|
$rootScope.$broadcast('ds:saved', that);
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(records, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
updateMass: function (values, ids) {
|
|
|
|
var domain = this._lastDomain;
|
|
var context = this._lastContext;
|
|
var filter = this._filter;
|
|
|
|
var items = _.compact(ids);
|
|
if (items.length > 0) {
|
|
if (domain) {
|
|
domain = domain + " AND self.id IN (:__ids__)";
|
|
} else {
|
|
domain = "self.id IN (:__ids__)";
|
|
}
|
|
context = _.extend({
|
|
__ids__: items
|
|
}, context);
|
|
}
|
|
|
|
var query = extend({
|
|
_domain: domain,
|
|
_domainContext: context,
|
|
_archived: this._showArchived
|
|
}, filter);
|
|
|
|
|
|
|
|
var promise = this._request('updateMass').post({
|
|
records: [values],
|
|
sortBy: this._sortBy,
|
|
data: query
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
var res = response.data;
|
|
fn(res);
|
|
});
|
|
return promise;
|
|
};
|
|
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
remove: function(record) {
|
|
|
|
var that = this,
|
|
page = this._page,
|
|
records = this._data,
|
|
promise = this._request('remove', record.id).post({
|
|
data: record
|
|
});
|
|
|
|
promise = promise.then(function(reponse){
|
|
var index = -1;
|
|
for(var i = 0 ; i < records.length ; i++) {
|
|
if (records[i].id == record.id) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index > -1) {
|
|
records.splice(index, 1);
|
|
page.total -= 1;
|
|
page.size -= 1;
|
|
}
|
|
|
|
that.trigger('change', records, page);
|
|
that.trigger('on:remove', [record]);
|
|
$rootScope.$broadcast('ds:removed', that);
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(records, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
removeAll: function(selection) {
|
|
|
|
var that = this,
|
|
page = this._page,
|
|
records = this._data,
|
|
promise;
|
|
|
|
selection = _.map(selection, function(record){
|
|
return { "id" : record.id, "version": record.version };
|
|
});
|
|
|
|
promise = this._request('removeAll').post({
|
|
records: selection
|
|
});
|
|
|
|
promise = promise.then(function(response){
|
|
var res = response.data;
|
|
function remove(id) {
|
|
var rec = _.find(records, function(record, i) {
|
|
return record.id == id;
|
|
});
|
|
var index = _.indexOf(records, rec);
|
|
if (index > -1) {
|
|
records.splice(index, 1);
|
|
page.total -= 1;
|
|
page.size -= 1;
|
|
}
|
|
}
|
|
_.each(res.data, function(record) {
|
|
remove(record.id);
|
|
});
|
|
that.trigger('change', records, page);
|
|
that.trigger('on:remove', selection);
|
|
$rootScope.$broadcast('ds:removed', that);
|
|
});
|
|
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
fn(records, page);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
|
|
return promise;
|
|
},
|
|
|
|
copy: function(id) {
|
|
var promise = this._request('copy', id).get();
|
|
promise.success = function(fn) {
|
|
promise.then(function(response){
|
|
var res = response.data,
|
|
record = res.data;
|
|
if (isArray(record))
|
|
record = record[0];
|
|
fn(record);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
details: function(id, name) {
|
|
var promise = this._request('details', id).get({
|
|
params: {
|
|
name: name
|
|
}
|
|
});
|
|
promise.success = function(fn){
|
|
promise.then(function(response){
|
|
var res = response.data,
|
|
record = res.data;
|
|
if (isArray(record))
|
|
record = record[0];
|
|
fn(record);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
},
|
|
|
|
/**
|
|
* Get current page info.
|
|
*
|
|
*/
|
|
page: function() {
|
|
return this._page;
|
|
},
|
|
|
|
next: function(fields) {
|
|
var page = this._page;
|
|
return this.search({
|
|
offset: page.from + page.limit,
|
|
fields: fields
|
|
});
|
|
},
|
|
|
|
prev: function(fields) {
|
|
var page = this._page;
|
|
return this.search({
|
|
offset: Math.max(0, page.from - page.limit),
|
|
fields: fields
|
|
});
|
|
},
|
|
|
|
nextItem: function(success) {
|
|
var self = this,
|
|
page = this._page,
|
|
index = page.index + 1,
|
|
record = this.at(index);
|
|
|
|
if (index < page.size) {
|
|
page.index = index;
|
|
return success(record);
|
|
}
|
|
|
|
this.next().success(function(){
|
|
page.index = 0;
|
|
record = self.at(0);
|
|
success(record);
|
|
});
|
|
},
|
|
|
|
prevItem: function(success) {
|
|
var self = this,
|
|
page = this._page,
|
|
index = page.index - 1,
|
|
record = this.at(index);
|
|
|
|
if (index > -1) {
|
|
page.index = index;
|
|
return success(record);
|
|
}
|
|
|
|
this.prev().success(function(){
|
|
page.index = page.size - 1;
|
|
record = self.at(page.index);
|
|
success(record);
|
|
});
|
|
},
|
|
|
|
canNext: function() {
|
|
var page = this._page;
|
|
return page.to < page.total;
|
|
},
|
|
|
|
canPrev: function() {
|
|
var page = this._page;
|
|
return page.from > 0;
|
|
},
|
|
|
|
_pageInfo: function(res) {
|
|
var records = res.data || [];
|
|
var page = _.extend({}, this._page);
|
|
|
|
page.from = res.offset === undefined ? page.from : res.offset;
|
|
page.to = page.from + records.length;
|
|
page.total = res.total === undefined ? page.total : res.total;
|
|
page.size = records.length;
|
|
|
|
return page;
|
|
},
|
|
|
|
_accept: function(res) {
|
|
var page = this._page,
|
|
records = this._data,
|
|
data = res.data,
|
|
accepted = null;
|
|
|
|
if (isArray(data)) {
|
|
|
|
records.length = 0;
|
|
forEach(data, function(record){
|
|
records.push(record);
|
|
});
|
|
|
|
_.extend(page, this._pageInfo(res));
|
|
|
|
accepted = records;
|
|
|
|
} else if (isObject(data)) {
|
|
|
|
var record = data;
|
|
var index = -1;
|
|
|
|
for(var i = 0 ; i < records.length ; i++) {
|
|
if (records[i].id === data.id) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index > -1) {
|
|
var old = records.splice(index, 1, data)[0];
|
|
_.each(old, function (value, key) {
|
|
if (key.indexOf('.') > -1 && !data.hasOwnProperty(key)) {
|
|
data[key] = value;
|
|
}
|
|
});
|
|
} else {
|
|
records.push(record);
|
|
page.total += 1;
|
|
page.size += 1;
|
|
page.index = page.size - 1;
|
|
}
|
|
|
|
accepted = record;
|
|
}
|
|
|
|
this.trigger('change', records, page);
|
|
|
|
return accepted;
|
|
},
|
|
|
|
export_: function(fields) {
|
|
var domain = this._lastDomain || this._domain;
|
|
var context = this._lastContext;
|
|
var filter = this._filter;
|
|
var action = this._lastAction;
|
|
|
|
var query = extend({
|
|
_domain: domain,
|
|
_domainContext: context,
|
|
_domainAction: action || undefined,
|
|
_archived: this._showArchived
|
|
}, filter);
|
|
|
|
var params = {
|
|
fields: fields,
|
|
data: query,
|
|
sortBy: this._sortBy
|
|
};
|
|
|
|
var promise = this._request('export').post(params);
|
|
|
|
promise.success = function(fn){
|
|
promise.then(function(response){
|
|
var res = response.data,
|
|
records = res.data;
|
|
fn(records);
|
|
});
|
|
return promise;
|
|
};
|
|
promise.error = function(fn) {
|
|
promise.then(null, fn);
|
|
return promise;
|
|
};
|
|
return promise;
|
|
}
|
|
};
|
|
|
|
return {
|
|
create: create
|
|
};
|
|
|
|
function create(model, options) {
|
|
return new DataSource(model, options);
|
|
}
|
|
|
|
}]);
|
|
|
|
})();
|