Ä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
Änderungskommentar: Migrated property [defaultCategories] from class [XWiki.WikiMacroClass]
Auf Version 6.1
bearbeitet von xwikiadmin
am 2025/01/07 11:32
Änderungskommentar: Install extension [com.xwiki.mocca-calendar:application-mocca-calendar-ui/2.15]

Zusammenfassung

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 - * Deleting an event
760 + * 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">&times;</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