1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2025-01-18 07:52:21 +01:00

Implement rename group. Refs #97

This commit is contained in:
Thomas Tanghus 2013-05-21 23:39:50 +02:00
parent 9b6a2fde01
commit e8c7047869
7 changed files with 232 additions and 120 deletions

View File

@ -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}') $this->create('contacts_categories_addto', 'groups/addto/{categoryid}')
->post() ->post()
->action( ->action(

View File

@ -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) { $(document).bind('status.group.contactadded', function(e, result) {
console.log('status.group.contactadded', result); console.log('status.group.contactadded', result);
var contact = self.contacts.findById(result.contactid); var contact = self.contacts.findById(result.contactid);

View File

@ -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) { Contact.prototype.pushToUndo = function(params) {
// Check if the same property has been changed before // Check if the same property has been changed before
// and update it's checksum if so. // and update it's checksum if so.
@ -1926,7 +1949,7 @@ OC.Contacts = OC.Contacts || {};
id = String(id); id = String(id);
if(typeof this.contacts[id] === 'undefined') { if(typeof this.contacts[id] === 'undefined') {
console.warn('Could not find contact with id', id); console.warn('Could not find contact with id', id);
console.trace(); //console.trace();
return null; return null;
} }
return this.contacts[String(id)]; return this.contacts[String(id)];

View File

@ -21,34 +21,36 @@ OC.Contacts = OC.Contacts || {};
this.$groupList = groupList; this.$groupList = groupList;
var self = this; var self = this;
var numtypes = ['category', 'fav', 'all']; var numtypes = ['category', 'fav', 'all'];
this.$groupList.on('click', 'li', function(event) { this.$groupList.on('click', 'li.group', function(event) {
$('.tipsy').remove(); $('.tipsy').remove();
if(wrongKey(event)) { if(wrongKey(event)) {
return; return;
} }
console.log($(event.target)); console.log('group click', $(this));
if($(event.target).is('.action.delete')) { if($(event.target).is('.action.delete')) {
event.stopPropagation();
event.preventDefault();
var id = $(event.target).parents('li').first().data('id'); var id = $(event.target).parents('li').first().data('id');
self.deleteGroup(id, function(response) { self.deleteGroup(id, function(response) {
if(response.error) { if(response.error) {
OC.notify({message:response.data.message}); OC.notify({message:response.data.message});
} }
}); });
} else if($(event.target).is('.add-group')) { } else if($(event.target).is('.action.edit')) {
//self.editGroup(); event.stopPropagation();
} else if($(event.target).is('.add-contact')) { event.preventDefault();
$.noop(); // handled elsewhere in app.js self.editGroup($(this));
} else { } else {
self.selectGroup({element:$(this)}); if($(this).is(':not(.editing)')) {
self.selectGroup({element:$(this)});
}
} }
}); });
var $addInput = this.$groupList.find('.add-group'); var $addInput = this.$groupList.find('.add-group');
$addInput.addnew({ $addInput.addnew({
ok: function(event, name) { ok: function(event, name) {
console.log('add-address-book ok', name);
$addInput.addClass('loading'); $addInput.addClass('loading');
self.addGroup({name:name}, function(response) { self.addGroup({name:name}, function(response) {
console.log('response', response);
if(response.error) { if(response.error) {
$(document).trigger('status.contact.error', { $(document).trigger('status.contact.error', {
message: response.message message: response.message
@ -117,6 +119,16 @@ OC.Contacts = OC.Contacts || {};
this.selectGroup({id:this.lastgroup}); 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. * 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(); //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. /** Get the group element by id.
* *
* @param integer id. The numeric group or addressbook id. * @param integer id. The numeric group or addressbook id.
@ -460,94 +488,78 @@ OC.Contacts = OC.Contacts || {};
/** /**
* Edit a groups name. * 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. * @param object $element jQuery element
* FIXME: This works fine for adding, but will need refactoring
* if used for renaming.
*/ */
/*GroupList.prototype.editGroup = function(id) { GroupList.prototype.editGroup = function($element) {
console.log('editGroup', $element);
var self = this; var self = this;
if(this.$editelem) { var oldname = $element.data('rawname');
console.log('Already editing, returning'); var id = $element.data('id');
return;
} var $editInput = $('<input type="text" />').val(oldname);
// NOTE: Currently this only works for adding, not renaming $element.hide();
var saveChanges = function($elem, $input) { $editInput.insertBefore($element).wrap('<li class="group editing" />');
console.log('saveChanges', $input.val()); var $tmpelem = $editInput.parent('li');
var name = $.trim($input.val()); console.log('tmpelem', $tmpelem);
if(name.length === 0) {
return false; $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 = $('<input type="text" class="active" /><a class="action checked disabled" />');
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 = $('<input type="text" class="active" value="' + name + '" /><a class="action checked disabled />');
$elem.prepend($input).addClass('editing');
$input.focus();
} else { /**
throw { name: 'WrongParameterType', message: 'GroupList.editGroup only accept integers.'}; * Rename a group.
} *
};*/ * @param string from
* @param string to
* @param function cb
*/
GroupList.prototype.renameGroup = function(from, to, cb) {
$.when(this.storage.renameGroup(from, to)).then(function(response) {
cb({error:false});
})
.fail(function(response) {
console.log( "Request Failed: " + response);
cb({error:true});
$(document).trigger('status.contact.error', {
message: t('contacts', 'Failed renaming group: {error}', {error:response.message})
});
});
};
/** /**
* Add a new group. * Add a new group.
@ -572,14 +584,8 @@ OC.Contacts = OC.Contacts || {};
//console.log('GroupList.addGroup', params); //console.log('GroupList.addGroup', params);
var name = params.name; var name = params.name;
var contacts = []; // $.map(contacts, function(c) {return parseInt(c)}); var contacts = []; // $.map(contacts, function(c) {return parseInt(c)});
var self = this, exists = false; var self = this;
self.$groupList.find('li[data-type="category"]').each(function() { if(this.hasGroup(name)) {
if ($(this).data('rawname').toLowerCase() === name.toLowerCase()) {
exists = true;
return false; //break out of loop
}
});
if(exists) {
if(typeof cb === 'function') { if(typeof cb === 'function') {
cb({error:true, message:t('contacts', 'A group named {group} already exists', {group: escapeHTML(name)})}); cb({error:true, message:t('contacts', 'A group named {group} already exists', {group: escapeHTML(name)})});
} }
@ -627,11 +633,10 @@ OC.Contacts = OC.Contacts || {};
} }
} }
}) })
.fail(function(jqxhr, textStatus, error) { .fail(function(response) {
var err = textStatus + ', ' + error; console.log( "Request Failed: " + response);
console.log( "Request Failed: " + err);
$(document).trigger('status.contact.error', { $(document).trigger('status.contact.error', {
message: t('contacts', 'Failed adding group: {error}', {error:err}) message: t('contacts', 'Failed adding group: {error}', {error:response.message})
}); });
}); });
}; };
@ -761,9 +766,11 @@ OC.Contacts = OC.Contacts || {};
cb(); cb();
} }
}) })
.fail(function(jqxhr, textStatus, error) { .fail(function(response) {
var err = textStatus + ', ' + error; console.log( "Request Failed: " + response);
console.log( "Request Failed: " + err); $(document).trigger('status.contact.error', {
message: t('contacts', 'Failed loading groups: {error}', {error:response.message})
});
}); });
}; };

View File

@ -11,9 +11,10 @@ OC.Contacts = OC.Contacts || {};
this.getAllResponseHeaders = jqXHR.getAllResponseHeaders; this.getAllResponseHeaders = jqXHR.getAllResponseHeaders;
this.getResponseHeader = jqXHR.getResponseHeader; this.getResponseHeader = jqXHR.getResponseHeader;
this.status = jqXHR.status; this.status = jqXHR.status;
if(!response || !response.status || response.status === 'error') { if(!response) {
console.log('jqXHR', jqXHR);
this.error = true; this.error = true;
this.message = response.data.message || 'Unknown error.'; this.message = jqXHR.statusText;
} else { } else {
this.error = false; this.error = false;
if(response.data) { if(response.data) {
@ -392,6 +393,21 @@ OC.Contacts = OC.Contacts || {};
); );
} }
/**
* Rename a group
*
* @param string from
* @param string to
*/
Storage.prototype.renameGroup = function(from, to) {
return this.requestRoute(
'contacts_categories_rename',
'POST',
{},
{from: from, to: to}
);
}
/** /**
* Add contacts to a group * Add contacts to a group
* *

View File

@ -80,8 +80,9 @@ class GroupController extends BaseController {
$name = $this->request->post['name']; $name = $this->request->post['name'];
$response = new JSONResponse(); $response = new JSONResponse();
if(is_null($name) || $name === "") { if(is_null($name) || $name === '') {
$response->bailOut(App::$l10n->t('No group name given.')); $response->bailOut(App::$l10n->t('No group name given.'));
return $response;
} }
$catman = new \OC_VCategories('contact', $this->api->getUserId()); $catman = new \OC_VCategories('contact', $this->api->getUserId());
@ -89,6 +90,49 @@ class GroupController extends BaseController {
return $response; 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 * @IsAdminExemption

View File

@ -137,6 +137,17 @@
</div> </div>
</script> </script>
<script id="groupListItemTemplate" type="text/template">
<li class="group" data-type="{type}" data-id="{id}">
<a class="name" role="button">{name}</a>
<span class="utils">
<a class="action delete tooltipped rightwards" title="<?php p($l->t('Delete group')); ?>"></a>
<a class="action edit tooltipped rightwards" title="<?php p($l->t('Rename group')); ?>"></a>
<span class="action numcontacts">{num}</span>
</span>
</li>
</script>
<script id="mergeContactsTemplate" type="text/template"> <script id="mergeContactsTemplate" type="text/template">
<div id="dialog-merge-contacts" title="<?php p($l->t('Merge contacts')); ?>"> <div id="dialog-merge-contacts" title="<?php p($l->t('Merge contacts')); ?>">
<p><?php p($l->t('Which contact should the data be merged into?')); ?></p> <p><?php p($l->t('Which contact should the data be merged into?')); ?></p>
@ -173,16 +184,6 @@
</div> </div>
</script> </script>
<script id="groupListItemTemplate" type="text/template">
<li class="group" data-type="{type}" data-id="{id}">
<a role="button">{name}</a>
<span class="utils">
<a class="action delete tooltipped rightwards" title="<?php p($l->t('Delete group')); ?>"></a>
<span class="action numcontacts">{num}</span>
</span>
</li>
</script>
<script id="contactFullTemplate" type="text/template"> <script id="contactFullTemplate" type="text/template">
<form action="<?php print_unescaped(OCP\Util::linkTo('contacts', 'index.php')); ?>" method="post" enctype="multipart/form-data"> <form action="<?php print_unescaped(OCP\Util::linkTo('contacts', 'index.php')); ?>" method="post" enctype="multipart/form-data">
<section id="contact" data-id="{id}"> <section id="contact" data-id="{id}">