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 / admin / layouts / analytics / script.php
vikappointments / admin / layouts / analytics Last commit date
config.php 2 days ago dashboard.php 2 days ago index.html 2 days ago script.php 2 days ago
script.php
326 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 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 /**
15 * Layout variables
16 * -----------------
17 * @var array $dashboard An array
18 */
19 extract($displayData);
20
21 $vik = VAPApplication::getInstance();
22
23 ?>
24
25 <script>
26
27 (function($) {
28 'use strict';
29
30 /**
31 * Prepare any chart to be responsive.
32 */
33 Chart.defaults.global.responsive = true;
34
35 /**
36 * Keep a reference of the widget that was clicked
37 * to update its configuration.
38 *
39 * @var integer
40 */
41 var SELECTED_WIDGET = null;
42
43 /**
44 * A pool containing the active AJAX requests for each
45 * widget, so that we can abort an existing request
46 * before launching a new one.
47 *
48 * @var object
49 */
50 var CHARTS_REQUESTS_POOL = {};
51
52 /**
53 * Opens the inspector to allow the management of the
54 * selected widget.
55 *
56 * @param integer widget The widget ID.
57 *
58 * @return void
59 */
60 const openWidgetConfiguration = (widget) => {
61 SELECTED_WIDGET = widget;
62
63 // open inspector
64 vapOpenInspector('widget-config-inspector');
65 }
66
67 /**
68 * Updates the configuration of the last edited widget.
69 *
70 * @param integer id The widget ID.
71 * @param object config The widget configuration.
72 * @param mixed tmp True to avoid saving the configuration.
73 *
74 * @return void
75 */
76 const updateWidgetContents = (id, config, tmp) => {
77 if (typeof config === 'undefined') {
78 // get widget configuration if not specified
79 config = getWidgetConfig(id);
80 }
81
82 // abort any existing request already made for this widget
83 if (CHARTS_REQUESTS_POOL.hasOwnProperty(id)) {
84 CHARTS_REQUESTS_POOL[id].abort();
85 }
86
87 // keep a reference to the widget
88 var box = $('#widget-' + id);
89
90 // get widget class
91 var widget = box.data('widget');
92
93 // prepare request data
94 Object.assign(config, {
95 id: id,
96 widget: widget,
97 location: 'dashboard',
98 });
99
100 if (tmp) {
101 // skip settings save
102 config.tmp = true;
103 }
104
105 // hide generic error message
106 $(box).find('.widget-error-box').hide();
107 // show widget body
108 $(box).find('.widget-body').show();
109
110 if (WIDGET_PREFLIGHTS.hasOwnProperty(id)) {
111 // let the widget prepares the contents without
112 // waiting for the request completion
113 WIDGET_PREFLIGHTS[id](box, config);
114 }
115
116 // make request to load widget dataset
117 var xhr = UIAjax.do(
118 '<?php echo $vik->ajaxUrl('index.php?option=com_vikappointments&task=analytics.loadwidgetdata'); ?>',
119 config,
120 (resp) => {
121 // delete request from pool
122 delete CHARTS_REQUESTS_POOL[id];
123
124 // check if the widget registered its own update method
125 if (WIDGET_CALLBACKS.hasOwnProperty(id)) {
126 // let the widget callback finalizes the update
127 WIDGET_CALLBACKS[id](box, resp, config);
128 } else {
129 if (typeof resp === 'string') {
130 // replace widget body with returned string/HTML
131 $(box).find('.widget-body').html(resp);
132 }
133 }
134 },
135 (error) => {
136 // delete request from pool
137 delete CHARTS_REQUESTS_POOL[id];
138
139 // hide widget body
140 $(box).find('.widget-body').hide();
141 // show generic error message
142 $(box).find('.widget-error-box').show();
143 }
144 );
145
146 // update request pool
147 CHARTS_REQUESTS_POOL[id] = xhr;
148 }
149
150 /**
151 * Saves the configuration of the last edited widget.
152 *
153 * @param integer id The widget ID.
154 * @param object config The widget configuration.
155 *
156 * @return Promise
157 */
158 const saveWidgetContents = (id, config) => {
159 if (typeof config === 'undefined') {
160 // get widget configuration if not specified
161 config = getWidgetConfig(id);
162 }
163
164 // keep a reference to the widget
165 var box = $('#widget-' + id);
166
167 // get widget class
168 var widget = box.data('widget');
169
170 // prepare request data
171 Object.assign(config, {
172 id: id,
173 widget: widget,
174 location: 'dashboard',
175 });
176
177 // create and return promise
178 return new Promise((resolve, reject) => {
179 // make request to load widget dataset
180 UIAjax.do(
181 '<?php echo $vik->ajaxUrl('index.php?option=com_vikappointments&task=analytics.savewidgetdata'); ?>',
182 config,
183 (resp) => {
184 // saved successfully
185 resolve(resp);
186 },
187 (err) => {
188 // an error occurred
189 reject(err);
190 }
191 );
192 });
193 }
194
195 /**
196 * Make some helper functions accessible from the outside, because
197 * the widgets might need a way to easily refresh their contents.
198 *
199 * @param string method The method to perform.
200 * @param mixed data The data that the method will have to use.
201 *
202 * @return mixed The value returned by the method.
203 */
204 $.vapWidgetDo = (method, data) => {
205 if (typeof method !== 'string') {
206 // invalid method
207 throw 'Invalid method';
208 }
209
210 if (method.match(/^load$/i)) {
211 // load widget configuration, assume data is an integer
212 updateWidgetContents(data);
213 } else if (method.match(/^(refresh|reload)$/i)) {
214 // Refresh widget configuration, assume data is an integer.
215 // Since nothing has changed, do not save the settings.
216 updateWidgetContents(data, undefined, true);
217 } else if (method.match(/^(update|set)$/)) {
218 // update configuration
219 if (updateWidgetConfig(data.id, data.key, data.val)) {
220 // refresh widget contents
221 updateWidgetContents(data.id);
222 }
223 } else if (method.match(/^(save|commit)$/)) {
224 // save configuration, assume data is an integer
225 return saveWidgetContents(data);
226 } else if (method.match(/^(get|config)$/)) {
227 // load configuration, assume data is an integer
228 return getWidgetConfig(data);
229 }
230 };
231
232 /**
233 * Include an helper script to deal with modals.
234 *
235 * @param string method The method to perform.
236 * @param mixed data The data that the method will have to use.
237 *
238 * @return mixed The selected element.
239 */
240 $.fn.vapJModal = function(method, data) {
241 if (typeof method !== 'string') {
242 // invalid method
243 throw 'Invalid method';
244 }
245
246 // immediately exit in case of no element found
247 if ($(this).length == 0) {
248 return this;
249 }
250
251 // extract modal ID
252 let id = $(this).attr('id').replace(/^jmodal-/, '');
253
254 if (method.match(/^(open|show|ease)$/i)) {
255 let url = typeof data === 'object' ? data.url : data;
256 let jqmodal = true;
257
258 // include script to open modal
259 <?php echo $vik->bootOpenModalJS(); ?>
260 } else if (method.match(/^(close|hide|fade|dismiss)$/i)) {
261 // include script to close modal
262 <?php echo $vik->bootDismissModalJS(); ?>
263 }
264
265 return this;
266 };
267
268 $(function() {
269 // open inspector when clicking the config button
270 $('.widget-config-btn').on('click', function() {
271 openWidgetConfiguration($(this).data('id'));
272 });
273
274 // fill the form before showing the inspector
275 $('#widget-config-inspector').on('inspector.show', function() {
276 setupWidgetConfig(SELECTED_WIDGET);
277 });
278
279 // refresh widget
280 $('#widget-save-config').on('click', function() {
281 // refresh the new contents displayed within the widget
282 $.vapWidgetDo('load', SELECTED_WIDGET);
283
284 // dismiss inspector
285 $('#widget-config-inspector').inspector('dismiss');
286 });
287
288 // handle widget tables ordering
289 $(document).on('click', 'table[data-widget-id] a[data-order-col]', function() {
290 // extract ordering data
291 let col = $(this).data('order-col');
292 let dir = $(this).data('order-dir');
293
294 // find widget ID
295 let id = $(this).closest('table').data('widget-id');
296
297 // manually update setting
298 $.vapWidgetDo('update', {
299 id: id,
300 key: 'ordering',
301 val: [col, dir].join('.')
302 });
303
304 return false;
305 });
306
307 <?php
308 // iterate dashboard widgets
309 foreach ($dashboard as $widgets)
310 {
311 // iterate position widgets
312 foreach ($widgets as $widget)
313 {
314 // Load widget contents once the page is ready.
315 // Avoid to save the settings at the first widget load.
316 ?>
317 updateWidgetContents('<?php echo $widget->getID(); ?>', undefined, true);
318 <?php
319 }
320 }
321 ?>
322 });
323 })(jQuery);
324
325 </script>
326