3 commits - plugins/calendar plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Fri Aug 3 21:34:34 CEST 2012
plugins/calendar/calendar.php | 31 +++-
plugins/calendar/calendar_base.js | 25 ++-
plugins/calendar/calendar_ui.js | 2
plugins/calendar/skins/classic/templates/freebusylegend.html | 10 -
plugins/calendar/skins/larry/templates/freebusylegend.html | 10 -
plugins/tasklist/drivers/database/tasklist_database_driver.php | 68 +++++++++-
plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php | 25 +++
plugins/tasklist/drivers/tasklist_driver.php | 23 +++
plugins/tasklist/tasklist.php | 41 ++++++
9 files changed, 206 insertions(+), 29 deletions(-)
New commits:
commit 7b660767057374d6d509741d81705fcf7e2fa591
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Fri Aug 3 21:34:00 2012 +0200
Hook into the alarms infrastructure of the calendar plugin. This is to be refactored into a libcalendaring plugin
diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index 9bd0625..2b3ff90 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -338,6 +338,70 @@ class tasklist_database_driver extends tasklist_driver
}
/**
+ * Get a list of pending alarms to be displayed to the user
+ *
+ * @param integer Current time (unix timestamp)
+ * @param mixed List of list IDs to show alarms for (either as array or comma-separated string)
+ * @return array A list of alarms, each encoded as hash array with task properties
+ * @see tasklist_driver::pending_alarms()
+ */
+ public function pending_alarms($time, $lists = null)
+ {
+ if (empty($lists))
+ $lists = array_keys($this->lists);
+ else if (is_string($lists))
+ $lists = explode(',', $lists);
+
+ // only allow to select from calendars with activated alarms
+ $list_ids = array();
+ foreach ($lists as $lid) {
+ if ($this->lists[$lid] && $this->lists[$lid]['showalarms'])
+ $list_ids[] = $lid;
+ }
+ $list_ids = array_map(array($this->rc->db, 'quote'), $list_ids);
+
+ $alarms = array();
+ if (!empty($list_ids)) {
+ $result = $this->rc->db->query(sprintf(
+ "SELECT * FROM " . $this->db_tasks . "
+ WHERE tasklist_id IN (%s)
+ AND notify <= %s AND date > %s",
+ join(',', $list_ids),
+ $this->rc->db->fromunixtime($time),
+ $this->rc->db->fromunixtime($time)
+ ));
+
+ while ($result && ($rec = $this->rc->db->fetch_assoc($result)))
+ $alarms[] = $this->_read_postprocess($rec);
+ }
+
+ return $alarms;
+ }
+
+ /**
+ * Feedback after showing/sending an alarm notification
+ *
+ * @see tasklist_driver::dismiss_alarm()
+ */
+ public function dismiss_alarm($task_id, $snooze = 0)
+ {
+ // set new notifyat time or unset if not snoozed
+ $notify_at = $snooze > 0 ? date('Y-m-d H:i:s', time() + $snooze) : null;
+
+ $query = $this->rc->db->query(sprintf(
+ "UPDATE " . $this->db_tasks . "
+ SET changed=%s, notify=?
+ WHERE task_id=?
+ AND tasklist_id IN (" . $this->list_ids . ")",
+ $this->rc->db->now()),
+ $notify_at,
+ $task_id
+ );
+
+ return $this->rc->db->affected_rows($query);
+ }
+
+ /**
* Map some internal database values to match the generic "API"
*/
private function _read_postprocess($rec)
@@ -514,9 +578,9 @@ class tasklist_database_driver extends tasklist_driver
// fake object properties to suit the expectations of calendar::get_next_alarm()
// TODO: move all that to libcalendaring plugin
if ($task['date'])
- $task['start'] = new DateTime($task['date'] . ' ' . ($task['time'] ?: '23:00'), $this->plugin->timezone);
+ $task['start'] = new DateTime($task['date'] . ' ' . ($task['time'] ?: '12:00'), $this->plugin->timezone);
if ($task['startdate'])
- $task['end'] = new DateTime($task['startdate'] . ' ' . ($task['starttime'] ?: '06:00'), $this->plugin->timezone);
+ $task['end'] = new DateTime($task['startdate'] . ' ' . ($task['starttime'] ?: '12:00'), $this->plugin->timezone);
else
$task['end'] = $tast['start'];
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 25d4c08..03b9926 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -317,6 +317,31 @@ class tasklist_kolab_driver extends tasklist_driver
}
/**
+ * Get a list of pending alarms to be displayed to the user
+ *
+ * @param integer Current time (unix timestamp)
+ * @param mixed List of list IDs to show alarms for (either as array or comma-separated string)
+ * @return array A list of alarms, each encoded as hash array with task properties
+ * @see tasklist_driver::pending_alarms()
+ */
+ public function pending_alarms($time, $lists = null)
+ {
+ // TODO: implement this
+ }
+
+ /**
+ * (User) feedback after showing an alarm notification
+ * This should mark the alarm as 'shown' or snooze it for the given amount of time
+ *
+ * @param string Task identifier
+ * @param integer Suspend the alarm for this number of seconds
+ */
+ public function dismiss_alarm($id, $snooze = 0)
+ {
+ // TODO: implement this
+ }
+
+ /**
* Convert from Kolab_Format to internal representation
*/
private function _to_rcube_task($record)
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index 924da21..0d3a365 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -129,6 +129,29 @@ abstract class tasklist_driver
abstract function list_tasks($filter, $lists = null);
/**
+ * Get a list of pending alarms to be displayed to the user
+ *
+ * @param integer Current time (unix timestamp)
+ * @param mixed List of list IDs to show alarms for (either as array or comma-separated string)
+ * @return array A list of alarms, each encoded as hash array with task properties
+ * id: Task identifier
+ * uid: Unique identifier of this task
+ * date: Task due date
+ * time: Task due time
+ * title: Task title/summary
+ */
+ abstract function pending_alarms($time, $lists = null);
+
+ /**
+ * (User) feedback after showing an alarm notification
+ * This should mark the alarm as 'shown' or snooze it for the given amount of time
+ *
+ * @param string Task identifier
+ * @param integer Suspend the alarm for this number of seconds
+ */
+ abstract function dismiss_alarm($id, $snooze = 0);
+
+ /**
* Return data of a specific task
*
* @param mixed Hash array with task properties or task UID
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 13635a7..9589354 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -113,6 +113,10 @@ class tasklist extends rcube_plugin
$this->ui = new tasklist_ui($this);
$this->ui->init();
}
+
+ // add hooks for alarms handling
+ $this->add_hook('pending_alarms', array($this, 'pending_alarms'));
+ $this->add_hook('dismiss_alarms', array($this, 'dismiss_alarms'));
}
@@ -619,6 +623,43 @@ class tasklist extends rcube_plugin
}
+ /**
+ * Handler for pending_alarms plugin hook triggered by the calendar module on keep-alive requests.
+ * This will check for pending notifications and pass them to the client
+ */
+ public function pending_alarms($p)
+ {
+ $this->load_driver();
+ if ($alarms = $this->driver->pending_alarms($p['time'] ?: time())) {
+ foreach ($alarms as $alarm) {
+ // encode alarm object to suit the expectations of the calendaring code
+ if ($alarm['date'])
+ $alarm['start'] = new DateTime($alarm['date'].' '.$alarm['time'], $this->timezone);
+
+ $alarm['id'] = 'task:' . $alarm['id']; // prefix ID with task:
+ $alarm['allday'] = empty($alarm['time']) ? 1 : 0;
+ $p['alarms'][] = $alarm;
+ }
+ }
+
+ return $p;
+ }
+
+ /**
+ * Handler for alarm dismiss hook triggered by the calendar module
+ */
+ public function dismiss_alarms($p)
+ {
+ $this->load_driver();
+ foreach ((array)$p['ids'] as $id) {
+ if (strpos($id, 'task:') === 0)
+ $p['success'] |= $this->driver->dismiss_alarm(substr($id, 5), $p['snooze']);
+ }
+
+ return $p;
+ }
+
+
/******* Attachment handling *******/
/*** pretty much the same as in plugins/calendar/calendar.php ***/
commit c0fc38ab9c4585e29abd44d7bdf21ea95fcbeb81
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Fri Aug 3 21:29:10 2012 +0200
Trigger plugin hooks to display and snooze/dismiss alarms
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 5061f20..e0c7126 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -772,8 +772,13 @@ class calendar extends rcube_plugin
break;
case "dismiss":
- foreach (explode(',', $event['id']) as $id)
- $success |= $this->driver->dismiss_alarm($id, $event['snooze']);
+ $event['ids'] = explode(',', $event['id']);
+ $plugin = $this->rc->plugins->exec_hook('dismiss_alarms', $event);
+ $success = $plugin['success'];
+ foreach ($event['ids'] as $id) {
+ if (strpos($id, 'cal:') === 0)
+ $success |= $this->driver->dismiss_alarm(substr($id, 4), $event['snooze']);
+ }
break;
}
@@ -833,15 +838,25 @@ class calendar extends rcube_plugin
*/
function keep_alive($attr)
{
+ $timestamp = time();
$this->load_driver();
- $alarms = $this->driver->pending_alarms(time());
- if ($alarms) {
+ $alarms = $this->driver->pending_alarms($timestamp);
+ foreach ($alarms as $i => $alarm) {
+ $alarms[$i]['id'] = 'cal:' . $alarm['id']; // prefix ID with cal:
+ }
+
+ $plugin = $this->rc->plugins->exec_hook('pending_alarms', array(
+ 'time' => $timestamp,
+ 'alarms' => $alarms,
+ ));
+
+ if (!$plugin['abort'] && $plugin['alarms']) {
// make sure texts and env vars are available on client
if ($this->rc->task != 'calendar') {
$this->add_texts('localization/', true);
$this->rc->output->set_env('snooze_select', $this->ui->snooze_select());
}
- $this->rc->output->command('plugin.display_alarms', $this->_alarms_output($alarms));
+ $this->rc->output->command('plugin.display_alarms', $this->_alarms_output($plugin['alarms']));
}
}
@@ -1181,9 +1196,9 @@ class calendar extends rcube_plugin
foreach ($alarms as $alarm) {
$out[] = array(
'id' => $alarm['id'],
- 'start' => $this->adjust_timezone($alarm['start'])->format('c'),
- 'end' => $this->adjust_timezone($alarm['end'])->format('c'),
- 'allDay' => ($event['allday'] == 1)?true:false,
+ 'start' => $alarm['start'] ? $this->adjust_timezone($alarm['start'])->format('c') : '',
+ 'end' => $alarm['end'] ? $this->adjust_timezone($alarm['end'])->format('c') : '',
+ 'allDay' => ($alarm['allday'] == 1)?true:false,
'title' => $alarm['title'],
'location' => $alarm['location'],
'calendar' => $alarm['calendar'],
diff --git a/plugins/calendar/calendar_base.js b/plugins/calendar/calendar_base.js
index a77af01..d0a4a58 100644
--- a/plugins/calendar/calendar_base.js
+++ b/plugins/calendar/calendar_base.js
@@ -46,15 +46,24 @@ function rcube_calendar(settings)
// create a nice human-readable string for the date/time range
this.event_date_text = function(event)
{
+ if (!event.start)
+ return '';
+ if (!event.end)
+ event.end = event.start;
+
var fromto, duration = event.end.getTime() / 1000 - event.start.getTime() / 1000;
- if (event.allDay)
- fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + (duration > 86400 || event.start.getDay() != event.end.getDay() ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
- else if (duration < 86400 && event.start.getDay() == event.end.getDay())
- fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format']) + ' — '
- + $.fullCalendar.formatDate(event.end, settings['time_format']);
- else
- fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format']) + ' — '
- + $.fullCalendar.formatDate(event.end, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.end, settings['time_format']);
+ if (event.allDay) {
+ fromto = $.fullCalendar.formatDate(event.start, settings['date_format'])
+ + (duration > 86400 || event.start.getDay() != event.end.getDay() ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
+ }
+ else if (duration < 86400 && event.start.getDay() == event.end.getDay()) {
+ fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format'])
+ + (duration > 0 ? ' — ' + $.fullCalendar.formatDate(event.end, settings['time_format']) : '');
+ }
+ else {
+ fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format'])
+ + (duration > 0 ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.end, settings['time_format']) : '');
+ }
return fromto;
};
commit 370b60e3eefdbc0189963b1e1a0fb1b52544d4a2
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Fri Aug 3 21:25:38 2012 +0200
Change location to blank.gif which has changed in Roundcube core
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 2c27590..56725db 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1464,7 +1464,7 @@ function rcube_calendar_ui(settings)
var html = '<td class="role">' + select + '</td>' +
'<td class="name">' + dispname + '</td>' +
- '<td class="availability"><img src="./program/blank.gif" class="availabilityicon ' + avail + '" /></td>' +
+ '<td class="availability"><img src="./program/resources/blank.gif" class="availabilityicon ' + avail + '" /></td>' +
'<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '">' + Q(data.status) + '</span></td>' +
'<td class="options">' + (organizer || readonly ? '' : dellink) + '</td>';
diff --git a/plugins/calendar/skins/classic/templates/freebusylegend.html b/plugins/calendar/skins/classic/templates/freebusylegend.html
index 5cc01a1..85a565c 100644
--- a/plugins/calendar/skins/classic/templates/freebusylegend.html
+++ b/plugins/calendar/skins/classic/templates/freebusylegend.html
@@ -1,7 +1,7 @@
<div id="edit-attendees-legend" class="availability">
- <span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
- <span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
- <span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
- <span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
- <span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
+ <span class="legend"><img class="availabilityicon free" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
+ <span class="legend"><img class="availabilityicon busy" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
+ <span class="legend"><img class="availabilityicon tentative" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
+ <span class="legend"><img class="availabilityicon out-of-office" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
+ <span class="legend"><img class="availabilityicon unknown" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
</div>
diff --git a/plugins/calendar/skins/larry/templates/freebusylegend.html b/plugins/calendar/skins/larry/templates/freebusylegend.html
index 51e5ddc..45f627a 100644
--- a/plugins/calendar/skins/larry/templates/freebusylegend.html
+++ b/plugins/calendar/skins/larry/templates/freebusylegend.html
@@ -1,7 +1,7 @@
<div id="edit-attendees-legend" class="availability">
- <span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
- <span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
- <span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
- <span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
- <span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
+ <span class="legend"><img class="availabilityicon free" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
+ <span class="legend"><img class="availabilityicon busy" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
+ <span class="legend"><img class="availabilityicon tentative" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
+ <span class="legend"><img class="availabilityicon out-of-office" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
+ <span class="legend"><img class="availabilityicon unknown" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
</div>
More information about the commits
mailing list