PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / mvc / admin / views / overrides / tmpl / default_editor.php
vikappointments / libraries / mvc / admin / views / overrides / tmpl Last commit date
default.php 6 days ago default_diff.php 6 days ago default_editor.php 6 days ago default_file.php 6 days ago default_folder.php 6 days ago default_guide.php 6 days ago
default_editor.php
455 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2024 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 $vik = VAPApplication::getInstance();
15
16 ?>
17
18 <style>
19 .vap-overrides-manager .overrides-body .override-file {
20 display: flex;
21 align-items: center;
22 padding: 10px;
23 border-bottom: 1px solid #ccc;
24 }
25 .vap-overrides-manager .overrides-body .override-file #override-options {
26 font-size: 16px;
27 margin-right: 10px;
28 }
29 .vap-overrides-manager .overrides-body .override-file input {
30 flex: 1;
31 margin-right: 4px;
32 }
33
34 .vap-overrides-manager .overrides-body .overrides-differences {
35 border-bottom: 1px solid #ccc;
36 }
37 .vap-overrides-manager .overrides-body .overrides-differences .notice {
38 margin: 10px;
39 }
40
41 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="columns"] {
42 display: flex;
43 flex-wrap: wrap;
44 }
45 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="columns"] > * {
46 width: 50%;
47 box-sizing: border-box;
48 }
49 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="columns"] > *:only-of-type {
50 width: 100%;
51 }
52
53 .vap-overrides-manager .overrides-body .overrides-editor .overrides-editor-default {
54 visibility: hidden;
55 position: fixed;
56 transform: translateX(200%);
57 }
58 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="columns"] .overrides-editor-default,
59 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="rows"] .overrides-editor-default {
60 visibility: visible;
61 position: initial;
62 transform: none;
63 }
64 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="columns"] .overrides-editor-default {
65 border-left: 1px solid #ccc;
66 }
67 .vap-overrides-manager .overrides-body .overrides-editor[data-layout="rows"] .overrides-editor-default {
68 border-top: 1px solid #ccc;
69 }
70
71 .vap-overrides-manager .overrides-body .CodeMirror {
72 height: 100%;
73 }
74 </style>
75
76 <!-- Toolbar -->
77
78 <div class="override-file">
79 <i class="fas fa-cog" id="override-options"></i>
80
81 <input type="text" readonly value="<?php echo $this->escape($this->filters['override']); ?>" />
82
83 <button type="button" class="button" id="override-copy"><?php echo __('Copy'); ?></button>
84 </div>
85
86 <!-- Differences -->
87
88 <div class="overrides-differences" style="display: none;">
89 <?php
90 if (empty($this->filters['differences']))
91 {
92 echo $vik->alert(__('The are no differences among the override and the original file.', 'vikappointments'));
93 }
94 else
95 {
96 echo $this->loadTemplate('diff');
97 }
98 ?>
99 </div>
100
101 <!-- Editor box -->
102
103 <div class="overrides-editor">
104
105 <div class="overrides-editor-code">
106 <?php
107 // Display code mirror editor.
108 // Take the editor outside the form in order to
109 // prevent XSS blocks handled by the browser.
110 echo $vik->getCodeMirror('__code', $this->filters['code']);
111 ?>
112 </div>
113
114 <div class="overrides-editor-default">
115 <?php
116 // Display code mirror editor.
117 // Take the editor outside the form in order to
118 // prevent XSS blocks handled by the browser.
119 echo $vik->getCodeMirror('__default', $this->filters['defaultcode']);
120 ?>
121 </div>
122
123 </div>
124
125 <?php
126 JText::script('VAPCONNECTIONLOSTERROR');
127 JText::script('JLIB_APPLICATION_SAVE_SUCCESS');
128 JText::script('VAPCONFDIALOGMSG');
129 ?>
130
131 <script>
132 (function($) {
133 'use strict';
134
135 $(function() {
136 // mark default editor as readonly
137 Joomla.editors.instances.__default.element.codemirror.setOption('readOnly', true);
138
139 let hasOverride = <?php echo $this->filters['hasoverride'] ? 'true' : 'false'; ?>;
140 let isPublished = <?php echo $this->filters['published'] ? 'true' : 'false'; ?>;
141
142 // implement copy callback
143 $('#override-copy').on('click', function() {
144 // copy path within the clipboard
145 copyToClipboard($(this).prev('input')).then(() => {
146 // display successful message on copy
147 VAPToast.dispatch(new VAPToastMessageOS({
148 body: '<?php echo addslashes(__('Copied!')); ?>',
149 status: VAPToast.SUCCESS_STATUS,
150 delay: 'auto',
151 }));
152 }).catch(() => {
153 // cannot copy
154 VAPToast.dispatch(new VAPToastMessageOS({
155 body: '<?php echo addslashes(__('Cannot copy the files! Please proceed manually.')); ?>',
156 status: VAPToast.ERROR_STATUS,
157 delay: 'auto',
158 }));
159 });
160 });
161
162 let isSaving = false;
163
164 // override click of toolbar button
165 Joomla.submitbutton = (task) => {
166 if (task == 'override.save') {
167 if (isSaving) {
168 // already saving, do not go ahead
169 return false;
170 }
171
172 isSaving = true;
173
174 // extract code from editor
175 let code = Joomla.editors.instances.__code.getValue();
176
177 // build post data object
178 const postData = {
179 code: code,
180 client: '<?php echo addslashes($this->filters['client']); ?>',
181 selectedfile: '<?php echo addslashes($this->filters['file']); ?>',
182 overridefile: '<?php echo base64_encode($this->filters['override']); ?>',
183 status: isPublished || !hasOverride ? 1 : 0,
184 };
185
186 // save code
187 UIAjax.do(
188 'admin-ajax.php?action=vikappointments&task=override.save',
189 postData,
190 (resp) => {
191 // display successful message
192 VAPToast.dispatch(new VAPToastMessageOS({
193 body: Joomla.JText._('JLIB_APPLICATION_SAVE_SUCCESS'),
194 status: VAPToast.SUCCESS_STATUS,
195 delay: 'auto',
196 }));
197
198 if (!hasOverride) {
199 // add override style to file link
200 $('a.file[data-path="' + postData.selectedfile + '"]')
201 .find('i').addClass('has-override');
202
203 // we now have an active override
204 hasOverride = isPublished = true;
205 }
206
207 // no more pending changes after save
208 SOMETHING_HAS_CHANGED = false;
209
210 isSaving = false;
211 },
212 (error) => {
213 // prompt error message
214 VAPToast.dispatch(new VAPToastMessageOS({
215 body: error.responseText || Joomla.JText._('VAPCONNECTIONLOSTERROR'),
216 status: VAPToast.ERROR_STATUS,
217 }));
218
219 isSaving = false;
220 }
221 );
222 } else {
223 // submit form
224 Joomla.submitform(task, document.adminForm);
225 }
226 }
227
228 let layoutMode;
229
230 // retrieve current layout mode from local storage, if suppoered
231 if (typeof Storage !== 'undefined') {
232 layoutMode = localStorage.getItem('overrideLayoutMode');
233
234 // init layout data
235 $('.overrides-editor').attr('data-layout', layoutMode);
236 }
237
238 // layout mode button click implementor
239 const saveOverrideLayoutMode = function(root, event) {
240 // register layout mode
241 layoutMode = this.layoutMode;
242
243 // register layout within the local storage, if supported
244 if (typeof Storage !== 'undefined') {
245 localStorage.setItem('overrideLayoutMode', layoutMode);
246 }
247
248 // apply layout data
249 $('.overrides-editor').attr('data-layout', layoutMode);
250 };
251
252 // check whether the current button is selected
253 const isLayoutModeSelected = function(root, event) {
254 if (this.layoutMode == layoutMode || (!this.layoutMode && !layoutMode)) {
255 return 'fas fa-check';
256 }
257
258 return '';
259 };
260
261 let showDifferences = 0
262
263 if (typeof Storage !== 'undefined') {
264 showDifferences = parseInt(localStorage.getItem('overrideShowDifferences')) || 0;
265 }
266
267 if (showDifferences) {
268 $('.overrides-differences').show();
269 } else {
270 $('.overrides-differences').hide();
271 }
272
273 // set up context menu for layout handling
274 $('#override-options').vikContextMenu({
275 clickable: true,
276 buttons: [
277 // HIDE NAVIGATOR
278 {
279 state: 1,
280 text: '<?php echo addslashes(__('Show files tree', 'vikappointments')); ?>',
281 action: function(root, event) {
282 // get opposite state
283 this.state ^= 1;
284
285 if (this.state) {
286 $('.overrides-navigator').show();
287 } else {
288 $('.overrides-navigator').hide();
289 }
290 },
291 icon: function(root, event) {
292 if (this.state) {
293 return 'fas fa-check';
294 }
295
296 return '';
297 },
298 },
299 // HIDE NAVIGATOR
300 {
301 state: showDifferences,
302 text: '<?php echo addslashes(__('Show differences', 'vikappointments')); ?>',
303 separator: true,
304 action: function(root, event) {
305 // get opposite state
306 this.state ^= 1;
307
308 if (this.state) {
309 $('.overrides-differences').show();
310 } else {
311 $('.overrides-differences').hide();
312 }
313
314 if (typeof Storage !== 'undefined') {
315 localStorage.setItem('overrideShowDifferences', this.state);
316 }
317 },
318 icon: function(root, event) {
319 if (this.state) {
320 return 'fas fa-check';
321 }
322
323 return '';
324 },
325 },
326 // HIDE ORIGINAL CODE
327 {
328 text: '<?php echo addslashes(__('Hide original file', 'vikappointments')); ?>',
329 action: saveOverrideLayoutMode,
330 icon: isLayoutModeSelected,
331 layoutMode: '',
332 },
333 // SHOW IN COLUMNS
334 {
335 text: '<?php echo addslashes(__('Show both in columns', 'vikappointments')); ?>',
336 action: saveOverrideLayoutMode,
337 icon: isLayoutModeSelected,
338 layoutMode: 'columns',
339 },
340 // SHOW IN ROWS
341 {
342 text: '<?php echo addslashes(__('Show one over the other', 'vikappointments')); ?>',
343 action: saveOverrideLayoutMode,
344 icon: isLayoutModeSelected,
345 layoutMode: 'rows',
346 separator: true,
347 },
348 // ACTIVATE
349 {
350 text: '<?php echo addslashes(__('Activate')); ?>',
351 class: 'success',
352 separator: true,
353 action: (root, event) => {
354 // submit form to publish override
355 Joomla.submitbutton('override.publish');
356 },
357 visible: (root, event) => {
358 // display button only in case of deactivated override
359 return hasOverride === true && isPublished === false;
360 },
361 },
362 // DEACTIVATE
363 {
364 text: '<?php echo addslashes(__('Deactivate')); ?>',
365 class: 'warning',
366 separator: true,
367 action: (root, event) => {
368 // submit form to publish override
369 Joomla.submitbutton('override.unpublish');
370 },
371 disabled: (root, event) => {
372 // disable button in case of missing override
373 return hasOverride === false;
374 },
375 visible: (root, event) => {
376 // display button only in case of activated override
377 return hasOverride === true && isPublished === true;
378 },
379 },
380 // SAVE
381 {
382 text: '<?php echo addslashes(__('Save')); ?>',
383 action: (root, event) => {
384 Joomla.submitbutton('override.save');
385 },
386 // Always keep button hidden. Declare it just
387 // to implement the CMD+S shortcut for saving.
388 visible: false,
389 shortcut: (() => {
390 if (window.navigator.platform.match(/^MAC/i)) {
391 // Mac OS
392 return ['meta', 's'];
393 }
394 // Windows
395 return ['ctrl', 's'];
396
397 })(),
398 },
399 // DELETE
400 {
401 icon: 'fas fa-times',
402 text: '<?php echo addslashes(__('Delete')); ?>',
403 class: 'danger',
404 action: (root, event) => {
405 // dispatch confirmation and delete in a thread so that
406 // we can complete the closure of the context menu
407 setTimeout(() => {
408 // ask for a confirmation
409 const r = confirm(Joomla.JText._('VAPCONFDIALOGMSG'));
410
411 // unset flag because we don't care of any pending
412 // changes in case we are going to delete the file
413 SOMETHING_HAS_CHANGED = false;
414
415 if (r) {
416 // delete override
417 Joomla.submitbutton('override.delete');
418 }
419 }, 32);
420 },
421 disabled: (root, event) => {
422 // disable button in case of missing override
423 return hasOverride === false;
424 },
425 },
426 ],
427 });
428
429 // flag used to check whether the code has changed
430 let SOMETHING_HAS_CHANGED = false;
431
432 Joomla.editors.instances.__code.element.codemirror.on('change', () => {
433 // the user change the content of the editor, register flag
434 SOMETHING_HAS_CHANGED = true;
435 });
436
437 // register event to block the user while attempting
438 // to leave the page with pending changes
439 $(window).on('beforeunload', (event) => {
440 // check whether something has changed
441 if (SOMETHING_HAS_CHANGED) {
442 // The translated message is meant to work only
443 // for internal purposes as almost all the browsers
444 // uses their own localised strings.
445 const dialogText = 'Do you want to leave the page? Your changes will be lost if you don\'t save them.';
446
447 event.returnValue = dialogText;
448
449 // return the message to trigger the browser prompt
450 return dialogText;
451 }
452 });
453 });
454 })(jQuery);
455 </script>