PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / views / dashboard / tmpl / default_widgets.php

default_widgets.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/views/dashboard/tmpl/default_widgets.php

1,345 lines 57.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Always check for customer records with a "short" PIN code to suggest normalization.
15 *
16 * @since 1.18.6 (J) - 1.8.6 (WP)
17 * @since 1.18.7 (J) - 1.8.7 (WP) enforcement for urgent normalization.
18 */
19 if (VikBooking::getCPinInstance()->countShortPins()) {
20 // access last alert date
21 $config = VBOFactory::getConfig();
22 $warn_last_ts = (int) $config->get('warn_cpin_ts', 0);
23 if ($warn_last_ts && (time() - $warn_last_ts) > (86400 * 2)) {
24 // enforce urgent normalization
25 $config->set('warn_cpin_ts', 0);
26 JFactory::getApplication()->redirect(
27 VBOFactory::getPlatform()->getUri()->addCSRF('index.php?option=com_vikbooking&task=maintenance.normalize_short_pins', $xhtml = false)
28 );
29 JFactory::getApplication()->close();
30 }
31 // update last alert date
32 $config->set('warn_cpin_ts', time());
33 // display alert message with button to normalize records
34 JFactory::getApplication()->enqueueMessage(sprintf(
35 '%s <a class="btn btn-warning" href="%s">%s</a>',
36 JText::translate('VBO_CUSTOMERS_SHORT_PIN_ALERT'),
37 VBOFactory::getPlatform()->getUri()->addCSRF('index.php?option=com_vikbooking&task=maintenance.normalize_short_pins', $xhtml = true),
38 JText::translate('VBADMINNOTESUPD')
39 ), 'warning');
40 }
41
42 $vbo_app = VikBooking::getVboApplication();
43
44 // get admin widgets helper
45 $widgets_helper = VikBooking::getAdminWidgetsInstance();
46 $widgets_map = $widgets_helper->getWidgetsMap();
47
48 // get all widgets by preloading their assets (if any)
49 $widgets_names = $widgets_helper->getWidgetNames($preload = true);
50
51 $widgets_welcome = $widgets_helper->showWelcome();
52
53 // global permissions are necessary to customize the admin widgets
54 $vbo_auth_global = JFactory::getUser()->authorise('core.vbo.global', 'com_vikbooking');
55
56 // check if the notification audio file exists within VCM
57 $notif_audio_path = implode(DIRECTORY_SEPARATOR, [VCM_ADMIN_PATH, 'assets', 'css', 'audio', 'new_notification.mp3']);
58 $notif_audio_url = is_file($notif_audio_path) ? (VCM_ADMIN_URI . implode('/', ['assets', 'css', 'audio', 'new_notification.mp3'])) : null;
59
60 // theme color preferences
61 $color_scheme = VikBooking::getAppearancePref();
62 $scheme_name = JText::translate('VBO_APPEARANCE_PREF_AUTO');
63 $current_mode = 'magic';
64 if ($color_scheme == 'light') {
65 $scheme_name = JText::translate('VBO_APPEARANCE_PREF_LIGHT');
66 $current_mode = 'sun';
67 } elseif ($color_scheme == 'dark') {
68 $scheme_name = JText::translate('VBO_APPEARANCE_PREF_DARK');
69 $current_mode = 'moon';
70 }
71
72 // load sortable library
73 JHtml::fetch('jquery.framework', true, true);
74 JHtml::fetch('script', VBO_SITE_URI.'resources/jquery-ui.sortable.min.js');
75
76 // load language vars for JavaScript
77 JText::script('VBO_WIDGETS_WELCOME');
78 JText::script('VBO_WIDGETS_ADDWIDGCONT');
79 JText::script('VBO_WIDGETS_RESTDEFAULT');
80 JText::script('VBO_WIDGETS_ADDNEWWIDG');
81 JText::script('VBO_WIDGETS_SAVINGMAP');
82 JText::script('VBO_WIDGETS_ERRSAVINGMAP');
83 JText::script('VBO_WIDGETS_LASTUPD');
84 JText::script('VBO_WIDGETS_ENTERSECTNAME');
85 JText::script('VBO_WIDGETS_NEWSECT');
86 JText::script('VBO_WIDGETS_CONFRMELEM');
87 JText::script('VBO_WIDGETS_SELCONTSIZE');
88 JText::script('VBO_WIDGETS_UPDWIDGCONT');
89 JText::script('VBO_WIDGETS_EDITWIDGCONT');
90 JText::script('VBO_WIDGETS_ERRDISPWIDG');
91 JText::script('VBO_STICKYN_TITLE');
92 JText::script('VBO_STICKYN_TEXT');
93 JText::script('VBO_STICKYN_TEXT2');
94 JText::script('VBO_STICKYN_CUSTOMURI');
95 JText::script('VBO_BROWSER_NOTIFS_ON');
96 JText::script('VBO_BROWSER_NOTIFS_OFF');
97 JText::script('VBO_BROWSER_NOTIFS_OFF_HELP');
98 JText::script('VBO_ADMIN_WIDGET');
99 JText::script('VBO_CONGRATS');
100 JText::script('VBO_APPEARANCE_PREF_AUTO');
101 JText::script('VBO_APPEARANCE_PREF_LIGHT');
102 JText::script('VBO_APPEARANCE_PREF_DARK');
103
104 /**
105 * Monitor request vars to see if a widget should be loaded within a modal.
106 * Only the dashboard at the moment allows to render an admin widget within
107 * a modal through query string values, because all other pages will render
108 * the multitask panel that can quickly render any admin widget.
109 *
110 * @since 1.16.0 (J) - 1.6.0 (WP)
111 * @since 1.16.5 (J) - 1.6.5 (WP) added payload support for clicked Push notifications.
112 */
113 $app = JFactory::getApplication();
114
115 $load_widget = $app->input->get('load_widget', '');
116 $multitask_data = $app->input->get('multitask_data', [], 'array');
117 $multitask_options = [];
118 $push_notification = $app->input->get('push_notification', '', 'base64');
119 if (!$load_widget && $push_notification) {
120 // parse the payload to detect the proper type of widget to render
121 list($load_widget, $multitask_data, $multitask_options) = VBOMultitaskParser::queryPushData($multitask_data, base64_decode($push_notification));
122 }
123
124 // process widget data, if any
125 if (!empty($load_widget) && $desired_widget = $widgets_helper->getWidget($load_widget)) {
126 $multitask_data['_modalTitle'] = $desired_widget->getName();
127 $data_payload = json_encode($multitask_data);
128 $options_payload = json_encode($multitask_options);
129
130 // append script to DOM to render the widget within a modal
131 JFactory::getDocument()->addScriptDeclaration(
132 <<<JS
133 (function($) {
134 'use strict';
135
136 $(function() {
137 setTimeout(() => {
138 VBOCore.renderModalWidget('$load_widget', $data_payload, $options_payload, false);
139 }, 500);
140 });
141 })(jQuery);
142 JS
143 );
144 }
145
146 ?>
147 <div class="vbo-admin-widgets-wrap">
148 <?php
149 if ($vbo_auth_global) {
150 ?>
151 <div class="vbo-admin-widgets-commands">
152 <div class="vbo-admin-widgets-commands-info" data-vbomanagewidgets="1" style="display: none;">
153 <div class="vbo-admin-widgets-commands-info-inner">
154 <span class="vbo-admin-widgets-commands-info-txt"><?php echo JText::translate('VBO_WIDGETS_AUTOSAVE'); ?></span>
155 <div class="vbo-admin-widgets-commands-info-restore">
156 <a href="index.php?option=com_vikbooking&task=reset_admin_widgets" class="btn btn-secondary" onclick="return vboWidgetsRestoreMap();"><?php echo JText::translate('VBO_WIDGETS_RESTDEFAULTSHORT'); ?></a>
157 </div>
158 <div class="vbo-sidepanel-colorscheme vbo-dashboard-colorscheme">
159 <span class="vbo-tooltip vbo-tooltip-top vbo-sidepanel-colorscheme-current" data-tooltiptext="<?php echo JHtml::fetch('esc_attr', $scheme_name); ?>"><?php VikBookingIcons::e($current_mode); ?></span>
160 <div class="vbo-sidepanel-colorscheme-list">
161 <div class="vbo-sidepanel-colorscheme-option<?php echo $color_scheme == 'auto' ? ' vbo-sidepanel-colorscheme-option-active' : ''; ?>" data-scheme="auto">
162 <span><?php VikBookingIcons::e('magic'); ?> <?php echo JText::translate('VBO_APPEARANCE_PREF_AUTO'); ?></span>
163 </div>
164 <div class="vbo-sidepanel-colorscheme-option<?php echo $color_scheme == 'light' ? ' vbo-sidepanel-colorscheme-option-active' : ''; ?>" data-scheme="light">
165 <span><?php VikBookingIcons::e('sun'); ?> <?php echo JText::translate('VBO_APPEARANCE_PREF_LIGHT'); ?></span>
166 </div>
167 <div class="vbo-sidepanel-colorscheme-option<?php echo $color_scheme == 'dark' ? ' vbo-sidepanel-colorscheme-option-active' : ''; ?>" data-scheme="dark">
168 <span><?php VikBookingIcons::e('moon'); ?> <?php echo JText::translate('VBO_APPEARANCE_PREF_DARK'); ?></span>
169 </div>
170 </div>
171 </div>
172 <div class="vbo-admin-widgets-suggest-notifications-cont" style="display: none;">
173 <span class="vbo-suggest-notifications-wrap">
174 <button class="vbo-dash-suggest-notifications-btn vbo-suggest-notifications-btn" type="button"><?php VikBookingIcons::e('bell', 'can-shake') ?></button>
175 </span>
176 </div>
177 </div>
178 </div>
179 <div class="vbo-admin-widgets-commands-mng">
180 <span class="vbo-admin-widgets-commands-mng-toggle"><?php echo $vbo_app->printYesNoButtons('vbocustwidgets', JText::translate('VBYES'), JText::translate('VBNO'), 0, 1, 0, 'vboWidgetsToggleManage(false);'); ?></span>
181 <span class="vbo-admin-widgets-commands-mng-lbl" onclick="vboWidgetsToggleManage(true);"><?php VikBookingIcons::e('cogs'); ?> <?php echo JText::translate('VBO_WIDGETS_CUSTWIDGETS'); ?></span>
182 </div>
183 </div>
184 <?php
185 }
186 ?>
187 <div class="vbo-admin-widgets-list">
188 <?php
189 foreach ($widgets_map->sections as $seck => $section) {
190 ?>
191 <div class="vbo-admin-widgets-section">
192 <div class="vbo-admin-widgets-section-name" data-vbomanagewidgets="1" style="display: none;">
193 <span class="vbo-admin-widgets-elem-cmds-drag"><?php VikBookingIcons::e('ellipsis-v'); ?></span>
194 <span class="vbo-admin-widgets-section-name-val"><?php echo $section->name; ?></span>
195 <div class="vbo-admin-widget-elem-cmds vbo-admin-widgets-section-cmds">
196 <span class="vbo-admin-widgets-elem-cmds-edit" onclick="vboWidgetsEditSection(this);"><?php VikBookingIcons::e('edit'); ?></span>
197 <span class="vbo-admin-widgets-elem-cmds-remove" onclick="vboWidgetsRemoveSection(this);"><?php VikBookingIcons::e('trash'); ?></span>
198 </div>
199 </div>
200 <?php
201 if (!isset($section->containers)) {
202 $section->containers = array();
203 }
204 $tot_containers = count($section->containers);
205 foreach ($section->containers as $conk => $container) {
206 $container_css = $widgets_helper->getContainerCssClass($container->size);
207 ?>
208 <div class="vbo-admin-widgets-container <?php echo $container_css; ?>" data-vbowidgetcontsize="<?php echo $container->size; ?>" data-totcontainers="<?php echo $tot_containers; ?>">
209 <div class="vbo-admin-widgets-container-name" data-vbomanagewidgets="1" style="display: none;">
210 <span class="vbo-admin-widgets-container-name-val"><?php echo $widgets_helper->getContainerName($container->size); ?></span>
211 <div class="vbo-admin-widget-elem-cmds vbo-admin-widgets-container-cmds">
212 <span class="vbo-admin-widgets-elem-cmds-edit" onclick="vboWidgetsEditContainer(this);"><?php VikBookingIcons::e('edit'); ?></span>
213 <span class="vbo-admin-widgets-elem-cmds-remove" onclick="vboWidgetsRemoveContainer(this);"><?php VikBookingIcons::e('trash'); ?></span>
214 </div>
215 </div>
216 <?php
217 if (!isset($container->widgets)) {
218 $container->widgets = array();
219 }
220 foreach ($container->widgets as $widk => $widget_id) {
221 $widget_instance = $widgets_helper->getWidget($widget_id);
222 if ($widget_instance === false) {
223 continue;
224 }
225 ?>
226 <div class="vbo-admin-widgets-widget" data-vbowidgetid="<?php echo $widget_instance->getIdentifier(); ?>">
227 <div class="vbo-admin-widgets-widget-info" data-vbomanagewidgets="1" style="display: none;">
228 <div class="vbo-admin-widgets-widget-info-inner">
229 <div class="vbo-admin-widgets-widget-details">
230 <span class="vbo-admin-widgets-widget-info-drag"><?php VikBookingIcons::e('ellipsis-v'); ?></span>
231 <h4 class="vbo-admin-widgets-widget-info-name">
232 <span><?php echo $widget_instance->getName(); ?></span>
233 <span class="vbo-admin-widgets-widget-remove" onclick="vboWidgetsRemoveWidget(this);"><?php VikBookingIcons::e('trash'); ?></span>
234 </h4>
235 </div>
236 <div class="vbo-admin-widgets-widget-info-descr"><?php echo $widget_instance->getDescription(); ?></div>
237 </div>
238 </div>
239 <div class="vbo-admin-widgets-widget-output">
240 <?php $widget_instance->render(); ?>
241 </div>
242 </div>
243 <?php
244 }
245 ?>
246 <div class="vbo-admin-widgets-widget vbo-admin-widgets-widget-addnew" data-vbomanagewidgets="1" style="display: none;">
247 <div class="vbo-admin-widgets-plus-box" onclick="vboWidgetsAddWidget(this);">
248 <span><?php VikBookingIcons::e('plus-circle'); ?></span>
249 </div>
250 </div>
251 </div>
252 <?php
253 }
254 ?>
255 <div class="vbo-admin-widgets-container vbo-admin-widgets-container-addnew" data-vbomanagewidgets="1" style="display: none;">
256 <div class="vbo-admin-widgets-plus-box" onclick="vboWidgetsAddContainer(this);">
257 <span><?php VikBookingIcons::e('plus-circle'); ?></span>
258 </div>
259 </div>
260 </div>
261 <?php
262 }
263 ?>
264 <div class="vbo-admin-widgets-section vbo-admin-widgets-section-addnew" data-vbomanagewidgets="1" style="display: none;">
265 <div class="vbo-admin-widgets-plus-box" onclick="vboWidgetsAddSection();">
266 <span><?php VikBookingIcons::e('plus-circle'); ?></span>
267 </div>
268 </div>
269 </div>
270 </div>
271
272 <div class="vbo-modal-overlay-block vbo-modal-overlay-block-dashwidgets">
273 <a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
274 <div class="vbo-modal-overlay-content vbo-modal-overlay-content-dashwidgets">
275 <div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-dashwidgets">
276 <h3><span id="vbo-modal-widgets-title"></span> <span class="vbo-modal-overlay-close-times" onclick="hideVboModalWidgets();">&times;</span></h3>
277 </div>
278 <div class="vbo-modal-overlay-content-body vbo-modal-overlay-content-body-scroll">
279 <div class="vbo-modal-widgets-newcontainer vbo-modal-widgets-forms" style="display: none;">
280 <div class="vbo-modal-widgets-form-data-fields">
281 <div class="vbo-modal-widgets-form-data-field">
282 <label for="vbo-newcontainer-size"><?php echo JText::translate('VBO_WIDGETS_CONTSIZE'); ?></label>
283 <select id="vbo-newcontainer-size">
284 <?php
285 foreach ($widgets_helper->getContainerClassNames() as $class_key => $class_name_data) {
286 ?>
287 <option value="<?php echo $class_key; ?>" data-cssclass="<?php echo $class_name_data['css']; ?>"><?php echo $class_name_data['name']; ?></option>
288 <?php
289 }
290 ?>
291 </select>
292 <input type="hidden" id="vbo-newcontainer-upd" value="0" />
293 </div>
294 </div>
295 </div>
296 <div class="vbo-modal-widgets-newwidget vbo-modal-widgets-forms" style="display: none;">
297 <div class="vbo-modal-widgets-form-data-fields">
298 <div class="vbo-modal-widgets-form-data-field">
299 <label><?php echo JText::translate('VBO_WIDGETS_SELWIDGADD'); ?></label>
300 </div>
301 <div class="vbo-modal-widgets-form-data-field vbo-modal-widgets-list">
302 <input type="hidden" id="vbo-newwidget-id" value="" />
303 <?php
304 foreach ($widgets_names as $widget_data) {
305 ?>
306 <div class="vbo-modal-widget-wrap vbo-admin-widget-style-<?php echo $widget_data->style; ?>" data-vbowidgetid="<?php echo $widget_data->id; ?>" onclick="vboWidgetsSelectWidget('<?php echo $widget_data->id; ?>');">
307 <div class="vbo-modal-widget-cont-top">
308 <div class="vbo-modal-widget-icon">
309 <span><?php echo $widget_data->icon; ?></span>
310 </div>
311 <div class="vbo-modal-widget-add">
312 <span onclick="vboWidgetsAddWidgetToDoc('<?php echo $widget_data->id; ?>');"><?php VikBookingIcons::e('plus-circle'); ?></span>
313 </div>
314 </div>
315 <div class="vbo-modal-widget-cont-main">
316 <div class="vbo-modal-widget-name">
317 <span><?php echo $widget_data->name; ?></span>
318 </div>
319 <div class="vbo-modal-widget-descr">
320 <span><?php echo $widget_data->descr; ?></span>
321 </div>
322 </div>
323 </div>
324 <?php
325 }
326 ?>
327 </div>
328 <div class="vbo-modal-widgets-form-data-field vbo-newwidget-descr" style="display: none;"></div>
329 </div>
330 </div>
331 <?php
332 if ($widgets_welcome) {
333 ?>
334 <div class="vbo-widgets-welcome-wrap vbo-modal-widgets-forms" style="display: none;">
335 <div class="vbo-widgets-welcome-inner">
336 <p><?php echo JText::translate('VBO_WIDGETS_WELCOME_DESC1'); ?></p>
337 <p><?php echo JText::translate('VBO_WIDGETS_WELCOME_DESC2'); ?></p>
338 <div class="vbo-widgets-welcome-demo">
339 <div class="vbo-widgets-welcome-demo-section">
340 <span class="vbo-widgets-welcome-demo-section-lbl"><?php echo JText::translate('VBO_WIDGETS_NEWSECT'); ?></span>
341 <div class="vbo-widgets-welcome-demo-container">
342 <span class="vbo-widgets-welcome-demo-container-lbl"><?php echo JText::translate('VBO_WIDGETS_ADDWIDGCONT'); ?></span>
343 <div class="vbo-widgets-welcome-demo-widget">
344 <span class="vbo-widgets-welcome-demo-widget-lbl"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_WIDGETS_ADDNEWWIDG'); ?></span>
345 </div>
346 </div>
347 <div class="vbo-widgets-welcome-demo-container">
348 <span class="vbo-widgets-welcome-demo-container-lbl"><?php echo JText::translate('VBO_WIDGETS_ADDWIDGCONT'); ?></span>
349 <div class="vbo-widgets-welcome-demo-widget">
350 <span class="vbo-widgets-welcome-demo-widget-lbl"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_WIDGETS_ADDNEWWIDG'); ?></span>
351 </div>
352 </div>
353 </div>
354 </div>
355 </div>
356 </div>
357 <?php
358 }
359 ?>
360 </div>
361 <div class="vbo-modal-overlay-content-footer">
362 <div class="vbo-modal-footer-newcontainer vbo-modal-widgets-forms-footer" style="display: none;">
363 <div class="vbo-modal-overlay-content-footer-right">
364 <button type="button" class="btn btn-success" id="vbo-newcontainer-btn" onclick="vboWidgetsAddContainerToDoc();"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_WIDGETS_ADDWIDGCONT'); ?></button>
365 </div>
366 </div>
367 <div class="vbo-modal-footer-newwidget vbo-modal-widgets-forms-footer" style="display: none;">
368 <div class="vbo-modal-overlay-content-footer-right">
369 <button type="button" class="btn btn-success" onclick="vboWidgetsAddWidgetToDoc();"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_WIDGETS_ADDNEWWIDG'); ?></button>
370 </div>
371 </div>
372 <div class="vbo-modal-footer-welcome vbo-modal-widgets-forms-footer" style="display: none;">
373 <div class="vbo-modal-overlay-content-footer-left">
374 <button type="button" class="btn btn-secondary" onclick="vboWidgetsCloseWelcome(1);"><?php echo JText::translate('VBOBTNDONTREMIND'); ?></button>
375 </div>
376 <div class="vbo-modal-overlay-content-footer-right">
377 <button type="button" class="btn btn-success" onclick="vboWidgetsCloseWelcome(0);"><?php echo JText::translate('VBOBTNKEEPREMIND'); ?></button>
378 </div>
379 </div>
380 </div>
381 </div>
382 </div>
383
384 <script type="text/javascript">
385 /**
386 * Declare global scope variables.
387 */
388 var vbo_admin_widgets_map = <?php echo json_encode($widgets_map); ?>;
389 var vbo_admin_widgets_names = <?php echo json_encode($widgets_names); ?>;
390
391 var vbo_admin_widgets_last_section = null,
392 vbo_admin_widgets_last_container = null,
393 vbo_admin_widgets_initpos_section = 0,
394 vbo_admin_widgets_initpos_container = 0,
395 vbo_admin_widgets_initpos_widget = 0,
396 vbo_admin_widgets_initinst_widget = -1,
397 vbo_admin_widgets_allow_drop = false,
398 vbo_admin_widgets_sugg_notifs = false;
399
400 var vbo_modal_widgets_on = false;
401
402 var vbo_admin_widgets_welcome = <?php echo $widgets_welcome ? 'true' : 'false'; ?>;
403
404 /**
405 * Shows the modal window
406 */
407 function vboOpenModalWidgets() {
408 jQuery('.vbo-modal-overlay-block-dashwidgets').show();
409 vbo_modal_widgets_on = true;
410 }
411
412 /**
413 * Hides the modal window
414 */
415 function hideVboModalWidgets() {
416 if (vbo_modal_widgets_on === true) {
417 jQuery(".vbo-modal-overlay-block-dashwidgets").fadeOut(400, function() {
418 jQuery(".vbo-modal-overlay-content-dashwidgets").show();
419 jQuery(".vbo-modal-widgets-forms").hide();
420 jQuery(".vbo-modal-widgets-forms-footer").hide();
421 });
422 // turn flag off
423 vbo_modal_widgets_on = false;
424 }
425 }
426
427 /**
428 * Toggles the widget customizer mode
429 */
430 function vboWidgetsToggleManage(trigger) {
431 if (trigger === true) {
432 jQuery('input[name="vbocustwidgets"]').trigger('click');
433 return;
434 }
435 if (!jQuery('input[name="vbocustwidgets"]').is(':checked')) {
436 jQuery('div[data-vbomanagewidgets="1"]').hide();
437 jQuery('.vbo-admin-widgets-widget-output').show();
438 jQuery('.vbo-admin-widgets-list').removeClass('vbo-admin-widgets-list-customize');
439 } else {
440 jQuery('.vbo-admin-widgets-widget-output').hide();
441 jQuery('div[data-vbomanagewidgets="1"]').show();
442 jQuery('.vbo-admin-widgets-list').addClass('vbo-admin-widgets-list-customize');
443 // show welcome (if necessary)
444 vboWidgetsShowWelcome();
445 // handle notification suggestions
446 if (!vbo_admin_widgets_sugg_notifs && VBOCore.notificationsEnabled() === false) {
447 vbo_admin_widgets_sugg_notifs = true;
448 jQuery('.vbo-admin-widgets-suggest-notifications-cont').show();
449 VBOCore.suggestNotifications('.vbo-dash-suggest-notifications-btn');
450 }
451 }
452 }
453
454 /**
455 * Opens the modal window with the welcome message for the admin widgets customizer.
456 */
457 function vboWidgetsShowWelcome() {
458 if (!vbo_admin_widgets_welcome || !jQuery('.vbo-widgets-welcome-wrap').length) {
459 return;
460 }
461 // prevent this from being displayed again in the same page flow
462 vbo_admin_widgets_welcome = false;
463 // display welcome container
464 jQuery('.vbo-widgets-welcome-wrap').show();
465 jQuery('.vbo-modal-footer-welcome').show();
466 // set modal title
467 jQuery('#vbo-modal-widgets-title').text(Joomla.JText._('VBO_WIDGETS_WELCOME'));
468 // display modal
469 vboOpenModalWidgets();
470 // declare timeouts to add the animate class to the welcome elements
471 setTimeout(() => {
472 // animate container
473 jQuery('.vbo-widgets-welcome-demo-section').addClass('vbo-widgets-welcome-animate');
474 }, 1000);
475 setTimeout(() => {
476 // animate first section
477 jQuery('.vbo-widgets-welcome-demo-container').first().addClass('vbo-widgets-welcome-animate');
478 }, 2000);
479 setTimeout(() => {
480 // animate last section
481 jQuery('.vbo-widgets-welcome-demo-container').last().addClass('vbo-widgets-welcome-animate');
482 }, 3000);
483 setTimeout(() => {
484 // animate widgets
485 jQuery('.vbo-widgets-welcome-demo-widget').addClass('vbo-widgets-welcome-animate');
486 }, 4000);
487 }
488
489 /**
490 * Closes the modal window for the welcome text by storing an action.
491 */
492 function vboWidgetsCloseWelcome(hidenext) {
493 // dismiss modal
494 hideVboModalWidgets();
495 // AJAX request to update the welcome status
496 VBOCore.doAjax(
497 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=admin_widgets_welcome'); ?>",
498 {
499 hide_welcome: hidenext,
500 tmpl: "component"
501 },
502 (response) => {
503 try {
504 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
505 if (!obj_res.hasOwnProperty('status')) {
506 // request failed
507 console.error('Could not update welcome status', obj_res);
508 }
509 } catch(err) {
510 console.error('could not parse JSON response when updating the welcome status', err, response);
511 }
512 },
513 (error) => {
514 console.error(error);
515 }
516 );
517 }
518
519 /**
520 * This will fire during the throttle of the save-map event.
521 * Saves the updated admin widgets map onto the database.
522 */
523 function vboHandleMapSaving() {
524 // update info status to "saving..."
525 jQuery('.vbo-admin-widgets-commands-info-txt').removeClass('vbo-admin-widgets-error').html('<?php VikBookingIcons::e('refresh', 'fa-spin fa-fw'); ?> ' + Joomla.JText._('VBO_WIDGETS_SAVINGMAP'));
526
527 // prepare AJAX request data
528 var saving_request = {
529 tmpl: "component"
530 }
531 Object.assign(saving_request, vbo_admin_widgets_map);
532
533 // make the request
534 VBOCore.doAjax(
535 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=save_admin_widgets'); ?>",
536 saving_request,
537 (response) => {
538 try {
539 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
540 if (!obj_res.status) {
541 // request failed
542 console.error('Could not update the map', obj_res);
543 // update info status to "error..."
544 jQuery('.vbo-admin-widgets-commands-info-txt').addClass('vbo-admin-widgets-error').text(Joomla.JText._('VBO_WIDGETS_ERRSAVINGMAP'));
545 } else {
546 // set last updated time
547 var now = new Date;
548 var hours = now.getHours();
549 hours = hours < 10 ? '0' + hours : hours;
550 var minutes = now.getMinutes();
551 minutes = minutes < 10 ? '0' + minutes : minutes;
552 var seconds = now.getSeconds();
553 seconds = seconds < 10 ? '0' + seconds : seconds;
554 var full_time_now = hours + ':' + minutes + ':' + seconds;
555 // update info status to "last update time"
556 jQuery('.vbo-admin-widgets-commands-info-txt').removeClass('vbo-admin-widgets-error').html('<?php VikBookingIcons::e('check-circle'); ?> ' + Joomla.JText._('VBO_WIDGETS_LASTUPD') + ': ' + full_time_now);
557 }
558 } catch(err) {
559 console.error('could not parse JSON response when updating the map', err, response);
560 // update info status to "error..."
561 jQuery('.vbo-admin-widgets-commands-info-txt').addClass('vbo-admin-widgets-error').text(Joomla.JText._('VBO_WIDGETS_ERRSAVINGMAP'));
562 }
563 },
564 (error) => {
565 console.error(error.responseText);
566 // update info status to "error..."
567 jQuery('.vbo-admin-widgets-commands-info-txt').addClass('vbo-admin-widgets-error').text(Joomla.JText._('VBO_WIDGETS_ERRSAVINGMAP'));
568 }
569 );
570 }
571
572 /**
573 * Makes all sections sortable. Do not use .disableSelection() or this
574 * will break all [contenteditable] elements and their focus/selection events.
575 */
576 function vboMakeSectionsSortable() {
577 jQuery('.vbo-admin-widgets-list').sortable({
578 axix: 'x',
579 cursor: 'move',
580 handle: '.vbo-admin-widgets-section-name .vbo-admin-widgets-elem-cmds-drag',
581 items: '.vbo-admin-widgets-section:not(.vbo-admin-widgets-section-addnew)',
582 revert: false,
583 start: function(event, ui) {
584 // update global initial position for section
585 vbo_admin_widgets_initpos_section = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(jQuery(ui.item));
586 },
587 update: function(event, ui) {
588 var new_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(jQuery(ui.item));
589 // update global map object - move originial section to new position
590 vbo_admin_widgets_map.sections.splice(new_sect_index, 0, vbo_admin_widgets_map.sections.splice(vbo_admin_widgets_initpos_section, 1)[0]);
591
592 // trigger the save-map event
593 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
594 }
595 });
596 }
597
598 /**
599 * Makes all widgets sortable. Do not use .disableSelection() or this
600 * will break all [contenteditable] elements and their focus/selection events.
601 */
602 function vboMakeWidgetsSortable() {
603 jQuery('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').sortable({
604 connectWith: '.vbo-admin-widgets-container:not(.vbo-admin-widgets-container-addnew)',
605 cursor: 'move',
606 dropOnEmpty: true,
607 handle: '.vbo-admin-widgets-widget-details .vbo-admin-widgets-widget-info-drag',
608 helper: 'clone',
609 items: '.vbo-admin-widgets-widget:not(.vbo-admin-widgets-widget-addnew)',
610 placeholder: 'vbo-admin-widgets-container-tmpdrop',
611 revert: false,
612 start: function(event, ui) {
613 // allow drop
614 vbo_admin_widgets_allow_drop = true;
615 // calculate initial positions
616 var initial_widget = jQuery(ui.item);
617 var initial_section = initial_widget.closest('.vbo-admin-widgets-section');
618 var initial_container = initial_widget.closest('.vbo-admin-widgets-container');
619 // update global initial position for section
620 vbo_admin_widgets_initpos_section = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(initial_section);
621 // update global initial position for container
622 vbo_admin_widgets_initpos_container = initial_section.find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').index(initial_container);
623 // update global initial position for widget
624 vbo_admin_widgets_initpos_widget = initial_container.find('.vbo-admin-widgets-widget').not('.vbo-admin-widgets-widget-addnew').index(initial_widget);
625 // update global initial instance index for this type of widget
626 var widget_type = initial_widget.attr('data-vbowidgetid');
627 vbo_admin_widgets_initinst_widget = jQuery('.vbo-admin-widgets-widget[data-vbowidgetid="' + widget_type + '"]').index(initial_widget);
628 },
629 update: function(event, ui) {
630 var dropped_widget = jQuery(ui.item);
631 var dropped_section = dropped_widget.closest('.vbo-admin-widgets-section');
632 var dropped_container = dropped_widget.closest('.vbo-admin-widgets-container');
633 // calculate new element positions
634 var new_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(dropped_section);
635 var new_cont_index = dropped_section.find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').index(dropped_container);
636 var new_widg_index = dropped_container.find('.vbo-admin-widgets-widget').not('.vbo-admin-widgets-widget-addnew').index(dropped_widget);
637
638 if (new_sect_index != vbo_admin_widgets_initpos_section || new_cont_index != vbo_admin_widgets_initpos_container) {
639 /**
640 * Widget has been moved to a connected list, to a different section or container.
641 * Multiple "update" events will be fired, one for each target, so 2 in total.
642 */
643 if (vbo_admin_widgets_allow_drop !== true) {
644 // both events contain the same dropped target information (ui), so we skip any later event
645 return;
646 }
647
648 // disable drop for any sub-sequent event
649 vbo_admin_widgets_allow_drop = false;
650
651 // update global map object - remove original widget
652 vbo_admin_widgets_map.sections[vbo_admin_widgets_initpos_section]['containers'][vbo_admin_widgets_initpos_container]['widgets'].splice(vbo_admin_widgets_initpos_widget, 1);
653
654 // update global map object - push new widget
655 vbo_admin_widgets_map.sections[new_sect_index]['containers'][new_cont_index]['widgets'].splice(new_widg_index, 0, dropped_widget.attr('data-vbowidgetid'));
656 } else {
657 /**
658 * Widget has been sorted from the same section and container list.
659 * Only one "update" event will be fired.
660 */
661
662 // update global map object - move original widget to new position
663 vbo_admin_widgets_map.sections[vbo_admin_widgets_initpos_section]['containers'][vbo_admin_widgets_initpos_container]['widgets'].splice(
664 new_widg_index,
665 0,
666 vbo_admin_widgets_map.sections[vbo_admin_widgets_initpos_section]['containers'][vbo_admin_widgets_initpos_container]['widgets'].splice(vbo_admin_widgets_initpos_widget, 1)[0]
667 );
668 }
669
670 // calculate new instance index for this type of widget
671 var widget_type = dropped_widget.attr('data-vbowidgetid');
672 var new_instance_index = jQuery('.vbo-admin-widgets-widget[data-vbowidgetid="' + widget_type + '"]').index(dropped_widget);
673 if (vbo_admin_widgets_initinst_widget >= 0 && new_instance_index >= 0 && vbo_admin_widgets_initinst_widget != new_instance_index) {
674 // widget instance index has changed, and since we have multiple instances of this widget, we may need to update its settings
675
676 // the widget method to call
677 var call_method = 'sortInstance';
678 // make a silent call for the widget in case it needs to perform actions when removing an instance
679 VBOCore.doAjax(
680 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=exec_admin_widget'); ?>",
681 {
682 widget_id: widget_type,
683 widget_index_old: vbo_admin_widgets_initinst_widget,
684 widget_index_new: new_instance_index,
685 call: call_method,
686 tmpl: "component"
687 },
688 (response) => {
689 try {
690 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
691 if (!obj_res.hasOwnProperty(call_method)) {
692 console.error('Unexpected JSON response', obj_res);
693 }
694 } catch(err) {
695 console.error('could not parse JSON response', err, response);
696 }
697 },
698 (error) => {
699 console.error(error.responseText);
700 }
701 );
702 }
703
704 // trigger the save-map event
705 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
706
707 }
708 });
709 }
710
711 /**
712 * Declares document ready event processes.
713 */
714 jQuery(function() {
715
716 /**
717 * Dismiss modal window with Esc.
718 */
719 jQuery(document).keydown(function(e) {
720 if (e.keyCode == 27) {
721 if (vbo_modal_widgets_on === true) {
722 hideVboModalWidgets();
723 }
724 }
725 });
726
727 /**
728 * Dismiss modal window by clicking on an external element.
729 */
730 jQuery(document).mouseup(function(e) {
731 if (!vbo_modal_widgets_on) {
732 return;
733 }
734 if (vbo_modal_widgets_on) {
735 var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-dashwidgets");
736 if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
737 hideVboModalWidgets();
738 }
739 }
740 });
741
742 /**
743 * Make all current sections and widgets sortable.
744 */
745 vboMakeSectionsSortable();
746 vboMakeWidgetsSortable();
747
748 /**
749 * Add event listener to the save-map event with debounce handler.
750 */
751 document.addEventListener('vbo-admin-widgets-savemap', VBOCore.debounceEvent(vboHandleMapSaving, 2000));
752
753 /**
754 * Setup browser notifications and admin widgets core features.
755 */
756 VBOCore.setOptions({
757 is_vbo: true,
758 cms: "<?php echo VBOPlatformDetection::isWordPress() ? 'wordpress' : 'joomla'; ?>",
759 widget_ajax_uri: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=exec_admin_widget'); ?>",
760 assets_ajax_uri: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=widgets_get_assets'); ?>",
761 multitask_ajax_uri: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=exec_multitask_widgets'); ?>",
762 watchdata_ajax_uri: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=widgets_watch_data'); ?>",
763 current_page: "dashboard",
764 current_page_uri: "<?php echo htmlspecialchars((string) JUri::getInstance(), ENT_QUOTES); ?>",
765 root_uri: "<?php echo htmlspecialchars(JUri::root(), ENT_QUOTES); ?>",
766 panel_opts: {
767 notif_on_class: "vbo-sidepanel-notifications-on",
768 notif_off_class: "vbo-sidepanel-notifications-off",
769 },
770 notif_audio_url: "<?php echo $notif_audio_url; ?>",
771 tn_texts: {
772 notifs_enabled: Joomla.JText._('VBO_BROWSER_NOTIFS_ON'),
773 notifs_disabled: Joomla.JText._('VBO_BROWSER_NOTIFS_OFF'),
774 notifs_disabled_help: Joomla.JText._('VBO_BROWSER_NOTIFS_OFF_HELP'),
775 admin_widget: Joomla.JText._('VBO_ADMIN_WIDGET'),
776 congrats: Joomla.JText._('VBO_CONGRATS'),
777 },
778 default_loading_body: '<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>',
779 service_worker_path: '<?php echo VBOWebappServiceworker::getUri(); ?>',
780 service_worker_scope: '<?php echo VBOWebappServiceworker::getScope(); ?>',
781 push: <?php echo json_encode(VBOWebappPush::getConfig()); ?>,
782 }).setupNotifications();
783
784 /**
785 * Install Service Worker
786 */
787 VBOCore.installServiceWorker().then((registration) => {
788 VBOCore.handlePushSubscription(registration).then((subscription) => {
789 console.info('Push notifications are enabled');
790 }).catch((error) => {
791 console.warn(error);
792 });
793 }).catch((error) => {
794 console.warn(error);
795 });
796
797 // color scheme preferences
798 jQuery('.vbo-sidepanel-colorscheme-current').on('click', function() {
799 jQuery('.vbo-sidepanel-colorscheme-list').toggleClass('vbo-sidepanel-colorscheme-list-show');
800 });
801
802 // color scheme selection
803 jQuery('.vbo-sidepanel-colorscheme-option').on('click', function() {
804 let set_mode = jQuery(this).attr('data-scheme');
805
806 let vbo_css_base_uri = '<?php echo VBO_ADMIN_URI . (VBOPlatformDetection::isWordPress() ? 'resources/' : '') . 'vbo-appearance-%s.css'; ?>';
807 let vbo_css_base_id = 'vbo-css-appearance-';
808 let vcm_css_base_id = 'vcm-css-appearance-';
809 let vbo_css_modes = {
810 auto: vbo_css_base_uri.replace('%s', 'auto'),
811 dark: vbo_css_base_uri.replace('%s', 'dark'),
812 light: null,
813 };
814 let vbo_mode_texts = {
815 auto: Joomla.JText._('VBO_APPEARANCE_PREF_AUTO'),
816 dark: Joomla.JText._('VBO_APPEARANCE_PREF_DARK'),
817 light: Joomla.JText._('VBO_APPEARANCE_PREF_LIGHT'),
818 };
819 let vbo_mode_icons = {
820 auto: '<?php VikBookingIcons::e('magic') ?>',
821 dark: '<?php VikBookingIcons::e('moon') ?>',
822 light: '<?php VikBookingIcons::e('sun') ?>',
823 };
824
825 if (!vbo_css_modes.hasOwnProperty(set_mode)) {
826 return false;
827 }
828
829 // toggle active class
830 jQuery('.vbo-sidepanel-colorscheme-option').removeClass('vbo-sidepanel-colorscheme-option-active');
831 jQuery(this).addClass('vbo-sidepanel-colorscheme-option-active');
832
833 // adjust current preference content
834 jQuery('.vbo-sidepanel-colorscheme-current')
835 .attr('data-tooltiptext', vbo_mode_texts[set_mode])
836 .html(vbo_mode_icons[set_mode]);
837
838 // set/unset CSS files from DOM
839 for (let app_mode in vbo_css_modes) {
840 if (!vbo_css_modes.hasOwnProperty(app_mode) || !vbo_css_modes[app_mode]) {
841 continue;
842 }
843 if (app_mode == set_mode) {
844 // set this CSS file
845 jQuery('head').append('<link rel="stylesheet" id="' + vbo_css_base_id + app_mode + '" href="' + vbo_css_modes[app_mode] + '" media="all">');
846 } else {
847 // unset this CSS file
848 if (jQuery('link#' + vbo_css_base_id + app_mode).length) {
849 jQuery('link#' + vbo_css_base_id + app_mode).remove();
850 } else if (jQuery('link#' + vbo_css_base_id + app_mode + '-css').length) {
851 // WP framework may add "-css" as suffix to the given ID
852 jQuery('link#' + vbo_css_base_id + app_mode + '-css').remove();
853 }
854 // check if the VCM related CSS file should be unset too
855 if (jQuery('link#' + vcm_css_base_id + app_mode).length) {
856 jQuery('link#' + vcm_css_base_id + app_mode).remove();
857 } else if (jQuery('link#' + vcm_css_base_id + app_mode + '-css').length) {
858 // WP framework may add "-css" as suffix to the given ID
859 jQuery('link#' + vcm_css_base_id + app_mode + '-css').remove();
860 }
861 }
862 }
863
864 // close menu-list
865 jQuery('.vbo-sidepanel-colorscheme-list').removeClass('vbo-sidepanel-colorscheme-list-show');
866
867 // silently update configuration value
868 VBOCore.doAjax(
869 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=configuration.update'); ?>",
870 {
871 settings: {
872 appearance_pref: set_mode,
873 }
874 },
875 (success) => {
876 // do nothing
877 },
878 (error) => {
879 console.error(error);
880 }
881 );
882 });
883
884 });
885
886 /**
887 * Asks for confirmation to restore the default widgets map
888 */
889 function vboWidgetsRestoreMap() {
890 if (confirm(Joomla.JText._('VBO_WIDGETS_RESTDEFAULT'))) {
891 return true;
892 } else {
893 return false;
894 }
895 }
896
897 /**
898 * Adds a new section to the document
899 */
900 function vboWidgetsAddSection() {
901 var tot_sections = jQuery('.vbo-admin-widgets-section').length;
902 var sect_name_new = prompt(Joomla.JText._('VBO_WIDGETS_ENTERSECTNAME'), Joomla.JText._('VBO_WIDGETS_NEWSECT') + ' #' + (tot_sections + 1));
903 if (sect_name_new != null && sect_name_new != '') {
904 var html_section_new = '<div class="vbo-admin-widgets-section" id="vbo-admin-widgets-section-' + (tot_sections + 1) + '">';
905 html_section_new += ' <div class="vbo-admin-widgets-section-name" data-vbomanagewidgets="1">';
906 html_section_new += ' <span class="vbo-admin-widgets-elem-cmds-drag"><?php VikBookingIcons::e('ellipsis-v'); ?></span>';
907 html_section_new += ' <span class="vbo-admin-widgets-section-name-val">' + sect_name_new + '</span>';
908 html_section_new += ' <div class="vbo-admin-widget-elem-cmds vbo-admin-widgets-section-cmds">';
909 html_section_new += ' <span class="vbo-admin-widgets-elem-cmds-edit" onclick="vboWidgetsEditSection(this);"><?php VikBookingIcons::e('edit'); ?></span>';
910 html_section_new += ' <span class="vbo-admin-widgets-elem-cmds-remove" onclick="vboWidgetsRemoveSection(this);"><?php VikBookingIcons::e('trash'); ?></span>';
911 html_section_new += ' </div>';
912 html_section_new += ' </div>';
913 html_section_new += ' <div class="vbo-admin-widgets-container vbo-admin-widgets-container-addnew" data-vbomanagewidgets="1">';
914 html_section_new += ' <div class="vbo-admin-widgets-plus-box" onclick="vboWidgetsAddContainer(this);">';
915 html_section_new += ' <span><?php VikBookingIcons::e('plus-circle'); ?></span>';
916 html_section_new += ' </div>';
917 html_section_new += ' </div>';
918 html_section_new += '</div>';
919 jQuery('.vbo-admin-widgets-section-addnew').before(html_section_new);
920
921 // update global map object
922 vbo_admin_widgets_map.sections.push({
923 name: sect_name_new,
924 containers: []
925 });
926
927 // trigger the save-map event
928 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
929 }
930 }
931
932 /**
933 * Prompts the new section name to update it
934 */
935 function vboWidgetsEditSection(elem) {
936 var cur_sect_name_elm = jQuery(elem).closest('.vbo-admin-widgets-section-name').find('.vbo-admin-widgets-section-name-val');
937 if (!cur_sect_name_elm || !cur_sect_name_elm.length) {
938 console.error('Could not find section to edit');
939 return false;
940 }
941 var cur_sect_name_val = cur_sect_name_elm.text();
942 // find current index of selected section in the map
943 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(jQuery(elem).closest('.vbo-admin-widgets-section'));
944 var sect_name_new = prompt(Joomla.JText._('VBO_WIDGETS_ENTERSECTNAME'), cur_sect_name_val);
945 if (sect_name_new != null && sect_name_new != '') {
946 cur_sect_name_elm.text(sect_name_new);
947 // update global map object
948 vbo_admin_widgets_map.sections[cur_sect_index]['name'] = sect_name_new;
949 // trigger the save-map event
950 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
951 }
952 }
953
954 /**
955 * Asks for confirmation before removing the selected section
956 */
957 function vboWidgetsRemoveSection(elem) {
958 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(jQuery(elem).closest('.vbo-admin-widgets-section'));
959 if (confirm(Joomla.JText._('VBO_WIDGETS_CONFRMELEM'))) {
960 // remove section from document
961 jQuery(elem).closest('.vbo-admin-widgets-section').remove();
962 // update global map object
963 vbo_admin_widgets_map.sections.splice(cur_sect_index, 1);
964 // trigger the save-map event
965 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
966 }
967 }
968
969 /**
970 * Displays the modal window to create a new widgets container
971 */
972 function vboWidgetsAddContainer(elem) {
973 // update last section selected
974 vbo_admin_widgets_last_section = jQuery(elem).closest('.vbo-admin-widgets-section');
975 if (!vbo_admin_widgets_last_section || !vbo_admin_widgets_last_section.length) {
976 // parent section not found
977 console.error('parent section not found for adding a container');
978 return false;
979 }
980 // turn update flag off
981 jQuery('#vbo-newcontainer-upd').val(0);
982 // display new container form
983 jQuery('.vbo-modal-widgets-newcontainer').show();
984 jQuery('.vbo-modal-footer-newcontainer').show();
985 // set new container form button
986 jQuery('#vbo-newcontainer-btn').html('<?php VikBookingIcons::e('plus-circle'); ?> ' + Joomla.JText._('VBO_WIDGETS_ADDWIDGCONT'));
987 // set modal title
988 jQuery('#vbo-modal-widgets-title').text(Joomla.JText._('VBO_WIDGETS_ADDWIDGCONT'));
989 // display modal
990 vboOpenModalWidgets();
991 }
992
993 /**
994 * Adds or updates one widgets container in the document.
995 */
996 function vboWidgetsAddContainerToDoc() {
997 var mode = jQuery('#vbo-newcontainer-upd').val() > 0 ? 'update' : 'new';
998 if (mode == 'new' && (!vbo_admin_widgets_last_section || !vbo_admin_widgets_last_section.length)) {
999 // parent section not found
1000 console.error('parent section not found for adding a container');
1001 return false;
1002 }
1003 if (mode == 'update' && (!vbo_admin_widgets_last_container || !vbo_admin_widgets_last_container.length)) {
1004 // current container not found
1005 console.error('current container not found');
1006 return false;
1007 }
1008
1009 // get new container size and CSS class
1010 var cont_size = jQuery('#vbo-newcontainer-size').val();
1011 var cont_css = jQuery('#vbo-newcontainer-size').find('option:selected').attr('data-cssclass');
1012 var cont_name = jQuery('#vbo-newcontainer-size').find('option:selected').text();
1013 if (!cont_size || !cont_size.length || !cont_css.length) {
1014 console.error('new container size missing');
1015 alert(Joomla.JText._('VBO_WIDGETS_SELCONTSIZE'));
1016 return false;
1017 }
1018
1019 if (mode == 'update') {
1020 // update container class, size and title
1021 vbo_admin_widgets_last_container.removeClass().addClass('vbo-admin-widgets-container ' + cont_css).attr('data-vbowidgetcontsize', cont_size).find('.vbo-admin-widgets-container-name-val').text(cont_name);
1022
1023 // update global map object
1024 var cur_cont_index = vbo_admin_widgets_last_container.closest('.vbo-admin-widgets-section').find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').index(vbo_admin_widgets_last_container);
1025 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(vbo_admin_widgets_last_container.closest('.vbo-admin-widgets-section'));
1026 vbo_admin_widgets_map.sections[cur_sect_index]['containers'][cur_cont_index]['size'] = cont_size;
1027
1028 // trigger the save-map event
1029 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
1030 } else {
1031 // update containers count for a better styling
1032 var all_sect_conts = vbo_admin_widgets_last_section.find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew');
1033 var new_sect_conts = all_sect_conts.length + 1;
1034 all_sect_conts.attr('data-totcontainers', new_sect_conts);
1035
1036 // build new container
1037 var html_container_new = '<div class="vbo-admin-widgets-container ' + cont_css + '" data-vbowidgetcontsize="' + cont_size + '" data-totcontainers="' + new_sect_conts + '">';
1038 html_container_new += ' <div class="vbo-admin-widgets-container-name" data-vbomanagewidgets="1">';
1039 html_container_new += ' <span class="vbo-admin-widgets-container-name-val">' + cont_name + '</span>';
1040 html_container_new += ' <div class="vbo-admin-widget-elem-cmds vbo-admin-widgets-container-cmds">';
1041 html_container_new += ' <span class="vbo-admin-widgets-elem-cmds-edit" onclick="vboWidgetsEditContainer(this);"><?php VikBookingIcons::e('edit'); ?></span>';
1042 html_container_new += ' <span class="vbo-admin-widgets-elem-cmds-remove" onclick="vboWidgetsRemoveContainer(this);"><?php VikBookingIcons::e('trash'); ?></span>';
1043 html_container_new += ' </div>';
1044 html_container_new += ' </div>';
1045 html_container_new += ' <div class="vbo-admin-widgets-widget vbo-admin-widgets-widget-addnew" data-vbomanagewidgets="1">';
1046 html_container_new += ' <div class="vbo-admin-widgets-plus-box" onclick="vboWidgetsAddWidget(this);">';
1047 html_container_new += ' <span><?php VikBookingIcons::e('plus-circle'); ?></span>';
1048 html_container_new += ' </div>';
1049 html_container_new += ' </div>';
1050 html_container_new += '</div>';
1051
1052 // append new container HTML
1053 vbo_admin_widgets_last_section.find('.vbo-admin-widgets-container-addnew').before(html_container_new);
1054
1055 // update global map object
1056 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(vbo_admin_widgets_last_section);
1057 vbo_admin_widgets_map.sections[cur_sect_index]['containers'].push({
1058 size: cont_size,
1059 widgets: []
1060 });
1061
1062 // trigger the save-map event
1063 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
1064 }
1065
1066 // close modal window
1067 hideVboModalWidgets();
1068
1069 // unset last section and container
1070 vbo_admin_widgets_last_section = null;
1071 vbo_admin_widgets_last_container = null;
1072 }
1073
1074 /**
1075 * Displays the modal window for editing the selected container
1076 */
1077 function vboWidgetsEditContainer(elem) {
1078 // update last container selected
1079 vbo_admin_widgets_last_container = jQuery(elem).closest('.vbo-admin-widgets-container');
1080 if (!vbo_admin_widgets_last_container || !vbo_admin_widgets_last_container.length) {
1081 // parent container not found
1082 console.error('parent container not found');
1083 return false;
1084 }
1085 // turn update flag on
1086 jQuery('#vbo-newcontainer-upd').val(1);
1087 // set current container size
1088 jQuery('#vbo-newcontainer-size').val(vbo_admin_widgets_last_container.attr('data-vbowidgetcontsize')).trigger('change');
1089 // display edit container form
1090 jQuery('.vbo-modal-widgets-newcontainer').show();
1091 jQuery('.vbo-modal-footer-newcontainer').show();
1092 // set edit container form button
1093 jQuery('#vbo-newcontainer-btn').html('<?php VikBookingIcons::e('check'); ?> ' + Joomla.JText._('VBO_WIDGETS_UPDWIDGCONT'));
1094 // set modal title
1095 jQuery('#vbo-modal-widgets-title').text(Joomla.JText._('VBO_WIDGETS_EDITWIDGCONT'));
1096 // display modal
1097 vboOpenModalWidgets();
1098 }
1099
1100 /**
1101 * Asks for confirmation before removing the selected container
1102 */
1103 function vboWidgetsRemoveContainer(elem) {
1104 var all_sect_conts = jQuery(elem).closest('.vbo-admin-widgets-section').find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew');
1105 var new_sect_conts = (all_sect_conts.length - 1);
1106 var cur_cont_index = all_sect_conts.index(jQuery(elem).closest('.vbo-admin-widgets-container'));
1107 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(jQuery(elem).closest('.vbo-admin-widgets-section'));
1108 if (confirm(Joomla.JText._('VBO_WIDGETS_CONFRMELEM'))) {
1109 // update containers count for a better styling
1110 all_sect_conts.attr('data-totcontainers', new_sect_conts);
1111 // remove container from document
1112 jQuery(elem).closest('.vbo-admin-widgets-container').remove();
1113 // update global map object
1114 vbo_admin_widgets_map.sections[cur_sect_index]['containers'].splice(cur_cont_index, 1);
1115 // trigger the save-map event
1116 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
1117 }
1118 }
1119
1120 /**
1121 * Displays the modal window to create a new widget
1122 */
1123 function vboWidgetsAddWidget(elem) {
1124 // update last container selected
1125 vbo_admin_widgets_last_container = jQuery(elem).closest('.vbo-admin-widgets-container');
1126 if (!vbo_admin_widgets_last_container || !vbo_admin_widgets_last_container.length) {
1127 // parent container not found
1128 console.error('parent container not found for adding a widget');
1129 return false;
1130 }
1131 // display new widget form
1132 jQuery('.vbo-modal-widgets-newwidget').show();
1133 jQuery('.vbo-modal-footer-newwidget').show();
1134 // unset any previously selected widget
1135 jQuery('#vbo-newwidget-id').val('');
1136 jQuery('.vbo-modal-widget-wrap').removeClass('vbo-modal-widget-selected vbo-modal-widget-notselected');
1137 // set modal title
1138 jQuery('#vbo-modal-widgets-title').text(Joomla.JText._('VBO_WIDGETS_ADDNEWWIDG'));
1139 // display modal
1140 vboOpenModalWidgets();
1141 }
1142
1143 /**
1144 * Updates the description in the modal window for the selected widget
1145 */
1146 function vboWidgetSetNewDescr(widget_id) {
1147 // always empty the description box
1148 jQuery('.vbo-newwidget-descr').html('');
1149 if (!widget_id.length) {
1150 return '';
1151 }
1152 // seek for this widget id
1153 for (var i in vbo_admin_widgets_names) {
1154 if (!vbo_admin_widgets_names.hasOwnProperty(i)) {
1155 continue;
1156 }
1157 if (vbo_admin_widgets_names[i]['id'] == widget_id) {
1158 jQuery('.vbo-newwidget-descr').html(vbo_admin_widgets_names[i]['descr']);
1159 return vbo_admin_widgets_names[i]['descr'];
1160 }
1161 }
1162 return '';
1163 }
1164
1165 /**
1166 * Makes the current widget selected, ready to be added to the document
1167 */
1168 function vboWidgetsSelectWidget(widget_id) {
1169 if (!widget_id) {
1170 return false;
1171 }
1172
1173 // remove selected class from all widgets, add un-selected class
1174 jQuery('.vbo-modal-widget-wrap').removeClass('vbo-modal-widget-selected').not('[data-vbowidgetid="' + widget_id + '"]').addClass('vbo-modal-widget-notselected');
1175 // add selected class to the current widget
1176 jQuery('.vbo-modal-widget-wrap[data-vbowidgetid="' + widget_id + '"]').addClass('vbo-modal-widget-selected').removeClass('vbo-modal-widget-notselected');
1177 // populate hidden field value
1178 jQuery('#vbo-newwidget-id').val(widget_id);
1179
1180 return true;
1181 }
1182
1183 /**
1184 * Adds the new selected widget to the document
1185 */
1186 function vboWidgetsAddWidgetToDoc(force_widget_id) {
1187 if (!vbo_admin_widgets_last_container || !vbo_admin_widgets_last_container.length) {
1188 // parent container not found
1189 console.error('parent container not found for adding a container');
1190 return false;
1191 }
1192
1193 // get new widget id, name and descr
1194 var widget_id = null,
1195 widget_name = null,
1196 widget_descr = null;
1197 if (force_widget_id) {
1198 // plus button clicked on widget
1199 jQuery('#vbo-newwidget-id').val(force_widget_id);
1200 // remove selected class from all widgets, add un-selected class
1201 jQuery('.vbo-modal-widget-wrap').removeClass('vbo-modal-widget-selected').not('[data-vbowidgetid="' + force_widget_id + '"]').addClass('vbo-modal-widget-notselected');
1202 // add selected class to the current widget
1203 jQuery('.vbo-modal-widget-wrap[data-vbowidgetid="' + force_widget_id + '"]').addClass('vbo-modal-widget-selected').removeClass('vbo-modal-widget-notselected');
1204 widget_id = force_widget_id;
1205 } else {
1206 // selected widget was clicked to be added
1207 widget_id = jQuery('#vbo-newwidget-id').val();
1208 }
1209 widget_name = jQuery('.vbo-modal-widget-wrap[data-vbowidgetid="' + widget_id + '"]').find('.vbo-modal-widget-name').text();
1210 if (!widget_id || !widget_id.length || !widget_name || !widget_name.length) {
1211 console.error('new widget id missing');
1212 return false;
1213 }
1214 // get and update the description for the currently selected widget
1215 widget_descr = vboWidgetSetNewDescr(widget_id);
1216
1217 // build new widget
1218 var html_widget_new = '<div class="vbo-admin-widgets-widget" data-vbowidgetid="' + widget_id + '">';
1219 html_widget_new += ' <div class="vbo-admin-widgets-widget-info" data-vbomanagewidgets="1">';
1220 html_widget_new += ' <div class="vbo-admin-widgets-widget-info-inner">';
1221 html_widget_new += ' <div class="vbo-admin-widgets-widget-details">';
1222 html_widget_new += ' <span class="vbo-admin-widgets-widget-info-drag"><?php VikBookingIcons::e('ellipsis-v'); ?></span>';
1223 html_widget_new += ' <h4 class="vbo-admin-widgets-widget-info-name">';
1224 html_widget_new += ' <span>' + widget_name + '</span>';
1225 html_widget_new += ' <span class="vbo-admin-widgets-widget-remove" onclick="vboWidgetsRemoveWidget(this);"><?php VikBookingIcons::e('trash'); ?></span>';
1226 html_widget_new += ' </h4>';
1227 html_widget_new += ' </div>';
1228 html_widget_new += ' <div class="vbo-admin-widgets-widget-info-descr">' + widget_descr + '</div>';
1229 html_widget_new += ' </div>';
1230 html_widget_new += ' </div>';
1231 html_widget_new += ' <div class="vbo-admin-widgets-widget-output" style="display: none;"></div>';
1232 html_widget_new += '</div>';
1233
1234 // wrap the new HTML into a collection object
1235 var elem_widget_new = jQuery(html_widget_new);
1236
1237 // append new widget HTML
1238 vbo_admin_widgets_last_container.find('.vbo-admin-widgets-widget-addnew').before(elem_widget_new);
1239
1240 // update global map object
1241 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(vbo_admin_widgets_last_container.closest('.vbo-admin-widgets-section'));
1242 var cur_cont_index = vbo_admin_widgets_last_container.closest('.vbo-admin-widgets-section').find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').index(vbo_admin_widgets_last_container);
1243 vbo_admin_widgets_map.sections[cur_sect_index]['containers'][cur_cont_index]['widgets'].push(widget_id);
1244
1245 // trigger the save-map event
1246 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
1247
1248 // close modal window
1249 hideVboModalWidgets();
1250
1251 // unset last container
1252 vbo_admin_widgets_last_container = null;
1253
1254 // populate widget output via AJAX
1255 vboWidgetsLoadWidgetContent(elem_widget_new, widget_id);
1256 }
1257
1258 /**
1259 * Asks for confirmation before removing the selected widget
1260 */
1261 function vboWidgetsRemoveWidget(elem) {
1262 var vbo_widget_elem = jQuery(elem).closest('.vbo-admin-widgets-widget');
1263 var cur_widg_id = vbo_widget_elem.attr('data-vbowidgetid');
1264 var cur_sect_index = jQuery('.vbo-admin-widgets-section').not('.vbo-admin-widgets-section-addnew').index(vbo_widget_elem.closest('.vbo-admin-widgets-section'));
1265 var cur_cont_index = vbo_widget_elem.closest('.vbo-admin-widgets-section').find('.vbo-admin-widgets-container').not('.vbo-admin-widgets-container-addnew').index(vbo_widget_elem.closest('.vbo-admin-widgets-container'));
1266 var cur_widg_index = vbo_widget_elem.closest('.vbo-admin-widgets-container').find('.vbo-admin-widgets-widget').not('.vbo-admin-widgets-widget-addnew').index(vbo_widget_elem.closest('.vbo-admin-widgets-widget'));
1267 if (confirm(Joomla.JText._('VBO_WIDGETS_CONFRMELEM'))) {
1268 // calculate widget instance index for its type
1269 var widget_instance_index = jQuery('.vbo-admin-widgets-widget[data-vbowidgetid="' + cur_widg_id + '"]').index(vbo_widget_elem);
1270
1271 // the widget method to call
1272 var call_method = 'removeInstance';
1273 // make a silent call for the widget in case it needs to perform actions when removing an instance
1274 VBOCore.doAjax(
1275 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=exec_admin_widget'); ?>",
1276 {
1277 widget_id: cur_widg_id,
1278 widget_instance: widget_instance_index,
1279 call: call_method,
1280 tmpl: "component"
1281 },
1282 (response) => {
1283 try {
1284 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
1285 if (!obj_res.hasOwnProperty(call_method)) {
1286 console.error('Unexpected JSON response', obj_res);
1287 }
1288 } catch(err) {
1289 console.error('could not parse JSON response', err, response);
1290 }
1291 },
1292 (error) => {
1293 console.error(error.responseText);
1294 }
1295 );
1296
1297 // remove widget from document
1298 vbo_widget_elem.remove();
1299 // update global map object
1300 vbo_admin_widgets_map.sections[cur_sect_index]['containers'][cur_cont_index]['widgets'].splice(cur_widg_index, 1);
1301 // trigger the save-map event
1302 document.dispatchEvent(new Event('vbo-admin-widgets-savemap'));
1303 }
1304 }
1305
1306 /**
1307 * Populates the content of the newly added widget.
1308 */
1309 function vboWidgetsLoadWidgetContent(container, widget_id) {
1310 if (!container || !container.find('.vbo-admin-widgets-widget-output').length) {
1311 console.error('Could not find new widget container');
1312 return false;
1313 }
1314
1315 // the widget method to call
1316 var call_method = 'render';
1317
1318 VBOCore.doAjax(
1319 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=exec_admin_widget'); ?>",
1320 {
1321 widget_id: widget_id,
1322 call: call_method,
1323 tmpl: "component"
1324 },
1325 (response) => {
1326 try {
1327 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
1328 if (obj_res.hasOwnProperty(call_method)) {
1329 // populate new widget content
1330 container.find('.vbo-admin-widgets-widget-output').html(obj_res[call_method]);
1331 } else {
1332 console.error('Unexpected JSON response', obj_res);
1333 }
1334 } catch(err) {
1335 console.error('could not parse JSON response', err, response);
1336 }
1337 },
1338 (error) => {
1339 console.error(error.responseText);
1340 alert(Joomla.JText._('VBO_WIDGETS_ERRDISPWIDG'));
1341 }
1342 );
1343 }
1344 </script>
1345