Partial invitations handling, participants autocompletion (T726, T729)
This commit is contained in:
parent
9d32f5cbae
commit
48ddb0eea4
5 changed files with 277 additions and 16 deletions
|
@ -1125,7 +1125,9 @@ function manticore_init()
|
|||
var info = rcmail.env.file_data;
|
||||
|
||||
rcmail.enable_command('document-save', 'document-export', true);
|
||||
rcmail.enable_command('files-close', info && info.session && info.session.is_owner);
|
||||
|
||||
if (info && info.session && info.session.is_owner)
|
||||
rcmail.enable_command('files-close', 'document-editors', true);
|
||||
};
|
||||
|
||||
rcube_webmail.prototype.document_save = function()
|
||||
|
@ -1138,6 +1140,144 @@ rcube_webmail.prototype.document_export = function(type)
|
|||
manticore.export(type || 'odt');
|
||||
};
|
||||
|
||||
rcube_webmail.prototype.document_editors = function()
|
||||
{
|
||||
var info = rcmail.env.file_data;
|
||||
|
||||
if (!info || !info.session || !info.session.is_owner)
|
||||
return;
|
||||
|
||||
kolab_files_editors_dialog(info.session);
|
||||
};
|
||||
|
||||
// close editing session
|
||||
rcube_webmail.prototype.files_close = function()
|
||||
{
|
||||
// @todo: check document "unsaved changes" state and display a warning
|
||||
file_api.document_delete(this.env.file_data.session.id);
|
||||
};
|
||||
|
||||
// document editors management dialog
|
||||
function kolab_files_editors_dialog(session)
|
||||
{
|
||||
var ac_props, items = [], buttons = {},
|
||||
dialog = $('#document-editors-dialog');
|
||||
|
||||
// always add the session organizer
|
||||
items.push(kolab_files_attendee_record(session.owner, 'organizer'));
|
||||
|
||||
$.each(session.invitations || [], function() {
|
||||
items.push(kolab_files_attendee_record(this.user, this.status));
|
||||
});
|
||||
|
||||
$('table > tbody', dialog).html(items);
|
||||
|
||||
buttons[rcmail.gettext('kolab_files.close')] = function() {
|
||||
kolab_dialog_close(this);
|
||||
};
|
||||
|
||||
// show dialog window
|
||||
kolab_dialog_show(dialog, {
|
||||
title: rcmail.gettext('kolab_files.manageeditors'),
|
||||
buttons: buttons,
|
||||
button_classes: ['mainaction']
|
||||
});
|
||||
|
||||
if (!rcmail.env.editors_dialog) {
|
||||
rcmail.env.editors_dialog = dialog;
|
||||
|
||||
// init attendees autocompletion
|
||||
if (rcmail.env.autocomplete_threads > 0) {
|
||||
ac_props = {
|
||||
threads: rcmail.env.autocomplete_threads,
|
||||
sources: rcmail.env.autocomplete_sources
|
||||
};
|
||||
}
|
||||
|
||||
rcmail.init_address_input_events($('#invitation-editor-name'), ac_props);
|
||||
|
||||
rcmail.addEventListener('autocomplete_insert', function(e) {
|
||||
var success = false;
|
||||
if (e.field.name == 'participant') {
|
||||
success = kolab_files_add_attendees(e.insert, 'invited', e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL');
|
||||
}
|
||||
if (e.field && success) {
|
||||
e.field.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
$('#invitation-editor-add').click(function() {
|
||||
var input = $('#invitation-editor-name');
|
||||
rcmail.ksearch_blur();
|
||||
if (kolab_files_add_attendees(input.val(), 'invited', 'INDIVIDUAL')) {
|
||||
input.val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// add the given list of participants
|
||||
function kolab_files_add_attendees(names)
|
||||
{
|
||||
var i, item, email, name, attendees = {}, counter = 0;
|
||||
|
||||
names = file_api.explode_quoted_string(names.replace(/,\s*$/, ''), ',');
|
||||
|
||||
// parse name/email pairs
|
||||
for (i = 0; i < names.length; i++) {
|
||||
email = name = '';
|
||||
item = $.trim(names[i]);
|
||||
|
||||
if (!item.length) {
|
||||
continue;
|
||||
} // address in brackets without name (do nothing)
|
||||
else if (item.match(/^<[^@]+@[^>]+>$/)) {
|
||||
email = item.replace(/[<>]/g, '');
|
||||
} // address without brackets and without name (add brackets)
|
||||
else if (rcube_check_email(item)) {
|
||||
email = item;
|
||||
} // address with name
|
||||
else if (item.match(/([^\s<@]+@[^>]+)>*$/)) {
|
||||
email = RegExp.$1;
|
||||
name = item.replace(email, '').replace(/^["\s<>]+/, '').replace(/["\s<>]+$/, '');
|
||||
}
|
||||
|
||||
if (email) {
|
||||
attendees[email] = {user: email, name: name};
|
||||
counter++;
|
||||
}
|
||||
else {
|
||||
alert(rcmail.gettext('noemailwarning'));
|
||||
}
|
||||
}
|
||||
|
||||
// remove already existing entries
|
||||
if (counter) {
|
||||
if (attendees[rcmail.env.file_data.session.owner]) {
|
||||
delete attendees[this.user];
|
||||
counter--;
|
||||
}
|
||||
$.each(rcmail.env.file_data.session.invitations || [], function() {
|
||||
if (this.user in attendees) {
|
||||
delete attendees[this.user];
|
||||
counter--;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (counter)
|
||||
file_api.document_invite(rcmail.env.file_data.session.id, attendees);
|
||||
};
|
||||
|
||||
function kolab_files_attendee_record(user, status)
|
||||
{
|
||||
return $('<tr>').attr('class', 'invitation' + (status ? ' ' + status : ''))
|
||||
.append($('<td class="name">').text(user))
|
||||
.append($('<td class="status">').text(rcmail.gettext('kolab_files.status' + status)))
|
||||
.append($('<td class="options">'));
|
||||
// @todo: delete and accept button
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************/
|
||||
/********** Commands **********/
|
||||
|
@ -1283,13 +1423,7 @@ rcube_webmail.prototype.files_edit = function(session)
|
|||
}
|
||||
};
|
||||
|
||||
// close editing session
|
||||
rcube_webmail.prototype.files_close = function()
|
||||
{
|
||||
// @todo: check document "unsaved changes" state and display a warning
|
||||
file_api.document_delete(this.env.file_data.session.id);
|
||||
};
|
||||
|
||||
// save changes to the file
|
||||
rcube_webmail.prototype.files_save = function()
|
||||
{
|
||||
if (!this.file_editor)
|
||||
|
@ -2935,6 +3069,36 @@ function kolab_files_ui()
|
|||
// @todo: force sessions info update
|
||||
};
|
||||
|
||||
// Invite document session participants
|
||||
this.document_invite = function(id, attendees)
|
||||
{
|
||||
var list = [];
|
||||
|
||||
// expect attendees to be email => name hash
|
||||
$.each(attendees || {}, function() { list.push(this); });
|
||||
|
||||
if (list.length) {
|
||||
this.req = this.set_busy(true, 'kolab_files.documentinviting');
|
||||
this.request('document_invite', {id: id, users: list}, 'document_invite_response');
|
||||
}
|
||||
};
|
||||
|
||||
// document invite response handler
|
||||
this.document_invite_response = function(response)
|
||||
{
|
||||
if (!this.response(response))
|
||||
return;
|
||||
|
||||
var info = rcmail.env.file_data,
|
||||
table = $('#document-editors-dialog table > tbody');
|
||||
|
||||
$.each(response.list || {}, function() {
|
||||
table.appned(kolab_files_attendee_record(this.user, this.status));
|
||||
if (info.session && info.session.invitations)
|
||||
info.session.invitations.push($.merge({status: 'invited'}, this));
|
||||
});
|
||||
};
|
||||
|
||||
// handle auth errors on folder list
|
||||
this.folder_list_auth_errors = function(result)
|
||||
{
|
||||
|
|
|
@ -147,6 +147,7 @@ class kolab_files_engine
|
|||
'file-edit-dialog' => array($this, 'file_edit_dialog'),
|
||||
'filelist' => array($this, 'file_list'),
|
||||
'filequotadisplay' => array($this, 'quota_display'),
|
||||
'document-editors-dialog' => array($this, 'document_editors_dialog'),
|
||||
));
|
||||
|
||||
if ($this->rc->task != 'files') {
|
||||
|
@ -342,6 +343,37 @@ class kolab_files_engine
|
|||
return '<div></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Template object for dcument editors dialog
|
||||
*/
|
||||
public function document_editors_dialog($attrib)
|
||||
{
|
||||
$table = new html_table(array('cols' => 3, 'border' => 0, 'cellpadding' => 0, 'class' => 'records-table'));
|
||||
|
||||
$table->add_header('username', $this->plugin->gettext('participant'));
|
||||
$table->add_header('status', $this->plugin->gettext('status'));
|
||||
$table->add_header('options', null);
|
||||
|
||||
$input = new html_inputfield(array('name' => 'participant', 'id' => 'invitation-editor-name', 'size' => 30));
|
||||
$textarea = new html_textarea(array('name' => 'comment', 'id' => 'invitation-comment',
|
||||
'rows' => 4, 'cols' => 55, 'title' => $this->plugin->gettext('invitationtexttitle')));
|
||||
$button = new html_inputfield(array('type' => 'button', 'class' => 'button', 'id' => 'invitation-editor-add', 'value' => $this->plugin->gettext('addparticipant')));
|
||||
|
||||
$this->plugin->add_label('close', 'manageeditors', 'statusorganizer', 'statusaccepted',
|
||||
'statusinvited', 'statusdeclined', 'statusrequested'
|
||||
);
|
||||
|
||||
// initialize attendees autocompletion
|
||||
$this->rc->autocomplete_init();
|
||||
|
||||
return '<div>' . $table->show() . html::div(null,
|
||||
html::div(null, $input->show() . " " . $button->show())
|
||||
. html::p('attendees-commentbox', html::label(null,
|
||||
$this->plugin->gettext('invitationtextlabel') . $textarea->show())
|
||||
)
|
||||
) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Template object for file_rename form
|
||||
*/
|
||||
|
|
|
@ -49,6 +49,7 @@ $labels['createandedit'] = 'Create and Edit';
|
|||
$labels['copyfile'] = 'Copy a file';
|
||||
$labels['copyandedit'] = 'Copy and Edit';
|
||||
$labels['documenttitle'] = 'Title:';
|
||||
$labels['close'] = 'Close';
|
||||
|
||||
$labels['collection_audio'] = 'Audio';
|
||||
$labels['collection_video'] = 'Video';
|
||||
|
@ -104,6 +105,18 @@ $labels['select'] = 'Select';
|
|||
$labels['terminatesession'] = 'Terminate the session';
|
||||
$labels['terminate'] = 'Terminate';
|
||||
$labels['sessionterminating'] = 'Terminating the session...';
|
||||
$labels['manageeditors'] = 'Invite to document';
|
||||
$labels['participant'] = 'Participant';
|
||||
$labels['status'] = 'Status';
|
||||
$labels['addparticipant'] = 'Add participant';
|
||||
$labels['delparticipant'] = 'Remove participant';
|
||||
$labels['invitationtexttitle'] = 'This comment will be attached to the invitation/notification message sent to the participant';
|
||||
$labels['invitationtextlabel'] = 'Invitation/notification comment';
|
||||
$labels['statusorganizer'] = 'Organizer';
|
||||
$labels['statusinvited'] = 'Invited';
|
||||
$labels['statusaccepted'] = 'Accepted';
|
||||
$labels['statusdeclined'] = 'Declined';
|
||||
$labels['statusrequested'] = 'Requested';
|
||||
|
||||
$labels['storepasswords'] = 'remember password';
|
||||
$labels['storepasswordsdesc'] = 'Stored passwords will be encrypted. Enable this if you do not want to be asked for the password on every login or you want this storage to be available via WebDAV.';
|
||||
|
|
|
@ -82,6 +82,10 @@
|
|||
text-shadow: 0 1px 1px #eee;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li span.saveas {
|
||||
background: url(images/buttons.png) -5px -253px no-repeat;
|
||||
}
|
||||
|
||||
#document-title {
|
||||
width: 200px;
|
||||
}
|
||||
|
@ -102,6 +106,15 @@
|
|||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#collaborators a.button.add {
|
||||
background: url(../../../../skins/larry/images/buttons.png) -5px -357px no-repeat;
|
||||
min-width: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#quicksearchbar #filesearchmenulink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
|
@ -400,7 +413,8 @@
|
|||
#files-folder-mount-dialog,
|
||||
#files-folder-auth-dialog,
|
||||
#files-folder-create-dialog,
|
||||
#files-folder-edit-dialog {
|
||||
#files-folder-edit-dialog,
|
||||
#document-editors-dialog {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -489,10 +503,6 @@ a.filesaveall {
|
|||
width: 200px;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li span.saveas {
|
||||
background: url(images/buttons.png) -5px -253px no-repeat;
|
||||
}
|
||||
|
||||
table.propform td.source.selected {
|
||||
background-color: #c7e3ef;
|
||||
}
|
||||
|
@ -542,3 +552,43 @@ table.propform td.source table.propform td {
|
|||
.auth-options label {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#document-editors-dialog textarea {
|
||||
width: 98%
|
||||
}
|
||||
|
||||
#document-editors-dialog label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#document-editors-dialog table {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#document-editors-dialog table th.status {
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
#document-editors-dialog table th.options {
|
||||
width: 40px
|
||||
}
|
||||
|
||||
#document-editors-dialog table td {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
#document-editors-dialog table td.name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#document-editors-dialog table tr:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#document-editors-dialog table tr.organizer td {
|
||||
color: #888;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
<h2 id="aria-label-collaborators" class="voice"><roundcube:label name="kolab_files.arialabelcollaborators" /></h2>
|
||||
<div id="collaborators" class="toolbar" role="toolbar" aria-labelledby="aria-label-collaborators">
|
||||
<roundcube:button command="document-editors" type="link" class="button add disabled" classAct="button add" classSel="button add pressed" content=" " title="kolab_files.manageeditors" />
|
||||
<div id="members"></div>
|
||||
</div>
|
||||
|
||||
|
@ -49,11 +50,12 @@
|
|||
<h3 id="aria-label-exportmenu" class="voice"><roundcube:label name="kolab_files.arialabelexportoptions" /></h3>
|
||||
<ul id="exportmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-exportmenu"></ul>
|
||||
</div>
|
||||
<!--
|
||||
<div id="editors-dialog" class="uidialog" data-editable="true" role="dialog" aria-labelledby="aria-label-doceditorsdialog" aria-hidden="true">
|
||||
|
||||
<div id="document-editors-dialog" class="uidialog" data-editable="true" role="dialog" aria-labelledby="aria-label-doceditorsdialog" aria-hidden="true">
|
||||
<h3 id="aria-label-doceditorsdialog" class="voice"><roundcube:label name="kolab_files.arialabeldoceditorsdialog" /></h3>
|
||||
<roundcube:object name="document-editors-dialog" />
|
||||
</div>
|
||||
-->
|
||||
|
||||
<roundcube:include file="/includes/footer.html" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
Loading…
Add table
Reference in a new issue