diff --git a/action/ajax.php b/action/ajax.php --- a/action/ajax.php +++ b/action/ajax.php @@ -1,157 +1,159 @@ 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')); + $page = trim($INPUT->post->str('page')); $params = $INPUT->post->arr('params'); $user = $_SERVER['REMOTE_USER']; $write = false; $multi = false; $data = array(); $data['result'] = false; $data['html'] = $this->getLang('unknown_error'); // Check if we have access to the calendar ($id is given by parameters, // that's not necessarily the page we come from) $acl = auth_quickaclcheck($id); if($acl > AUTH_READ) { $write = true; } // Retrieve the calendar pages based on the meta data - $calendarPages = $this->hlp->getCalendarPagesByMeta($id); + $calendarPages = $this->hlp->getCalendarPagesByMeta($page); if($calendarPages === false) { - $calendarPages = array($id); + $calendarPages = array($page); } if(count($calendarPages) > 1) $multi = true; // Parse the requested action switch($action) { // Add a new Event 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; // Retrieve existing Events case 'getEvents': $startDate = $INPUT->post->str('start'); $endDate = $INPUT->post->str('end'); $data = array(); - foreach($calendarPages as $page) + foreach($calendarPages as $calPage) { - $data = array_merge($data, $this->hlp->getEventsWithinDateRange($page, + $data = array_merge($data, $this->hlp->getEventsWithinDateRange($calPage, $user, $startDate, $endDate)); } break; // Edit an event 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; // Delete an Event 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; // Get personal settings case 'getSettings': $data['result'] = true; $data['settings'] = $this->hlp->getPersonalSettings($user); $data['settings']['multi'] = $multi; $data['settings']['calids'] = $this->hlp->getCalendarMapForIDs($calendarPages); $data['settings']['readonly'] = !$write; - $data['settings']['syncurl'] = $this->hlp->getSyncUrlForPage($id, $user); - $data['settings']['privateurl'] = $this->hlp->getPrivateURLForPage($id); + $data['settings']['syncurl'] = $this->hlp->getSyncUrlForPage($page, $user); + $data['settings']['privateurl'] = $this->hlp->getPrivateURLForPage($page); + $data['settings']['meta'] = $this->hlp->getCalendarMetaForPage($page); break; // Save personal settings case 'saveSettings': $settings = array(); $settings['weeknumbers'] = $params['weeknumbers']; $settings['timezone'] = $params['timezone']; $settings['workweek'] = $params['workweek']; $settings['monday'] = $params['monday']; 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/plugin.info.txt b/plugin.info.txt --- a/plugin.info.txt +++ b/plugin.info.txt @@ -1,7 +1,7 @@ base davcal author Andreas Boehler email dev@aboehler.at -date 2015-09-25 +date 2015-09-29 name Calendar PlugIn with CalDAV sharing support desc Create one calendar per page and share/subscribe via CalDAV url http://www.dokuwiki.org/plugin:davcal diff --git a/script.js b/script.js --- a/script.js +++ b/script.js @@ -1,690 +1,698 @@ /* 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 */ /* DOKUWIKI:include_once jstz.js */ /** * Initialize the DAVCal script, attaching some event handlers and triggering * the initial load of the fullcalendar 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 var calendarpage = jQuery('#fullCalendar').data('calendarpage'); if(!calendarpage) return; dw_davcal__modals.page = calendarpage; 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 ''; } ); } ); // First, retrieve the current settings. // Upon success, initialize fullcalendar. var postArray = { }; jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_davcal', id: dw_davcal__modals.page, + page: dw_davcal__modals.page, 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; var ro = false; var firstday = 0; var detectedTz = jstz.determine().name(); dw_davcal__modals.detectedTz = detectedTz; if(data['settings']['weeknumbers'] == 1) wknum = true; if(data['settings']['timezone'] !== '') tz = data['settings']['timezone']; if(data['settings']['workweek'] == 1) we = false; if(data['settings']['monday'] == 1) firstday = 1; + var defaultView = data['settings']['meta']['view']; // Initialize the davcal popup var res = jQuery('#fullCalendar').fullCalendar({ dayClick: function(date, jsEvent, view) { dw_davcal__modals.showEditEventDialog(date, false); }, eventClick: function(calEvent, jsEvent, view) { dw_davcal__modals.showEditEventDialog(calEvent, true); }, events: { url: DOKU_BASE + 'lib/exe/ajax.php', type: 'POST', data: { call: 'plugin_davcal', action: 'getEvents', - id: dw_davcal__modals.page + id: dw_davcal__modals.page, + page: dw_davcal__modals.page }, error: function() { dw_davcal__modals.msg = LANG.plugins.davcal['error_retrieving_data']; dw_davcal__modals.showDialog(false); } }, header: { left: 'title', center: 'today prev,next', right: 'month,agendaWeek,agendaDay' }, lang: JSINFO.plugin.davcal['language'], weekNumbers: wknum, timezone: tz, weekends: we, - firstDay: firstday + firstDay: firstday, + defaultView: defaultView }); } } ); }); /** * This holds all modal windows that DAVCal uses. */ var dw_davcal__modals = { $editEventDialog: null, $dialog: null, $settingsDialog: null, msg: null, completeCb: null, action: null, uid: null, settings: null, page: null, detectedTz: null, /** * Show the settings dialog */ // FIXME: Hide URLs for multi-calendar showSettingsDialog : function() { if(dw_davcal__modals.$settingsDialog) return; // Dialog buttons are language-dependent and defined here. // Attach event handlers for save and cancel. 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(''); jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_davcal', id: dw_davcal__modals.page, + page: dw_davcal__modals.page, 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( '
' + //'' + '' + '' + '' + '' + '' + '' + '
' + LANG.plugins.davcal['use_lang_tz'] + '
' + LANG.plugins.davcal['timezone'] + '
' + LANG.plugins.davcal['weeknumbers'] + '
' + LANG.plugins.davcal['only_workweek'] + '
' + LANG.plugins.davcal['start_monday'] + '
' + LANG.plugins.davcal['sync_url'] + '
' + LANG.plugins.davcal['private_url'] + '
' + '
' + '
' ) .parent() .attr('id','dw_davcal__settings') .show() .appendTo('.dokuwiki:first'); jQuery('#dw_davcal__settings').position({ my: "center", at: "center", of: window }); // Initialize current settings jQuery('#dw_davcal__settings_syncurl').on('click', function() { jQuery(this).select(); }); jQuery('#dw_davcal__settings_privateurl').on('click', function() { jQuery(this).select(); }); var $tzdropdown = jQuery('#dw_davcal__settings_timezone'); jQuery('#fullCalendarTimezoneList option').each(function() { jQuery(''); } if(edit || (dw_davcal__modals.settings['calids'].length < 1)) { $dropdown.prop('disabled', true); } // Set up existing/predefined values jQuery('#dw_davcal__tz_edit').val(dw_davcal__modals.detectedTz); 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')); jQuery('#dw_davcal__eventfromtime_edit').val(calEvent.start.format('HH:mm')); jQuery('#dw_davcal__eventdescription_edit').val(calEvent.description); 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', formatDate:'YYYY-MM-DD', datepicker: true, timepicker: false, }); jQuery('#dw_davcal__eventfromtime_edit').datetimepicker({format:'HH:mm', formatTime:'HH:mm', datepicker: false, timepicker: true, step: 15}); 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', datepicker: false, timepicker: true, step:15}); jQuery('#dw_davcal__allday_edit').change(function() { if(jQuery(this).is(":checked")) { jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', true); jQuery('#dw_davcal__eventtotime_edit').prop('readonly', true); } else { jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', false); jQuery('#dw_davcal__eventtotime_edit').prop('readonly', false); } }); jQuery('#dw_davcal__allday_edit').change(); }, /** * Show an info/confirmation dialog * @param {Object} confirm Whether a confirmation dialog (true) or an info dialog (false) is requested */ showDialog : function(confirm) { if(dw_davcal__modals.$confirmDialog) return; var dialogButtons = {}; var title = ''; if(confirm) { title = LANG.plugins.davcal['confirmation']; var pageid = dw_davcal__modals.page; if(dw_davcal__modals.settings['multi']) { pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val(); } dialogButtons[LANG.plugins.davcal['yes']] = function() { jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_davcal', id: pageid, + page: dw_davcal__modals.page, action: dw_davcal__modals.action, params: { uid: dw_davcal__modals.uid } }, function(data) { dw_davcal__modals.completeCb(data); } ); dw_davcal__modals.hideDialog(); }; dialogButtons[LANG.plugins.davcal['cancel']] = function() { dw_davcal__modals.hideDialog(); }; } else { title = LANG.plugins.davcal['info']; dialogButtons[LANG.plugins.davcal['ok']] = function() { dw_davcal__modals.hideDialog(); }; } dw_davcal__modals.$dialog = jQuery(document.createElement('div')) .dialog({ autoOpen: false, draggable: true, title: title, resizable: true, buttons: dialogButtons, }) .html( '
' + dw_davcal__modals.msg + '
' ) .parent() .attr('id','dw_davcal__confirm') .show() .appendTo('.dokuwiki:first'); jQuery('#dw_davcal__confirm').position({ my: "center", at: "center", of: window }); // attach event handlers jQuery('#dw_davcal__confirm .ui-dialog-titlebar-close').click(function(){ dw_davcal__modals.hideDialog(); }); }, /** * Hide the edit event dialog */ hideEditEventDialog : function() { dw_davcal__modals.$editEventDialog.empty(); dw_davcal__modals.$editEventDialog.remove(); dw_davcal__modals.$editEventDialog = null; }, /** * Hide the confirm/info dialog */ hideDialog: function() { dw_davcal__modals.$dialog.empty(); dw_davcal__modals.$dialog.remove(); dw_davcal__modals.$dialog = null; }, /** * Hide the settings dialog */ hideSettingsDialog: function() { dw_davcal__modals.$settingsDialog.empty(); dw_davcal__modals.$settingsDialog.remove(); dw_davcal__modals.$settingsDialog = null; } }; diff --git a/syntax.php b/syntax.php --- a/syntax.php +++ b/syntax.php @@ -1,134 +1,141 @@ */ // 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' => $ID, 'description' => $this->getLang('created_by_davcal'), 'id' => array(), 'settings' => 'show', + 'view' => 'month' ); $lastid = $ID; foreach($options as $option) { list($key, $val) = explode('=', $option); $key = strtolower(trim($key)); $val = trim($val); switch($key) { case 'id': $lastid = $val; if(!in_array($val, $data['id'])) $data['id'][$val] = '#3a87ad'; break; case 'color': $data['id'][$lastid] = $val; break; + case 'view': + if(in_array($val, array('month', 'basicDay', 'basicWeek', 'agendaWeek', 'agendaDay'))) + $data['view'] = $val; + else + $data['view'] = 'month'; + break; default: $data[$key] = $val; } } // Handle the default case when the user didn't enter a different ID if(empty($data['id'])) { $data['id'] = array($ID => '#3a87ad'); } // Only update the calendar name/description if the ID matches the page ID. // Otherwise, the calendar is included in another page and we don't want // to interfere with its data. if(in_array($ID, array_keys($data['id']))) { $this->hlp->setCalendarNameForPage($data['name'], $data['description'], $ID, $_SERVER['REMOTE_USER']); $this->hlp->setCalendarColorForPage($data['id'][$ID], $ID); } p_set_metadata($ID, array('plugin_davcal' => $data)); return $data; } /** * Create output */ function render($format, &$R, $data) { if($format != 'xhtml') return false; global $ID; $tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL); // Render the Calendar. Timezone list is within a hidden div, // the calendar ID is in a data-calendarid tag. $R->doc .= '
'; $R->doc .= ''; if(($this->getConf('hide_settings') !== 1) && ($data['settings'] !== 'hide')) { $R->doc .= '
'.$this->getLang('settings').'
'; } } } // vim:ts=4:sw=4:et:enc=utf-8: