summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-09-11 15:55:01 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2014-09-11 15:55:01 (GMT)
commit086e2b2e1fa86cdd37a298fdaadd3472518d53b7 (patch)
tree0738bd6d2e6bcae5d737846bebe76fb861330cc0
parent6b7fc6729d23e273f4e5a9cbbd2f6cd7ec8b9ba8 (diff)
downloadroundcubemail-plugins-kolab-086e2b2e1fa86cdd37a298fdaadd3472518d53b7.tar.gz
Render preview agenda for iTip requests below RSVP buttons (#3161)
-rw-r--r--plugins/calendar/calendar.php58
-rw-r--r--plugins/calendar/localization/en_US.inc2
-rw-r--r--plugins/calendar/skins/classic/calendar.css36
-rw-r--r--plugins/calendar/skins/larry/calendar.css38
-rw-r--r--plugins/libcalendaring/lib/libcalendaring_itip.php3
-rw-r--r--plugins/libcalendaring/libcalendaring.js14
6 files changed, 150 insertions, 1 deletions
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 9c0a892..5616b28 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -2237,6 +2237,37 @@ class calendar extends rcube_plugin
$response['select'] = html::tag('input', array('type' => 'hidden', 'name' => 'calendar', 'id' => 'itip-saveto', 'value' => ''));
}
+ // render small agenda view for the respective day
+ if ($data['method'] == 'REQUEST' && !empty($data['date']) && $response['action'] == 'rsvp') {
+ $event_start = rcube_utils::anytodatetime($data['date']);
+ $day_start = new Datetime(gmdate('Y-m-d 00:00', $data['date']), $this->lib->timezone);
+ $day_end = new Datetime(gmdate('Y-m-d 23:59', $data['date']), $this->lib->timezone);
+
+ // get events on that day from the user's personal calendars
+ $calendars = $this->driver->list_calendars(false, true);
+ $events = $this->driver->load_events($day_start->format('U'), $day_end->format('U'), null, array_keys($calendars));
+ usort($events, function($a, $b) { return $a['start'] > $b['start'] ? 1 : -1; });
+
+ $before = $after = array();
+ foreach ($events as $event) {
+ // TODO: skip events with free_busy == 'free' ?
+ if ($event['uid'] == $data['uid'] || $event['end'] < $day_start || $event['start'] > $day_end)
+ continue;
+ else if ($event['start'] < $event_start)
+ $before[] = $this->mail_agenda_event_row($event);
+ else
+ $after[] = $this->mail_agenda_event_row($event);
+ }
+
+ $response['append'] = array(
+ 'selector' => '.calendar-agenda-preview',
+ 'replacements' => array(
+ '%before%' => !empty($before) ? join("\n", array_slice($before, -3)) : html::div('event-row no-event', $this->gettext('noearlierevents')),
+ '%after%' => !empty($after) ? join("\n", array_slice($after, 0, 3)) : html::div('event-row no-event', $this->gettext('nolaterevents')),
+ ),
+ );
+ }
+
$this->rc->output->command('plugin.update_itip_object_status', $response);
}
@@ -2338,6 +2369,21 @@ class calendar extends rcube_plugin
$hidden = new html_hiddenfield(array('name' => "_t", 'value' => $this->token));
return html::tag('form', array('action' => $this->rc->url(array('task' => 'calendar', 'action' => 'attend')), 'method' => 'post', 'noclose' => true) + $attrib) . $hidden->show();
}
+
+ /**
+ *
+ */
+ private function mail_agenda_event_row($event, $class = '')
+ {
+ $time = $event['all-day'] ? $this->gettext('allday') :
+ $this->rc->format_date($event['start'], $this->rc->config->get('time_format')) . ' - ' .
+ $this->rc->format_date($event['end'], $this->rc->config->get('time_format'));
+
+ return html::div(rtrim('event-row ' . $class),
+ html::span('event-date', $time) .
+ html::span('event-title', Q($event['title']))
+ );
+ }
/**
*
@@ -2391,6 +2437,16 @@ class calendar extends rcube_plugin
// get prepared inline UI for this event object
if ($ical_objects->method) {
+ $append = '';
+
+ // prepare a small agenda preview to be filled with actual event data on async request
+ if ($ical_objects->method == 'REQUEST') {
+ $append = html::div('calendar-agenda-preview',
+ html::tag('h3', 'preview-title', $this->gettext('agenda') . ' ' .
+ html::span('date', $this->rc->format_date($event['start'], $this->rc->config->get('date_format')))
+ ) . '%before%' . $this->mail_agenda_event_row($event, 'current') . '%after%');
+ }
+
$html .= html::div('calendar-invitebox',
$this->itip->mail_itip_inline_ui(
$event,
@@ -2399,7 +2455,7 @@ class calendar extends rcube_plugin
'calendar',
rcube_utils::anytodatetime($ical_objects->message_date),
$this->rc->url(array('task' => 'calendar')) . '&view=agendaDay&date=' . $event['start']->format('U')
- )
+ ) . $append
);
}
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index 76fbcee..7755aa7 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -202,6 +202,8 @@ $labels['saveincalendar'] = 'save in';
$labels['updatemycopy'] = 'Update in my calendar';
$labels['savetocalendar'] = 'Save to calendar';
$labels['openpreview'] = 'Check Calendar';
+$labels['noearlierevents'] = 'No earlier events';
+$labels['nolaterevents'] = 'No later events';
// resources
$labels['resource'] = 'Resource';
diff --git a/plugins/calendar/skins/classic/calendar.css b/plugins/calendar/skins/classic/calendar.css
index f7e0c1c..f8a4fa3 100644
--- a/plugins/calendar/skins/classic/calendar.css
+++ b/plugins/calendar/skins/classic/calendar.css
@@ -1688,6 +1688,42 @@ div.calendar-invitebox .rsvp-status.delegated {
background-position: 2px -180px;
}
+div.calendar-invitebox .calendar-agenda-preview {
+ display: none;
+ border-top: 1px solid #dfdfdf;
+ margin-top: 1em;
+ padding-top: 0.6em;
+}
+
+div.calendar-invitebox .calendar-agenda-preview h3.preview-title {
+ margin: 0 0 0.5em 0;
+ font-size: 12px;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row {
+ color: #777;
+ padding: 2px 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row.current {
+ color: #000;
+ font-weight: bold;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row.no-event {
+ font-style: italic;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-date {
+ display: inline-block;
+ min-width: 8em;
+ margin-right: 1em;
+ white-space: nowrap;
+}
+
/* iTIP attend reply page */
.calendaritipattend .centerbox {
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 54e0141..40d79fd 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -2110,6 +2110,44 @@ div.calendar-invitebox .rsvp-status.needs-action {
background-position: 2px 0;
}
+div.calendar-invitebox .calendar-agenda-preview {
+ display: none;
+ border-top: 1px solid #dfdfdf;
+ margin-top: 1em;
+ padding-top: 0.6em;
+}
+
+div.calendar-invitebox .calendar-agenda-preview h3.preview-title {
+ margin: 0 0 0.5em 0;
+ font-size: 12px;
+ color: #333;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row {
+ color: #777;
+ padding: 2px 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row.current {
+ color: #333;
+ font-weight: bold;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-row.no-event {
+ font-style: italic;
+}
+
+div.calendar-invitebox .calendar-agenda-preview .event-date {
+ display: inline-block;
+ min-width: 8em;
+ margin-right: 1em;
+ white-space: nowrap;
+}
+
+
/* iTIP attend reply page */
.calendaritipattend .centerbox {
diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php
index a5b056f..6740bfa 100644
--- a/plugins/libcalendaring/lib/libcalendaring_itip.php
+++ b/plugins/libcalendaring/lib/libcalendaring_itip.php
@@ -434,6 +434,9 @@ class libcalendaring_itip
$emails = $this->lib->get_user_emails();
$title = $event['sequence'] > 0 ? $this->gettext('itipupdate') : $this->gettext('itipinvitation');
$metadata['rsvp'] = true;
+ if (is_object($event['start'])) {
+ $metadata['date'] = $event['start']->format('U');
+ }
// check for X-KOLAB-INVITATIONTYPE property and only show accept/decline buttons
if (self::get_custom_property($event, 'X-KOLAB-INVITATIONTYPE') == 'CONFIRMATION') {
diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index b23a3fe..5b8ad5c 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -912,6 +912,20 @@ rcube_libcalendaring.update_itip_object_status = function(p)
// show rsvp/import buttons (with calendar selector)
$('#'+p.action+'-'+p.id).show().find('input.button').last().after(p.select);
+
+ // show itip box appendix after replacing the given placeholders
+ if (p.append && p.append.selector) {
+ var elem = $(p.append.selector);
+ if (p.append.replacements) {
+ $.each(p.append.replacements, function(k, html) {
+ elem.html(elem.html().replace(k, html));
+ });
+ }
+ else if (p.append.html) {
+ elem.html(p.append.html)
+ }
+ elem.show();
+ }
};
/**