1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2024-11-28 10:24:11 +01:00
OwncloudContactsOfficial/js/storage.js
2014-10-11 01:47:49 +02:00

723 lines
20 KiB
JavaScript

OC.Contacts = OC.Contacts || {};
(function(window, $, OC) {
'use strict';
var JSONResponse = function(jqXHR) {
this.getAllResponseHeaders = jqXHR.getAllResponseHeaders;
this.getResponseHeader = jqXHR.getResponseHeader;
this.statusCode = jqXHR.status;
var response = jqXHR.responseJSON;
this.error = false;
console.log('jqXHR', jqXHR);
if (!response) {
// 204 == No content
// 304 == Not modified
if ([204, 304].indexOf(this.statusCode) === -1) {
this.error = true;
}
this.message = jqXHR.statusText;
} else {
// We need to allow for both the 'old' success/error status property
// with the body in the data property, and the newer where we rely
// on the status code, and the entire body is used.
if (response.status === 'error'|| this.statusCode >= 400) {
this.error = true;
if (!response.data || !response.data.message) {
this.message = t('contacts', 'Server error! Please inform system administator');
} else {
console.log('JSONResponse', response);
this.message = (response.data && response.data.message)
? response.data.message
: response;
}
} else {
this.data = response.data || response;
// Kind of a hack
if (response.metadata) {
this.metadata = response.metadata;
}
}
}
};
/**
* An object for saving contact data to backends
*
* All methods returns a jQuery.Deferred object which resolves
* to either the requested response or an error object:
* {
* error: true,
* message: The error message
* }
*
* @param string user The user to query for. Defaults to current user
*/
var Storage = function(user) {
this.user = user ? user : OC.currentUser;
};
/**
* Test if localStorage is working
*
* @return bool
*/
Storage.prototype.hasLocalStorage = function() {
if (Modernizr && !Modernizr.localStorage) {
return false;
}
// Some browsers report support but doesn't have it
// e.g. Safari in private browsing mode.
try {
OC.localStorage.setItem('Hello', 'World');
OC.localStorage.removeItem('Hello');
} catch (e) {
return false;
}
return true;
};
/**
* When the response isn't returned from requestRoute(), you can
* wrap it in a JSONResponse so that it's parsable by other objects.
*
* @param XMLHTTPRequest http://api.jquery.com/jQuery.ajax/#jqXHR
*/
Storage.prototype.formatResponse = function(jqXHR) {
return new JSONResponse(jqXHR);
};
/**
* Get all address books registered for this user.
*
* @return An array containing object of address book metadata e.g.:
* {
* backend:'local',
* id:'1234'
* permissions:31,
* displayname:'Contacts'
* }
*/
Storage.prototype.getAddressBooksForUser = function() {
return this.requestRoute(
'addressbooks/',
'GET',
{}
);
};
/**
* Add an address book to a specific backend
*
* @param string backend - currently defaults to 'local'
* @param object params An object {displayname:"My contacts", description:""}
* @return An array containing contact data e.g.:
* {
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'My contacts',
* lastmodified: (unix timestamp),
* owner: 'joye',
* }
*/
Storage.prototype.addAddressBook = function(backend, parameters) {
console.log('Storage.addAddressBook', backend);
return this.requestRoute(
'addressbook/{backend}/add',
'POST',
{backend: backend},
JSON.stringify(parameters)
);
};
/**
* Update an address book in a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param object params An object {displayname:"My contacts", description:""}
* @return An array containing contact data e.g.:
* {
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'My contacts',
* lastmodified: (unix timestamp),
* owner: 'joye',
* }
*/
Storage.prototype.updateAddressBook = function(backend, addressBookId, properties) {
console.log('Storage.updateAddressBook', backend, addressBookId, properties);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}',
'POST',
{backend: backend, addressBookId: addressBookId},
JSON.stringify(properties)
);
};
/**
* Delete an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
*/
Storage.prototype.deleteAddressBook = function(backend, addressBookId) {
var key = 'contacts::' + backend + '::' + addressBookId;
if(this.hasLocalStorage() && OC.localStorage.hasItem(key)) {
OC.localStorage.removeItem(key);
}
console.log('Storage.deleteAddressBook', backend, addressBookId);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}',
'DELETE',
{backend: backend, addressBookId: addressBookId}
);
};
/**
* (De)active an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param bool state
*/
Storage.prototype.activateAddressBook = function(backend, addressBookId, state) {
console.log('Storage.activateAddressBook', backend, addressBookId, state);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/activate',
'POST',
{backend: backend, addressBookId: addressBookId},
JSON.stringify({state: state})
);
};
/**
* Update an address book in a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param object params An object {displayname:"My contacts", description:""}
* @return An array containing contact data e.g.:
* {
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'My contacts',
* lastmodified: (unix timestamp),
* owner: 'joye',
* }
*/
Storage.prototype.getConnectors = function(backend) {
console.log('Storage.getConnectors', backend);
return this.requestRoute(
'connectors/{backend}',
'GET',
{backend: backend}
);
};
/**
* Get metadata from an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @return
*
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'Contacts',
* lastmodified: (unix timestamp),
* owner: 'joye'
* }
*/
Storage.prototype.getAddressBook = function(backend, addressBookId) {
var defer = $.Deferred();
$.when(this.requestRoute(
'addressbook/{backend}/{addressBookId}',
'GET',
{backend: backend, addressBookId: addressBookId},
''
))
.then(function(response) {
console.log('response', response);
defer.resolve(response);
})
.fail(function(response) {
console.warn('Request Failed:', response.message);
defer.reject(response);
});
return defer;
};
/**
* Get contacts from an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @return
* An array containing contact data e.g.:
* {
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'John Q. Public',
* lastmodified: (unix timestamp),
* owner: 'joye',
* parent: (id of the parent address book)
* data: //array of VCard data
* }
*/
Storage.prototype.getContacts = function(backend, addressBookId) {
var self = this,
headers = {},
data,
key = 'contacts::' + backend + '::' + addressBookId,
defer = $.Deferred();
if(this.hasLocalStorage() && OC.localStorage.hasItem(key)) {
data = OC.localStorage.getItem(key);
headers['If-None-Match'] = data.Etag;
}
$.when(this.requestRoute(
'addressbook/{backend}/{addressBookId}/contacts',
'GET',
{backend: backend, addressBookId: addressBookId},
'',
headers
))
.then(function(response) {
console.log('response', response);
if(response.statusCode === 200) {
console.log('Returning fetched address book');
if(response.data) {
response.data.Etag = response.getResponseHeader('Etag');
if (!self.hasLocalStorage()) {
OC.localStorage.setItem(key, response.data);
}
defer.resolve(response);
}
} else if(response.statusCode === 304) {
console.log('Returning stored address book');
response.data = data;
defer.resolve(response);
}
})
.fail(function(response) {
console.warn('Request Failed:', response.message);
defer.reject(response);
});
return defer;
};
/**
* Add a contact to an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @return An array containing contact data e.g.:
* {
* metadata:
* {
* id:'1234'
* permissions:31,
* displayname:'John Q. Public',
* lastmodified: (unix timestamp),
* owner: 'joye',
* parent: (id of the parent address book)
* data: //array of VCard data
* }
*/
Storage.prototype.addContact = function(backend, addressBookId) {
console.log('Storage.addContact', backend, addressBookId);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/add',
'POST',
{backend: backend, addressBookId: addressBookId}
);
};
/**
* Delete a contact from an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Address book ID
*/
Storage.prototype.deleteContact = function(backend, addressBookId, contactId) {
console.log('Storage.deleteContact', backend, addressBookId, contactId);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/{contactId}',
'DELETE',
{backend: backend, addressBookId: addressBookId, contactId: contactId}
);
};
/**
* Delete a list of contacts from an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param array contactIds Address book ID
*/
Storage.prototype.deleteContacts = function(backend, addressBookId, contactIds) {
console.log('Storage.deleteContacts', backend, addressBookId, contactIds);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/deleteContacts',
'POST',
{backend: backend, addressBookId: addressBookId},
JSON.stringify({contacts: contactIds})
);
};
/**
* Move a contact to an address book from a specific backend
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Address book ID
*/
Storage.prototype.moveContact = function(backend, addressBookId, contactId, target) {
console.log('Storage.moveContact', backend, addressBookId, contactId, target);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/{contactId}',
'POST',
{backend: backend, addressBookId: addressBookId, contactId: contactId},
JSON.stringify(target)
);
};
/**
* Get Image instance for a contacts profile picture
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Address book ID
* @return Image
*/
Storage.prototype.getContactPhoto = function(backend, addressBookId, contactId) {
var photo = new Image();
var url = OC.generateUrl(
'apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/photo',
{backend: backend, addressBookId: addressBookId, contactId: contactId}
);
var defer = $.Deferred();
$.when(
$(photo).on('load', function() {
defer.resolve(photo);
})
.error(function() {
console.log('Error loading contact photo');
defer.reject();
})
.attr('src', url + '?refresh=' + Math.random())
)
.fail(function(jqxhr, textStatus, error) {
defer.reject();
var err = textStatus + ', ' + error;
console.warn('Request Failed:', + err);
$(document).trigger('status.contact.error', {
message: t('contacts', 'Failed loading photo: {error}', {error:err})
});
});
return defer.promise();
};
/**
* Get Image instance for cropping contacts profile picture
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Address book ID
* @param string key The key to the cache where the photo is stored.
* @return Image
*/
Storage.prototype.getTempContactPhoto = function(backend, addressBookId, contactId, key) {
var photo = new Image();
var url = OC.generateUrl(
'apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/photo/{key}/tmp',
{backend: backend, addressBookId: addressBookId, contactId: contactId, key: key, refresh: Math.random()}
);
console.log('url', url);
var defer = $.Deferred();
$.when(
$(photo).on('load', function() {
defer.resolve(photo);
})
.error(function(event) {
console.warn('Error loading temporary photo', event);
defer.reject();
})
.attr('src', url)
)
.fail(function(jqxhr, textStatus, error) {
defer.reject();
var err = textStatus + ', ' + error;
console.warn('Request Failed:', err);
$(document).trigger('status.contact.error', {
message: t('contacts', 'Failed loading photo: {error}', {error:err})
});
});
return defer.promise();
};
/**
* Crop a contact phot.
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Contact ID
* @param string key The key to the cache where the temporary image is saved.
* @param object coords An object with the properties: x, y, w, h
*/
Storage.prototype.cropContactPhoto = function(backend, addressBookId, contactId, key, coords) {
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/{contactId}/photo/{key}/crop',
'POST',
{backend: backend, addressBookId: addressBookId, contactId: contactId, key: key},
JSON.stringify(coords)
);
};
/**
* Update a contact.
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Contact ID
* @param object params An object with the following properties:
* @param string name The name of the property e.g. EMAIL.
* @param string|array|null value The of the property
* @param array parameters Optional parameters for the property
* @param string checksum For non-singular properties such as email this must contain
* an 8 character md5 checksum of the serialized \Sabre\Property
*/
Storage.prototype.patchContact = function(backend, addressBookId, contactId, params) {
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/{contactId}',
'PATCH',
{backend: backend, addressBookId: addressBookId, contactId: contactId},
JSON.stringify(params)
);
};
/**
* Save all properties. Used when merging contacts.
*
* @param string backend
* @param string addressBookId Address book ID
* @param string contactId Contact ID
* @param object params An object with the all properties:
*/
Storage.prototype.saveAllProperties = function(backend, addressBookId, contactId, params) {
console.log('Storage.saveAllProperties', params);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/contact/{contactId}/save',
'POST',
{backend: backend, addressBookId: addressBookId, contactId: contactId},
JSON.stringify(params)
);
};
/**
* Get all groups for this user.
*
* @return An array containing the groups, the favorites, any shared
* address books, the last selected group and the sort order of the groups.
* {
* 'categories': [{'id':1',Family'}, {...}],
* 'favorites': [123,456],
* 'shared': [],
* 'lastgroup':'1',
* 'sortorder':'3,2,4'
* }
*/
Storage.prototype.getGroupsForUser = function() {
console.log('getGroupsForUser');
return this.requestRoute(
'groups/',
'GET',
{}
);
};
/**
* Add a group
*
* @param string name
* @return A JSON object containing the (maybe sanitized) group name and its ID:
* {
* 'id':1234,
* 'name':'My group'
* }
*/
Storage.prototype.addGroup = function(name) {
console.log('Storage.addGroup', name);
return this.requestRoute(
'groups/add',
'POST',
{},
JSON.stringify({name: name})
);
};
/**
* Delete a group
*
* @param string name
*/
Storage.prototype.deleteGroup = function(id, name) {
return this.requestRoute(
'groups/delete',
'POST',
{},
JSON.stringify({id: id, name: name})
);
};
/**
* Rename a group
*
* @param string from
* @param string to
*/
Storage.prototype.renameGroup = function(from, to) {
return this.requestRoute(
'groups/rename',
'POST',
{},
JSON.stringify({from: from, to: to})
);
};
/**
* Add contacts to a group
*
* @param array contactIds
*/
Storage.prototype.addToGroup = function(contactIds, categoryId, categoryName) {
console.log('Storage.addToGroup', contactIds, categoryId);
return this.requestRoute(
'groups/addto/{categoryId}',
'POST',
{categoryId: categoryId},
JSON.stringify({contactIds: contactIds, name: categoryName})
);
};
/**
* Remove contacts from a group
*
* @param array contactIds
*/
Storage.prototype.removeFromGroup = function(contactIds, categoryId, categoryName) {
console.log('Storage.removeFromGroup', contactIds, categoryId);
return this.requestRoute(
'groups/removefrom/{categoryId}',
'POST',
{categoryId: categoryId},
JSON.stringify({contactIds: contactIds, name: categoryName})
);
};
/**
* Set a user preference
*
* @param string key
* @param string value
*/
Storage.prototype.setPreference = function(key, value) {
return this.requestRoute(
'preference/set',
'POST',
{},
JSON.stringify({key: key, value:value})
);
};
Storage.prototype.prepareImport = function(backend, addressBookId, importType, params) {
console.log('Storage.prepareImport', backend, addressBookId, importType);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/{importType}/import/prepare',
'POST',
{backend: backend, addressBookId: addressBookId, importType: importType},
JSON.stringify(params)
);
};
Storage.prototype.startImport = function(backend, addressBookId, importType, params) {
console.log('Storage.startImport', backend, addressBookId, importType);
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/{importType}/import/start',
'POST',
{backend: backend, addressBookId: addressBookId, importType: importType},
JSON.stringify(params)
);
};
Storage.prototype.importStatus = function(backend, addressBookId, importType, params) {
return this.requestRoute(
'addressbook/{backend}/{addressBookId}/{importType}/import/status',
'GET',
{backend: backend, addressBookId: addressBookId, importType: importType},
params
);
};
Storage.prototype.requestRoute = function(route, type, routeParams, params, additionalHeaders) {
var isJSON = (typeof params === 'string');
var contentType = isJSON
? (type === 'PATCH' ? 'application/json-merge-patch' : 'application/json')
: 'application/x-www-form-urlencoded';
var processData = !isJSON;
contentType += '; charset=UTF-8';
var url = OC.generateUrl('apps/contacts/' + route, routeParams);
var headers = {
Accept : 'application/json; charset=utf-8'
};
if(typeof additionalHeaders === 'object') {
headers = $.extend(headers, additionalHeaders);
}
var ajaxParams = {
type: type,
url: url,
dataType: 'json',
headers: headers,
contentType: contentType,
processData: processData,
data: params
};
var defer = $.Deferred();
$.ajax(ajaxParams)
.done(function(response, textStatus, jqXHR) {
console.log(jqXHR);
defer.resolve(new JSONResponse(jqXHR));
})
.fail(function(jqXHR/*, textStatus, error*/) {
console.log(jqXHR);
var response = jqXHR.responseText ? $.parseJSON(jqXHR.responseText) : null;
console.log('response', response);
defer.reject(new JSONResponse(jqXHR));
});
return defer.promise();
};
OC.Contacts.Storage = Storage;
})(window, jQuery, OC);