e7da4c19b8
Fixes #4989
320 lines
9.1 KiB
JavaScript
320 lines
9.1 KiB
JavaScript
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
/**
|
|
* @name Resource
|
|
* @constructor
|
|
* @param {Object} $http - the Angular HTTP service
|
|
* @param {Object} $q - the Angular promise/deferred service
|
|
* @param {String} path - the base path of the external resource
|
|
* @param {Object} options - extra attributes to be associated to the object
|
|
*/
|
|
function Resource($http, $q, $window, $cookies, path, activeUser, options) {
|
|
angular.extend(this, {
|
|
_http: $http,
|
|
_q: $q,
|
|
_window: $window,
|
|
_cookies: $cookies,
|
|
_path: path,
|
|
_activeUser: activeUser
|
|
});
|
|
angular.extend(this, options);
|
|
// Trim trailing slash
|
|
this._path = this._path.replace(/\/$/, '');
|
|
}
|
|
|
|
/**
|
|
* @memberof Resource
|
|
* @desc The factory we'll use to register with Angular.
|
|
* @return a new Resource object
|
|
*/
|
|
Resource.$factory = ['$http', '$q', '$window', '$cookies', function($http, $q, $window, $cookies) {
|
|
return function(path, activeUser, options) {
|
|
return new Resource($http, $q, $window, $cookies, path, activeUser, options);
|
|
};
|
|
}];
|
|
|
|
/**
|
|
* @module SOGo.Common
|
|
* @desc Factory registration of Resource in Angular module.
|
|
*/
|
|
angular.module('SOGo.Common').factory('Resource', Resource.$factory);
|
|
|
|
Resource.prototype.encodeURL = function(url) {
|
|
var _this = this,
|
|
segments = url;
|
|
|
|
if (!angular.isArray(segments)) {
|
|
segments = url.split('/');
|
|
}
|
|
return _.map(segments, function(segment) {
|
|
return _this._window.encodeURIComponent(segment.toString());
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @function userResource
|
|
* @memberof Resource.prototype
|
|
* @desc Create a new Resource object associated to a username different than the active user.
|
|
* @param {String} uid - the user UID
|
|
* @return a new Resource object
|
|
*/
|
|
Resource.prototype.userResource = function(uid) {
|
|
var path = _.compact(this._activeUser.folderURL.split('/'));
|
|
|
|
if (uid)
|
|
path.splice(path.length - 1, 1, escape(uid));
|
|
|
|
return new Resource(this._http, this._q, this._window, this._cookies, '/' + path.join('/'), this._activeUser);
|
|
};
|
|
|
|
/**
|
|
* @function path
|
|
* @memberof Resource.prototype
|
|
* @desc Create a URL of the resource context with any number of additional segments
|
|
* @return an absolute URL
|
|
*/
|
|
Resource.prototype.path = function() {
|
|
var path = [this._path];
|
|
|
|
if (arguments.length > 0)
|
|
Array.prototype.push.apply(path, Array.prototype.slice.call(arguments));
|
|
|
|
return path.join('/');
|
|
};
|
|
|
|
/**
|
|
* @function fetch
|
|
* @memberof Resource.prototype
|
|
* @desc Fetch resource using a specific folder, action and/or parameters.
|
|
* @param {string} folderId - the folder on which the action will be applied (ex: addressbook, calendar)
|
|
* @param {string} action - the action to be used in the URL
|
|
* @param {Object} params - Object parameters injected through the $http service
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.fetch = function(folderId, action, params) {
|
|
var deferred = this._q.defer(),
|
|
path = [this._path];
|
|
if (folderId) path.push(this.encodeURL(folderId));
|
|
if (action) path.push(action);
|
|
path = _.compact(_.flatten(path)).join('/');
|
|
|
|
this._http({
|
|
method: 'GET',
|
|
url: path,
|
|
params: params
|
|
})
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
/**
|
|
* @function quietFetch
|
|
* @memberof Resource.prototype
|
|
* @desc Fetch resource using a specific folder, action and/or parameters, but disable the global
|
|
* error interceptor.
|
|
* @param {string} folderId - the folder on which the action will be applied (ex: addressbook, calendar)
|
|
* @param {string} action - the action to be used in the URL
|
|
* @param {Object} params - Object parameters injected through the $http service
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.quietFetch = function(folderId, action, params) {
|
|
var deferred = this._q.defer(),
|
|
path = [this._path];
|
|
if (folderId) path.push(this.encodeURL(folderId));
|
|
if (action) path.push(action);
|
|
path = _.compact(_.flatten(path)).join('/');
|
|
|
|
this._http({
|
|
method: 'GET',
|
|
url: path,
|
|
params: params,
|
|
transformResponse: function(data) {
|
|
var jsonData;
|
|
try {
|
|
jsonData = angular.fromJson(data);
|
|
}
|
|
catch (e) {
|
|
jsonData = {};
|
|
}
|
|
return angular.extend({ quiet: true }, jsonData);
|
|
}
|
|
})
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
/**
|
|
* @function newguid
|
|
* @memberof Resource.prototype
|
|
* @desc Fetch a new GUID on the specified folder ID.
|
|
* @return a promise of the new data structure
|
|
*/
|
|
Resource.prototype.newguid = function(folderId) {
|
|
var deferred = this._q.defer(),
|
|
path = this._path + '/' + folderId + '/newguid';
|
|
|
|
this._http
|
|
.get(path)
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
/**
|
|
* @function create
|
|
* @memberof Resource.prototype
|
|
* @desc Create a new resource using a specific action (post).
|
|
* @param {string} action - the action to be used in the URL
|
|
* @param {string} name - the new resource's name
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.create = function(action, name) {
|
|
var deferred = this._q.defer(),
|
|
path = this._path + '/' + action;
|
|
|
|
this._http
|
|
.post(path, { name: name })
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
/**
|
|
* @function post
|
|
* @memberof Resource.prototype
|
|
* @desc Post a resource attributes on the server.
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.post = function(id, action, data) {
|
|
var deferred = this._q.defer(),
|
|
path = [this._path];
|
|
if (id) path.push(this.encodeURL(id));
|
|
if (action) path.push(action);
|
|
path = _.compact(_.flatten(path)).join('/');
|
|
|
|
this._http
|
|
.post(path, data)
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
/**
|
|
* @function save
|
|
* @memberof Resource.prototype
|
|
* @desc Save a resource attributes on the server (post /save).
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.save = function(id, newValue, options) {
|
|
var action = (options && options.action)? options.action : 'save';
|
|
|
|
return this.post(id, action, newValue);
|
|
};
|
|
|
|
/**
|
|
* @function download
|
|
* @memberof Resource.prototype
|
|
* @desc Download a file from the server. Requires FileSaver.js.
|
|
* @see {@link http://blog.davidjs.com/2015/07/download-files-via-post-request-in-angularjs/|Download files via POST request in AngularJs}
|
|
* @see {@link https://github.com/eligrey/FileSaver.js|FileSaver.js}
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.download = function(id, action, data, options) {
|
|
var deferred = this._q.defer(),
|
|
type = (options && options.type)? options.type : 'application/zip',
|
|
path = [this._path];
|
|
if (id) path.push(this.encodeURL(id));
|
|
if (action) path.push(action);
|
|
path = _.compact(_.flatten(path)).join('/');
|
|
|
|
if (typeof saveAs == 'undefined') {
|
|
throw new Error('To use Resource.download, FileSaver.js must be loaded.');
|
|
}
|
|
|
|
function getFileNameFromHeader(header) {
|
|
var result;
|
|
|
|
if (!header) return null;
|
|
result = header.split(";")[1].trim().split("=")[1];
|
|
|
|
return result.replace(/"/g, '');
|
|
}
|
|
|
|
return this._http({
|
|
method: 'POST',
|
|
url: path,
|
|
data: data,
|
|
headers: {
|
|
accept: type
|
|
},
|
|
responseType: 'arraybuffer',
|
|
cache: false,
|
|
transformResponse: function (data, headers, status) {
|
|
var fileName, result, blob = null;
|
|
|
|
if (status < 200 || status > 299) {
|
|
throw new Error('Bad gateway');
|
|
}
|
|
if (data) {
|
|
blob = new Blob([data], { type: type });
|
|
}
|
|
if (options && options.filename) {
|
|
fileName = options.filename;
|
|
}
|
|
else {
|
|
getFileNameFromHeader(headers('content-disposition'));
|
|
}
|
|
saveAs(blob, fileName);
|
|
}
|
|
});
|
|
};
|
|
|
|
Resource.prototype.open = function(id, action) {
|
|
var path = [this._path], xsrfToken;
|
|
xsrfToken = this._cookies.get('XSRF-TOKEN');
|
|
if (id) path.push(id);
|
|
if (action) path.push(action);
|
|
path = _.compact(_.flatten(path)).join('/');
|
|
if (xsrfToken) {
|
|
path += '?X-XSRF-TOKEN=' + xsrfToken;
|
|
}
|
|
|
|
this._window.location.href = path;
|
|
};
|
|
|
|
/**
|
|
* @function remove
|
|
* @memberof Resource.prototype
|
|
* @desc Delete a resource (get /delete).
|
|
* @return a promise
|
|
*/
|
|
Resource.prototype.remove = function(uid) {
|
|
var deferred = this._q.defer(),
|
|
path = _.flatten([this._path, this.encodeURL(uid), 'delete']).join('/');
|
|
|
|
this._http
|
|
.get(path)
|
|
.then(function(response) {
|
|
return deferred.resolve(response.data);
|
|
}, deferred.reject);
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
})();
|