diff --git a/appinfo/routes.php b/appinfo/routes.php index 0d3aa354..82346416 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -215,6 +215,15 @@ $this->create('contacts_categories_delete', 'groups/delete') } ); +$this->create('contacts_categories_rename', 'groups/rename') + ->post() + ->action( + function($params) { + session_write_close(); + Main::main('GroupController', 'renameGroup', $params, new DIContainer()); + } + ); + $this->create('contacts_categories_addto', 'groups/addto/{categoryid}') ->post() ->action( diff --git a/js/app.js b/js/app.js index 0039aec0..7b5351f2 100644 --- a/js/app.js +++ b/js/app.js @@ -577,6 +577,18 @@ OC.Contacts = OC.Contacts || { }); }); + $(document).bind('status.group.grouprenamed', function(e, result) { + console.log('status.group.grouprenamed', result); + $.each(result.contacts, function(idx, contactid) { + var contact = self.contacts.findById(contactid); + if(!contact) { + console.log('Couldn\'t find contact', contactid) + return true; // continue + } + contact.renameGroup(result.from, result.to); + }); + }); + $(document).bind('status.group.contactadded', function(e, result) { console.log('status.group.contactadded', result); var contact = self.contacts.findById(result.contactid); diff --git a/js/contacts.js b/js/contacts.js index 932f2b99..58a8cd8e 100644 --- a/js/contacts.js +++ b/js/contacts.js @@ -165,6 +165,29 @@ OC.Contacts = OC.Contacts || {}; }*/ }; + /** + * Update group name internally. No saving as this is done by groups backend. + */ + Contact.prototype.renameGroup = function(from, to) { + if(!this.data.CATEGORIES.length) { + console.warn(this.getDisplayName(), 'had no groups!?!'); + return; + } + var groups = this.data.CATEGORIES[0].value; + var self = this; + $.each(groups, function(idx, group) { + if(from.toLowerCase() === group.toLowerCase()) { + console.log('Updating group name for', self.getDisplayName(), group, to); + self.data.CATEGORIES[0].value[idx] = to; + return false; // break + } + }); + $(document).trigger('status.contact.updated', { + property: 'CATEGORIES', + contact: this + }); + }; + Contact.prototype.pushToUndo = function(params) { // Check if the same property has been changed before // and update it's checksum if so. @@ -1926,7 +1949,7 @@ OC.Contacts = OC.Contacts || {}; id = String(id); if(typeof this.contacts[id] === 'undefined') { console.warn('Could not find contact with id', id); - console.trace(); + //console.trace(); return null; } return this.contacts[String(id)]; diff --git a/js/groups.js b/js/groups.js index 3fa1614f..27c5642b 100644 --- a/js/groups.js +++ b/js/groups.js @@ -21,34 +21,36 @@ OC.Contacts = OC.Contacts || {}; this.$groupList = groupList; var self = this; var numtypes = ['category', 'fav', 'all']; - this.$groupList.on('click', 'li', function(event) { + this.$groupList.on('click', 'li.group', function(event) { $('.tipsy').remove(); if(wrongKey(event)) { return; } - console.log($(event.target)); + console.log('group click', $(this)); if($(event.target).is('.action.delete')) { + event.stopPropagation(); + event.preventDefault(); var id = $(event.target).parents('li').first().data('id'); self.deleteGroup(id, function(response) { if(response.error) { OC.notify({message:response.data.message}); } }); - } else if($(event.target).is('.add-group')) { - //self.editGroup(); - } else if($(event.target).is('.add-contact')) { - $.noop(); // handled elsewhere in app.js + } else if($(event.target).is('.action.edit')) { + event.stopPropagation(); + event.preventDefault(); + self.editGroup($(this)); } else { - self.selectGroup({element:$(this)}); + if($(this).is(':not(.editing)')) { + self.selectGroup({element:$(this)}); + } } }); var $addInput = this.$groupList.find('.add-group'); $addInput.addnew({ ok: function(event, name) { - console.log('add-address-book ok', name); $addInput.addClass('loading'); self.addGroup({name:name}, function(response) { - console.log('response', response); if(response.error) { $(document).trigger('status.contact.error', { message: response.message @@ -117,6 +119,16 @@ OC.Contacts = OC.Contacts || {}; this.selectGroup({id:this.lastgroup}); } + /** + * Test if a group with this name exists (case-insensitive) + * + * @param string name + * @return bool + */ + GroupList.prototype.hasGroup = function(name) { + return (this.findByName(name) !== null); + } + /** * Get the group name by id. * @@ -131,6 +143,22 @@ OC.Contacts = OC.Contacts || {}; //return $.trim(this.findById(id).clone().find("*").remove().end().text()); //.contents().filter(function(){ return(this.nodeType == 3); }).text().trim(); }; + /** Get the group element by name. + * + * @param string name. The name of the group to search for (case-insensitive). + * @returns object|null The jQuery object. + */ + GroupList.prototype.findByName = function(name) { + var $elem = null; + self.$groupList.find('li[data-type="category"]').each(function() { + if ($(this).data('rawname').toLowerCase() === name.toLowerCase()) { + $elem = $(this); + return false; //break out of loop + } + }); + return $elem; + }; + /** Get the group element by id. * * @param integer id. The numeric group or addressbook id. @@ -460,94 +488,78 @@ OC.Contacts = OC.Contacts || {}; /** * Edit a groups name. - * Currently only used for adding, as renaming a group also - * requires updating all contacts in that group. * - * @param integer id. Group id NOTE: Not used yet. - * FIXME: This works fine for adding, but will need refactoring - * if used for renaming. + * @param object $element jQuery element */ - /*GroupList.prototype.editGroup = function(id) { + GroupList.prototype.editGroup = function($element) { + console.log('editGroup', $element); var self = this; - if(this.$editelem) { - console.log('Already editing, returning'); - return; - } - // NOTE: Currently this only works for adding, not renaming - var saveChanges = function($elem, $input) { - console.log('saveChanges', $input.val()); - var name = $.trim($input.val()); - if(name.length === 0) { - return false; + var oldname = $element.data('rawname'); + var id = $element.data('id'); + + var $editInput = $('').val(oldname); + $element.hide(); + $editInput.insertBefore($element).wrap('
  • '); + var $tmpelem = $editInput.parent('li'); + console.log('tmpelem', $tmpelem); + + $editInput.addnew({ + autoOpen: true, + addText: t('contacts', 'Save'), + ok: function(event, newname) { + console.log('New name', newname); + $editInput.addClass('loading'); + self.renameGroup(oldname, newname, function(response) { + if(response.error) { + $(document).trigger('status.contact.error', { + message: response.message + }); + } else { + $editInput.addnew('close'); + $(document).trigger('status.group.grouprenamed', { + groupid: id, + from: oldname, + to: newname, + contacts: $element.data('contacts') + }); + $element.data('rawname', newname); + $element.find('.name').text(escapeHTML(newname)); + } + $editInput.removeClass('loading'); + }); + }, + cancel: function(event) { + console.log('cancel'); + $editInput.removeClass('loading'); + }, + close: function() { + console.log('close'); + $tmpelem.remove(); + $element.show(); } - $input.prop('disabled', true); - $elem.data('rawname', ''); - self.addGroup({name:name}, function(response) { - if(!response.error) { - $elem.remove(); - self.$editelem = null; - } else { - $input.prop('disabled', false); - OC.notify({message:response.message}); - } - }); - }; + }); - if(typeof id === 'undefined') { - // Add new group - var tmpl = this.$groupListItemTemplate; - self.$editelem = (tmpl).octemplate({ - id: 'new', - type: 'category', - num: 0, - name: '' - }); - var $input = $(''); - self.$editelem.prepend($input).addClass('editing'); - self.$editelem.data('contacts', []); - self.$editelem.data('rawname', ''); - this.$groupList.find('li.group[data-type="category"]').first().before(self.$editelem); - this.selectGroup({element:self.$editelem}); - $input.on('input', function(event) { - if($(this).val().length > 0) { - $(this).next('.checked').removeClass('disabled'); - } else { - $(this).next('.checked').addClass('disabled'); - } - }); - $input.on('keyup', function(event) { - var keyCode = Math.max(event.keyCode, event.which); - if(keyCode === 13) { - saveChanges(self.$editelem, $(this)); - } else if(keyCode === 27) { - self.$editelem.remove(); - self.$editelem = null; - } - }); - $input.next('.checked').on('click keydown', function(event) { - console.log('clicked', event); - if(wrongKey(event)) { - return; - } - saveChanges(self.$editelem, $input); - }); - $input.focus(); - } else if(utils.isUInt(id)) { - alert('Renaming groups is not implemented!'); - return; - var $elem = this.findById(id); - var $text = $elem.contents().filter(function(){ return(this.nodeType == 3); }); - var name = $text.text(); - console.log('Group name', $text, name); - $text.remove(); - var $input = $('request->post['name']; $response = new JSONResponse(); - if(is_null($name) || $name === "") { + if(is_null($name) || $name === '') { $response->bailOut(App::$l10n->t('No group name given.')); + return $response; } $catman = new \OC_VCategories('contact', $this->api->getUserId()); @@ -89,6 +90,49 @@ class GroupController extends BaseController { return $response; } + /** + * @IsAdminExemption + * @IsSubAdminExemption + * @Ajax + */ + public function renameGroup() { + $from = $this->request->post['from']; + $to = $this->request->post['to']; + + $response = new JSONResponse(); + if(is_null($from) || $from === '') { + $response->bailOut(App::$l10n->t('No group name to rename from given.')); + return $response; + } + if(is_null($to) || $to === '') { + $response->bailOut(App::$l10n->t('No group name to rename to given.')); + return $response; + } + + $catman = new \OC_VCategories('contact', $this->api->getUserId()); + if(!$catman->rename($from, $to)) { + $response->bailOut(App::$l10n->t('Error renaming group.')); + return $response; + } + $ids = $catman->idsForCategory($to); + $app = new App($this->api->getUserId()); + $backend = $app->getBackend('local'); + foreach($ids as $id) { + $contact = $backend->getContact(null, $id, true); + $obj = \Sabre\VObject\Reader::read( + $contact['carddata'], + \Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES + ); + if($obj) { + if(!isset($obj->CATEGORIES)) { + continue; + } + $obj->CATEGORIES->renameGroup($from, $to); + $backend->updateContact(null, $id, $obj, true); + } + } + return $response; + } /** * @IsAdminExemption diff --git a/templates/contacts.php b/templates/contacts.php index 3f6d43ce..72465675 100644 --- a/templates/contacts.php +++ b/templates/contacts.php @@ -137,6 +137,17 @@ + + - -