From 2123ea7d97bb4cf464e8fcd4634a071489f21187 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Wed, 9 Apr 2014 13:54:04 +0200 Subject: [PATCH] Add property for event status; specially annotate CANCELLED events in the UI --- plugins/calendar/calendar.php | 4 +- plugins/calendar/calendar_ui.js | 10 +++ plugins/calendar/drivers/calendar_driver.php | 1 + .../drivers/database/SQL/mysql.initial.sql | 1 + .../drivers/database/SQL/mysql/2014040900.sql | 3 + .../drivers/database/SQL/postgres.initial.sql | 1 + .../database/SQL/postgres/2014040900.sql | 3 + .../drivers/database/SQL/sqlite.initial.sql | 1 + .../database/SQL/sqlite/2014040900.sql | 67 ++++++++++++++++++ .../drivers/database/database_driver.php | 21 +++--- .../calendar/drivers/kolab/kolab_calendar.php | 4 ++ plugins/calendar/lib/calendar_ui.php | 15 ++++ plugins/calendar/localization/en_US.inc | 3 + plugins/calendar/skins/classic/calendar.css | 8 +++ .../skins/classic/images/badge_cancelled.png | Bin 0 -> 1707 bytes .../skins/classic/templates/eventedit.html | 4 ++ plugins/calendar/skins/larry/calendar.css | 8 +++ .../skins/larry/images/badge_cancelled.png | Bin 0 -> 1707 bytes .../skins/larry/images/badge_confidential.png | Bin 3441 -> 3244 bytes .../skins/larry/images/badge_private.png | Bin 3359 -> 3209 bytes .../skins/larry/templates/calendar.html | 4 ++ .../skins/larry/templates/eventedit.html | 4 ++ plugins/libcalendaring/libcalendaring.php | 2 +- 23 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 plugins/calendar/drivers/database/SQL/mysql/2014040900.sql create mode 100644 plugins/calendar/drivers/database/SQL/postgres/2014040900.sql create mode 100644 plugins/calendar/drivers/database/SQL/sqlite/2014040900.sql create mode 100644 plugins/calendar/skins/classic/images/badge_cancelled.png create mode 100644 plugins/calendar/skins/larry/images/badge_cancelled.png diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 19aa4bdb..e4c3b291 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -1652,11 +1652,11 @@ class calendar extends rcube_plugin */ private function notify_attendees($event, $old, $action = 'edit') { - if ($action == 'remove') { + if ($action == 'remove' || ($event['status'] == 'CANCELLED' && $old['status'] != $event['status'])) { $event['cancelled'] = true; $is_cancelled = true; } - + $itip = $this->load_itip(); $emails = $this->get_user_emails(); diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index e8678564..92a17653 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -325,6 +325,11 @@ function rcube_calendar_ui(settings) $('#event-priority').show().children('.event-text').html(Q(event.priority+' '+priolabels[event.priority])); } + if (event.status) { + var status_lc = String(event.status).toLowerCase(); + $('#event-status').show().children('.event-text').html(Q(rcmail.gettext(status_lc,'calendar'))); + $dialog.addClass('status-'+status_lc); + } if (event.sensitivity && event.sensitivity != 'public') { $('#event-sensitivity').show().children('.event-text').html(Q(sensitivitylabels[event.sensitivity])); $dialog.addClass('sensitivity-'+event.sensitivity); @@ -491,6 +496,7 @@ function rcube_calendar_ui(settings) var vurl = $('#edit-url').val(event.vurl || ''); var categories = $('#edit-categories').val(event.categories); var calendars = $('#edit-calendar').val(event.calendar); + var eventstatus = $('#edit-event-status').val(event.status); var freebusy = $('#edit-free-busy').val(event.free_busy); var priority = $('#edit-priority').val(event.priority); var sensitivity = $('#edit-sensitivity').val(event.sensitivity); @@ -682,6 +688,7 @@ function rcube_calendar_ui(settings) free_busy: freebusy.val(), priority: priority.val(), sensitivity: sensitivity.val(), + status: eventstatus.val(), recurrence: '', alarms: '', attendees: event_attendees, @@ -2146,6 +2153,9 @@ function rcube_calendar_ui(settings) if (event.alarms) element.find('div.fc-event-time').append(''); } + if (event.status) { + element.addClass('cal-event-status-' + String(event.status).toLowerCase()); + } }; diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php index d883f18c..6769cfdc 100644 --- a/plugins/calendar/drivers/calendar_driver.php +++ b/plugins/calendar/drivers/calendar_driver.php @@ -52,6 +52,7 @@ * 'recurrence_id' => 'ID of the recurrence group', // usually the ID of the starting event * 'categories' => 'Event category', * 'free_busy' => 'free|busy|outofoffice|tentative', // Show time as + * 'status' => 'TENTATIVE|CONFIRMED|CANCELLED', // event status according to RFC 2445 * 'priority' => 0-9, // Event priority (0=undefined, 1=highest, 9=lowest) * 'sensitivity' => 'public|private|confidential', // Event sensitivity * 'alarms' => '-15M:DISPLAY', // DEPRECATED Reminder settings inspired by valarm definition (e.g. display alert 15 minutes before event) diff --git a/plugins/calendar/drivers/database/SQL/mysql.initial.sql b/plugins/calendar/drivers/database/SQL/mysql.initial.sql index 945d429b..c45b3f2a 100644 --- a/plugins/calendar/drivers/database/SQL/mysql.initial.sql +++ b/plugins/calendar/drivers/database/SQL/mysql.initial.sql @@ -44,6 +44,7 @@ CREATE TABLE IF NOT EXISTS `events` ( `free_busy` tinyint(1) NOT NULL DEFAULT '0', `priority` tinyint(1) NOT NULL DEFAULT '0', `sensitivity` tinyint(1) NOT NULL DEFAULT '0', + `status` varchar(32) NOT NULL DEFAULT '', `alarms` varchar(255) DEFAULT NULL, `attendees` text DEFAULT NULL, `notifyat` datetime DEFAULT NULL, diff --git a/plugins/calendar/drivers/database/SQL/mysql/2014040900.sql b/plugins/calendar/drivers/database/SQL/mysql/2014040900.sql new file mode 100644 index 00000000..814e10d4 --- /dev/null +++ b/plugins/calendar/drivers/database/SQL/mysql/2014040900.sql @@ -0,0 +1,3 @@ +-- MySQL database updates since version 1.0 + +ALTER TABLE `events` ADD `status` VARCHAR(32) NOT NULL AFTER `sensitivity`; diff --git a/plugins/calendar/drivers/database/SQL/postgres.initial.sql b/plugins/calendar/drivers/database/SQL/postgres.initial.sql index 00a91c20..007bbf29 100644 --- a/plugins/calendar/drivers/database/SQL/postgres.initial.sql +++ b/plugins/calendar/drivers/database/SQL/postgres.initial.sql @@ -60,6 +60,7 @@ CREATE TABLE events ( free_busy smallint NOT NULL DEFAULT 0, priority smallint NOT NULL DEFAULT 0, sensitivity smallint NOT NULL DEFAULT 0, + status character varying(32) NOT NULL, alarms varchar(255) DEFAULT NULL, attendees text DEFAULT NULL, notifyat timestamp without time zone DEFAULT NULL, diff --git a/plugins/calendar/drivers/database/SQL/postgres/2014040900.sql b/plugins/calendar/drivers/database/SQL/postgres/2014040900.sql new file mode 100644 index 00000000..310744c9 --- /dev/null +++ b/plugins/calendar/drivers/database/SQL/postgres/2014040900.sql @@ -0,0 +1,3 @@ +-- Postgres database updates since version 1.0 + +ALTER TABLE events ADD status character varying(32) NOT NULL; diff --git a/plugins/calendar/drivers/database/SQL/sqlite.initial.sql b/plugins/calendar/drivers/database/SQL/sqlite.initial.sql index 6e0643b1..3d359073 100644 --- a/plugins/calendar/drivers/database/SQL/sqlite.initial.sql +++ b/plugins/calendar/drivers/database/SQL/sqlite.initial.sql @@ -43,6 +43,7 @@ CREATE TABLE events ( free_busy tinyint(1) NOT NULL default '0', priority tinyint(1) NOT NULL default '0', sensitivity tinyint(1) NOT NULL default '0', + status varchar(32) NOT NULL default '', alarms varchar(255) default NULL, attendees text default NULL, notifyat datetime default NULL, diff --git a/plugins/calendar/drivers/database/SQL/sqlite/2014040900.sql b/plugins/calendar/drivers/database/SQL/sqlite/2014040900.sql new file mode 100644 index 00000000..ff8ed173 --- /dev/null +++ b/plugins/calendar/drivers/database/SQL/sqlite/2014040900.sql @@ -0,0 +1,67 @@ +-- SQLite database updates since version 0.9-beta + +-- ALTER TABLE events ADD url varchar(255) NOT NULL AFTER categories; + +CREATE TABLE temp_events ( + event_id integer NOT NULL PRIMARY KEY, + calendar_id integer NOT NULL default '0', + recurrence_id integer NOT NULL default '0', + uid varchar(255) NOT NULL default '', + created datetime NOT NULL default '1000-01-01 00:00:00', + changed datetime NOT NULL default '1000-01-01 00:00:00', + sequence integer NOT NULL default '0', + start datetime NOT NULL default '1000-01-01 00:00:00', + end datetime NOT NULL default '1000-01-01 00:00:00', + recurrence varchar(255) default NULL, + title varchar(255) NOT NULL, + description text NOT NULL, + location varchar(255) NOT NULL default '', + categories varchar(255) NOT NULL default '', + url varchar(255) NOT NULL default '', + all_day tinyint(1) NOT NULL default '0', + free_busy tinyint(1) NOT NULL default '0', + priority tinyint(1) NOT NULL default '0', + sensitivity tinyint(1) NOT NULL default '0', + alarms varchar(255) default NULL, + attendees text default NULL, + notifyat datetime default NULL +); + +INSERT INTO temp_events (event_id, calendar_id, recurrence_id, uid, created, changed, sequence, start, end, recurrence, title, description, location, categories, url, all_day, free_busy, priority, sensitivity, alarms, attendees, notifyat) + SELECT event_id, calendar_id, recurrence_id, uid, created, changed, sequence, start, end, recurrence, title, description, location, categories, url, all_day, free_busy, priority, sensitivity, alarms, attendees, notifyat + FROM events; + +DROP TABLE events; + +CREATE TABLE events ( + event_id integer NOT NULL PRIMARY KEY, + calendar_id integer NOT NULL default '0', + recurrence_id integer NOT NULL default '0', + uid varchar(255) NOT NULL default '', + created datetime NOT NULL default '1000-01-01 00:00:00', + changed datetime NOT NULL default '1000-01-01 00:00:00', + sequence integer NOT NULL default '0', + start datetime NOT NULL default '1000-01-01 00:00:00', + end datetime NOT NULL default '1000-01-01 00:00:00', + recurrence varchar(255) default NULL, + title varchar(255) NOT NULL, + description text NOT NULL, + location varchar(255) NOT NULL default '', + categories varchar(255) NOT NULL default '', + url varchar(255) NOT NULL default '', + all_day tinyint(1) NOT NULL default '0', + free_busy tinyint(1) NOT NULL default '0', + priority tinyint(1) NOT NULL default '0', + sensitivity tinyint(1) NOT NULL default '0', + status varchar(32) NOT NULL default '', + alarms varchar(255) default NULL, + attendees text default NULL, + notifyat datetime default NULL, + CONSTRAINT fk_events_calendar_id FOREIGN KEY (calendar_id) + REFERENCES calendars(calendar_id) +); + +INSERT INTO events (event_id, calendar_id, recurrence_id, uid, created, changed, sequence, start, end, recurrence, title, description, location, categories, url, all_day, free_busy, priority, sensitivity, alarms, attendees, notifyat) + SELECT event_id, calendar_id, recurrence_id, uid, created, changed, sequence, start, end, recurrence, title, description, location, categories, url, all_day, free_busy, priority, sensitivity, alarms, attendees, notifyat + FROM temp_events; + diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php index b50b23bb..77e49518 100644 --- a/plugins/calendar/drivers/database/database_driver.php +++ b/plugins/calendar/drivers/database/database_driver.php @@ -271,8 +271,8 @@ class database_driver extends calendar_driver $this->rc->db->query(sprintf( "INSERT INTO " . $this->db_events . " - (calendar_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, attendees, alarms, notifyat) - VALUES (?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + (calendar_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, attendees, alarms, notifyat) + VALUES (?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $this->rc->db->quote_identifier('start'), $this->rc->db->quote_identifier('end'), $this->rc->db->now(), @@ -292,6 +292,7 @@ class database_driver extends calendar_driver intval($event['free_busy']), intval($event['priority']), intval($event['sensitivity']), + strval($event['status']), $event['attendees'], $event['alarms'], $event['notifyat'] @@ -450,7 +451,11 @@ class database_driver extends calendar_driver $event['_recurrence'] = rtrim($rrule, ';'); $event['free_busy'] = intval($this->free_busy_map[strtolower($event['free_busy'])]); $event['sensitivity'] = intval($this->sensitivity_map[strtolower($event['sensitivity'])]); - + + if ($event['free_busy'] == 'tentative') { + $event['status'] = 'TENTATIVE'; + } + if (isset($event['allday'])) { $event['all_day'] = $event['allday'] ? 1 : 0; } @@ -499,13 +504,13 @@ class database_driver extends calendar_driver { $event = $this->_save_preprocess($event); $sql_set = array(); - $set_cols = array('start', 'end', 'all_day', 'recurrence_id', 'sequence', 'title', 'description', 'location', 'categories', 'url', 'free_busy', 'priority', 'sensitivity', 'attendees', 'alarms', 'notifyat'); + $set_cols = array('start', 'end', 'all_day', 'recurrence_id', 'sequence', 'title', 'description', 'location', 'categories', 'url', 'free_busy', 'priority', 'sensitivity', 'status', 'attendees', 'alarms', 'notifyat'); foreach ($set_cols as $col) { if (is_object($event[$col]) && is_a($event[$col], 'DateTime')) $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($event[$col]->format(self::DB_DATE_FORMAT)); else if (is_array($event[$col])) $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote(join(',', $event[$col])); - else if (isset($event[$col])) + else if (array_key_exists($col, $event)) $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($event[$col]); } @@ -581,11 +586,11 @@ class database_driver extends calendar_driver $next_start->setTimezone($this->server_timezone); $next_end = clone $next_start; $next_end->add($duration); - $notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end)); + $notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end, 'status' => $event['status'])); $query = $this->rc->db->query(sprintf( "INSERT INTO " . $this->db_events . " - (calendar_id, recurrence_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, alarms, attendees, notifyat) - SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, alarms, attendees, ? + (calendar_id, recurrence_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, notifyat) + SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, ? FROM " . $this->db_events . " WHERE event_id=? AND calendar_id IN (" . $this->calendar_ids . ")", $this->rc->db->quote_identifier('start'), $this->rc->db->quote_identifier('end'), diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index 129d30f4..46fbed90 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -597,6 +597,10 @@ class kolab_calendar if (is_array($record['categories'])) $record['categories'] = $record['categories'][0]; + // the cancelled flag transltes into status=CANCELLED + if ($record['cancelled']) + $record['status'] = 'CANCELLED'; + // The web client only supports DISPLAY type of alarms if (!empty($record['alarms'])) $record['alarms'] = preg_replace('/:[A-Z]+$/', ':DISPLAY', $record['alarms']); diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php index 00306859..2f544999 100644 --- a/plugins/calendar/lib/calendar_ui.php +++ b/plugins/calendar/lib/calendar_ui.php @@ -74,6 +74,7 @@ class calendar_ui $this->cal->register_handler('plugin.calendar_select', array($this, 'calendar_select')); $this->cal->register_handler('plugin.identity_select', array($this, 'identity_select')); $this->cal->register_handler('plugin.category_select', array($this, 'category_select')); + $this->cal->register_handler('plugin.status_select', array($this, 'status_select')); $this->cal->register_handler('plugin.freebusy_select', array($this, 'freebusy_select')); $this->cal->register_handler('plugin.priority_select', array($this, 'priority_select')); $this->cal->register_handler('plugin.sensitivity_select', array($this, 'sensitivity_select')); @@ -303,6 +304,20 @@ class calendar_ui return $select->show(null); } + /** + * Render a HTML select box for status property + */ + function status_select($attrib = array()) + { + $attrib['name'] = 'status'; + $select = new html_select($attrib); + $select->add('---', ''); + $select->add($this->cal->gettext('confirmed'), 'CONFIRMED'); + $select->add($this->cal->gettext('cancelled'), 'CANCELLED'); + //$select->add($this->cal->gettext('tentative'), 'TENTATIVE'); + return $select->show(null); + } + /** * Render a HTML select box for free/busy/out-of-office property */ diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc index b243c24b..3df791cd 100644 --- a/plugins/calendar/localization/en_US.inc +++ b/plugins/calendar/localization/en_US.inc @@ -60,6 +60,9 @@ $labels['free'] = 'Free'; $labels['busy'] = 'Busy'; $labels['outofoffice'] = 'Out of Office'; $labels['tentative'] = 'Tentative'; +$labels['status'] = 'Status'; +$labels['confirmed'] = 'Confirmed'; +$labels['cancelled'] = 'Cancelled'; $labels['priority'] = 'Priority'; $labels['sensitivity'] = 'Privacy'; $labels['public'] = 'public'; diff --git a/plugins/calendar/skins/classic/calendar.css b/plugins/calendar/skins/classic/calendar.css index 87ef2da0..937a7b65 100644 --- a/plugins/calendar/skins/classic/calendar.css +++ b/plugins/calendar/skins/classic/calendar.css @@ -446,6 +446,10 @@ a.miniColors-trigger { margin: 0 -0.2em; } +#eventshow.status-cancelled { + background: url(images/badge_cancelled.png) top right no-repeat; +} + #eventshow.sensitivity-private { background: url(images/badge_private.png) top right no-repeat; } @@ -1257,6 +1261,10 @@ span.spacer { font-weight: bold; } +.cal-event-status-cancelled .fc-event-title { + text-decoration: line-through; +} + .fc-event-hori .fc-event-title { font-weight: normal; white-space: nowrap; diff --git a/plugins/calendar/skins/classic/images/badge_cancelled.png b/plugins/calendar/skins/classic/images/badge_cancelled.png new file mode 100644 index 0000000000000000000000000000000000000000..b89029e0d760d673435e3e6acc5e48b5234c1f27 GIT binary patch literal 1707 zcmV;c22}ZpP)#HgRS`}9cby*M$f{F`E1l=ig8L*3P1Rq#i!AEy4UAlAYM%}om zHfi2BH;bo*+*ML?8kYh(H9A1>^)kegwz>lGTpr5lHbMqfd1N z3-28d*1rEP`1{6kBltD@cuXK|0;#`vI9UDW>maW27{>^tS&)YTavu_wGDe^72v)z1 zhu8$c7>;#6+w+h>as}Zsqi8nm{suG`oRshar#*AT^w>-b`_7%P}0A216hj zK&D_8|Kjt;*ZzDK z=LFIkNSdfWcPRLC@zVdQXT9f414$rl0%5WZ;-6bQzcffTT05rx5O;S$A!yGT|+QG1L)3IHL*Ra|Shi6;oFgZ*|fs68YH zkPiWJ4j>~)R#eo&vnWHbikNb)(&w?M+xSaB`We?Mar5;HBs+*DoXK_@L0kxHtQvt7 z1mcF9bbcL$bQ$|g(i{TG3B(f520|b?R)~dv3&kJ^=3b*L<2reAM#O#sI&CT3Dws7pfv#yQaGr@NA4DJ_5W{~*BGaTP_^q<{A=6 zHV`J>eGX!$wg%!t2&7FQyq84;R?2lOO{@yPB3w9u6ue});a3Ea2;_orX%k4nAbv&I zzT$##)90)0D*|Z|WDp=@NLF0@5hkA%Fo|R{tdFlY&iYpY7B|;0Kt2;l>mYveT@XvW zJBDb}I87Ev8$qIu5#j=ttE5U3NX{U)aJJPdgg|lx`4zWBnDn#|ZWRfnNsyBO83M>S zZ-c}{Jpv+W9QT&Exkdz%4W#bvA$*@SrtwTY223CYgZL1aajlY6X#yz-q!kE(cAoiW_LvYMo_zOI2Ryk22g&aT#!Ph7V z8@Cev0QNF|Oh_07f-n}|?23h8tcSmYD2$vyMgUUhy{L$o@%9kDw_{hFikZhU6*q@6 zUm(aLs^zBhdxflyxX%isV2~|;=n@cawFo0mkVgUX0FoFJ*KlP{00x(-q_Gytc7Y(x zhB93u5M?6 znot%?1fmR<2t?T{5r{HZA`oS*L?Fsoi9nRC5`idFw;7}ckQqSC2%}se%20_wl%4W` zyrayN2c%P3DG$g&Wu!bH_bMCZ0l8C|C=bZ4e*uFuXYT-qgL?n~002ovPDHLkV1np~ B_G|zE literal 0 HcmV?d00001 diff --git a/plugins/calendar/skins/classic/templates/eventedit.html b/plugins/calendar/skins/classic/templates/eventedit.html index 3bc4a488..7e7170d2 100644 --- a/plugins/calendar/skins/classic/templates/eventedit.html +++ b/plugins/calendar/skins/classic/templates/eventedit.html @@ -52,6 +52,10 @@ +
+ + +
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css index 46f0b3c7..25ad82cf 100644 --- a/plugins/calendar/skins/larry/calendar.css +++ b/plugins/calendar/skins/larry/calendar.css @@ -536,6 +536,10 @@ a.miniColors-trigger { margin: 0 -0.2em; } +#eventshow.status-cancelled { + background: url(images/badge_cancelled.png) top right no-repeat; +} + #eventshow.sensitivity-private { background: url(images/badge_private.png) top right no-repeat; } @@ -1395,6 +1399,10 @@ a.dropdown-link:after { font-weight: bold; } +.cal-event-status-cancelled .fc-event-title { + text-decoration: line-through; +} + .fc-event-hori .fc-event-title { font-weight: normal; white-space: nowrap; diff --git a/plugins/calendar/skins/larry/images/badge_cancelled.png b/plugins/calendar/skins/larry/images/badge_cancelled.png new file mode 100644 index 0000000000000000000000000000000000000000..b89029e0d760d673435e3e6acc5e48b5234c1f27 GIT binary patch literal 1707 zcmV;c22}ZpP)#HgRS`}9cby*M$f{F`E1l=ig8L*3P1Rq#i!AEy4UAlAYM%}om zHfi2BH;bo*+*ML?8kYh(H9A1>^)kegwz>lGTpr5lHbMqfd1N z3-28d*1rEP`1{6kBltD@cuXK|0;#`vI9UDW>maW27{>^tS&)YTavu_wGDe^72v)z1 zhu8$c7>;#6+w+h>as}Zsqi8nm{suG`oRshar#*AT^w>-b`_7%P}0A216hj zK&D_8|Kjt;*ZzDK z=LFIkNSdfWcPRLC@zVdQXT9f414$rl0%5WZ;-6bQzcffTT05rx5O;S$A!yGT|+QG1L)3IHL*Ra|Shi6;oFgZ*|fs68YH zkPiWJ4j>~)R#eo&vnWHbikNb)(&w?M+xSaB`We?Mar5;HBs+*DoXK_@L0kxHtQvt7 z1mcF9bbcL$bQ$|g(i{TG3B(f520|b?R)~dv3&kJ^=3b*L<2reAM#O#sI&CT3Dws7pfv#yQaGr@NA4DJ_5W{~*BGaTP_^q<{A=6 zHV`J>eGX!$wg%!t2&7FQyq84;R?2lOO{@yPB3w9u6ue});a3Ea2;_orX%k4nAbv&I zzT$##)90)0D*|Z|WDp=@NLF0@5hkA%Fo|R{tdFlY&iYpY7B|;0Kt2;l>mYveT@XvW zJBDb}I87Ev8$qIu5#j=ttE5U3NX{U)aJJPdgg|lx`4zWBnDn#|ZWRfnNsyBO83M>S zZ-c}{Jpv+W9QT&Exkdz%4W#bvA$*@SrtwTY223CYgZL1aajlY6X#yz-q!kE(cAoiW_LvYMo_zOI2Ryk22g&aT#!Ph7V z8@Cev0QNF|Oh_07f-n}|?23h8tcSmYD2$vyMgUUhy{L$o@%9kDw_{hFikZhU6*q@6 zUm(aLs^zBhdxflyxX%isV2~|;=n@cawFo0mkVgUX0FoFJ*KlP{00x(-q_Gytc7Y(x zhB93u5M?6 znot%?1fmR<2t?T{5r{HZA`oS*L?Fsoi9nRC5`idFw;7}ckQqSC2%}se%20_wl%4W` zyrayN2c%P3DG$g&Wu!bH_bMCZ0l8C|C=bZ4e*uFuXYT-qgL?n~002ovPDHLkV1np~ B_G|zE literal 0 HcmV?d00001 diff --git a/plugins/calendar/skins/larry/images/badge_confidential.png b/plugins/calendar/skins/larry/images/badge_confidential.png index e12e788eed8461f168bd03a22da6ddf9377310eb..5b0bd7c390e8acffd31b52c280ad1619882761ce 100644 GIT binary patch delta 3241 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 delta 3357 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
+
+ + +
diff --git a/plugins/calendar/skins/larry/templates/eventedit.html b/plugins/calendar/skins/larry/templates/eventedit.html index 95be8eab..85b3a771 100644 --- a/plugins/calendar/skins/larry/templates/eventedit.html +++ b/plugins/calendar/skins/larry/templates/eventedit.html @@ -48,6 +48,10 @@
+
+ + +
diff --git a/plugins/libcalendaring/libcalendaring.php b/plugins/libcalendaring/libcalendaring.php index d33df671..edc0ddee 100644 --- a/plugins/libcalendaring/libcalendaring.php +++ b/plugins/libcalendaring/libcalendaring.php @@ -400,7 +400,7 @@ class libcalendaring extends rcube_plugin */ public static function get_next_alarm($rec, $type = 'event') { - if (!$rec['alarms']) + if (!$rec['alarms'] || $rec['cancelled'] || $rec['status'] == 'CANCELLED') return null; if ($type == 'task') {