diff --git a/appinfo/routes.php b/appinfo/routes.php index ac5472e8..8d7d7681 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -8,6 +8,8 @@ */ namespace OCA\Contacts; +require_once __DIR__.'/../ajax/loghandler.php'; + //define the routes //for the index $this->create('contacts_index', '/') @@ -29,7 +31,7 @@ $this->create('contacts_index', '/') $this->create('contacts_address_books_for_user', 'addressbooks/{user}/') ->get() ->action( - function($params){ + function($params) { session_write_close(); $app = new App($params['user']); $addressBooks = $app->getAddressBooksForUser(); @@ -43,15 +45,16 @@ $this->create('contacts_address_books_for_user', 'addressbooks/{user}/') ) )); } - )->defaults(array('user' => \OCP\User::getUser())); + ) + ->defaults(array('user' => \OCP\User::getUser())); -$this->create('contacts_address_book_collection', 'addressbook/{user}/{backend}/{id}/contacts') +$this->create('contacts_address_book_collection', 'addressbook/{user}/{backend}/{addressbookid}/contacts') ->get() ->action( - function($params){ + function($params) { session_write_close(); $app = new App($params['user']); - $addressBook = $app->getAddressBook($params['backend'], $params['id']); + $addressBook = $app->getAddressBook($params['backend'], $params['addressbookid']); $lastModified = $addressBook->lastModified(); if(!is_null($lastModified)) { \OCP\Response::enableCaching(); @@ -73,4 +76,265 @@ $this->create('contacts_address_book_collection', 'addressbook/{user}/{backend}/ ) )); } - )->defaults(array('user' => \OCP\User::getUser())); + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_address_book_add', 'addressbook/{user}/{backend}/add') + ->post() + ->action( + function($params) { + session_write_close(); + $app = new App($params['user']); + $backend = App::getBackend('database', $params['user']); + $id = $backend->createAddressBook($_POST); + if($id === false) { + bailOut(App::$l10n->t('Error creating address book')); + } + \OCP\JSON::success(array( + 'data' => $backend->getAddressBook($id) + )); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_address_book_delete', 'addressbook/{user}/{backend}/{addressbookid}/delete') + ->post() + ->action( + function($params) { + session_write_close(); + $app = new App($params['user']); + $backend = App::getBackend('database', $params['user']); + if(!$backend->deleteAddressBook($params['addressbookid'])) { + bailOut(App::$l10n->t('Error deleting address book')); + } + \OCP\JSON::success(array( + 'data' => $backend->getAddressBook($id) + )); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_address_book_add_contact', 'addressbook/{user}/{backend}/{addressbookid}/contact/add') + ->post() + ->action( + function($params) { + session_write_close(); + $app = new App($params['user']); + $addressBook = $app->getAddressBook($params['backend'], $params['addressbookid']); + $id = $addressBook->addChild(); + if($id === false) { + bailOut(App::$l10n->t('Error creating contact.')); + } + $contact = $addressBook->getChild($id); + \OCP\JSON::success(array( + 'data' => Utils\JSONSerializer::serializeContact($contact), + )); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_contact_delete_property', 'addressbook/{user}/{backend}/{addressbookid}/contact/{contactid}/property/delete') + ->post() + ->action( + function($params) { + session_write_close(); + $name = isset($_POST['name']) ? $_POST['name'] : null; + $checksum = isset($_POST['checksum']) ? $_POST['checksum'] : null; + + debug('contacts_contact_delete_property, name: ' . print_r($name, true)); + debug('contacts_contact_delete_property, checksum: ' . print_r($checksum, true)); + + $app = new App($params['user']); + $contact = $app->getContact($params['backend'], $params['addressbookid'], $params['contactid']); + + if(!$contact) { + bailOut(App::$l10n->t('Couldn\'t find contact.')); + } + if(!$name) { + bailOut(App::$l10n->t('Property name is not set.')); + } + if(!$checksum && in_array($name, Utils\Properties::$multi_properties)) { + bailOut(App::$l10n->t('Property checksum is not set.')); + } + if(!is_null($checksum)) { + try { + $contact->unsetPropertyByChecksum($checksum); + } catch(Exception $e) { + bailOut(App::$l10n->t('Information about vCard is incorrect. Please reload the page.')); + } + } else { + unset($contact->{$name}); + } + if(!$contact->save()) { + bailOut(App::$l10n->t('Error saving contact to backend.')); + } + \OCP\JSON::success(array( + 'data' => array( + 'backend' => $params['backend'], + 'addressbookid' => $params['addressbookid'], + 'contactid' => $params['contactid'], + 'lastmodified' => $contact->lastModified(), + ) + )); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_contact_save_property', 'addressbook/{user}/{backend}/{addressbookid}/contact/{contactid}/property/save') + ->post() + ->action( + function($params) { + session_write_close(); + // TODO: When value is empty unset the property and return a checksum of 'new' if multi_property + $name = isset($_POST['name']) ? $_POST['name'] : null; + $value = isset($_POST['value']) ? $_POST['value'] : null; + $parameters = isset($_POST['parameters']) ? $_POST['parameters'] : array(); + $checksum = isset($_POST['checksum']) ? $_POST['checksum'] : null; + + debug('contacts_contact_save_property, name: ' . print_r($name, true)); + debug('contacts_contact_save_property, value: ' . print_r($value, true)); + debug('contacts_contact_save_property, parameters: ' . print_r($parameters, true)); + debug('contacts_contact_save_property, checksum: ' . print_r($checksum, true)); + + $app = new App($params['user']); + $contact = $app->getContact($params['backend'], $params['addressbookid'], $params['contactid']); + + $response = array('contactid' => $params['contactid']); + + if(!$contact) { + bailOut(App::$l10n->t('Couldn\'t find contact.')); + } + if(!$name) { + bailOut(App::$l10n->t('Property name is not set.')); + } + if(!$checksum && in_array($name, Utils\Properties::$multi_properties)) { + bailOut(App::$l10n->t('Property checksum is not set.')); + } elseif($checksum && in_array($name, Utils\Properties::$multi_properties)) { + try { + $checksum = $contact->setPropertyByChecksum($checksum, $name, $value, $parameters); + $response['checksum'] = $checksum; + } catch(Exception $e) { + bailOut(App::$l10n->t('Information about vCard is incorrect. Please reload the page.')); + } + } elseif(!in_array($name, Utils\Properties::$multi_properties)) { + if(!$contact->setPropertyByName($name, $value, $parameters)) { + bailOut(App::$l10n->t('Error setting property')); + } + } + if(!$contact->save()) { + bailOut(App::$l10n->t('Error saving property to backend')); + } + $response['lastmodified'] = $contact->lastModified(); + $contact->save(); + \OCP\JSON::success(array('data' => $response)); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_categories_list', 'groups/{user}/') + ->get() + ->action( + function($params) { + session_write_close(); + $catmgr = new \OC_VCategories('contact', $params['user']); + $categories = $catmgr->categories(\OC_VCategories::FORMAT_MAP); + foreach($categories as &$category) { + $ids = $catmgr->idsForCategory($category['name']); + $category['contacts'] = $ids; + } + + $favorites = $catmgr->getFavorites(); + + \OCP\JSON::success(array( + 'data' => array( + 'categories' => $categories, + 'favorites' => $favorites, + 'shared' => \OCP\Share::getItemsSharedWith('addressbook', Share_Backend_Addressbook::FORMAT_ADDRESSBOOKS), + 'lastgroup' => \OCP\Config::getUserValue( + $params['user'], + 'contacts', + 'lastgroup', 'all'), + 'sortorder' => \OCP\Config::getUserValue( + $params['user'], + 'contacts', + 'groupsort', ''), + ) + ) + ); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_categories_add', 'groups/{user}/add') + ->post() + ->action( + function($params) { + session_write_close(); + $name = isset($_POST['name']) ? trim(strip_tags($_POST['name'])) : null; + + if(is_null($name) || $name === "") { + bailOut(App::$l10n->t('No group name given.')); + } + + $catman = new \OC_VCategories('contact', $params['user']); + $id = $catman->add($name); + + if($id !== false) { + \OCP\JSON::success(array('data' => array('id'=>$id, 'name' => $name))); + } else { + bailOut(App::$l10n->t('Error adding group.')); + } + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_categories_delete', 'groups/{user}/delete') + ->post() + ->action( + function($params) { + session_write_close(); + $name = isset($_POST['name']) ? trim(strip_tags($_POST['name'])) : null; + + if(is_null($name) || $name === "") { + bailOut(App::$l10n->t('No group name given.')); + } + + $catman = new \OC_VCategories('contact', $params['user']); + $catman->delete($name); + + \OCP\JSON::success(); + } + ) + ->defaults(array('user' => \OCP\User::getUser())); + +$this->create('contacts_setpreference', 'preference/{user}/set') + ->post() + ->action( + function($params) { + session_write_close(); + $key = isset($_POST['key']) ? trim(strip_tags($_POST['key'])) : null; + $value = isset($_POST['value']) ? trim(strip_tags($_POST['value'])) : null; + + if(is_null($key) || $key === "") { + bailOut(App::$l10n->t('No key is given.')); + } + + if(is_null($value) || $value === "") { + bailOut(App::$l10n->t('No value is given.')); + } + + if(\OCP\Config::setUserValue($params['user'], 'contacts', $key, $value)) { + \OCP\JSON::success(array( + 'data' => array( + 'key' => $key, + 'value' => $value) + ) + ); + } else { + bailOut(App::$l10n->t( + 'Could not set preference: ' . $key . ':' . $value) + ); + } + } + ) + ->defaults(array('user' => \OCP\User::getUser())); diff --git a/js/app.js b/js/app.js index fc1cb555..b4cecdd7 100644 --- a/js/app.js +++ b/js/app.js @@ -319,6 +319,7 @@ OC.Contacts = OC.Contacts || { self.hideActions(); }); + // Keep error messaging at one place to be able to replace it. $(document).bind('status.contact.error', function(e, data) { OC.notify({message:data.message}); }); @@ -427,7 +428,7 @@ OC.Contacts = OC.Contacts || { $(document).bind('request.contact.export', function(e, data) { var id = parseInt(data.id); console.log('contact', data.id, 'request.contact.export'); - document.location.href = OC.linkTo('contacts', 'export.php') + '?contactid=' + self.currentid; + document.location.href = OC.linkTo('contacts', 'export.php') + '?' + $.param(data); }); $(document).bind('request.contact.close', function(e, data) { @@ -501,10 +502,17 @@ OC.Contacts = OC.Contacts || { // Group sorted, save the sort order $(document).bind('status.groups.sorted', function(e, result) { console.log('status.groups.sorted', result); - $.post(OC.filePath('contacts', 'ajax', 'setpreference.php'), {'key':'groupsort', 'value':result.sortorder}, function(jsondata) { - if(jsondata.status !== 'success') { - OC.notify({message: jsondata ? jsondata.data.message : t('contacts', 'Network or server error. Please inform administrator.')}); + $.when(self.storage.setPreference('groupsort', result.sortorder)).then(function(response) { + if(response.status !== 'success') { + OC.notify({message: response ? response.data.message : t('contacts', 'Network or server error. Please inform administrator.')}); } + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed saving sort order: {error}', {error:err}) + }); }); }); // Group selected, only show contacts from that group @@ -527,10 +535,17 @@ OC.Contacts = OC.Contacts || { } else { self.contacts.showContacts(self.currentgroup); } - $.post(OC.filePath('contacts', 'ajax', 'setpreference.php'), {'key':'lastgroup', 'value':self.currentgroup}, function(jsondata) { - if(!jsondata || jsondata.status !== 'success') { - OC.notify({message: (jsondata && jsondata.data) ? jsondata.data.message : t('contacts', 'Network or server error. Please inform administrator.')}); + $.when(self.storage.setPreference('lastgroup', self.currentgroup)).then(function(response) { + if(!response || response.status !== 'success') { + OC.notify({message: (response && response.data) ? response.data.message : t('contacts', 'Network or server error. Please inform administrator.')}); } + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed saving last group: {error}', {error:err}) + }); }); self.$rightContent.scrollTop(0); }); @@ -796,34 +811,25 @@ OC.Contacts = OC.Contacts || { var id = parseInt($(this).parents('li').first().data('id')); console.log('delete', id); var $li = $(this).parents('li').first(); - $.ajax({ - type:'POST', - url:OC.filePath('contacts', 'ajax', 'addressbook/delete.php'), - data:{ id: id }, - success:function(jsondata) { - console.log(jsondata); - if(jsondata.status == 'success') { - self.contacts.unsetAddressbook(id); - $li.remove(); - OC.notify({ - message:t('contacts','Deleting done. Click here to cancel reloading.'), - timeout:5, - timeouthandler:function() { - console.log('reloading'); - window.location.href = OC.linkTo('contacts', 'index.php'); - }, - clickhandler:function() { - console.log('reloading cancelled'); - OC.notify({cancel:true}); - } - }); - } else { - OC.notify({message:jsondata.data.message}); - } - }, - error:function(jqXHR, textStatus, errorThrown) { - OC.notify({message:textStatus + ': ' + errorThrown}); - id = false; + $.when(this.storage.deleteAddressBook('database',{addressbookid:id})) + .then(function(response) { + if(response.status == 'success') { + self.contacts.unsetAddressbook(id); + $li.remove(); + OC.notify({ + message:t('contacts','Deleting done. Click here to cancel reloading.'), + timeout:5, + timeouthandler:function() { + console.log('reloading'); + window.location.href = OC.Router.generate('contacts_index'); + }, + clickhandler:function() { + console.log('reloading cancelled'); + OC.notify({cancel:true}); + } + }); + } else { + OC.notify({message:response.data.message}); } }); }); @@ -864,10 +870,8 @@ OC.Contacts = OC.Contacts || { $addinput.addClass('loading'); $addAddressbookPart.find('button input').prop('disabled', true); console.log('adding', name); - self.addAddressbook({ - name: name, - description: '' - }, function(response) { + $.when(this.storage.addAddressBook('database', + {name: name, description: ''})).then(function(response) { if(!response || !response.status) { OC.notify({ message:t('contacts', 'Network or server error. Please inform administrator.') @@ -884,6 +888,13 @@ OC.Contacts = OC.Contacts || { $addinput.removeClass('loading'); $addAddressbookPart.find('button input').prop('disabled', false); $addAddressbookPart.hide().prev('button').show(); + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed adding address book: {error}', {error:err}) + }); }); } } else if($(this).is('.addaddressbookcancel')) { @@ -924,10 +935,8 @@ OC.Contacts = OC.Contacts || { var addAddressbookCallback = function(select, name) { var id = false; - self.addAddressbook({ - name: name, - description: '' - }, function(response) { + $.when(this.storage.addAddressBook('database', + {name: name, description: ''})).then(function(response) { if(!response || !response.status) { OC.notify({ message:t('contacts', 'Network or server error. Please inform administrator.') @@ -937,8 +946,15 @@ OC.Contacts = OC.Contacts || { OC.notify({message: response.message}); return false; } else if(response.status === 'success') { - id = response.addressbook.id; + id = response.data.id; } + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed adding addres books: {error}', {error:err}) + }); }); return id; }; @@ -1615,126 +1631,6 @@ OC.Contacts = OC.Contacts || { } }); }, - addAddressbook:function(data, cb) { - $.ajax({ - type:'POST', - async:false, - url:OC.filePath('contacts', 'ajax', 'addressbook/add.php'), - data:{ name: data.name, description: data.description }, - success:function(jsondata) { - if(jsondata.status == 'success') { - if(typeof cb === 'function') { - cb({ - status:'success', - addressbook: jsondata.data.addressbook - }); - } - } else { - if(typeof cb === 'function') { - cb({status:'error', message:jsondata.data.message}); - } else { - OC.notify({message:textStatus + ': ' + errorThrown}); - } - } - }, - error:function(jqXHR, textStatus, errorThrown) { - if(typeof cb === 'function') { - cb({ - status:'success', - message: textStatus + ': ' + errorThrown - }); - } else { - OC.notify({message:textStatus + ': ' + errorThrown}); - } - } - }); - }, - // NOTE: Deprecated - selectAddressbook:function(cb) { - var self = this; - var jqxhr = $.get(OC.filePath('contacts', 'templates', 'selectaddressbook.html'), function(data) { - $('body').append('
'); - var $dlg = $('#addressbook_dialog').html(data).octemplate({ - nameplaceholder: t('contacts', 'Enter name'), - descplaceholder: t('contacts', 'Enter description') - }).dialog({ - modal: true, height: 'auto', width: 'auto', - title: t('contacts', 'Select addressbook'), - buttons: { - 'Ok':function() { - aid = $(this).find('input:checked').val(); - if(aid == 'new') { - var displayname = $(this).find('input.name').val(); - var description = $(this).find('input.desc').val(); - if(!$.trim(displayname)) { - OC.dialogs.alert(t('contacts', 'The address book name cannot be empty.'), t('contacts', 'Error')); - return false; - } - console.log('ID, name and desc', aid, displayname, description); - if(typeof cb === 'function') { - // TODO: Create addressbook - var data = {name:displayname, description:description}; - self.addAddressbook(data, function(data) { - if(data.status === 'success') { - cb({ - status:'success', - addressbook:data.addressbook - }); - } else { - cb({status:'error'}); - } - }); - } - $(this).dialog('close'); - } else { - console.log('aid ' + aid); - if(typeof cb === 'function') { - cb({ - status:'success', - addressbook:self.contacts.addressbooks[parseInt(aid)] - }); - } - $(this).dialog('close'); - } - }, - 'Cancel':function() { - $(this).dialog('close'); - } - }, - close: function(event, ui) { - $(this).dialog('destroy').remove(); - $('#addressbook_dialog').remove(); - }, - open: function(event, ui) { - console.log('open', $(this)); - var $lastrow = $(this).find('tr.new'); - $.each(self.contacts.addressbooks, function(i, book) { - console.log('book', i, book); - if(book.owner === OC.currentUser - || (book.permissions & OC.PERMISSION_UPDATE - || book.permissions & OC.PERMISSION_CREATE - || book.permissions & OC.PERMISSION_DELETE)) { - var row = '' - + '' - + '{description}'; - var $row = $(row).octemplate({ - id:book.id, - displayname:book.displayname, - description:book.description - }); - $lastrow.before($row); - } - }); - $(this).find('input[type="radio"]').first().prop('checked', true); - $lastrow.find('input.name,input.desc').on('focus', function(e) { - $lastrow.find('input[type="radio"]').prop('checked', true); - }); - } - }); - }).error(function() { - OC.notify({message: t('contacts', 'Network or server error. Please inform administrator.')}); - }); - } }; $(document).ready(function() { diff --git a/js/contacts.js b/js/contacts.js index d70072e5..2a3b3a94 100644 --- a/js/contacts.js +++ b/js/contacts.js @@ -16,6 +16,7 @@ OC.Contacts = OC.Contacts || {}; var Contact = function(parent, id, metadata, data, listtemplate, dragtemplate, fulltemplate, detailtemplates) { //console.log('contact:', id, metadata, data); //parent, id, data, listtemplate, fulltemplate); this.parent = parent, + this.storage = parent.storage, this.id = id, this.metadata = metadata, this.data = data, @@ -34,24 +35,6 @@ OC.Contacts = OC.Contacts || {}; } }; - Contact.prototype.setThumbnail = function(refresh) { - if(this.getPreferredValue('PHOTO', null) === null) { - return; - } - var $elem = this.getListItemElement().find('td.name'); - if(!$elem.hasClass('thumbnail')) { - return; - } - $elem.removeClass('thumbnail'); - var refreshstr = refresh ? '&refresh='+Math.random() : ''; - $elem.css('background-image', 'url(' + OC.filePath('', '', 'remote.php') - +'/contactthumbnail?backend=' - +this.metadata.backend+'&parent=' - +this.metadata.parent+'&id=' - +this.id+refreshstr + ')' - ); - } - Contact.prototype.setAsSaving = function(obj, state) { if(!obj) { return; @@ -155,6 +138,8 @@ OC.Contacts = OC.Contacts || {}; console.log('Contact.deleteProperty, element', element, $container); var params = { name: element, + backend: this.metadata.backend, + addressbookid: this.metadata.parent, id: this.id }; if(this.multi_properties.indexOf(element) !== -1) { @@ -171,8 +156,9 @@ OC.Contacts = OC.Contacts || {}; } this.setAsSaving(obj, true); var self = this; - $.post(OC.filePath('contacts', 'ajax', 'contact/deleteproperty.php'), params, function(jsondata) { - if(!jsondata) { + $.when(this.storage.deleteProperty(this.metadata.backend, this.metadata.parent, this.id, params)) + .then(function(response) { + if(!response) { $(document).trigger('status.contact.error', { status: 'error', message: t('contacts', 'Network or server error. Please inform administrator.') @@ -180,7 +166,7 @@ OC.Contacts = OC.Contacts || {}; self.setAsSaving(obj, false); return false; } - if(jsondata.status == 'success') { + if(response.status == 'success') { // TODO: Test if removing from internal data structure works if(self.multi_properties.indexOf(element) !== -1) { // First find out if an existing element by looking for checksum @@ -225,12 +211,20 @@ OC.Contacts = OC.Contacts || {}; } else { $(document).trigger('status.contact.error', { status: 'error', - message: jsondata.data.message + message: response.data.message }); self.setAsSaving(obj, false); return false; } - },'json'); + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed deleting property: {error}', {error:err}) + }); + }); +; }; /** @@ -259,12 +253,15 @@ OC.Contacts = OC.Contacts || {}; } var obj = null; var element = null; - var q = ''; + var args = [], q = ''; if(params.obj) { obj = params.obj; + args = this.argumentsFor(obj); + args['parameters'] = this.parametersFor(obj); q = this.queryStringFor(obj); element = this.propertyTypeFor(obj); } else { + args = params; element = params.name; var value = utils.isArray(params.value) ? $.param(params.value) @@ -272,10 +269,12 @@ OC.Contacts = OC.Contacts || {}; q = 'id=' + this.id + '&value=' + value + '&name=' + element; } console.log('q', q); + console.log('args', args); var self = this; this.setAsSaving(obj, true); - $.post(OC.filePath('contacts', 'ajax', 'contact/saveproperty.php'), q, function(jsondata){ - if(!jsondata) { + $.when(this.storage.saveProperty(this.metadata.backend, this.metadata.parent, this.id, args)) + .then(function(response) { + if(!response) { $(document).trigger('status.contact.error', { status: 'error', message: t('contacts', 'Network or server error. Please inform administrator.') @@ -284,7 +283,7 @@ OC.Contacts = OC.Contacts || {}; self.setAsSaving(obj, false); return false; } - if(jsondata.status == 'success') { + if(response.status == 'success') { if(!self.data[element]) { self.data[element] = []; } @@ -297,7 +296,7 @@ OC.Contacts = OC.Contacts || {}; self.pushToUndo({ action:'save', name: element, - newchecksum: jsondata.data.checksum, + newchecksum: response.data.checksum, oldchecksum: checksum, newvalue: value, oldvalue: obj.defaultValue @@ -308,7 +307,7 @@ OC.Contacts = OC.Contacts || {}; name: element, value: value, parameters: parameters, - checksum: jsondata.data.checksum + checksum: response.data.checksum }; return false; } @@ -318,17 +317,17 @@ OC.Contacts = OC.Contacts || {}; self.pushToUndo({ action:'add', name: element, - newchecksum: jsondata.data.checksum, + newchecksum: response.data.checksum, newvalue: value, }); self.data[element].push({ name: element, value: value, parameters: parameters, - checksum: jsondata.data.checksum, + checksum: response.data.checksum, }); } - self.propertyContainerFor(obj).data('checksum', jsondata.data.checksum); + self.propertyContainerFor(obj).data('checksum', response.data.checksum); } else { // Save value and parameters internally var value = obj ? self.valueFor(obj) : params.value; @@ -417,7 +416,7 @@ OC.Contacts = OC.Contacts || {}; name: element, value: value, parameters: self.parametersFor(obj), - checksum: jsondata.data.checksum + checksum: response.data.checksum }; break; default: @@ -433,12 +432,12 @@ OC.Contacts = OC.Contacts || {}; } else { $(document).trigger('status.contact.error', { status: 'error', - message: jsondata.data.message + message: response.data.message }); self.setAsSaving(obj, false); return false; } - },'json'); + }); }; /** @@ -513,23 +512,24 @@ OC.Contacts = OC.Contacts || {}; * @returns The callback gets an object as argument with a variable 'status' of either 'success' * or 'error'. On success the 'data' property of that object contains the contact id as 'id', the * addressbook id as 'aid' and the contact data structure as 'details'. + * TODO: Use Storage for adding and make sure to get all metadata. */ Contact.prototype.add = function(params, cb) { var self = this; - $.post(OC.filePath('contacts', 'ajax', 'contact/add.php'), - params, function(jsondata) { - if(!jsondata) { + $.when(this.storage.addContact(this.metadata.backend, this.metadata.parent)) + .then(function(response) { + if(!response) { $(document).trigger('status.contact.error', { status: 'error', message: t('contacts', 'Network or server error. Please inform administrator.') }); return false; } - if(jsondata.status === 'success') { - self.id = String(jsondata.data.id); - self.metadata.owner = String(jsondata.data.parent); - self.data = jsondata.data.details; - self.$groupSelect.multiselect('enable'); + if(response.status === 'success') { + self.id = String(response.data.metadata.id); + self.metadata = response.data.metadata; + self.data = response.data.data; + self.$groupSelect.multiselect('widget').show(); // Add contact to current group if(self.groupprops && self.groupprops.currentgroup.id !== 'all' && self.groupprops.currentgroup.id !== 'fav') { @@ -550,7 +550,7 @@ OC.Contacts = OC.Contacts || {}; }); } if(typeof cb == 'function') { - cb(jsondata); + cb(response); } }); }; @@ -589,6 +589,39 @@ OC.Contacts = OC.Contacts || {}; }); }; + Contact.prototype.argumentsFor = function(obj) { + var args = {}; + var ptype = this.propertyTypeFor(obj); + args['name'] = ptype; + + if(this.multi_properties.indexOf(ptype) !== -1) { + args['checksum'] = this.checksumFor(obj); + } + + if($(obj).hasClass('propertycontainer')) { + if($(obj).is('select[data-element="categories"]')) { + args['value'] = []; + $.each($(obj).find(':selected'), function(idx, e) { + args['value'].push($(e).text()); + }); + } else { + args['value'] = $(obj).val(); + } + } else { + var $elements = this.propertyContainerFor(obj) + .find('input.value,select.value,textarea.value'); + if($elements.length > 1) { + args['value'] = []; + $.each($elements, function(idx, e) { + args['value'].push($(e).text()); + }); + } else { + args['value'] = $elements.val(); + } + } + return args; + }; + Contact.prototype.queryStringFor = function(obj) { var q = 'id=' + this.id; var ptype = this.propertyTypeFor(obj); @@ -631,7 +664,7 @@ OC.Contacts = OC.Contacts || {}; Contact.prototype.valueFor = function(obj) { var $container = this.propertyContainerFor(obj); console.assert($container.length > 0, 'Couldn\'t find container for ' + $(obj)); - return $container.is('input') + return $container.is('input.value') ? $container.val() : (function() { var $elem = $container.find('textarea.value,input.value:not(:checkbox)'); @@ -650,23 +683,29 @@ OC.Contacts = OC.Contacts || {}; Contact.prototype.parametersFor = function(obj, asText) { var parameters = []; - $.each(this.propertyContainerFor(obj).find('select.parameter,input:checkbox:checked.parameter,textarea'), function(i, elem) { + $.each(this.propertyContainerFor(obj) + .find('select.parameter,input:checkbox:checked.parameter,textarea'), // Why do I look for textarea? + function(i, elem) { var $elem = $(elem); var paramname = $elem.data('parameter'); if(!parameters[paramname]) { parameters[paramname] = []; } - var val; - if(asText) { - if($elem.is(':checkbox')) { - val = $elem.attr('title'); - } else if($elem.is('select')) { - val = $elem.find(':selected').text(); + if($elem.is(':checkbox')) { + if(asText) { + parameters[paramname].push($elem.attr('title')); + } else { + parameters[paramname].push($elem.attr('value')); } - } else { - val = $elem.val(); + } else if($elem.is('select')) { + $.each($elem.find(':selected'), function(idx, e) { + if(asText) { + parameters[paramname].push($(e).text()); + } else { + parameters[paramname].push($(e).val()); + } + }); } - parameters[paramname].push(val); }); return parameters; }; @@ -739,7 +778,7 @@ OC.Contacts = OC.Contacts || {}; }); self.$groupSelect.bind('multiselectclick', function(event, ui) { var action = ui.checked ? 'addtogroup' : 'removefromgroup'; - console.assert(typeof self.id === 'number', 'ID is not a number') + console.assert(typeof self.id === 'string', 'ID is not a string') $(document).trigger('request.contact.' + action, { id: self.id, groupid: parseInt(ui.value) @@ -751,10 +790,38 @@ OC.Contacts = OC.Contacts || {}; } }); if(!self.id) { - self.$groupSelect.multiselect('disable'); + self.$groupSelect.multiselect('widget').hide(); } }; + var buildAddressBookSelect = function(availableAddressBooks) { + console.log('address books', availableAddressBooks.length, availableAddressBooks); + /* TODO: + * - Check address books permissions. + * - Add method to change address book. + */ + $.each(availableAddressBooks, function(idx, addressBook) { + console.log('addressBook', idx, addressBook); + var $option = $(''); + if(self.metadata.parent === addressBook.id + && self.metadata.backend === addressBook.backend) { + $option.attr('selected', 'selected'); + } + self.$addressBookSelect.append($option); + }); + self.$addressBookSelect.multiselect({ + header: false, + selectedList: 3, + noneSelectedText: self.$addressBookSelect.attr('title'), + selectedText: t('contacts', '# groups') + }); + if(self.id) { + self.$addressBookSelect.multiselect('widget').hide(); + } + }; + var n = this.getPreferredValue('N', ['', '', '', '', '']); //console.log('Contact.renderContact', this.data); var values = this.data @@ -786,6 +853,11 @@ OC.Contacts = OC.Contacts || {}; this.$groupSelect = this.$fullelem.find('#contactgroups'); buildGroupSelect(groupprops.groups); + if(Object.keys(this.parent.addressbooks).length > 1) { + this.$addressBookSelect = this.$fullelem.find('#contactaddressbooks'); + buildAddressBookSelect(this.parent.addressbooks); + } + this.$addMenu = this.$fullelem.find('#addproperty'); this.$addMenu.on('change', function(event) { //console.log('add', $(this).val()); @@ -837,11 +909,15 @@ OC.Contacts = OC.Contacts || {}; }); } else if($(this).is('.export')) { $(document).trigger('request.contact.export', { - id: self.id + backend: self.metadata.backend, + parent: self.metadata.parent, + contactid: self.id }); } else if($(this).is('.delete')) { $(document).trigger('request.contact.delete', { - id: self.id + backend: self.metadata.backend, + parent: self.metadata.parent, + contactid: self.id }); } return false; @@ -864,6 +940,7 @@ OC.Contacts = OC.Contacts || {}; return; } console.log('change', this.defaultValue, this.value); + this.defaultValue = this.value; self.saveProperty({obj:event.target}); }); @@ -1167,6 +1244,27 @@ OC.Contacts = OC.Contacts || {}; return this.detailTemplates['impp'].octemplate(values); }; + /** + * Set a thumbnail for the contact if a PHOTO property exists + */ + Contact.prototype.setThumbnail = function(refresh) { + if(this.getPreferredValue('PHOTO', null) === null) { + return; + } + var $elem = this.getListItemElement().find('td.name'); + if(!$elem.hasClass('thumbnail')) { + return; + } + $elem.removeClass('thumbnail'); + var refreshstr = refresh ? '&refresh='+Math.random() : ''; + $elem.css('background-image', 'url(' + OC.filePath('', '', 'remote.php') + +'/contactthumbnail?backend=' + +this.metadata.backend+'&parent=' + +this.metadata.parent+'&id=' + +this.id+refreshstr + ')' + ); + } + /** * Render the PHOTO property. */ @@ -1174,8 +1272,14 @@ OC.Contacts = OC.Contacts || {}; var self = this; var id = this.id || 'new', backend = this.metadata.backend, - parent = this.metadata.parent; - var refreshstr = '&refresh='+Math.random(); + parent = this.metadata.parent, + src; + if(this.getPreferredValue('PHOTO', null) === null) { + src = this.storage.contactPhoto; + } else { + var refreshstr = '&refresh='+Math.random(); + src = OC.linkTo('contacts', 'photo.php')+'?backend='+backend+'&parent='+parent+'&id='+id+refreshstr; + } this.$photowrapper = this.$fullelem.find('#photowrapper'); this.$photowrapper.addClass('loading').addClass('wait'); var $phototools = this.$fullelem.find('#phototools'); @@ -1189,7 +1293,7 @@ OC.Contacts = OC.Contacts || {}; $(this).insertAfter($phototools).fadeIn(); }).error(function () { OC.notify({message:t('contacts','Error loading profile picture.')}); - }).attr('src', OC.linkTo('contacts', 'photo.php')+'?backend='+backend+'&parent='+parent+'&id='+id+refreshstr); + }).attr('src', src); if(!dontloadhandlers && this.isEditable()) { this.$photowrapper.on('mouseenter', function(event) { @@ -1429,6 +1533,14 @@ OC.Contacts = OC.Contacts || {}; }); }; + /** + * Get the number of contacts in the list + * @return integer + */ + ContactList.prototype.count = function() { + return Object.keys(this.contacts.contacts).length + } + /** * Show/hide contacts belonging to an addressbook. * @param int aid. Addressbook id. @@ -1698,10 +1810,17 @@ OC.Contacts = OC.Contacts || {}; * @param object props */ ContactList.prototype.addContact = function(props) { + var addressBook = this.addressbooks[Object.keys(this.addressbooks)[0]] + var metadata = { + parent: addressBook.id, + backend: addressBook.backend, + permissions: addressBook.permissions, + owner: addressBook.owner + }; var contact = new Contact( this, null, - {owner:OC.currentUser, permissions: 31}, + metadata, null, this.$contactListItemTemplate, this.$contactDragItemTemplate, @@ -1718,7 +1837,7 @@ OC.Contacts = OC.Contacts || {}; /** * Get contacts selected in list * - * @returns array of integer contact ids. + * @returns array of contact ids. */ ContactList.prototype.getSelectedContacts = function() { var contacts = []; @@ -1752,6 +1871,7 @@ OC.Contacts = OC.Contacts || {}; return $(a).find('td.name').text().toUpperCase().localeCompare($(b).find('td.name').text().toUpperCase()); }); + // TODO: Test if I couldn't just append rows. var items = []; $.each(rows, function(index, row) { items.push(row); @@ -1780,15 +1900,7 @@ OC.Contacts = OC.Contacts || {}; ContactList.prototype.setAddressbook = function(book) { console.log('setAddressbook', book.id, this.addressbooks); var id = String(book.id); - this.addressbooks[id] = book;/*{ - owner: book.userid, - uri: book.uri, - permissions: parseInt(book.permissions), - id: String(book.id), - displayname: book.displayname, - description: book.description - //active: Boolean(parseInt(book.active)) - };*/ + this.addressbooks[id] = book; }; /** @@ -1797,39 +1909,49 @@ OC.Contacts = OC.Contacts || {}; */ ContactList.prototype.getAddressBooks = function() { var self = this; - console.time('load_addressbooks'); - $.when(this.storage.getAddressBooksForUser()) - .then(function(response) { - console.timeEnd('load_addressbooks'); - console.log('response success', response, response.data.addressbooks.length); - var num = response.data.addressbooks.length; - $.each(response.data.addressbooks, function(idx, addressBook) { - self.setAddressbook(addressBook); - self.loadContacts( - addressBook['backend'], - addressBook['id'], - function(response) { - console.log('loaded', idx, response); - num -= 1; - if(num === 0) { - setTimeout(function() { - self.doSort(); - self.setCurrent(self.$contactList.find('tr:visible').first().data('id'), false); - } - , 2000); - $(document).trigger('status.contacts.loaded', { - status: true, - numcontacts: self.length, - is_indexed: true // FIXME: jsondata.data.is_indexed - }); + $.when(this.storage.getAddressBooksForUser()).then(function(response) { + console.log('response success', response, response.data.addressbooks.length); + var num = response.data.addressbooks.length; + $.each(response.data.addressbooks, function(idx, addressBook) { + self.setAddressbook(addressBook); + self.loadContacts( + addressBook['backend'], + addressBook['id'], + function(response) { + console.log('loaded', idx, response); + num -= 1; + if(num === 0 && self.length > 0) { + setTimeout(function() { + self.doSort(); // TODO: Test this + self.setCurrent(self.$contactList.find('tr:visible').first().data('id'), false); } - }); - }); - }) - .fail(function(jqxhr, textStatus, error) { - var err = textStatus + ', ' + error; - console.log( "Request Failed: " + err); + , 2000); + $(document).trigger('status.contacts.loaded', { + status: true, + numcontacts: self.length, + is_indexed: true // FIXME: jsondata.data.is_indexed + }); + if(self.length === 0) { + $(document).trigger('status.nomorecontacts'); + } + } + if(response.status === 'error') { + $(document).trigger('status.contact.error', { + message: + t('contacts', 'Failed loading contacts from {addressbook}: {error}', + {addressbook:addressBook['displayname'], error:err}) + }); + } + }); }); + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed loading address books: {error}', {error:err}) + }); + }); }; /** @@ -1838,56 +1960,51 @@ OC.Contacts = OC.Contacts || {}; */ ContactList.prototype.loadContacts = function(backend, addressBookId, cb) { var self = this; - $.when(this.storage.getContacts(backend, addressBookId)) - .then(function(response) { - console.log('response success', response); - var items = []; - if(response.data.contacts.length === 0) { - // FIXME: When loading addressbook independently this shouldn't be triggered..? - //$(document).trigger('status.nomorecontacts'); - } - $.each(response.data.contacts, function(c, contact) { - var id = String(contact.metadata.id); - contact.metadata.backend = backend; - self.contacts[id] - = new Contact( - self, - id, - contact.metadata, - contact.data, - self.$contactListItemTemplate, - self.$contactDragItemTemplate, - self.$contactFullTemplate, - self.contactDetailTemplates - ); - self.length +=1; - var $item = self.contacts[id].renderListItem(); - items.push($item.get(0)); - $item.find('td.name').draggable({ - cursor: 'move', - distance: 10, - revert: 'invalid', - helper: function (e,ui) { - return self.contacts[id].renderDragItem().appendTo('body'); - }, - opacity: 1, - scope: 'contacts' - }); - if(items.length === 100) { - self.$contactList.append(items); - items = []; - } + $.when(this.storage.getContacts(backend, addressBookId)).then(function(response) { + console.log('response success', response); + var items = []; + $.each(response.data.contacts, function(c, contact) { + var id = String(contact.metadata.id); + contact.metadata.backend = backend; + self.contacts[id] + = new Contact( + self, + id, + contact.metadata, + contact.data, + self.$contactListItemTemplate, + self.$contactDragItemTemplate, + self.$contactFullTemplate, + self.contactDetailTemplates + ); + self.length +=1; + var $item = self.contacts[id].renderListItem(); + items.push($item.get(0)); + $item.find('td.name').draggable({ + cursor: 'move', + distance: 10, + revert: 'invalid', + helper: function (e,ui) { + return self.contacts[id].renderDragItem().appendTo('body'); + }, + opacity: 1, + scope: 'contacts' }); - if(items.length > 0) { + if(items.length === 100) { self.$contactList.append(items); + items = []; } - cb({status:'success'}); - }) - .fail(function(jqxhr, textStatus, error) { - var err = textStatus + ', ' + error; - console.log( "Request Failed: " + err); - cb({status:'success'}); }); + if(items.length > 0) { + self.$contactList.append(items); + } + cb({status:'success'}); + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + cb({status:'error', message: err}); + }); }; OC.Contacts.ContactList = ContactList; diff --git a/js/groups.js b/js/groups.js index 4d236611..b15d0459 100644 --- a/js/groups.js +++ b/js/groups.js @@ -185,7 +185,7 @@ OC.Contacts = OC.Contacts || {}; } var self = this; var doPost = false; - if(typeof contactid === 'number') { + if(typeof contactid === 'string') { if(contacts.indexOf(contactid) === -1) { ids.push(contactid); doPost = true; @@ -300,6 +300,7 @@ OC.Contacts = OC.Contacts || {}; } } if(doPost) { + // TODO: Use Storage $.post(OC.filePath('contacts', 'ajax', 'categories/removefrom.php'), {contactids: ids, categoryid: groupid},function(jsondata) { if(!jsondata) { if(typeof cb === 'function') { @@ -397,8 +398,8 @@ OC.Contacts = OC.Contacts || {}; var contacts = $elem.data('contacts'); var self = this; console.log('delete group', groupid, contacts); - $.post(OC.filePath('contacts', 'ajax', 'categories/delete.php'), {categories: name}, function(jsondata) { - if (jsondata && jsondata.status == 'success') { + $.when(this.storage.deleteGroup(name)).then(function(response) { + if (response && response.status == 'success') { $(document).trigger('status.group.groupremoved', { groupid: groupid, newgroupid: parseInt($newelem.data('id')), @@ -411,8 +412,15 @@ OC.Contacts = OC.Contacts || {}; // } if(typeof cb === 'function') { - cb(jsondata); + cb(response); } + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed deleting group: {error}', {error:err}) + }); }); }; @@ -545,10 +553,10 @@ OC.Contacts = OC.Contacts || {}; } return; } - $.post(OC.filePath('contacts', 'ajax', 'categories/add.php'), {category: name}, function(jsondata) { - if (jsondata && jsondata.status == 'success') { - name = jsondata.data.name; - var id = jsondata.data.id; + $.when(this.storage.addGroup(name)).then(function(response) { + if (response && response.status == 'success') { + name = response.data.name; + var id = response.data.id; var tmpl = self.$groupListItemTemplate; var $elem = params.element ? params.element @@ -582,9 +590,16 @@ OC.Contacts = OC.Contacts || {}; } } else { if(typeof cb === 'function') { - cb({status:'error', message:jsondata.data.message}); + cb({status:'error', message:response.data.message}); } } + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ', ' + error; + console.log( "Request Failed: " + err); + $(document).trigger('status.contact.error', { + message: t('contacts', 'Failed adding group: {error}', {error:err}) + }); }); }; @@ -595,9 +610,7 @@ OC.Contacts = OC.Contacts || {}; var tmpl = this.$groupListItemTemplate; tmpl.octemplate({id: 'all', type: 'all', num: numcontacts, name: t('contacts', 'All')}).appendTo($groupList); - $.when(this.storage.getGroupsForUser()) - .then(function(jsondata) { - //$.getJSON(OC.filePath('contacts', 'ajax', 'categories/list.php'), {}, function(jsondata) { + $.when(this.storage.getGroupsForUser()).then(function(jsondata) { if (jsondata && jsondata.status == 'success') { self.lastgroup = jsondata.data.lastgroup; self.sortorder = jsondata.data.sortorder.length > 0 diff --git a/js/storage.js b/js/storage.js index 0a0814eb..a42227b3 100644 --- a/js/storage.js +++ b/js/storage.js @@ -42,6 +42,142 @@ OC.Contacts = OC.Contacts || {}; ); } + /** + * Add an address book to a specific backend + * + * @param string backend - currently defaults to 'database' + * @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( + 'contacts_address_book_add', + 'POST', + {user: this.user, backend: 'database'}, + params + ); + } + + /** + * Delete an address book from a specific backend + * + * @param string backend + * @param string addressbookid Address book ID + */ + Storage.prototype.deleteAddressBook = function(backend, addressbookid) { + console.log('Storage.deleteAddressBook', backend, addressbookid); + return this.requestRoute( + 'contacts_address_book_delete', + 'POST', + {user: this.user, backend: 'database', addressbookid: addressbookid} + ); + } + + /** + * 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) { + return this.requestRoute( + 'contacts_address_book_collection', + 'GET', + {user: this.user, backend: backend, addressbookid: addressbookid} + ); + } + + /** + * 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( + 'contacts_address_book_add_contact', + 'POST', + {user: this.user, backend: backend, addressbookid: addressbookid} + ); + } + + /** + * Delete a single property. + * + * @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 checksum For non-singular properties such as email this must contain + * an 8 character md5 checksum of the serialized \Sabre\Property + */ + Storage.prototype.deleteProperty = function(backend, addressbookid, contactid, params) { + return this.requestRoute( + 'contacts_contact_delete_property', + 'POST', + {user: this.user, backend: backend, addressbookid: addressbookid, contactid: contactid}, + params + ); + } + + /** + * Save a property. + * + * @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 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.saveProperty = function(backend, addressbookid, contactid, params) { + return this.requestRoute( + 'contacts_contact_save_property', + 'POST', + {user: this.user, backend: backend, addressbookid: addressbookid, contactid: contactid}, + params + ); + } + /** * Get all groups for this user. * @@ -65,60 +201,62 @@ OC.Contacts = OC.Contacts || {}; } /** - * Get contacts from an address book from a specific backend + * Add a group * - * @param string backend - * @param string id Address book ID - * @return An array containing contact data e.g.: + * @param string name + * @return A JSON object containing the (maybe sanitized) group name and its ID: * { - * 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 + * 'id':1234, + * 'name':'My group' * } */ - Storage.prototype.getContacts = function(backend, id) { + Storage.prototype.addGroup = function(name) { + console.log('Storage.addGroup', name); return this.requestRoute( - 'contacts_address_book_collection', - 'GET', - {user: this.user, backend: backend, id: id} + 'contacts_categories_add', + 'POST', + {user: this.user}, + {name: name} ); } - Storage.prototype.requestRoute = function(route, type, params) { + /** + * Delete a group + * + * @param string name + */ + Storage.prototype.deleteGroup = function(name) { + return this.requestRoute( + 'contacts_categories_delete', + 'POST', + {user: this.user}, + {name: name} + ); + } + + /** + * Set a user preference + * + * @param string key + * @param string value + */ + Storage.prototype.setPreference = function(key, value) { + return this.requestRoute( + 'contacts_setpreference', + 'POST', + {user: this.user}, + {key: key, value:value} + ); + } + + Storage.prototype.requestRoute = function(route, type, routeParams, params) { var self = this; - //var dfd = new $.Deferred(); - var url = OC.Router.generate(route, params); - return $.ajax({type: type, url: url});/* - .done(function(jsondata) { - if(!jsondata || !jsondata.status) { - console.log(type, 'error. Response:', jsondata); - dfd.reject({ - status: 'error', - message: self.getMessage('network_or_server_error') - }); - } else if(jsondata.status === 'success') { - dfd.resolve(jsondata.data); - } else if(jsondata.status === 'error') { - dfd.reject({ - status: 'error', - message: jsondata.data.message - }); - } - }).fail(function(jqxhr, textStatus, error) { - var err = textStatus + ', ' + error; - console.log( "Request Failed: " + err); - dfd.reject({ - status: 'error', - message: t('contacts', 'Failed getting address books: {error}', {error: err}) - }); - }); - return dfd.promise();*/ + var url = OC.Router.generate(route, routeParams); + var ajaxParams = {type: type, url: url, dataType: 'json'}; + if(typeof params === 'object') { + ajaxParams['data'] = params; + } + return $.ajax(ajaxParams); } OC.Contacts.Storage = Storage;