Show RSVP buttons for assigned tasks which require a response
This commit is contained in:
parent
e48f0dbf15
commit
8fe64d7400
7 changed files with 109 additions and 16 deletions
|
@ -457,7 +457,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
$tomorrow_date = new DateTime('now + 1 day', $this->plugin->timezone);
|
||||
$tomorrow = $tomorrow_date->format('Y-m-d');
|
||||
|
||||
$counts = array('all' => 0, 'flagged' => 0, 'today' => 0, 'tomorrow' => 0, 'overdue' => 0, 'nodate' => 0);
|
||||
$counts = array('all' => 0, 'flagged' => 0, 'today' => 0, 'tomorrow' => 0, 'overdue' => 0, 'nodate' => 0, 'mytasks' => 0);
|
||||
foreach ($lists as $list_id) {
|
||||
if (!$folder = $this->get_folder($list_id)) {
|
||||
continue;
|
||||
|
@ -479,6 +479,8 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
$counts['tomorrow']++;
|
||||
else if ($rec['date'] < $today)
|
||||
$counts['overdue']++;
|
||||
if ($this->plugin->is_attendee($rec) !== false)
|
||||
$counts['mytasks']++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ $labels['attendeedelegated'] = 'Assignee has delegated to $delegatedto';
|
|||
$labels['attendeein-process'] = 'Assignee is in-process';
|
||||
$labels['attendeecompleted'] = 'Assignee has completed';
|
||||
|
||||
$labels['acceptinvitation'] = 'Do you accept this assignment?';
|
||||
$labels['itipdeclinetask'] = 'Decline your assignment to this task to the organizer';
|
||||
$labels['declinedeleteconfirm'] = 'Do you also want to delete this declined task from your tasks list?';
|
||||
$labels['itipcomment'] = 'Invitation/notification comment';
|
||||
|
|
|
@ -1132,12 +1132,18 @@ div.tasklist-invitebox td.label {
|
|||
padding-right: 1em;
|
||||
}
|
||||
|
||||
#event-rsvp .rsvp-buttons,
|
||||
#task-rsvp .rsvp-buttons,
|
||||
#task-rsvp .itip-reply-controls,
|
||||
div.tasklist-invitebox .itip-buttons div {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
#event-rsvp input.button,
|
||||
#task-rsvp .itip-reply-controls a,
|
||||
#task-rsvp .itip-reply-controls label {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#task-rsvp input.button,
|
||||
div.tasklist-invitebox input.button {
|
||||
font-weight: bold;
|
||||
margin-right: 0.5em;
|
||||
|
@ -1164,7 +1170,7 @@ div.tasklist-invitebox .rsvp-status.hint {
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp,
|
||||
#task-partstat .changersvp,
|
||||
.edit-attendees-table td.confirmstate span,
|
||||
div.tasklist-invitebox .rsvp-status.declined,
|
||||
div.tasklist-invitebox .rsvp-status.tentative,
|
||||
|
@ -1177,37 +1183,37 @@ div.tasklist-invitebox .rsvp-status.needs-action {
|
|||
background: url(images/attendee-status.png) 2px -20px no-repeat;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.declined,
|
||||
#task-partstat .changersvp.declined,
|
||||
div.tasklist-invitebox .rsvp-status.declined,
|
||||
.edit-attendees-table td.confirmstate span.declined {
|
||||
background-position: 2px -40px;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.tentative,
|
||||
#task-partstat .changersvp.tentative,
|
||||
div.tasklist-invitebox .rsvp-status.tentative,
|
||||
.edit-attendees-table td.confirmstate span.tentative {
|
||||
background-position: 2px -60px;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.delegated,
|
||||
#task-partstat .changersvp.delegated,
|
||||
div.tasklist-invitebox .rsvp-status.delegated,
|
||||
.edit-attendees-table td.confirmstate span.delegated {
|
||||
background-position: 2px -180px;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.needs-action,
|
||||
#task-partstat .changersvp.needs-action,
|
||||
div.tasklist-invitebox .rsvp-status.needs-action,
|
||||
.edit-attendees-table td.confirmstate span.needs-action {
|
||||
background-position: 2px 0;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.in-process,
|
||||
#task-partstat .changersvp.in-process,
|
||||
div.tasklist-invitebox .rsvp-status.in-process,
|
||||
.edit-attendees-table td.confirmstate span.in-process {
|
||||
background-position: 2px -200px;
|
||||
}
|
||||
|
||||
#event-partstat .changersvp.accepted,
|
||||
#task-partstat .changersvp.accepted,
|
||||
div.tasklist-invitebox .rsvp-status.accepted,
|
||||
.edit-attendees-table td.confirmstate span.accepted {
|
||||
background-position: 2px -220px;
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<li class="later" role="radio" aria-checked="false" aria-labelledby="aria-radio-later"><a href="#later" id="aria-radio-later"><roundcube:label name="tasklist.later" /></a></li>
|
||||
<li class="nodate" role="radio" aria-checked="false" aria-labelledby="aria-radio-nodate"><a href="#nodate" id="aria-radio-nodate"><roundcube:label name="tasklist.nodate" ucfirst="true" /></a></li>
|
||||
<roundcube:if condition="env:tasklist_driver == 'kolab'" />
|
||||
<li class="mytasks" role="radio" aria-checked="false" aria-labelledby="aria-radio-mytasks"><a href="#mytasks" id="aria-radio-mytasks" title="<roundcube:label name='tasklist.mytaskstitle'/>"><roundcube:label name="tasklist.mytasks" /></a></li>
|
||||
<li class="mytasks" role="radio" aria-checked="false" aria-labelledby="aria-radio-mytasks"><a href="#mytasks" id="aria-radio-mytasks" title="<roundcube:label name='tasklist.mytaskstitle'/>"><roundcube:label name="tasklist.mytasks" /><span class="count"></span></a></li>
|
||||
<li class="assigned" role="radio" aria-checked="false" aria-labelledby="aria-radio-assigned"><a href="#assigned" id="aria-radio-assigned" title="<roundcube:label name='tasklist.assignedtitle'/>"><roundcube:label name="tasklist.assigned" /></a></li>
|
||||
<roundcube:endif />
|
||||
<li class="complete" role="radio" aria-checked="false" aria-labelledby="aria-radio-complete"><a href="#complete" id="aria-radio-complete"><roundcube:label name="tasklist.complete" /><span class="count"></span></a></li>
|
||||
|
@ -195,6 +195,18 @@
|
|||
<label><roundcube:label name="attachments" /></label>
|
||||
<div class="task-text"></div>
|
||||
</div>
|
||||
<div id="task-created-changed" class="form-section">
|
||||
<label><roundcube:label name="tasklist.created" /></label>
|
||||
<span class="task-text task-created"></span>
|
||||
<label><roundcube:label name="tasklist.changed" /></label>
|
||||
<span class="task-text task-changed"></span>
|
||||
</div>
|
||||
<div id="task-rsvp-comment" class="form-section">
|
||||
<label><roundcube:label name="tasklist.rsvpcomment" /></label>
|
||||
<span class="task-text"></span>
|
||||
</div>
|
||||
|
||||
<roundcube:object name="plugin.task_rsvp_buttons" id="task-rsvp" class="task-dialog-message" style="display:none" />
|
||||
</div>
|
||||
|
||||
<roundcube:include file="/templates/taskedit.html" />
|
||||
|
|
|
@ -502,6 +502,35 @@ function rcube_tasklist_ui(settings)
|
|||
}
|
||||
});
|
||||
|
||||
// init RSVP widget
|
||||
$('#task-rsvp input.button').click(function(e) {
|
||||
var response = $(this).attr('rel');
|
||||
|
||||
if (me.selected_task && me.selected_task.attendees && response) {
|
||||
// update attendee status
|
||||
for (var data, i=0; i < me.selected_task.attendees.length; i++) {
|
||||
data = me.selected_task.attendees[i];
|
||||
if (settings.identity.emails.indexOf(';'+String(data.email).toLowerCase()) >= 0) {
|
||||
data.status = response.toUpperCase();
|
||||
delete data.rsvp; // unset RSVP flag
|
||||
}
|
||||
}
|
||||
|
||||
// submit status change to server
|
||||
saving_lock = rcmail.set_busy(true, 'tasklist.savingdata');
|
||||
rcmail.http_post('tasks/task', {
|
||||
action: 'rsvp',
|
||||
t: me.selected_task,
|
||||
filter: filtermask,
|
||||
status: response,
|
||||
noreply: $('#noreply-task-rsvp').prop('checked') ? 1 : 0,
|
||||
comment: $('#reply-comment-task-rsvp').val()
|
||||
});
|
||||
|
||||
task_show_dialog(me.selected_task.id);
|
||||
}
|
||||
});
|
||||
|
||||
// handle global document clicks: close popup menus
|
||||
$(document.body).click(clear_popups);
|
||||
|
||||
|
@ -1613,7 +1642,7 @@ function rcube_tasklist_ui(settings)
|
|||
$('#task-completeness .task-text').html(((rec.complete || 0) * 100) + '%');
|
||||
$('#task-status')[(rec.status ? 'show' : 'hide')]().children('.task-text').html(rcmail.gettext('status-'+String(rec.status).toLowerCase(),'tasklist'));
|
||||
$('#task-list .task-text').html(Q(me.tasklists[rec.list] ? me.tasklists[rec.list].name : ''));
|
||||
$('#task-attendees, #task-organizer').hide();
|
||||
$('#task-attendees, #task-organizer, #task-created-changed, #task-rsvp-comment').hide();
|
||||
|
||||
var itags = get_inherited_tags(rec);
|
||||
var taglist = $('#task-tags')[(rec.tags && rec.tags.length || itags.length ? 'show' : 'hide')]().children('.task-text').empty();
|
||||
|
@ -1657,7 +1686,6 @@ function rcube_tasklist_ui(settings)
|
|||
|
||||
// list task attendees
|
||||
if (list.attendees && rec.attendees) {
|
||||
console.log(rec.attendees)
|
||||
/*
|
||||
// sort resources to the end
|
||||
rec.attendees.sort(function(a,b) {
|
||||
|
@ -1720,13 +1748,16 @@ function rcube_tasklist_ui(settings)
|
|||
.children('.task-text')
|
||||
.html(Q(rcmail.gettext('itip' + mystatus, 'libcalendaring')));
|
||||
}
|
||||
|
||||
$('#task-rsvp')[(rsvp && !is_organizer(event) && rec.status != 'CANCELLED' ? 'show' : 'hide')]();
|
||||
*/
|
||||
var show_rsvp = rsvp && !is_organizer(rec) && rec.status != 'CANCELLED';
|
||||
$('#task-rsvp')[(show_rsvp ? 'show' : 'hide')]();
|
||||
$('#task-rsvp .rsvp-buttons input').prop('disabled', false).filter('input[rel='+mystatus+']').prop('disabled', true);
|
||||
|
||||
if (show_rsvp && rec.comment) {
|
||||
$('#task-rsvp-comment').show().children('.task-text').html(Q(rec.comment));
|
||||
}
|
||||
$('#task-rsvp a.reply-comment-toggle').show();
|
||||
$('#task-rsvp .itip-reply-comment textarea').hide().val('');
|
||||
*/
|
||||
|
||||
if (rec.organizer && !organizer) {
|
||||
$('#task-organizer').show().children('.task-text').html(task_attendee_html(rec.organizer));
|
||||
|
|
|
@ -321,6 +321,22 @@ class tasklist extends rcube_plugin
|
|||
|
||||
$this->rc->user->save_prefs(array('tasklist_collapsed_tasks' => join(',', array_unique($this->collapsed_tasks))));
|
||||
return; // avoid further actions
|
||||
|
||||
case 'rsvp':
|
||||
$status = get_input_value('status', RCUBE_INPUT_GPC);
|
||||
$task = $this->driver->get_task($rec);
|
||||
$task['attendees'] = $rec['attendees'];
|
||||
$rec = $task;
|
||||
|
||||
if ($success = $this->driver->edit_task($rec)) {
|
||||
$noreply = intval(get_input_value('noreply', RCUBE_INPUT_GPC)) || $status == 'needs-action';
|
||||
|
||||
if (!$noreply) {
|
||||
// let the reply clause further down send the iTip message
|
||||
$rec['_reportpartstat'] = $status;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
|
@ -354,6 +370,9 @@ class tasklist extends rcube_plugin
|
|||
$sender = $task['attendees'][$idx];
|
||||
$status = strtolower($sender['status']);
|
||||
|
||||
if (!empty($_POST['comment']))
|
||||
$task['comment'] = get_input_value('comment', RCUBE_INPUT_POST);
|
||||
|
||||
$itip = $this->load_itip();
|
||||
$itip->set_sender_email($sender['email']);
|
||||
|
||||
|
@ -1862,4 +1881,25 @@ class tasklist extends rcube_plugin
|
|||
$this->load_driver();
|
||||
return $this->driver->user_delete($args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Magic getter for public access to protected members
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'ical':
|
||||
return $this->get_ical();
|
||||
|
||||
case 'itip':
|
||||
return $this->load_itip();
|
||||
|
||||
case 'driver':
|
||||
$this->load_driver();
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ class tasklist_ui
|
|||
$this->plugin->register_handler('plugin.attendees_form', array($this, 'attendees_form'));
|
||||
$this->plugin->register_handler('plugin.identity_select', array($this, 'identity_select'));
|
||||
$this->plugin->register_handler('plugin.edit_attendees_notify', array($this, 'edit_attendees_notify'));
|
||||
$this->plugin->register_handler('plugin.task_rsvp_buttons', array($this->plugin->itip, 'itip_rsvp_buttons'));
|
||||
|
||||
$this->plugin->include_script('jquery.tagedit.js');
|
||||
$this->plugin->include_script('tasklist.js');
|
||||
|
|
Loading…
Add table
Reference in a new issue