Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1823449
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
55 KB
Subscribers
None
View Options
diff --git a/action/ajax.php b/action/ajax.php
--- a/action/ajax.php
+++ b/action/ajax.php
@@ -1,127 +1,128 @@
<?php
if(!defined('DOKU_INC')) die();
class action_plugin_davcal_ajax extends DokuWiki_Action_Plugin {
/**
* @var helper_plugin_publish
*/
private $hlp = null;
function __construct() {
$this->hlp =& plugin_load('helper','davcal');
}
function register(Doku_Event_Handler $controller) {
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown');
}
function handle_ajax_call_unknown(&$event, $param) {
if($event->data != 'plugin_davcal') return;
$event->preventDefault();
$event->stopPropagation();
global $INPUT;
$action = trim($INPUT->post->str('action'));
$id = trim($INPUT->post->str('id'));
$params = $INPUT->post->arr('params');
$user = $_SERVER['REMOTE_USER'];
$write = false;
$data = array();
$data['result'] = false;
$data['html'] = $this->getLang('unknown_error');
$acl = auth_quickaclcheck($id);
if($acl > AUTH_READ)
{
$write = true;
}
switch($action)
{
case 'newEvent':
if($write)
{
$data['result'] = true;
$data['html'] = $this->getLang('event_added');
$this->hlp->addCalendarEntryToCalendarForPage($id, $user, $params);
}
else
{
$data['result'] = false;
$data['html'] = $this->getLang('no_permission');
}
break;
case 'getEvents':
$startDate = $INPUT->post->str('start');
$endDate = $INPUT->post->str('end');
$data = $this->hlp->getEventsWithinDateRange($id, $user, $startDate, $endDate);
break;
case 'editEvent':
if($write)
{
$data['result'] = true;
$data['html'] = $this->getLang('event_edited');
$this->hlp->editCalendarEntryForPage($id, $user, $params);
}
else
{
$data['result'] = false;
$data['html'] = $this->getLang('no_permission');
}
break;
case 'deleteEvent':
if($write)
{
$data['result'] = true;
$data['html'] = $this->getLang('event_deleted');
$this->hlp->deleteCalendarEntryForPage($id, $params);
}
else
{
$data['result'] = false;
$data['html'] = $this->getLang('no_permission');
}
break;
case 'getSettings':
$data['result'] = true;
$data['settings'] = $this->hlp->getPersonalSettings($user);
+ $data['settings']['syncurl'] = $this->hlp->getSyncUrlForPage($id, $user);
break;
case 'saveSettings':
$settings = array();
$settings['weeknumbers'] = $params['weeknumbers'];
$settings['timezone'] = $params['timezone'];
$settings['workweek'] = $params['workweek'];
if($this->hlp->savePersonalSettings($settings, $user))
{
$data['result'] = true;
$data['html'] = $this->getLang('settings_saved');
}
else
{
$data['result'] = false;
$data['html'] = $this->getLang('error_saving');
}
break;
}
// If we are still here, JSON output is requested
//json library of DokuWiki
require_once DOKU_INC . 'inc/JSON.php';
$json = new JSON();
//set content type
header('Content-Type: application/json');
echo $json->encode($data);
}
}
\ No newline at end of file
diff --git a/helper.php b/helper.php
--- a/helper.php
+++ b/helper.php
@@ -1,366 +1,468 @@
<?php
/**
* Helper Class for the tagrevisions plugin
* This helper does the actual work.
*
* Configurable in DokuWiki's configuration
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
class helper_plugin_davcal extends DokuWiki_Plugin {
protected $sqlite = null;
/**
* Constructor to load the configuration
*/
public function helper_plugin_davcal() {
$this->sqlite =& plugin_load('helper', 'sqlite');
if(!$this->sqlite)
{
msg('This plugin requires the sqlite plugin. Please install it.');
return;
}
if(!$this->sqlite->init('davcal', DOKU_PLUGIN.'davcal/db/'))
{
return;
}
}
public function setCalendarNameForPage($name, $description, $id = null, $userid = null)
{
if(is_null($id))
{
global $ID;
$id = $ID;
}
if(is_null($userid))
$userid = $_SERVER['REMOTE_USER'];
$calid = $this->getCalendarIdForPage($id);
if($calid === false)
return $this->createCalendarForPage($name, $description, $id, $userid);
- // Update the calendar name here
-
+ $query = "UPDATE calendars SET displayname=".$this->sqlite->quote_string($name).", ".
+ "description=".$this->sqlite->quote_string($description)." WHERE ".
+ "id=".$this->sqlite->quote_string($calid);
+ $res = $this->sqlite->query($query);
+ if($res !== false)
+ return true;
+ return false;
}
public function savePersonalSettings($settings, $userid = null)
{
if(is_null($userid))
$userid = $_SERVER['REMOTE_USER'];
$this->sqlite->query("BEGIN TRANSACTION");
$query = "DELETE FROM calendarsettings WHERE userid=".$this->sqlite->quote_string($userid);
$this->sqlite->query($query);
foreach($settings as $key => $value)
{
$query = "INSERT INTO calendarsettings (userid, key, value) VALUES (".
$this->sqlite->quote_string($userid).", ".
$this->sqlite->quote_string($key).", ".
$this->sqlite->quote_string($value).")";
$res = $this->sqlite->query($query);
if($res === false)
return false;
}
$this->sqlite->query("COMMIT TRANSACTION");
return true;
}
public function getPersonalSettings($userid = null)
{
if(is_null($userid))
$userid = $_SERVER['REMOTE_USER'];
// Some sane default settings
$settings = array(
'timezone' => 'local',
'weeknumbers' => '0',
'workweek' => '0'
);
$query = "SELECT key, value FROM calendarsettings WHERE userid=".$this->sqlite->quote_string($userid);
$res = $this->sqlite->query($query);
$arr = $this->sqlite->res2arr($res);
foreach($arr as $row)
{
$settings[$row['key']] = $row['value'];
}
return $settings;
}
public function getCalendarIdForPage($id = null)
{
if(is_null($id))
{
global $ID;
$id = $ID;
}
$query = "SELECT calid FROM pagetocalendarmapping WHERE page=".$this->sqlite->quote_string($id);
$res = $this->sqlite->query($query);
$row = $this->sqlite->res2row($res);
if(isset($row['calid']))
return $row['calid'];
else
return false;
}
public function getCalendarIdToPageMapping()
{
$query = "SELECT calid, page FROM pagetocalendarmapping";
$res = $this->sqlite->query($query);
$arr = $this->sqlite->res2arr($res);
return $arr;
}
public function getCalendarIdsForUser($principalUri)
{
$user = explode('/', $principalUri);
$user = end($user);
$mapping = $this->getCalendarIdToPageMapping();
$calids = array();
foreach($mapping as $row)
{
$id = $row['calid'];
$page = $row['page'];
$acl = auth_quickaclcheck($page);
if($acl >= AUTH_READ)
{
$write = $acl > AUTH_READ;
$calids[$id] = array('readonly' => !$write);
}
}
return $calids;
}
public function createCalendarForPage($name, $description, $id = null, $userid = null)
{
if(is_null($id))
{
global $ID;
$id = $ID;
}
if(is_null($userid))
$userid = $_SERVER['REMOTE_USER'];
$values = array('principals/'.$userid,
$name,
str_replace(array('/', ' ', ':'), '_', $id),
$description,
'VEVENT,VTODO',
0,
1);
$query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) VALUES (".$this->sqlite->quote_and_join($values, ',').");";
$res = $this->sqlite->query($query);
if($res === false)
return false;
$query = "SELECT id FROM calendars WHERE principaluri=".$this->sqlite->quote_string($values[0])." AND ".
"displayname=".$this->sqlite->quote_string($values[1])." AND ".
"uri=".$this->sqlite->quote_string($values[2])." AND ".
"description=".$this->sqlite->quote_string($values[3]);
$res = $this->sqlite->query($query);
$row = $this->sqlite->res2row($res);
if(isset($row['id']))
{
$values = array($id, $row['id']);
$query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (".$this->sqlite->quote_and_join($values, ',').")";
$res = $this->sqlite->query($query);
return ($res !== false);
}
return false;
}
public function addCalendarEntryToCalendarForPage($id, $user, $params)
{
$settings = $this->getPersonalSettings($user);
if($settings['timezone'] !== '' && $settings['timezone'] !== 'local')
$timezone = new \DateTimeZone($settings['timezone']);
else
$timezone = new \DateTimeZone('UTC');
+ $startDate = explode('-', $params['eventfrom']);
+ $startTime = explode(':', $params['eventfromtime']);
+ $endDate = explode('-', $params['eventto']);
+ $endTime = explode(':', $params['eventtotime']);
require_once('vendor/autoload.php');
$vcalendar = new \Sabre\VObject\Component\VCalendar();
$event = $vcalendar->add('VEVENT');
+ $uuid = \Sabre\VObject\UUIDUtil::getUUID();
+ $event->add('UID', $uuid);
$event->summary = $params['eventname'];
- $dtStart = new \DateTime($params['eventfrom'], $timezone);
- $dtEnd = new \DateTime($params['eventto'], $timezone);
- $event->DTSTART = $dtStart;
- $event->DTEND = $dtEnd;
+ $dtStamp = new \DateTime(null, new \DateTimeZone('UTC'));
+ $event->add('DTSTAMP', $dtStamp);
+ $event->add('CREATED', $dtStamp);
+ $event->add('LAST-MODIFIED', $dtStamp);
+ $dtStart = new \DateTime();
+ $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2]));
+ if($params['allday'] != '1')
+ $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0);
+ $dtStart->setTimezone($timezone);
+ $dtEnd = new \DateTime();
+ $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2]));
+ if($params['allday'] != '1')
+ $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0);
+ $dtEnd->setTimezone($timezone);
+ // According to the VCal spec, we need to add a whole day here
+ if($params['allday'] == '1')
+ $dtEnd->add(new \DateInterval('P1D'));
+ $dtStartEv = $event->add('DTSTART', $dtStart);
+ $dtEndEv = $event->add('DTEND', $dtEnd);
+ if($params['allday'] == '1')
+ {
+ $dtStartEv['VALUE'] = 'DATE';
+ $dtEndEv['VALUE'] = 'DATE';
+ }
$calid = $this->getCalendarIdForPage($id);
$uri = uniqid('dokuwiki-').'.ics';
$now = new DateTime();
$eventStr = $vcalendar->serialize();
$values = array($calid,
$uri,
$eventStr,
$now->getTimestamp(),
'VEVENT',
$event->DTSTART->getDateTime()->getTimeStamp(),
$event->DTEND->getDateTime()->getTimeStamp(),
strlen($eventStr),
md5($eventStr),
uniqid()
);
$query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (".$this->sqlite->quote_and_join($values, ',').")";
$res = $this->sqlite->query($query);
if($res !== false)
{
$this->updateSyncTokenLog($calid, $uri, 'added');
return true;
}
return false;
}
+ public function getCalendarSettings($calid)
+ {
+ $query = "SELECT principaluri, displayname, uri, description, components, transparent, synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid);
+ $res = $this->sqlite->query($query);
+ $row = $this->sqlite->res2row($res);
+ return $row;
+ }
+
public function getEventsWithinDateRange($id, $user, $startDate, $endDate)
{
$settings = $this->getPersonalSettings($user);
if($settings['timezone'] !== '' && $settings['timezone'] !== 'local')
$timezone = new \DateTimeZone($settings['timezone']);
else
$timezone = new \DateTimeZone('UTC');
$data = array();
require_once('vendor/autoload.php');
$calid = $this->getCalendarIdForPage($id);
$startTs = new \DateTime($startDate);
$endTs = new \DateTime($endDate);
- $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid=".
+ $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE (calendarid=".
$this->sqlite->quote_string($calid)." AND firstoccurence > ".
$this->sqlite->quote_string($startTs->getTimestamp())." AND firstoccurence < ".
- $this->sqlite->quote_string($endTs->getTimestamp());
+ $this->sqlite->quote_string($endTs->getTimestamp()).") OR (calendarid=".
+ $this->sqlite->quote_string($calid)." AND lastoccurence > ".
+ $this->sqlite->quote_string($startTs->getTimestamp())." AND lastoccurence < ".
+ $this->sqlite->quote_string($endTs->getTimestamp()).")";
$res = $this->sqlite->query($query);
$arr = $this->sqlite->res2arr($res);
foreach($arr as $row)
{
if(isset($row['calendardata']))
{
+ $entry = array();
$vcal = \Sabre\VObject\Reader::read($row['calendardata']);
- $start = $vcal->VEVENT->DTSTART->getDateTime();
- $end = $vcal->VEVENT->DTEND->getDateTime();
- $start->setTimezone($timezone);
- $end->setTimezone($timezone);
- $summary = (string)$vcal->VEVENT->summary;
- $data[] = array("title" => $summary, "start" => $start->format(\DateTime::ATOM),
- "end" => $end->format(\DateTime::ATOM),
- "id" => $row['uid']);
+ $start = $vcal->VEVENT->DTSTART;
+ if($start !== null)
+ {
+ $dtStart = $start->getDateTime();
+ $dtStart->setTimezone($timezone);
+ $entry['start'] = $dtStart->format(\DateTime::ATOM);
+ if($start['VALUE'] == 'DATE')
+ $entry['allDay'] = true;
+ else
+ $entry['allDay'] = false;
+ }
+ $end = $vcal->VEVENT->DTEND;
+ if($end !== null)
+ {
+ $dtEnd = $end->getDateTime();
+ $dtEnd->setTimezone($timezone);
+ // Subtract the plus one day that was added earlier
+ //if($entry['allDay'] === true)
+ // $dtEnd->sub(new \DateInterval('P1D'));
+ $entry['end'] = $dtEnd->format(\DateTime::ATOM);
+ }
+ $entry['title'] = (string)$vcal->VEVENT->summary;
+ $entry['id'] = $row['uid'];
+ $data[] = $entry;
}
}
return $data;
}
public function getEventWithUid($uid)
{
$query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid=".
$this->sqlite->quote_string($uid);
$res = $this->sqlite->query($query);
$row = $this->sqlite->res2row($res);
return $row;
}
public function editCalendarEntryForPage($id, $user, $params)
{
$settings = $this->getPersonalSettings($user);
if($settings['timezone'] !== '' && $settings['timezone'] !== 'local')
$timezone = new \DateTimeZone($settings['timezone']);
else
$timezone = new \DateTimeZone('UTC');
+ $startDate = explode('-', $params['eventfrom']);
+ $startTime = explode(':', $params['eventfromtime']);
+ $endDate = explode('-', $params['eventto']);
+ $endTime = explode(':', $params['eventtotime']);
$uid = $params['uid'];
$event = $this->getEventWithUid($uid);
require_once('vendor/autoload.php');
if(!isset($event['calendardata']))
return false;
$uri = $event['uri'];
$calid = $event['calendarid'];
$vcal = \Sabre\VObject\Reader::read($event['calendardata']);
- $vcal->VEVENT->summary = $params['eventname'];
- $dtStart = new \DateTime($params['eventfrom'], $timezone);
- $dtEnd = new \DateTime($params['eventto'], $timezone);
- $vcal->VEVENT->DTSTART = $dtStart;
- $vcal->VEVENT->DTEND = $dtEnd;
+ $vevent = $vcal->VEVENT;
+ $vevent->summary = $params['eventname'];
+ $dtStamp = new \DateTime(null, new \DateTimeZone('UTC'));
+ $vevent->remove('DTSTAMP');
+ $vevent->remove('LAST-MODIFIED');
+ $vevent->add('DTSTAMP', $dtStamp);
+ $vevent->add('LAST-MODIFIED', $dtStamp);
+ $dtStart = new \DateTime();
+ $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2]));
+ if($params['allday'] != '1')
+ $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0);
+ $dtStart->setTimezone($timezone);
+ $dtEnd = new \DateTime();
+ $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2]));
+ if($params['allday'] != '1')
+ $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0);
+ $dtEnd->setTimezone($timezone);
+ // According to the VCal spec, we need to add a whole day here
+ if($params['allday'] == '1')
+ $dtEnd->add(new \DateInterval('P1D'));
+ $vevent->remove('DTSTART');
+ $vevent->remove('DTEND');
+ $dtStartEv = $vevent->add('DTSTART', $dtStart);
+ $dtEndEv = $vevent->add('DTEND', $dtEnd);
+ if($params['allday'] == '1')
+ {
+ $dtStartEv['VALUE'] = 'DATE';
+ $dtEndEv['VALUE'] = 'DATE';
+ }
$now = new DateTime();
$eventStr = $vcal->serialize();
$query = "UPDATE calendarobjects SET calendardata=".$this->sqlite->quote_string($eventStr).
", lastmodified=".$this->sqlite->quote_string($now->getTimestamp()).
", firstoccurence=".$this->sqlite->quote_string($dtStart->getTimestamp()).
", lastoccurence=".$this->sqlite->quote_string($dtEnd->getTimestamp()).
", size=".strlen($eventStr).
", etag=".$this->sqlite->quote_string(md5($eventStr)).
" WHERE uid=".$this->sqlite->quote_string($uid);
$res = $this->sqlite->query($query);
if($res !== false)
{
$this->updateSyncTokenLog($calid, $uri, 'modified');
return true;
}
return false;
}
public function deleteCalendarEntryForPage($id, $params)
{
$uid = $params['uid'];
$event = $this->getEventWithUid($uid);
$calid = $event['calendarid'];
$uri = $event['uri'];
$query = "DELETE FROM calendarobjects WHERE uid=".$this->sqlite->quote_string($uid);
$res = $this->sqlite->query($query);
if($res !== false)
{
$this->updateSyncTokenLog($calid, $uri, 'deleted');
}
return true;
}
public function getSyncTokenForCalendar($calid)
{
- $query = "SELECT synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid);
- $res = $this->sqlite->query($query);
- $row = $this->sqlite->res2row($res);
+ $row = $this->getCalendarSettings($calid);
if(isset($row['synctoken']))
return $row['synctoken'];
return false;
}
public function operationNameToOperation($operationName)
{
switch($operationName)
{
case 'added':
return 1;
break;
case 'modified':
return 2;
break;
case 'deleted':
return 3;
break;
}
return false;
}
private function updateSyncTokenLog($calid, $uri, $operation)
{
$currentToken = $this->getSyncTokenForCalendar($calid);
$operationCode = $this->operationNameToOperation($operation);
if(($operationCode === false) || ($currentToken === false))
return false;
$values = array($uri,
$currentToken,
$calid,
$operationCode
);
$query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(".
$this->sqlite->quote_and_join($values, ',').")";
$res = $this->sqlite->query($query);
if($res === false)
return false;
$currentToken++;
$query = "UPDATE calendars SET synctoken=".$this->sqlite->quote_string($currentToken)." WHERE id=".
$this->sqlite->quote_string($calid);
$res = $this->sqlite->query($query);
return ($res !== false);
}
+ public function getSyncUrlForPage($id, $user = null)
+ {
+ if(is_null($user))
+ $user = $_SERVER['REMOTE_USER'];
+
+ $calid = $this->getCalendarIdForPage($id);
+ if($calid === false)
+ return false;
+
+ $calsettings = $this->getCalendarSettings($calid);
+ if(!isset($calsettings['uri']))
+ return false;
+
+ $syncurl = DOKU_URL.'lib/plugins/davcal/calendarserver.php/calendars/'.$user.'/'.$calsettings['uri'];
+ return $syncurl;
+ }
+
}
diff --git a/lang/en/lang.php b/lang/en/lang.php
--- a/lang/en/lang.php
+++ b/lang/en/lang.php
@@ -1,32 +1,33 @@
<?php
$lang['created_by_davcal'] = 'Created by DAVCal for DokuWiki';
$lang['unknown_error'] = 'Unknown Error';
$lang['event_added'] = 'Event added';
$lang['event_edited'] = 'Event edited';
$lang['event_deleted'] = 'Event deleted';
$lang['no_permission'] = 'You don\'t have permission to modify this calendar';
$lang['settings'] = 'Settings/Sync';
$lang['settings_saved'] = 'Settings saved successfully';
$lang['error_saving'] = 'Error saving settings.';
$lang['local_time'] = 'Local time (Browser based)';
$lang['js']['create_new_event'] = 'Create new Event';
$lang['js']['cancel'] = 'Cancel';
$lang['js']['create'] = 'Create';
$lang['js']['save'] = 'Save';
$lang['js']['settings'] = 'Settings';
$lang['js']['edit'] = 'Edit';
$lang['js']['delete'] = 'Delete';
$lang['js']['edit_event'] = 'Edit Event';
$lang['js']['allday'] = 'All Day Event';
$lang['js']['title'] = 'Title';
$lang['js']['from'] = 'From';
$lang['js']['to'] = 'To';
$lang['js']['yes'] = 'Yes';
$lang['js']['confirmation'] = 'Confirmation';
$lang['js']['ok'] = 'OK';
$lang['js']['info'] = 'Info';
$lang['js']['really_delete_this_event'] = 'Really delete this event?';
$lang['js']['timezone'] = 'Timezone';
$lang['js']['weeknumbers'] = 'Week Numbers';
$lang['js']['use_lang_tz'] = 'Use Timezone from language setting';
$lang['js']['only_workweek'] = 'Show only Work Week';
+$lang['js']['sync_url'] = 'DAVCal URL';
diff --git a/script.js b/script.js
--- a/script.js
+++ b/script.js
@@ -1,507 +1,550 @@
/* DOKUWIKI:include_once fullcalendar-2.4.0/moment.js */
/* DOKUWIKI:include_once fullcalendar-2.4.0/fullcalendar.js */
/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/de.js */
/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/en.js */
/* DOKUWIKI:include_once datetimepicker-2.4.5/jquery.datetimepicker.js */
jQuery(function() {
// Redefine functions for using moment.js with datetimepicker
Date.parseDate = function( input, format ){
return moment(input,format).toDate();
};
Date.prototype.dateFormat = function( format ){
return moment(this).format(format);
};
// Attach to event links
jQuery('div.fullCalendarSettings a').each(function() {
var $link = jQuery(this);
var href = $link.attr('href');
if (!href) return;
$link.click(
function(e) {
dw_davcal__modals.showSettingsDialog();
e.preventDefault();
return '';
}
);
}
);
var postArray = { };
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_davcal',
id: JSINFO.id,
action: 'getSettings',
params: postArray
},
function(data)
{
var result = data['result'];
if(result === true)
{
dw_davcal__modals.settings = data['settings'];
var wknum = false;
var tz = false;
var we = true;
if(data['settings']['weeknumbers'] == 1)
wknum = true;
if(data['settings']['timezone'] !== '')
tz = data['settings']['timezone'];
if(data['settings']['workweek'] == 1)
we = false;
// Initialize the davcal popup
var res = jQuery('#fullCalendar').fullCalendar({
dayClick: function(date, jsEvent, view) {
dw_davcal__modals.showNewEventDialog(date);
},
eventClick: function(calEvent, jsEvent, view) {
dw_davcal__modals.showEditEventDialog(calEvent);
},
events: {
url: DOKU_BASE + 'lib/exe/ajax.php',
type: 'POST',
data: {
call: 'plugin_davcal',
action: 'getEvents',
id: JSINFO.id
},
error: function() {
//alert('there was an error retrieving calendar data');
}
},
header: {
left: 'title',
center: 'today prev,next',
right: 'month,agendaWeek,agendaDay'
},
lang: JSINFO.plugin.davcal['language'],
weekNumbers: wknum,
timezone: tz,
weekends: we,
});
}
}
);
});
var dw_davcal__modals = {
$newEventDialog : null,
$editEventDialog: null,
$infoDialog: null,
$confirmDialog: null,
$settingsDialog: null,
msg: null,
completeCb: null,
action: null,
uid: null,
settings: null,
showSettingsDialog : function() {
if(dw_davcal__modals.$settingsDialog)
return;
var dialogButtons = {};
dialogButtons[LANG.plugins.davcal['save']] = function() {
var postArray = { };
jQuery("input[class=dw_davcal__settings], select[class=dw_davcal__settings]").each(function() {
if(jQuery(this).attr('type') == 'checkbox')
{
postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
}
else
{
postArray[jQuery(this).prop('name')] = jQuery(this).val();
}
});
jQuery('#dw_davcal__ajaxsettings').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_davcal',
id: JSINFO.id,
action: 'saveSettings',
params: postArray
},
function(data)
{
var result = data['result'];
var html = data['html'];
jQuery('#dw_davcal__ajaxsettings').html(html);
if(result === true)
{
location.reload();
}
}
);
};
dialogButtons[LANG.plugins.davcal['cancel']] = function () {
dw_davcal__modals.hideSettingsDialog();
};
dw_davcal__modals.$settingsDialog = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: LANG.plugins.davcal['settings'],
resizable: true,
buttons: dialogButtons,
})
.html(
'<div><table>' +
//'<tr><td>' + LANG.plugins.davcal['use_lang_tz'] + '</td><td><input type="checkbox" name="use_lang_tz" id="dw_davcal__settings_use_lang_tz" class="dw_davcal__settings"></td></tr>' +
'<tr><td>' + LANG.plugins.davcal['timezone'] + '</td><td><select name="timezone" id="dw_davcal__settings_timezone" class="dw_davcal__settings"></select></td></tr>' +
'<tr><td>' + LANG.plugins.davcal['weeknumbers'] + '</td><td><input type="checkbox" name="weeknumbers" id="dw_davcal__settings_weeknumbers" class="dw_davcal__settings"></td></tr>' +
'<tr><td>' + LANG.plugins.davcal['only_workweek'] + '</td><td><input type="checkbox" name="workweek" id="dw_davcal__settings_workweek" class="dw_davcal__settings"></td></tr>' +
+ '<tr><td>' + LANG.plugins.davcal['sync_url'] + '</td><td><input type="text" name="syncurl" readonly="readonly" value="' + dw_davcal__modals.settings['syncurl'] + '"></td></tr>' +
'</table>' +
'</div>' +
'<div id="dw_davcal__ajaxsettings"></div>'
)
.parent()
.attr('id','dw_davcal__settings')
.show()
.appendTo('.dokuwiki:first');
// attach event handlers
jQuery('#dw_davcal__settings .ui-dialog-titlebar-close').click(function(){
dw_davcal__modals.hideSettingsDialog();
});
var $tzdropdown = jQuery('#dw_davcal__settings_timezone');
jQuery('#fullCalendarTimezoneList option').each(function() {
jQuery('<option />', {value: jQuery(this).val(),
text: jQuery(this).text()}).appendTo($tzdropdown);
});
if(dw_davcal__modals.settings)
{
if(dw_davcal__modals.settings['timezone'] !== '')
jQuery('#dw_davcal__settings_timezone').val(dw_davcal__modals.settings['timezone']);
if(dw_davcal__modals.settings['weeknumbers'] == 1)
jQuery('#dw_davcal__settings_weeknumbers').prop('checked', true);
else
jQuery('#dw_davcal__settings_weeknumbers').prop('checked', false);
if(dw_davcal__modals.settings['workweek'] == 1)
jQuery('#dw_davcal__settings_workweek').prop('checked', true);
else
jQuery('#dw_davcal__settings_workweek').prop('checked', false);
}
},
showEditEventDialog : function(calEvent) {
if(dw_davcal__modals.$editEventDialog)
return;
var dialogButtons = {};
dialogButtons[LANG.plugins.davcal['edit']] = function() {
var postArray = { };
- jQuery("input[class=dw_davcal__editevent]").each(function() {
+ jQuery("input.dw_davcal__editevent").each(function() {
if(jQuery(this).attr('type') == 'checkbox')
{
postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
}
else
{
postArray[jQuery(this).prop('name')] = jQuery(this).val();
}
});
jQuery('#dw_davcal__ajaxedit').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_davcal',
id: JSINFO.id,
action: 'editEvent',
params: postArray
},
function(data)
{
var result = data['result'];
var html = data['html'];
jQuery('#dw_davcal__ajaxedit').html(html);
if(result === true)
{
jQuery('#fullCalendar').fullCalendar('refetchEvents');
dw_davcal__modals.hideEditEventDialog();
}
}
);
};
dialogButtons[LANG.plugins.davcal['cancel']] = function() {
dw_davcal__modals.hideEditEventDialog();
};
dialogButtons[LANG.plugins.davcal['delete']] = function() {
dw_davcal__modals.action = 'deleteEvent';
dw_davcal__modals.msg = LANG.plugins.davcal['really_delete_this_event'];
dw_davcal__modals.completeCb = function(data) {
if(data.result == false)
{
dw_davcal__modals.msg = data.errmsg;
dw_davcal__modals.showInfoDialog();
}
else
{
jQuery('#fullCalendar').fullCalendar('refetchEvents');
dw_davcal__modals.hideEditEventDialog();
}
};
dw_davcal__modals.showConfirmDialog();
};
dw_davcal__modals.uid = calEvent.id;
dw_davcal__modals.$editEventDialog = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: LANG.plugins.davcal['edit_event'],
resizable: true,
buttons: dialogButtons,
})
.html(
'<div><table><tr><td>' + LANG.plugins.davcal['title'] + '</td><td><input type="text" id="dw_davcal__eventname_edit" name="eventname" class="dw_davcal__editevent"></td></tr>' +
- '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" name="eventfrom" id="dw_davcal__eventfrom_edit" class="dw_davcal__editevent"></td></tr>' +
- '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" id="dw_davcal__eventto_edit" class="dw_davcal__editevent"></td></tr>' +
+ '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" name="eventfrom" id="dw_davcal__eventfrom_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventfromtime" id="dw_davcal__eventfromtime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
+ '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" id="dw_davcal__eventto_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventtotime" id="dw_davcal__eventtotime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
'<tr><td colspan="2"><input type="checkbox" name="allday" id="dw_davcal__allday_edit" class="dw_davcal__editevent">' + LANG.plugins.davcal['allday'] + '</td></tr>' +
'</table>' +
'<input type="hidden" name="uid" id="dw_davcal__uid_edit" class="dw_davcal__editevent">' +
'</div>' +
'<div id="dw_davcal__ajaxedit"></div>'
)
.parent()
.attr('id','dw_davcal__edit')
.show()
.appendTo('.dokuwiki:first');
jQuery('#dw_davcal__uid_edit').val(calEvent.id);
jQuery('#dw_davcal__eventname_edit').val(calEvent.title);
- jQuery('#dw_davcal__eventfrom_edit').val(calEvent.start.format('YYYY-MM-DD HH:mm'));
- jQuery('#dw_davcal__eventto_edit').val(calEvent.end.format('YYYY-MM-DD HH:mm'));
+ jQuery('#dw_davcal__eventfrom_edit').val(calEvent.start.format('YYYY-MM-DD'));
+ jQuery('#dw_davcal__eventfromtime_edit').val(calEvent.start.format('HH:mm'));
+ if(calEvent.allDay && (calEvent.end === null))
+ {
+ jQuery('#dw_davcal__eventto_edit').val(calEvent.start.format('YYYY-MM-DD'));
+ jQuery('#dw_davcal__eventtotime_edit').val(calEvent.start.format('HH:mm'));
+ }
+ else if(calEvent.allDay)
+ {
+ endEvent = moment(calEvent.end);
+ endEvent.subtract(1, 'days');
+ jQuery('#dw_davcal__eventto_edit').val(endEvent.format('YYYY-MM-DD'));
+ jQuery('#dw_davcal__eventotime_edit').val(endEvent.format('HH:mm'));
+ }
+ else
+ {
+ jQuery('#dw_davcal__eventto_edit').val(calEvent.end.format('YYYY-MM-DD'));
+ jQuery('#dw_davcal__eventtotime_edit').val(calEvent.end.format('HH:mm'));
+ }
jQuery('#dw_davcal__allday_edit').prop('checked', calEvent.allDay);
// attach event handlers
jQuery('#dw_davcal__edit .ui-dialog-titlebar-close').click(function(){
dw_davcal__modals.hideEditEventDialog();
});
- jQuery('#dw_davcal__eventfrom_edit').datetimepicker({format:'YYYY-MM-DD HH:mm',
+ jQuery('#dw_davcal__eventfrom_edit').datetimepicker({format:'YYYY-MM-DD',
+ formatDate:'YYYY-MM-DD',
+ datepicker: true,
+ timepicker: false,
+ });
+ jQuery('#dw_davcal__eventfromtime_edit').datetimepicker({format:'HH:mm',
formatTime:'HH:mm',
- formatDate:'YYYY-MM-DD',
+ datepicker: false,
+ timepicker: true,
step: 15});
- jQuery('#dw_davcal__eventto_edit').datetimepicker({format:'YYYY-MM-DD HH:mm',
+ jQuery('#dw_davcal__eventto_edit').datetimepicker({format:'YYYY-MM-DD',
+ formatDate:'YYYY-MM-DD',
+ datepicker: true,
+ timepicker: false,
+ });
+ jQuery('#dw_davcal__eventtotime_edit').datetimepicker({format:'HH:mm',
formatTime:'HH:mm',
- formatDate:'YYYY-MM-DD',
- step: 15});
+ datepicker: false,
+ timepicker: true,
+ step:15});
jQuery('#dw_davcal__allday_edit').change(function() {
if(jQuery(this).is(":checked"))
{
- jQuery('#dw_davcal__eventfrom_edit').datetimepicker({timepicker: false});
- jQuery('#dw_davcal__eventto_edit').datetimepicker({timepicker: false});
+ jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', true);
+ jQuery('#dw_davcal__eventtotime_edit').prop('readonly', true);
}
else
{
- jQuery('#dw_davcal__eventfrom_edit').datetimepicker({timepicker: true});
- jQuery('#dw_davcal__eventto_edit').datetimepicker({timepicker: true});
+ jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', false);
+ jQuery('#dw_davcal__eventtotime_edit').prop('readonly', false);
}
- });
+ });
+ jQuery('#dw_davcal__allday_edit').change();
},
showNewEventDialog : function(date) {
if(dw_davcal__modals.$newEventDialog)
return;
var dialogButtons = {};
dialogButtons[LANG.plugins.davcal['create']] = function() {
var postArray = { };
- jQuery("input[class=dw_davcal__newevent]").each(function() {
+ jQuery("input.dw_davcal__newevent").each(function() {
if(jQuery(this).attr('type') == 'checkbox')
{
postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
}
else
{
postArray[jQuery(this).prop('name')] = jQuery(this).val();
}
});
jQuery('#dw_davcal__ajaxnew').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_davcal',
id: JSINFO.id,
action: 'newEvent',
params: postArray
},
function(data)
{
var result = data['result'];
var html = data['html'];
jQuery('#dw_davcal__ajaxnew').html(html);
if(result === true)
{
jQuery('#fullCalendar').fullCalendar('refetchEvents');
dw_davcal__modals.hideNewEventDialog();
}
}
);
};
dialogButtons[LANG.plugins.davcal['cancel']] = function() {
dw_davcal__modals.hideNewEventDialog();
};
dw_davcal__modals.$newEventDialog = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: LANG.plugins.davcal['create_new_event'],
resizable: true,
buttons: dialogButtons,
})
.html(
'<div><table><tr><td>' + LANG.plugins.davcal['title'] + '</td><td><input type="text" name="eventname" class="dw_davcal__newevent"></td></tr>' +
- '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" value="' + date.format('YYYY-MM-DD') + ' 12:00" name="eventfrom" id="dw_davcal__eventfrom" class="dw_davcal__newevent"></td></tr>' +
- '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" value="' + date.format('YYYY-MM-DD') + ' 12:00" id="dw_davcal__eventto" class="dw_davcal__newevent"></td></tr>' +
+ '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" value="' + date.format('YYYY-MM-DD') + '" name="eventfrom" id="dw_davcal__eventfrom" class="dw_davcal__newevent dw_davcal__date"><input type="text" value="12:00" name="eventfromtime" id="dw_davcal__eventfromtime" class="dw_davcal__newevent dw_davcal__time"></td></tr>' +
+ '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" value="' + date.format('YYYY-MM-DD') + '" id="dw_davcal__eventto" class="dw_davcal__newevent dw_davcal__date"><input type="text" name="eventtotime" value="12:00" id="dw_davcal__eventtotime" class="dw_davcal__newevent dw_davcal__time"></td></tr>' +
'<tr><td colspan="2"><input type="checkbox" name="allday" id="dw_davcal__allday" class="dw_davcal__newevent">' + LANG.plugins.davcal['allday'] + '</td></tr>' +
'</table>' +
'</div>' +
'<div id="dw_davcal__ajaxnew"></div>'
)
.parent()
.attr('id','dw_davcal__createnew')
.show()
.appendTo('.dokuwiki:first');
// attach event handlers
jQuery('#dw_davcal__createnew .ui-dialog-titlebar-close').click(function(){
dw_davcal__modals.hideNewEventDialog();
});
- jQuery('#dw_davcal__eventfrom').datetimepicker({format:'YYYY-MM-DD HH:mm',
+ jQuery('#dw_davcal__eventfrom').datetimepicker({format:'YYYY-MM-DD',
+ formatDate:'YYYY-MM-DD',
+ datepicker: true,
+ timepicker: false,
+ });
+ jQuery('#dw_davcal__eventfromtime').datetimepicker({format:'HH:mm',
formatTime:'HH:mm',
- formatDate:'YYYY-MM-DD',
+ datepicker: false,
+ timepicker: true,
step: 15});
- jQuery('#dw_davcal__eventto').datetimepicker({format:'YYYY-MM-DD HH:mm',
+ jQuery('#dw_davcal__eventto').datetimepicker({format:'YYYY-MM-DD',
+ formatDate:'YYYY-MM-DD',
+ datepicker: true,
+ timepicker: false,
+ });
+ jQuery('#dw_davcal__eventtotime').datetimepicker({format:'HH:mm',
formatTime:'HH:mm',
- formatDate:'YYYY-MM-DD',
- step: 15});
+ datepicker: false,
+ timepicker: true,
+ step:15});
jQuery('#dw_davcal__allday').change(function() {
if(jQuery(this).is(":checked"))
{
- jQuery('#dw_davcal__eventfrom').datetimepicker({timepicker: false});
- jQuery('#dw_davcal__eventto').datetimepicker({timepicker: false});
+ jQuery('#dw_davcal__eventfromtime').prop('readonly', true);
+ jQuery('#dw_davcal__eventtotime').prop('readonly', true);
}
else
{
- jQuery('#dw_davcal__eventfrom').datetimepicker({timepicker: true});
- jQuery('#dw_davcal__eventto').datetimepicker({timepicker: true});
+ jQuery('#dw_davcal__eventfromtime').prop('readonly', false);
+ jQuery('#dw_davcal__eventtotime').prop('readonly', false);
}
});
},
showConfirmDialog : function()
{
if(dw_davcal__modals.$confirmDialog)
return;
var dialogButtons = {};
dialogButtons[LANG.plugins.davcal['yes']] = function() {
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_davcal',
id: JSINFO.id,
action: dw_davcal__modals.action,
params: {
uid: dw_davcal__modals.uid
}
},
function(data)
{
dw_davcal__modals.completeCb(data);
}
);
dw_davcal__modals.hideConfirmDialog();
};
dialogButtons[LANG.plugins.tagrevisions['cancel']] = function() {
dw_davcal__modals.hideConfirmDialog();
};
dw_davcal__modals.$confirmDialog = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: LANG.plugins.tagrevisions['confirmation'],
resizable: true,
buttons: dialogButtons,
})
.html(
'<div>' + dw_davcal__modals.msg + '</div>'
)
.parent()
.attr('id','dw_davcal__confirm')
.show()
.appendTo('.dokuwiki:first');
// attach event handlers
jQuery('#dw_davcal__confirm .ui-dialog-titlebar-close').click(function(){
dw_davcal__modals.hideConfirmDialog();
});
},
showInfoDialog : function() {
if(dw_davcal__modal.$infoDialog)
return;
var dialogButtons = {};
dialogButtons[LANG.plugins.davcal['ok']] = function() {
dw_davcal__modals.hideInfoDialog();
};
dw_davcal__modals.$infoDialog = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: LANG.plugins.davcal['info'],
resizable: true,
buttons: dialogButtons,
})
.html(
'<div>' + dw_davcal__modals.msg + '</div>'
)
.parent()
.attr('id','dw_davcal__info')
.show()
.appendTo('.dokuwiki:first');
// attach event handlers
jQuery('#dw_davcal__info .ui-dialog-titlebar-close').click(function(){
dw_davcal__modals.hideInfoDialog();
});
},
hideNewEventDialog : function() {
dw_davcal__modals.$newEventDialog.empty();
dw_davcal__modals.$newEventDialog.remove();
dw_davcal__modals.$newEventDialog = null;
},
hideEditEventDialog : function() {
dw_davcal__modals.$editEventDialog.empty();
dw_davcal__modals.$editEventDialog.remove();
dw_davcal__modals.$editEventDialog = null;
},
hideInfoDialog : function() {
dw_davcal__modals.$infoDialog.empty();
dw_davcal__modals.$infoDialog.remove();
dw_davcal__modals.$infoDialog = null;
},
hideConfirmDialog: function() {
dw_davcal__modals.$confirmDialog.empty();
dw_davcal__modals.$confirmDialog.remove();
dw_davcal__modals.$confirmDialog = null;
},
hideSettingsDialog: function() {
dw_davcal__modals.$settingsDialog.empty();
dw_davcal__modals.$settingsDialog.remove();
dw_davcal__modals.$settingsDialog = null;
}
};
diff --git a/style.css b/style.css
--- a/style.css
+++ b/style.css
@@ -1,46 +1,54 @@
@import "fullcalendar-2.4.0/fullcalendar.less";
@import "datetimepicker-2.4.5/jquery.datetimepicker.less";
/* modal windows */
#dw_davcal__createnew,
#dw_davcal__edit,
#dw_davcal__info,
#dw_davcal__settings,
#dw_davcal__confirm {
position: absolute;
background-color: #fff;
color: #000;
z-index: 20;
overflow: hidden;
}
#dw_davcal__edit .ui-dialog-content,
#dw_davcal__info .ui-dialog-content,
#dw_davcal__confirm .ui-dialog-content,
#dw_davcal__settings .ui-dialog-content,
#dw_davcal__createnew .ui-dialog-content {
padding-left: 0;
padding-right: 0;
}
#dw_davcal__confirm,
#dw_davcal__info,
#dw_davcal__edit,
#dw_davcal__createnew {
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 260px;
margin:-130px 0 0 -150px;
}
#dw_davcal__settings {
position: absolute;
top: 50%;
left: 50%;
width: 350px;
- height: 280px;
- margin:-140px 0 0 -175px;
+ height: 320px;
+ margin:-160px 0 0 -175px;
}
+
+.dw_davcal__date {
+ width: 90px;
+}
+
+.dw_davcal__time {
+ width: 50px;
+}
diff --git a/syntax.php b/syntax.php
--- a/syntax.php
+++ b/syntax.php
@@ -1,98 +1,99 @@
<?php
/**
* DokuWiki Plugin tagrevisions (Syntax Component)
*
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
* @author Andreas Böhler <dev@aboehler.at>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
class syntax_plugin_davcal extends DokuWiki_Syntax_Plugin {
protected $hlp = null;
// Load the helper plugin
public function syntax_plugin_davcal() {
$this->hlp =& plugin_load('helper', 'davcal');
}
/**
* What kind of syntax are we?
*/
function getType(){
return 'substition';
}
/**
* What about paragraphs?
*/
function getPType(){
return 'normal';
}
/**
* Where to sort in?
*/
function getSort(){
return 165;
}
/**
* Connect pattern to lexer
*/
function connectTo($mode) {
$this->Lexer->addSpecialPattern('\{\{davcal>[^}]*\}\}',$mode,'plugin_davcal');
}
/**
* Handle the match
*/
function handle($match, $state, $pos, &$handler){
global $ID;
$options = trim(substr($match,9,-2));
$options = explode(',', $options);
- $data = array('name' => '',
+ $data = array('name' => $ID,
'description' => $this->getLang('created_by_davcal'));
foreach($options as $option)
{
list($key, $val) = explode('=', $option);
$key = strtolower(trim($key));
$val = trim($val);
$data[$key] = $val;
}
$this->hlp->setCalendarNameForPage($data['name'], $data['description'], $ID, $_SERVER['REMOTE_USER']);
return array($data);
}
/**
* Create output
*/
function render($format, &$R, $data) {
if($format != 'xhtml') return false;
+ global $ID;
$tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL);
$R->doc .= '<div id="fullCalendar"></div>';
$R->doc .= '<div id="fullCalendarTimezoneList" class="fullCalendarTimezoneList" style="display:none">';
$R->doc .= '<select id="fullCalendarTimezoneDropdown">';
$R->doc .= '<option value="local">'.$this->getLang('local_time').'</option>';
foreach($tzlist as $tz)
{
$R->doc .= '<option value="'.$tz.'">'.$tz.'</option>';
}
$R->doc .= '</select></div>';
$R->doc .= '<div class="fullCalendarSettings"><a href="#" class="fullCalendarSettings"><img src="'.DOKU_URL.'lib/plugins/davcal/images/settings.png'.'">'.$this->getLang('settings').'</a></div>';
}
}
// vim:ts=4:sw=4:et:enc=utf-8:
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Dec 25, 1:02 PM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
533776
Default Alt Text
(55 KB)
Attached To
rDAVCAL DokuWiki DAVCal PlugIn
Event Timeline
Log In to Comment