Änderungen von Dokument Calendar Macro
Zuletzt geändert von xwikiadmin am 2025/01/07 11:32
Von Version 2.1
bearbeitet von xwikiadmin
am 2022/08/11 16:36
am 2022/08/11 16:36
Änderungskommentar:
Migrated property [defaultCategories] from class [XWiki.WikiMacroClass]
Auf Version 6.1
bearbeitet von xwikiadmin
am 2025/01/07 11:32
am 2025/01/07 11:32
Änderungskommentar:
Install extension [com.xwiki.mocca-calendar:application-mocca-calendar-ui/2.15]
Zusammenfassung
-
Objekte (3 geändert, 4 hinzugefügt, 0 gelöscht)
Details
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,5 +1,11 @@ 1 -define('moccaCalendar', ['jquery', 'fullcalendar', 'moment'], function(jQuery, fullCalendar, moment) { 1 +require.config({ 2 + paths: { 3 + purify: "$services.webjars.url('org.webjars.npm:dompurify', 'dist/purify.js')" 4 + }, 5 +}); 2 2 7 +define('moccaCalendar', ['jquery', 'fullcalendar', 'moment', 'purify'], function(jQuery, fullCalendar, moment, purify) { 8 + 3 3 // Make sure the XWiki 'namespace' and the ModalPopup class exist. 4 4 if (typeof(XWiki) == "undefined" || typeof(XWiki.widgets) == "undefined" || typeof(XWiki.widgets.ModalPopup) == "undefined") { 5 5 if (typeof console != "undefined" && typeof console.warn == "function") { ... ... @@ -34,6 +34,9 @@ 34 34 this.timeFormat = ''; 35 35 this.dayFormat = dateFormat; 36 36 } 43 + document.addEventListener('calendarImportCompleted', () => { 44 + calendar.fullCalendar('refetchEvents'); 45 + }); 37 37 }, 38 38 displayError: function(errorMessage) { 39 39 if (!errorMessage) { ... ... @@ -121,6 +121,12 @@ 121 121 document.cookie = cookieName + value + "; path=/"; 122 122 }; 123 123 133 + function removeColorPickers() { 134 + jQuery('#mocca-event-edit-form .color-picker').each(function(index) { 135 + jQuery('#' + jQuery(this).data('colpickId')).remove(); 136 + }); 137 + } 138 + 124 124 // 125 125 // the dialog to show / edit events 126 126 // ... ... @@ -136,7 +136,7 @@ 136 136 // call constructor from ModalPopup with params content, shortcuts, options 137 137 $super( 138 138 // this element will end up as 'this.content' 139 - new Element('form', {'class' : 'xform'}), 154 + new Element('form', {'class' : 'xform', 'id' : 'mocca-event-edit-form'}), 140 140 { 141 141 "show": {method: this.showDialog, keys: []}, 142 142 "close": {method: this.closeDialog, keys: ['Esc']} ... ... @@ -147,6 +147,7 @@ 147 147 title : this.interactionParameters.editMode ? "$escapetool.javascript($services.localization.render('MoccaCalendar.calendarevent.create'))" : "$escapetool.javascript($services.localization.render('MoccaCalendar.calendarevent.view'))", 148 148 removeOnClose : true, 149 149 onClose : function() { 165 + removeColorPickers(); 150 150 document.stopObserving('xwiki:moccacalendar:editmode'); 151 151 document.stopObserving('xwiki:moccacalendar:instancesaved'); 152 152 } ... ... @@ -187,6 +187,7 @@ 187 187 // and we only listen for the results to close the dialog 188 188 document.observe('xwiki:moccacalendar:instancesaved', function(event) { 189 189 this.savedBox.show(); 206 + removeColorPickers(); 190 190 this.closeDialog(); 191 191 this.helper.calendar.fullCalendar('refetchEvents'); 192 192 }.bind(this)); ... ... @@ -282,6 +282,7 @@ 282 282 } else { 283 283 saveUrl = this.interactionParameters.event.saveUrl; 284 284 } 302 + this.content.title.value = purify.sanitize(this.content.title.value) 285 285 this.content.writeAttribute('action', saveUrl + '&xpage=plain&ajax=true'); 286 286 this.content.request({ 287 287 onSuccess: function() { ... ... @@ -288,6 +288,7 @@ 288 288 this.saving = false; 289 289 this.savingBox.hide(); 290 290 this.savedBox.show(); 309 + removeColorPickers(); 291 291 this.closeDialog(); 292 292 this.helper.calendar.fullCalendar('refetchEvents'); 293 293 }.bind(this), ... ... @@ -384,18 +384,20 @@ 384 384 var buttons = new Element('div', {'class':'buttons'}); 385 385 var oldSkin = ! $('body').hasClassName('skin-flamingo'); // FIXME: bad b/w compat hack 386 386 formcontent.insert(buttons); 406 + // When you are in a read only calendar you only need the close button for the modal and you MUST Not fire 407 + // the xwiki:moccacalendar:editloaded event because you will get a bunch of errors. 387 387 if (this.interactionParameters.editMode) { 388 388 var that = this; 389 - buttons.insert(this.createButton("submit","$escapetool.javascript($services.localization.render('save'))","","save-moccacalendar-event","btn")); 390 - buttons.down('#save-moccacalendar-event').observe('click', this.submitForm.bind(this)); 410 + if(this.helper.createEventBaseUrl.indexOf('disabled=disabled') === -1) { 411 + buttons.insert(this.createButton("submit","$escapetool.javascript($services.localization.render('save'))","","save-moccacalendar-event","btn")); 412 + buttons.down('#save-moccacalendar-event').observe('click', this.submitForm.bind(this)); 413 + // MOCCACAL-128: the event template has a space in the title to avoid showing the page name, but we want to remove this on load 414 + var titleField = formcontent.down('input[name="title"]') 415 + if (titleField && titleField.getAttribute('value').trim() == '') { titleField.setAttribute('value','') } 416 + document.fire('xwiki:moccacalendar:editloaded'); 417 + } 391 391 buttons.insert('<span class="buttonwrapper"><a href="#" id="cancel-moccacalendar-event" class="secondary button">' + "$escapetool.javascript($services.localization.render('cancel'))" + '</a></span>'); 392 392 buttons.down('#cancel-moccacalendar-event').observe('click', this.closeDialog.bind(this)); 393 - 394 - // MOCCACAL-128: the event template has a space in the title to avoid showing the page name, but we want to remove this on load 395 - var titleField = formcontent.down('input[name="title"]') 396 - if (titleField && titleField.getAttribute('value').trim() == '') { titleField.setAttribute('value','') } 397 - 398 - document.fire('xwiki:moccacalendar:editloaded'); 399 399 $("MoccaCalendarEvent.MoccaCalendarEventClass_0_title").focus(); 400 400 } else { 401 401 var leftGroup = new Element('div', {'class':'btn-group btn-group-left'}); ... ... @@ -410,13 +410,19 @@ 410 410 } 411 411 // FIXME: this should be a plain link, but then it has no styles 412 412 if (oldSkin) { 413 - leftGroup.insert(this.createButton("button","$escapetool.javascript($services.localization.render('view'))","","view-moccacalendar-event","btn")); 434 + if (this.interactionParameters.event.readOnly != true) { 435 + leftGroup.insert(this.createButton("button","$escapetool.javascript($services.localization.render('view'))","","view-moccacalendar-event","btn")); 436 + } 414 414 leftGroup.insert('<span class="buttonwrapper"><a href="#" id="cancel-moccacalendar-event" class="secondary button">' + "$escapetool.javascript($services.localization.render('cancel'))" + '</a></span>'); 415 415 } else { 416 - leftGroup.insert(' <button class="button btn btn-default" id="view-moccacalendar-event"><span class="glyphicon glyphicon-file"></span> '+"$escapetool.javascript($services.localization.render('view'))"+'</button>'); 439 + if (this.interactionParameters.event.readOnly != true) { 440 + leftGroup.insert(' <button class="button btn btn-default" id="view-moccacalendar-event"><span class="glyphicon glyphicon-file"></span> '+"$escapetool.javascript($services.localization.render('view'))"+'</button>'); 441 + } 417 417 leftGroup.insert('<button class="button btn btn-default" id="cancel-moccacalendar-event"><span class="glyphicon glyphicon-remove"></span> '+"$escapetool.javascript($services.localization.render('cancel'))"+'</button>'); 418 418 } 419 - leftGroup.down("#view-moccacalendar-event").observe('click', function(e) { e.stop(); window.location.href = this.interactionParameters.event.viewUrl; }.bind(this)); 444 + if (this.interactionParameters.event.readOnly != true) { 445 + leftGroup.down("#view-moccacalendar-event").observe('click', function(e) { e.stop(); window.location.href = this.interactionParameters.event.viewUrl; }.bind(this)); 446 + } 420 420 leftGroup.down('#cancel-moccacalendar-event').observe('click', this.closeDialog.bind(this)); 421 421 if (this.interactionParameters.event.canDelete) { 422 422 var rightGroup = new Element('div', {'class':'btn-group btn-group-right'}); ... ... @@ -456,6 +456,9 @@ 456 456 script.remove(); 457 457 }); 458 458 content.insert('<div id="formcontent"><div id="forminnercontent">' + container.innerHTML + '</div></div>'); 486 + 487 + var parentModalPopup = jQuery('.xdialog-box-moccacal-modal-popup').toArray(); 488 + document.fire('xwiki:dom:updated', {elements: parentModalPopup}); 459 459 }, 460 460 handleDatetimeFieldChange : function(event, element) { 461 461 if (this.saving) { return; } ... ... @@ -716,10 +716,21 @@ 716 716 717 717 }); 718 718 749 +define('mocca-calendar-import-notification', { 750 + prefix: 'MoccaCalendar.import.notification.', 751 + keys: [ 752 + 'inprogress', 753 + 'done', 754 + 'error', 755 + 'filetoolarge' 756 + ] 757 +}); 758 + 719 719 /** 720 - * Delet ingan event760 + * Delete event and calendar import actions. 721 721 */ 722 -require(['jquery'], function($) { 762 +require(['jquery', 'xwiki-meta', 'xwiki-job-runner', 'xwiki-l10n!mocca-calendar-import-notification'], 763 + function($, xwikiMeta, JobRunner, l10n) { 723 723 /** 724 724 * Events triggered before deleteEvents modal is shown: save the button that triggers 725 725 * the modal, close MoccaCalendarPopup, update the name of event on displayed text. ... ... @@ -754,4 +754,74 @@ 754 754 var calendarPopup = relatedTarget.data('calendarPopup'); 755 755 new XWiki.MoccaCalendar.MoccaCalendarPopup(calendarPopup.interactionParameters, calendarPopup.helper); 756 756 }); 798 + 799 + // Trigger the upload manually when the button is clicked. 800 + $(document).on('click', '#import-calendar-file-button', function(event) { 801 + var form = $('#import-calendar-file form').get(0); 802 + if (event) { 803 + event.preventDefault(); 804 + } 805 + startUploading(form); 806 + }); 807 + 808 + // Start uploading this file by creating a new XHR object with the file data. 809 + var startUploading = function (form) { 810 + var formData = new FormData(form); 811 + var select = form.down('#import-calendar-parent'); 812 + var input = form.down('#import-ical-file-input'); 813 + if (input.files[0].size < input.dataset.maxFileSize) { 814 + var params = {}; 815 + params[select.name] = select.value; 816 + formData.action = form.action + "?" + $.param(params); 817 + // Create XMLHttpRequest object and POST the data 818 + var request = this.request = new XMLHttpRequest(); 819 + request.open('POST', formData.action); 820 + request.send(formData); 821 + checkImportJob(select.value); 822 + } else { 823 + var notification = new XWiki.widgets.Notification(l10n.get('filetoolarge'), 'error'); 824 + } 825 + } 826 + 827 + const checkImportJob = function(selectedCalendar) { 828 + let documentReference = XWiki.Model.resolve('MoccaCalendar.Code.ImportJobResource', XWiki.EntityType.DOCUMENT); 829 + var targetURL = new XWiki.Document(documentReference).getURL('get'); 830 + var targetJobId = ['moccacalendar', 'import', selectedCalendar]; 831 + var data = []; 832 + data.push( 833 + {name: 'outputSyntax', value: 'plain'}, 834 + {name: 'sheet', value: 'MoccaCalendar.Code.ImportJobResource'}, 835 + {name: 'action', value: 'jobStatus'}, 836 + {name: 'jobId', value: targetJobId.join('/')}, 837 + {name: 'data', value: 'jobStatus'}, 838 + {name: 'form_token', value: xwikiMeta.form_token} 839 + ); 840 + var notification = new XWiki.widgets.Notification(l10n.get('inprogress'), 'inprogress'); 841 + $('#import-calendar-file-button').prop('disabled', true); 842 + return Promise.resolve(new JobRunner({ 843 + createStatusRequest: function(jobId) { 844 + return { 845 + url: targetURL, 846 + data: { 847 + outputSyntax: 'plain', 848 + sheet: 'MoccaCalendar.Code.ImportJobResource', 849 + data: 'jobStatus', 850 + jobId: jobId.join('/') 851 + } 852 + }; 853 + } 854 + }).run(targetURL, data)).then((response) => { 855 + if (response.error !== null) { 856 + throw new Error(response.error.message); 857 + } else { 858 + document.dispatchEvent(new Event('calendarImportCompleted')); 859 + notification.replace(new XWiki.widgets.Notification(l10n.get('done'),'done')); 860 + } 861 + }).catch((reason) => { 862 + notification.replace(new XWiki.widgets.Notification(l10n.get('error'),'error')); 863 + return Promise.reject(reason); 864 + }).finally(() => { 865 + $('#import-calendar-file-button').prop('disabled', false); 866 + }); 867 + }; 757 757 });
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -79,3 +79,24 @@ 79 79 .skin-flamingo .gadget .fc h2 { 80 80 font-size: 140%; 81 81 } 82 + 83 +.import-form { 84 + padding: 2em; 85 +} 86 + 87 +.import-form label { 88 + margin-bottom: 0.8em; 89 + font-weight: bold; 90 +} 91 + 92 +.import-form select, 93 +.import-form #import-ical-file-input { 94 + width: 100%; 95 + margin-bottom: 1.6em; 96 + border-radius: 0.4em; 97 +} 98 + 99 +.import-form #import-ical-file-input { 100 + padding: 0.6em 1em; 101 + border: 1px solid #ccc; 102 +}
- XWiki.WikiMacroClass[0]
-
- Makro-Code
-
... ... @@ -10,6 +10,13 @@ 10 10 #set($calcounter = $request.getAttribute('MoccaCalendar.Code.Macro:counter')) 11 11 #if(!$calcounter) #set($calcounter = 0) #else #set($calcounter = $calcounter + 1) #end 12 12 #set($discard = $request.setAttribute('MoccaCalendar.Code.Macro:counter', $calcounter)) 13 +#set ($wikis = "$!xcontext.macro.params.wikis") 14 +#set ($wikiList = []) 15 +#if ($wikis != '') 16 + #foreach ($wikiId in $wikis.split(',')) 17 + #set ($discard = $wikiList.add($wikiId.trim())) 18 + #end 19 +#end 13 13 #set($filter = $xcontext.macro.params.filter) 14 14 #if(!$filter) 15 15 #set($filter = 'page') ## possible values are wiki, space, page ... ... @@ -60,6 +60,33 @@ 60 60 #if(!$date) 61 61 #set($date = "") 62 62 #end 70 +#set($gCal = "$!xcontext.macro.params.gCal") 71 +#set($gApiKey = $xcontext.macro.params.gApiKey) 72 +#if(!$gApiKey) 73 + #set($gApiKey = "") 74 +#end 75 +#set($iCal = $xcontext.macro.params.iCal) 76 +#if(!$iCal) 77 + #set ($iCal = "") 78 +#end 79 +## Prepare the fields if the subscribed class is present 80 +#set ($subscribed = $doc.getObject('MoccaCalendar.MoccaCalendarSubscribeClass')) 81 +#if ($subscribed) 82 + #set ($subscribediCal = $subscribed.getValue('iCal')) 83 + #set ($subscribedgCals = $subscribed.getValue('gCal')) 84 + #set ($gApiKeySubscribed = $subscribed.getValue('gApiKey')) 85 + #set ($subscribedColor = $subscribed.getValue('color')) 86 + #set ($subscribedTextColor = $subscribed.getValue('textColor')) 87 + #set ($disableCreationEvent = 'disabled') 88 +#else 89 + #set ($subscribediCals = '') 90 + #set ($subscribedgCals = '') 91 + #set ($gApiKeySubscribed = '') 92 + #set ($subscribedColor = 'blue') 93 + #set ($subscribedTextColor = 'white') 94 + #set ($disableCreationEvent = "") 95 +#end 96 + 63 63 ## If the date format is not set in MoccaCalendarEventClass, we are going to use the date format from the current wiki. 64 64 #set($dateFormat = $!xwiki.getClass("MoccaCalendar.MoccaCalendarEventClass").get("startDate").getProperty('dateFormat').value) 65 65 #if("$!dateFormat" == "") ... ... @@ -117,17 +117,116 @@ 117 117 </div> 118 118 </div> 119 119 #end 154 + 155 +#macro(importCalendarFileModal) 156 + <div class="modal fade" id="import-calendar-file" tabindex="-1" role="dialog"> 157 + <div class="modal-dialog"> 158 + <div class="modal-content"> 159 + <div class="modal-header"> 160 + <button type="button" class="close" data-dismiss="modal">×</button> 161 + <h4 class="modal-title"> 162 + $escapetool.xml($services.localization.render('MoccaCalendar.import.modal.title')) 163 + </h4> 164 + </div> 165 + <div class="modal-body"> 166 + #set ($escapedCalendarSpace = $escapetool.xml($doc.getSpace())) 167 + #set ($escapedCalendarName = $escapetool.xml($doc.getDocumentReference().getName())) 168 + #set ($actionURL = "$request.getContextPath()/rest/moccacalendar/import") 169 + <form class="xform" action="$actionURL" method="post"> 170 + <div class="import-form"> 171 + <label for="import-calendar-parent"> 172 + $escapetool.xml($services.localization.render('MoccaCalendar.calendar'))</label> 173 + <select id="import-calendar-parent" name="parentCalendar"> 174 + #foreach ($item in $services.moccacalendar.getAllCalendars()) ## TODO: add filter here, see MOCCACAL-76 175 + #set ($itemdoc = $xwiki.getDocument($item)) 176 + #if ($!{itemdoc} && ${itemdoc.hasAccessLevel("edit")}) 177 + #set ($selected="") 178 + #if ($itemdoc.getId() == $doc.getId()) 179 + #set ($selected=" selected='selected'") 180 + #end 181 + <option value="$escapetool.html($itemdoc.getFullName())"$selected> 182 + $itemdoc.getDisplayTitle()</option> 183 + #end 184 + #end 185 + </select> 186 + <label for="import-ical-file-input">$escapetool.xml($services.localization.render( 187 + 'MoccaCalendar.import.modal.file.label'))</label> 188 + <input type="file" id="import-ical-file-input" accept=".ics" name="importedfile" 189 + data-max-file-size="$!escapetool.xml($xwiki.getSpacePreference('upload_maxsize'))"> 190 + </div> 191 + </form> 192 + </div> 193 + <div class="modal-footer"> 194 + <input type="button" class="btn btn-primary" id="import-calendar-file-button" 195 + value="$escapetool.xml($services.localization.render('MoccaCalendar.import.modal.button.start'))"> 196 + <input type="button" class="btn btn-default" 197 + value="$escapetool.xml($services.localization.render('cancel'))" data-dismiss="modal"> 198 + </div> 199 + </div> 200 + </div> 201 + </div> 202 +#end 120 120 {{/velocity}} 121 121 122 -{{include reference="Licenses.Code.VelocityMacros"/}} 123 - 124 124 {{velocity}} 206 +#macro(getSubscribedCalendars) 207 + #set ($query = ", BaseObject as obj where doc.fullName = obj.name and obj.className = 'MoccaCalendar.MoccaCalendarSubscribeClass'") 208 + #set ($calendarDocumentsReferences = $services.query.hql($query).execute()) 209 + #set ($properties = []) 210 + #foreach($reference in $calendarDocumentsReferences) 211 + #set ($document = $xwiki.getDocument($reference)) 212 + #set ($class = $document.getObject('MoccaCalendar.MoccaCalendarSubscribeClass')) 213 + #if ($class.getValue('globalDisplay') == '1') 214 + #set ($discard = $properties.add({ 215 + 'iCal': $class.getValue('iCal'), 216 + 'gCal': $class.getValue('gCal'), 217 + 'gApiKey': $class.getValue('gApiKey'), 218 + 'color': $class.getValue('color'), 219 + 'textColor': $class.getValue('textColor') 220 + })) 221 + #end 222 + #end 223 +#end 224 + 225 +## Macro for handling iCal sources 226 +#macro(handleICalSources $iCalList $color $textColor) 227 + #set($iCals = $stringtool.split($iCalList, ',')) 228 + #foreach($iCal in $iCals) 229 + #set($json = $xwiki.getDocument('Calendar.ICalToJSON').getURL('get', "iCal=$escapetool.url($stringtool.strip($iCal))")) 230 + { 231 + url: "$json&outputSyntax=plain&startfield=datetime", 232 + backgroundColor: "$color", 233 + textColor: "$textColor" 234 + } 235 + #if($foreach.count < $iCals.size()) 236 + , 237 + #end 238 + #end 239 +#end 240 + 241 +## Macro for handling Google Calendar sources 242 +#macro(handleGoogleCalendarSources $gCalList $apiKey $color, $textColor) 243 + #set($googleCalendars = $stringtool.split($gCalList, ',')) 244 + #foreach($calendar in $googleCalendars) 245 + { 246 + googleCalendarId: "$stringtool.strip($calendar)", 247 + googleCalendarApiKey: "$apiKey", 248 + backgroundColor: "$color", 249 + textColor: "$textColor" 250 + } 251 + #if($foreach.count < $googleCalendars.size()) 252 + , 253 + #end 254 + #end 255 +#end 256 + 257 + 125 125 ## We need to check if there is a valid license because the macro is registered even if the user doesn't have view right 126 126 ## on the macro definition page. See XWIKI-14828: Rendering macros defined in wiki pages are available to users that 127 127 ## don't have view right on those pages. 128 128 #set ($mainReference = $services.model.createDocumentReference('', 'MoccaCalendar', 'MoccaCalendarClass')) 129 129 #if (!$services.licensing.licensor.hasLicensureForEntity($mainReference)) 130 - {{ error}}#getMissingLicenseMessage('moccacalendar.extension.name'){{/error}}263 + {{missingLicenseMessage extensionName="moccacalendar.extension.name"/}} 131 131 #else 132 132 #if($xcontext.action=='view'){{html clean="false" wiki="false"}} 133 133 #if($canCreateEvents) ... ... @@ -134,6 +134,9 @@ 134 134 ## create event link 135 135 <div class="calendar-buttons"> 136 136 <span class="buttonwrapper"> 270 +<button data-toggle="modal" data-target="#import-calendar-file" 271 + title="$escapetool.xml($services.localization.render('MoccaCalendar.calendarevent.import.title'))"> 272 + $escapetool.html($services.localization.render('MoccaCalendar.calendarevent.import'))</button> 137 137 <button class="btn btn-success" id="calendar${calcounter}-btn"><span class="glyphicon glyphicon-plus"></span> $escapetool.html($services.localization.render('MoccaCalendar.calendarevent.create'))</button> 138 138 </span> 139 139 </div> ... ... @@ -141,38 +141,109 @@ 141 141 #end 142 142 <div id="calendar${calcounter}"></div> 143 143 <script type="text/javascript"> 144 -require(['jquery', 'moccaCalendar'], function(jQuery) { 280 +require.config({ 281 + paths: { 282 + purify: "$services.webjars.url('org.webjars.npm:dompurify', 'dist/purify.js')" 283 + }, 284 +}); 285 + 286 + 287 +require(['xwiki-meta', 'jquery', 'moment','purify', 'gcal', 'moccaCalendar'], function(xwikiMeta, jQuery, moment, purify) { 145 145 jQuery(document).ready(function() { 146 146 var defaultView = XWiki.MoccaCalendar.Helper.getCalendarView("$!escapetool.javascript($defaultView)"); 147 147 291 + var wikiList = $jsontool.serialize($wikiList); 292 + wikiList = wikiList.map(item => encodeURIComponent(item)); 293 + 148 148 var defaultEventData = { 149 149 xpage: 'plain', 150 150 outputSyntax: 'plain', 151 151 calendarDoc: "$!escapetool.javascript($calendarDoc)", 298 + wikis: wikiList, 152 152 filter: "$!escapetool.javascript($filter)", 153 153 filterDoc: "$!escapetool.javascript($filterDoc)", 154 154 classname: "MoccaCalendar.MoccaCalendarEventClass", 155 155 startfield: "startDate", 156 156 endfield: "endDate", 157 - durationfield: "" 304 + durationfield: "", 305 + form_token: xwikiMeta.form_token 158 158 }; 159 159 160 160 // page is now ready, initialize the calendar... 161 161 var calendar = jQuery('#calendar${calcounter}').fullCalendar({ 162 - events: { 163 - url : "$!escapetool.javascript($jsonUrl)", 164 - type: 'GET', 165 - data : function() { 166 - // as we also get called before the calendar is fully initialized 167 - // we cannot get the current view reliably from the calendar itself 168 - // instead use our trusty helper 169 - return jQuery.extend(defaultEventData, {'outputView': XWiki.MoccaCalendar.Helper.getCalendarView(defaultView)} ); 170 - }, 171 - error: function() { 172 - calendarHelper.displayError(); 173 - }, 174 - }, 310 + eventSources: [ 311 + ## Source where the xwiki events are stored. 312 + { 313 + url: "$!escapetool.javascript($jsonUrl)", 314 + type: 'GET', 315 + data: function() { 316 + // as we also get called before the calendar is fully initialized 317 + // we cannot get the current view reliably from the calendar itself 318 + // instead use our trusty helper 319 + return jQuery.extend(defaultEventData, {'outputView': XWiki.MoccaCalendar.Helper.getCalendarView(defaultView)} ); 320 + }, 321 + error: function() { 322 + calendarHelper.displayError(); 323 + }, 324 + traditional: true 325 + } 326 + ## Subscribed iCal sources 327 + #if($subscribediCal) 328 + , 329 + #handleICalSources($subscribediCal, $subscribedColor, $subscribedTextColor) 330 + #end 331 + ## Subscribed Google Calendar sources 332 + #if($!subscribedgCals != "") 333 + , 334 + #handleGoogleCalendarSources($subscribedgCals, $gApiKeySubscribed, $subscribedColor, $subscribedTextColor) 335 + #end 336 + ## Global events 337 + #if($doc.getFullName() == 'MoccaCalendar.WebHome') 338 + #getSubscribedCalendars() 339 + #foreach($property in $properties) 340 + , 341 + #handleICalSources($property['iCal'], $property['color'], $property['textColor']) 342 + , 343 + #handleGoogleCalendarSources($property['gCal'], $property['gApiKey'], $property['color'], $property['textColor']) 344 + #end 345 + #end 346 + ## In case the user uses the calendar macro directly and dosen't use the UI to create it. 347 + ## iCal sources 348 + #if($!iCal != "") 349 + , 350 + #handleICalSources($iCal 'black') 351 + #end 352 + ## Google Calendar public sources 353 + #if($!gCal != "") 354 + , 355 + #handleGoogleCalendarSources($gCal $gApiKey 'blue') 356 + #end 357 + ], 175 175 eventClick: function(calEvent, jsEvent, view) { 359 + // Prepare the read only events for the modal. 360 + if (!calEvent.viewUrl){ 361 + // The XWiki default format for date is yyyy/MM/dd, which translates into 2024/01/17. However, for some weird 362 + // reason, when using the date.format() from JavaScript, it translates into 2024/01/Mon. We need to use the 363 + // moment().toMomentFormatString(format) to get the right format. 364 + const dateFormat = moment().toMomentFormatString(calendarHelper.dateFormat); 365 + 366 + // Get the sheet URL. 367 + const sheetURL = new XWiki.Document('MoccaCalendarEventSheet', 'MoccaCalendar').getURL('get'); 368 + // Parameters for the modal content. 369 + const params = { 370 + title: purify.sanitize(calEvent.title), 371 + start: calEvent.start.format(dateFormat), 372 + end: calEvent.end ? calEvent.end.format(dateFormat) : null, 373 + allDay: calEvent.allDay ? "$escapetool.xml($services.localization.render('moccacalendar.subscribedevent.allday.yes'))" : 374 + "$escapetool.xml($services.localization.render('moccacalendar.subscribedevent.allday.no'))", 375 + description: purify.sanitize(calEvent.description), 376 + readOnly: 'true' 377 + }; 378 + const queryString = jQuery.param(params); 379 + const requestURL = `${sheetURL}?${queryString}`; 380 + calEvent.url = requestURL; 381 + calEvent.readOnly=true; 382 + } 176 176 new XWiki.MoccaCalendar.MoccaCalendarPopup({editMode: false, event: calEvent}, calendarHelper); 177 177 jsEvent.preventDefault(); 178 178 return false; ... ... @@ -241,7 +241,7 @@ 241 241 }); 242 242 jQuery('#calendar${calcounter}-btn').click( function(e) { calendarHelper.showCreateEvent(); e.preventDefault(); }); 243 243 // helper to be used in callback above 244 -#set($newPageParams = "template=MoccaCalendar.MoccaCalendarEventTemplate&parentFROM=${escapetool.url($calendarDoc)}&form_token=${services.csrf.getToken()}&ocalcaction=create") 451 +#set($newPageParams = "template=MoccaCalendar.MoccaCalendarEventTemplate&parentFROM=${escapetool.url($calendarDoc)}&form_token=${services.csrf.getToken()}&ocalcaction=create&disabled=$disableCreationEvent") 245 245 #set($randomDocUrl = $xwiki.getURL("randomPage${util.generateRandomString(10)}",'edit',$newPageParams)) 246 246 #set($updateUrlParams="?xpage=plain&outputSyntax=plain&calendarDoc=${escapetool.url(${calendarDoc})}&") 247 247 var calendarHelper = new XWiki.MoccaCalendar.Helper(calendar, ... ... @@ -260,6 +260,7 @@ 260 260 </script> 261 261 #if($calcounter == 0) 262 262 #showDeleteEventsModal 470 + #importCalendarFileModal 263 263 #end 264 264 {{/html}} 265 265 #else ## of #if($xcontext.action=='view') - Standardkategorie
-
... ... @@ -1,1 +1,0 @@ 1 -Content - Default categories
-
... ... @@ -1,0 +1,1 @@ 1 +Content
- XWiki.WikiMacroParameterClass[10]
-
- Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +wikis - Parameter-Beschreibung
-
... ... @@ -1,0 +1,1 @@ 1 +List of wiki identifiers whose events are shown, separated by a comma. If not specified, events of the current wiki are shown. If specified, the calendarDoc and filter parameters are not taken into account. - Parameter verpflichtend
-
... ... @@ -1,0 +1,1 @@ 1 +Nein
- XWiki.WikiMacroParameterClass[11]
-
- Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +gCal - Parameter verpflichtend
-
... ... @@ -1,0 +1,1 @@ 1 +Nein
- XWiki.WikiMacroParameterClass[12]
-
- Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +gApiKey - Parameter verpflichtend
-
... ... @@ -1,0 +1,1 @@ 1 +Nein
- XWiki.WikiMacroParameterClass[13]
-
- Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +iCal - Parameter verpflichtend
-
... ... @@ -1,0 +1,1 @@ 1 +Nein