Improve iTip REQUEST workflow:
- only increase sequence on significant changes that affect scheduling (acc. RFC 5545) - show RSVP buttons only for higher sequence updates (#1678) - provide a button to simply update the local copy otherwise
This commit is contained in:
parent
0c5465c2ad
commit
afb64c3948
5 changed files with 47 additions and 6 deletions
|
@ -285,7 +285,7 @@ class libcalendaring_itip
|
||||||
$action = 'import';
|
$action = 'import';
|
||||||
}
|
}
|
||||||
else if (in_array(strtolower($status), $this->rsvp_status)) {
|
else if (in_array(strtolower($status), $this->rsvp_status)) {
|
||||||
$html = html::div('rsvp-status ' . strtolower($status), $this->gettext('youhave'.strtolower($status)));
|
$html = html::div('rsvp-status ' . strtolower($status), $this->gettext(($latest ? 'youhave' : 'youhavepreviously') . strtolower($status)));
|
||||||
|
|
||||||
if ($existing && ($existing['sequence'] > $event['sequence'] || (!$event['sequence'] && $existing['changed'] && $existing['changed'] > $event['changed']))) {
|
if ($existing && ($existing['sequence'] > $event['sequence'] || (!$event['sequence'] && $existing['changed'] && $existing['changed'] > $event['changed']))) {
|
||||||
$action = ''; // nothing to do here, outdated invitation
|
$action = ''; // nothing to do here, outdated invitation
|
||||||
|
@ -293,6 +293,9 @@ class libcalendaring_itip
|
||||||
else if (!$existing && !$rsvp) {
|
else if (!$existing && !$rsvp) {
|
||||||
$action = 'import';
|
$action = 'import';
|
||||||
}
|
}
|
||||||
|
else if ($latest) {
|
||||||
|
$action = 'update';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// determine action for REPLY
|
// determine action for REPLY
|
||||||
|
@ -419,7 +422,15 @@ class libcalendaring_itip
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Simply import the event without replying
|
// 2. update the local copy with minor changes
|
||||||
|
$update_button = html::tag('input', array(
|
||||||
|
'type' => 'button',
|
||||||
|
'class' => 'button',
|
||||||
|
'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '$task')",
|
||||||
|
'value' => $this->gettext('updatemycopy'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// 3. Simply import the event without replying
|
||||||
$import_button = html::tag('input', array(
|
$import_button = html::tag('input', array(
|
||||||
'type' => 'button',
|
'type' => 'button',
|
||||||
'class' => 'button',
|
'class' => 'button',
|
||||||
|
@ -441,6 +452,7 @@ class libcalendaring_itip
|
||||||
$rsvp_buttons .= html::div('itip-reply-controls', $this->itip_rsvp_options_ui($dom_id));
|
$rsvp_buttons .= html::div('itip-reply-controls', $this->itip_rsvp_options_ui($dom_id));
|
||||||
|
|
||||||
$buttons[] = html::div(array('id' => 'rsvp-'.$dom_id, 'class' => 'rsvp-buttons', 'style' => 'display:none'), $rsvp_buttons);
|
$buttons[] = html::div(array('id' => 'rsvp-'.$dom_id, 'class' => 'rsvp-buttons', 'style' => 'display:none'), $rsvp_buttons);
|
||||||
|
$buttons[] = html::div(array('id' => 'update-'.$dom_id, 'style' => 'display:none'), $update_button);
|
||||||
}
|
}
|
||||||
// for CANCEL messages, we can:
|
// for CANCEL messages, we can:
|
||||||
else if ($method == 'CANCEL') {
|
else if ($method == 'CANCEL') {
|
||||||
|
|
|
@ -99,6 +99,13 @@ $labels['youhavetentative'] = 'You have tentatively accepted this invitation';
|
||||||
$labels['youhavedeclined'] = 'You have declined this invitation';
|
$labels['youhavedeclined'] = 'You have declined this invitation';
|
||||||
$labels['youhavedelegated'] = 'You have delegated this invitation';
|
$labels['youhavedelegated'] = 'You have delegated this invitation';
|
||||||
$labels['youhaveneeds-action'] = 'You have copied this invitation into your calendar';
|
$labels['youhaveneeds-action'] = 'You have copied this invitation into your calendar';
|
||||||
|
|
||||||
|
$labels['youhavepreviouslyaccepted'] = 'You have previously accepted this invitation';
|
||||||
|
$labels['youhavepreviouslytentative'] = 'You have previously accepted this invitation tentatively';
|
||||||
|
$labels['youhavepreviouslydeclined'] = 'You have previously declined this invitation';
|
||||||
|
$labels['youhavepreviouslydelegated'] = 'You have previously delegated this invitation';
|
||||||
|
$labels['youhavepreviouslyneeds-action'] = 'You have copied this invitation into your calendar';
|
||||||
|
|
||||||
$labels['attendeeaccepted'] = 'Participant has accepted';
|
$labels['attendeeaccepted'] = 'Participant has accepted';
|
||||||
$labels['attendeetentative'] = 'Participant has tentatively accepted';
|
$labels['attendeetentative'] = 'Participant has tentatively accepted';
|
||||||
$labels['attendeedeclined'] = 'Participant has declined';
|
$labels['attendeedeclined'] = 'Participant has declined';
|
||||||
|
|
|
@ -26,6 +26,8 @@ class kolab_format_event extends kolab_format_xcal
|
||||||
{
|
{
|
||||||
public $CTYPEv2 = 'application/x-vnd.kolab.event';
|
public $CTYPEv2 = 'application/x-vnd.kolab.event';
|
||||||
|
|
||||||
|
public static $scheduling_properties = array('start', 'end', 'allday', 'location');
|
||||||
|
|
||||||
protected $objclass = 'Event';
|
protected $objclass = 'Event';
|
||||||
protected $read_func = 'readEvent';
|
protected $read_func = 'readEvent';
|
||||||
protected $write_func = 'writeEvent';
|
protected $write_func = 'writeEvent';
|
||||||
|
|
|
@ -26,6 +26,8 @@ class kolab_format_task extends kolab_format_xcal
|
||||||
{
|
{
|
||||||
public $CTYPEv2 = 'application/x-vnd.kolab.task';
|
public $CTYPEv2 = 'application/x-vnd.kolab.task';
|
||||||
|
|
||||||
|
public static $scheduling_properties = array('start', 'due', 'summary', 'status');
|
||||||
|
|
||||||
protected $objclass = 'Todo';
|
protected $objclass = 'Todo';
|
||||||
protected $read_func = 'readTodo';
|
protected $read_func = 'readTodo';
|
||||||
protected $write_func = 'writeTodo';
|
protected $write_func = 'writeTodo';
|
||||||
|
|
|
@ -29,6 +29,7 @@ abstract class kolab_format_xcal extends kolab_format
|
||||||
public $CTYPE = 'application/calendar+xml';
|
public $CTYPE = 'application/calendar+xml';
|
||||||
|
|
||||||
public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
|
public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
|
||||||
|
public static $scheduling_properties = array('start', 'end', 'location');
|
||||||
|
|
||||||
protected $sensitivity_map = array(
|
protected $sensitivity_map = array(
|
||||||
'public' => kolabformat::ClassPublic,
|
'public' => kolabformat::ClassPublic,
|
||||||
|
@ -302,10 +303,27 @@ abstract class kolab_format_xcal extends kolab_format
|
||||||
// set common object properties
|
// set common object properties
|
||||||
parent::set($object);
|
parent::set($object);
|
||||||
|
|
||||||
// increment sequence on updates
|
// set sequence value
|
||||||
if (empty($object['sequence']))
|
if (!isset($object['sequence'])) {
|
||||||
$object['sequence'] = !$is_new ? $this->obj->sequence()+1 : 0;
|
if ($is_new) {
|
||||||
$this->obj->setSequence($object['sequence']);
|
$object['sequence'] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$object['sequence'] = $this->obj->sequence();
|
||||||
|
$old = $this->data['uid'] ? $this->data : $this->to_array();
|
||||||
|
|
||||||
|
// increment sequence when updating properties relevant for scheduling.
|
||||||
|
// RFC 5545: "It is incremented [...] each time the Organizer makes a significant revision to the calendar component."
|
||||||
|
// TODO: make the list of properties considered 'significant' for scheduling configurable
|
||||||
|
foreach (self::$scheduling_properties as $prop) {
|
||||||
|
if ($object[$prop] != $old[$prop]) {
|
||||||
|
$object['sequence']++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->obj->setSequence(intval($object['sequence']));
|
||||||
|
|
||||||
$this->obj->setSummary($object['title']);
|
$this->obj->setSummary($object['title']);
|
||||||
$this->obj->setLocation($object['location']);
|
$this->obj->setLocation($object['location']);
|
||||||
|
|
Loading…
Add table
Reference in a new issue