Add URL property for events; correct label for chair role of event attendees

This commit is contained in:
Thomas Bruederli 2013-05-16 13:32:01 +02:00
parent f4da6b44f6
commit ae85372d13
20 changed files with 144 additions and 17 deletions

View file

@ -1098,6 +1098,10 @@ class calendar extends rcube_plugin
$event['attachments'][$k]['classname'] = rcube_utils::file2class($attachment['mimetype'], $attachment['name']);
}
// mapping url => vurl because of the fullcalendar client script
$event['vurl'] = $event['url'];
unset($event['url']);
return array(
'_id' => $event['calendar'] . ':' . $event['id'], // unique identifier for fullcalendar
'start' => $this->lib->adjust_timezone($event['start'])->format('c'),
@ -1312,6 +1316,10 @@ class calendar extends rcube_plugin
array_unshift($event['attendees'], array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email'], 'status' => 'ACCEPTED'));
}
}
// mapping url => vurl because of the fullcalendar client script
$event['url'] = $event['vurl'];
unset($event['vurl']);
}
/**

View file

@ -146,7 +146,20 @@ function rcube_calendar_ui(settings)
var zeropad = function(num)
{
return (num < 10 ? '0' : '') + num;
return (num < 10 ? '0' : '') + num;
}
var render_link = function(url)
{
var islink = false, href = url;
if (url.match(/^[fhtpsmailo]+?:\/\//i)) {
islink = true;
}
else if (url.match(/^[a-z0-9.-:]+(\/|$)/i)) {
islink = true;
href = 'http://' + url;
}
return islink ? '<a href="' + Q(href) + '" target="_blank">' + Q(url) + '</a>' : Q(url);
}
// determine whether the given date is on a weekend
@ -279,6 +292,8 @@ function rcube_calendar_ui(settings)
$('#event-location').html('@ ' + text2html(event.location)).show();
if (event.description)
$('#event-description').show().children('.event-text').html(text2html(event.description, 300, 6));
if (event.vurl)
$('#event-url').show().children('.event-text').html(render_link(event.vurl));
// render from-to in a nice human-readable way
// -> now shown in dialog title
@ -347,7 +362,7 @@ function rcube_calendar_ui(settings)
.find('a.mailtolink').click(function(e) { rcmail.redirect(rcmail.url('mail/compose', { _to:this.href.substr(7) })); return false; });
}
$('#event-rsvp')[(rsvp?'show':'hide')]();
$('#event-rsvp')[(rsvp&&!organizer?'show':'hide')]();
$('#event-rsvp .rsvp-buttons input').prop('disabled', false).filter('input[rel='+rsvp+']').prop('disabled', true);
}
@ -419,6 +434,7 @@ function rcube_calendar_ui(settings)
var title = $('#edit-title').val(event.title || '');
var location = $('#edit-location').val(event.location || '');
var description = $('#edit-description').html(event.description || '');
var vurl = $('#edit-url').val(event.vurl || '');
var categories = $('#edit-categories').val(event.categories);
var calendars = $('#edit-calendar').val(event.calendar);
var freebusy = $('#edit-free-busy').val(event.free_busy);
@ -579,6 +595,7 @@ function rcube_calendar_ui(settings)
// init dialog buttons
var buttons = {};
// save action
buttons[rcmail.gettext('save', 'calendar')] = function() {
var start = parse_datetime(allday.checked ? '12:00' : starttime.val(), startdate.val());
var end = parse_datetime(allday.checked ? '13:00' : endtime.val(), enddate.val());
@ -599,6 +616,7 @@ function rcube_calendar_ui(settings)
description: description.val(),
location: location.val(),
categories: categories.val(),
vurl: vurl.val(),
free_busy: freebusy.val(),
priority: priority.val(),
sensitivity: sensitivity.val(),
@ -1428,7 +1446,7 @@ function rcube_calendar_ui(settings)
opts.ORGANIZER = rcmail.gettext('calendar.roleorganizer');
opts['REQ-PARTICIPANT'] = rcmail.gettext('calendar.rolerequired');
opts['OPT-PARTICIPANT'] = rcmail.gettext('calendar.roleoptional');
opts['CHAIR'] = rcmail.gettext('calendar.roleresource');
opts['CHAIR'] = rcmail.gettext('calendar.rolechair');
if (organizer && !readonly)
dispname = rcmail.env['identities-selector'];

View file

@ -39,6 +39,7 @@
* 'title' => 'Event title/summary',
* 'location' => 'Location string',
* 'description' => 'Event description',
* 'url' => 'URL to more information',
* 'recurrence' => array( // Recurrence definition according to iCalendar (RFC 2445) specification as list of key-value pairs
* 'FREQ' => 'DAILY|WEEKLY|MONTHLY|YEARLY',
* 'INTERVAL' => 1...n,

View file

@ -39,6 +39,7 @@ CREATE TABLE `events` (
`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',

View file

@ -0,0 +1,3 @@
-- MySQL database updates since version 0.9-beta
ALTER TABLE `events` ADD `url` VARCHAR(255) NOT NULL AFTER `categories`;

View file

@ -55,6 +55,7 @@ CREATE TABLE events (
description text NOT NULL,
location character varying(255) NOT NULL,
categories character varying(255) NOT NULL,
url character varying(255) NOT NULL,
all_day smallint NOT NULL DEFAULT 0,
free_busy smallint NOT NULL DEFAULT 0,
priority smallint NOT NULL DEFAULT 0,

View file

@ -0,0 +1,3 @@
-- Postgres database updates since version 0.9-beta
ALTER TABLE events ADD url character varying(255) NOT NULL;

View file

@ -38,6 +38,7 @@ CREATE TABLE events (
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',

View file

@ -0,0 +1,63 @@
-- 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 '',
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, 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, 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',
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, 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, all_day, free_busy, priority, sensitivity, alarms, attendees, notifyat FROM temp_events;

View file

@ -235,8 +235,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, 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, attendees, alarms, notifyat)
VALUES (?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
$this->rc->db->quote_identifier('start'),
$this->rc->db->quote_identifier('end'),
$this->rc->db->now(),
@ -252,6 +252,7 @@ class database_driver extends calendar_driver
strval($event['description']),
strval($event['location']),
strval($event['categories']),
strval($event['url']),
intval($event['free_busy']),
intval($event['priority']),
intval($event['sensitivity']),
@ -454,7 +455,7 @@ 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', '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', '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));
@ -537,8 +538,8 @@ class database_driver extends calendar_driver
$notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end));
$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, free_busy, priority, sensitivity, alarms, notifyat)
SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, alarms, ?
(calendar_id, recurrence_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, alarms, notifyat)
SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, alarms, ?
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'),

View file

@ -243,6 +243,7 @@ class calendar_ical
case 'DESCRIPTION':
case 'LOCATION':
case 'URL':
$event[strtolower($attr['name'])] = $attr['value'];
break;
@ -394,6 +395,9 @@ class calendar_ical
if (!empty($event['location'])) {
$vevent .= "LOCATION:" . self::escape($event['location']) . self::EOL;
}
if (!empty($event['url'])) {
$vevent .= "URL:" . self::escape($event['url']) . self::EOL;
}
if ($event['recurrence'] && !$recurrence_id) {
$vevent .= "RRULE:" . libcalendaring::to_rrule($event['recurrence'], self::EOL) . self::EOL;
}

View file

@ -106,7 +106,7 @@ $labels['addattendee'] = 'Hinzufügen';
$labels['roleorganizer'] = 'Organisator';
$labels['rolerequired'] = 'Erforderlich';
$labels['roleoptional'] = 'Optional';
$labels['roleresource'] = 'Ressource';
$labels['rolechair'] = 'Vorsitz';
$labels['availfree'] = 'Frei';
$labels['availbusy'] = 'Gebucht';
$labels['availunknown'] = 'Unbekannt';

View file

@ -106,7 +106,7 @@ $labels['addattendee'] = 'Hinzufügen';
$labels['roleorganizer'] = 'Organisator';
$labels['rolerequired'] = 'Erforderlich';
$labels['roleoptional'] = 'Optional';
$labels['roleresource'] = 'Ressource';
$labels['rolechair'] = 'Vorsitz';
$labels['availfree'] = 'Frei';
$labels['availbusy'] = 'Gebucht';
$labels['availunknown'] = 'Unbekannt';

View file

@ -47,6 +47,7 @@ $labels['all-day'] = 'all-day';
$labels['export'] = 'Export';
$labels['exporttitle'] = 'Export to iCalendar';
$labels['location'] = 'Location';
$labels['url'] = 'URL';
$labels['date'] = 'Date';
$labels['start'] = 'Start';
$labels['end'] = 'End';
@ -106,7 +107,11 @@ $labels['addattendee'] = 'Add participant';
$labels['roleorganizer'] = 'Organizer';
$labels['rolerequired'] = 'Required';
$labels['roleoptional'] = 'Optional';
$labels['roleresource'] = 'Resource';
$labels['rolechair'] = 'Chair';
$labels['cutypeindividual'] = 'Individual';
$labels['cutypegroup'] = 'Group';
$labels['cutyperesource'] = 'Resource';
$labels['cutyperoom'] = 'Room';
$labels['availfree'] = 'Free';
$labels['availbusy'] = 'Busy';
$labels['availunknown'] = 'Unknown';

View file

@ -19,10 +19,10 @@
<email>machniak@kolabsys.com</email>
<active>yes</active>
</developer>
<date>2012-11-08</date>
<date>2013-05-16</date>
<version>
<release>0.9-beta</release>
<api>0.9-beta</api>
<release>0.9.1</release>
<api>0.9.1</api>
</version>
<stability>
<release>stable</release>

View file

@ -51,6 +51,10 @@
<h5 class="label"><roundcube:label name="calendar.description" /></h5>
<div class="event-text"></div>
</div>
<div class="event-section" id="event-url">
<h5 class="label"><roundcube:label name="calendar.url" /></h5>
<div class="event-text"></div>
</div>
<div class="event-section" id="event-repeat">
<h5 class="label"><roundcube:label name="calendar.repeat" /></h5>
<div class="event-text"></div>
@ -131,7 +135,7 @@
<span class="attendee organizer"><roundcube:label name="calendar.roleorganizer" /></span>
<span class="attendee req-participant"><roundcube:label name="calendar.rolerequired" /></span>
<span class="attendee opt-participant"><roundcube:label name="calendar.roleoptional" /></span>
<span class="attendee chair"><roundcube:label name="calendar.roleresource" /></span>
<span class="attendee chair"><roundcube:label name="calendar.rolechair" /></span>
</div>
</div>

View file

@ -23,6 +23,11 @@
<br />
<textarea name="description" id="edit-description" class="text" rows="5" cols="40"></textarea>
</div>
<div class="event-section">
<label for="edit-url"><roundcube:label name="calendar.url" /></label>
<br />
<input type="text" class="text" name="vurl" id="edit-url" size="40" />
</div>
<div class="event-section">
<label style="float:right;padding-right:0.5em"><input type="checkbox" name="allday" id="edit-allday" value="1" /><roundcube:label name="calendar.all-day" /></label>
<label for="edit-startdate"><roundcube:label name="calendar.start" /></label>

View file

@ -533,7 +533,7 @@ div.form-section,
#eventshow div.event-section,
#eventtabs div.event-section {
margin-top: 0.2em;
margin-bottom: 0.8em;
margin-bottom: 0.6em;
}
#eventtabs .border-after {

View file

@ -65,6 +65,10 @@
<h5 class="label"><roundcube:label name="calendar.description" /></h5>
<div class="event-text"></div>
</div>
<div class="event-section" id="event-url">
<h5 class="label"><roundcube:label name="calendar.url" /></h5>
<div class="event-text"></div>
</div>
<div class="event-section" id="event-repeat">
<h5 class="label"><roundcube:label name="calendar.repeat" /></h5>
<div class="event-text"></div>
@ -145,7 +149,7 @@
<span class="attendee organizer"><roundcube:label name="calendar.roleorganizer" /></span>
<span class="attendee req-participant"><roundcube:label name="calendar.rolerequired" /></span>
<span class="attendee opt-participant"><roundcube:label name="calendar.roleoptional" /></span>
<span class="attendee chair"><roundcube:label name="calendar.roleresource" /></span>
<span class="attendee chair"><roundcube:label name="calendar.rolechair" /></span>
</div>
</div>

View file

@ -20,6 +20,11 @@
<br />
<textarea name="description" id="edit-description" class="text" rows="5" cols="40"></textarea>
</div>
<div class="event-section">
<label for="edit-url"><roundcube:label name="calendar.url" /></label>
<br />
<input type="text" class="text" name="vurl" id="edit-url" size="40" />
</div>
<div class="event-section">
<label style="float:right;padding-right:0.5em"><input type="checkbox" name="allday" id="edit-allday" value="1" /><roundcube:label name="calendar.all-day" /></label>
<label for="edit-startdate"><roundcube:label name="calendar.start" /></label>