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 / helpers / widgets / latest_events.php

latest_events.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/widgets/latest_events.php

746 lines 26.2 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 * Class handler for admin widget "latest events".
15 *
16 * @since 1.15.0 (J) - 1.5.0 (WP)
17 */
18 class VikBookingAdminWidgetLatestEvents extends VikBookingAdminWidget
19 {
20 /**
21 * The instance counter of this widget. Since we do not load individual parameters
22 * for each widget's instance, we use a static counter to determine its settings.
23 *
24 * @var int
25 */
26 protected static $instance_counter = -1;
27
28 /**
29 * Default number of events per page.
30 *
31 * @var int
32 */
33 protected $events_per_page = 6;
34
35 /**
36 * Default number of loading skeletons (should be less than events per page).
37 *
38 * @var int
39 */
40 protected $tot_skeletons = 4;
41
42 /**
43 * Class constructor will define the widget name and identifier.
44 */
45 public function __construct()
46 {
47 // call parent constructor
48 parent::__construct();
49
50 $this->widgetName = JText::translate('VBO_W_LATESTEVS_TITLE');
51 $this->widgetDescr = JText::translate('VBO_W_LATESTEVS_DESCR');
52 $this->widgetId = basename(__FILE__, '.php');
53
54 // define widget and icon and style name
55 $this->widgetIcon = '<i class="' . VikBookingIcons::i('history') . '"></i>';
56 $this->widgetStyleName = 'blue';
57
58 // load widget's settings
59 $this->widgetSettings = $this->loadSettings();
60 $this->widgetSettings = !is_array($this->widgetSettings) ? [] : $this->widgetSettings;
61 }
62
63 /**
64 * This widget returns the latest history record ID to schedule
65 * periodic watch data in order to be able to trigger notifications.
66 * No CSS/JS assets are needed during preloading.
67 *
68 * @return void|object
69 */
70 public function preload()
71 {
72 // lang vars for JS
73 JText::script('VBOBOOKHISTORYLBLTYPE');
74 JText::script('VBANYTHING');
75 JText::script('VBO_HISTORY_GROUPS');
76
77 // use the history class to get the latest event id
78 $history_obj = VikBooking::getBookingHistoryInstance();
79 $events = $history_obj->getLatestBookingEvents(0, 1);
80
81 if ($events) {
82 $watch_data = new stdClass;
83 $watch_data->history_id = $events[0]->id;
84
85 return $watch_data;
86 }
87
88 return null;
89 }
90
91 /**
92 * Checks for new notifications by using the previous preloaded watch-data.
93 *
94 * @param ?VBONotificationWatchdata $watch_data the preloaded watch-data object.
95 *
96 * @return array data object to watch next and notifications array.
97 *
98 * @see preload()
99 *
100 * @since 1.15.0 (J) - 1.5.0 (WP)
101 */
102 public function getNotifications(?VBONotificationWatchdata $watch_data = null)
103 {
104 // default empty values
105 $watch_next = null;
106 $notifications = null;
107
108 if (!$watch_data) {
109 return [$watch_next, $notifications];
110 }
111
112 $latest_history_id = (int)$watch_data->get('history_id', 0);
113 if (empty($latest_history_id)) {
114 return [$watch_next, $notifications];
115 }
116
117 // load the latest worthy-of-notification history events
118 $history_obj = VikBooking::getBookingHistoryInstance();
119 $events = $history_obj->getWorthyEvents($latest_history_id, 10);
120 if (!$events) {
121 return [$watch_next, $notifications];
122 }
123
124 // first off, build the next watch data for this widget
125 $watch_next = new stdClass;
126 $watch_next->history_id = $events[(count($events) - 1)]->id;
127
128 // filter the newest events by those who have not been dispatched before through Push notifications
129 $events = $watch_data->filterPushedReservations($events);
130
131 // compose the notification(s) to dispatch, if any
132 if ($events) {
133 $notifications = VBONotificationScheduler::getInstance()->buildHistoryDataObjects($events);
134 }
135
136 return [$watch_next, $notifications];
137 }
138
139 /**
140 * Custom method for this widget only to load the history events.
141 * The method is called by the admin controller through an AJAX request.
142 * The visibility should be public, it should not exit the process, and
143 * any content sent to output will be returned to the AJAX response.
144 * In this case we return an array because this method requires "return":1.
145 *
146 * It's the actual rendering of the widget which also allows navigation.
147 *
148 * @return mixed boolean false in case of error, or associative array.
149 */
150 public function loadHistoryEvents()
151 {
152 $instance = VikRequest::getInt('instance', 0, 'request');
153 $offset = VikRequest::getInt('offset', 0, 'request');
154 $evtype = VikRequest::getString('evtype', '', 'request');
155 $length = VikRequest::getInt('length', $this->events_per_page, 'request');
156 $wrapper = VikRequest::getString('wrapper', '', 'request');
157
158 // update widget's settings
159 if ($instance >= 0) {
160 if (!isset($this->widgetSettings[$instance])) {
161 // push a new instance
162 $this->widgetSettings[] = $this->getDefaultEventSettings($evtype);
163 $instance = count($this->widgetSettings) - 1;
164 }
165 $this->widgetSettings[$instance]->evtype = $evtype;
166 $this->updateSettings(json_encode($this->widgetSettings));
167 }
168
169 // use the history class to get the events
170 $history_obj = VikBooking::getBookingHistoryInstance();
171 $events = $history_obj->getLatestBookingEvents($offset, $length, $min_id = 0, [$evtype]);
172
173 // check if a next page can be available
174 $has_next_page = (count($events) >= $length);
175
176 // start output buffering
177 ob_start();
178
179 // loop through all history events
180 $now = time();
181 $today = date('Y-m-d');
182 foreach ($events as $history) {
183 if ($history->status == 'confirmed') {
184 $ord_status = '<span class="label label-success vbo-status-label">' . JText::translate('VBCONFIRMED') . '</span>';
185 } elseif ($history->status == 'standby') {
186 $ord_status = '<span class="label label-warning vbo-status-label">' . JText::translate('VBSTANDBY') . '</span>';
187 } else {
188 $ord_status = '<span class="label label-error vbo-status-label">' . JText::translate('VBCANCELLED') . '</span>';
189 }
190 if (!empty($history->booking_type) && !strcasecmp($history->booking_type, 'overbooking')) {
191 $ord_status .= ' <span class="label label-error vbo-status-label vbo-label-small">' . JText::translate('VBO_BTYPE_OVERBOOKING') . '</span>';
192 }
193 $nominative = strlen($history->nominative) > 1 ? $history->nominative : VikBooking::getFirstCustDataField($history->custdata);
194 $ch_logo_obj = VikBooking::getVcmChannelsLogo($history->channel, true);
195 $channel_logo = is_object($ch_logo_obj) ? $ch_logo_obj->getSmallLogoURL() : '';
196 $nights_lbl = $history->days > 1 ? JText::translate('VBDAYS') : JText::translate('VBDAY');
197
198 $dt_obj = new JDate($history->dt);
199 $dt_obj->setTimezone(new DateTimeZone(date_default_timezone_get()));
200
201 // calculate check-in date information
202 $checkin_info = getdate($history->checkin);
203 if (date('Y-m-d', $history->checkin) == $today) {
204 // check-in today
205 $checkind_lbl = JText::translate('VBTODAY');
206 $checkind_icn = '<i class="' . VikBookingIcons::i('plane-arrival') . '"></i>';
207 } elseif ($history->checkin > $now) {
208 // check-in in the future
209 $checkind_lbl = VikBooking::sayWeekDay($checkin_info['wday'], true) . ', ' . date(str_replace("/", $this->datesep, $this->df), $history->checkin);
210 $checkind_icn = '<i class="' . VikBookingIcons::i('sort-up') . '"></i> ';
211 } else {
212 // check-in in the past
213 $checkind_lbl = VikBooking::sayWeekDay($checkin_info['wday'], true) . ', ' . date(str_replace("/", $this->datesep, $this->df), $history->checkin);
214 $checkind_icn = '<i class="' . VikBookingIcons::i('sort-down') . '"></i> ';
215 }
216 ?>
217 <div class="vbo-widget-history-record" data-recordid="<?php echo $history->id; ?>" onclick="vboWidgetLatestEventsOpenBooking('<?php echo $history->idorder; ?>');">
218 <div class="vbo-widget-history-avatar">
219 <?php
220 if (!empty($channel_logo)) {
221 // channel logo has got the highest priority
222 ?>
223 <img class="vbo-widget-history-avatar-profile" src="<?php echo $channel_logo; ?>" />
224 <?php
225 } elseif (!empty($history->pic)) {
226 // customer profile picture
227 ?>
228 <img class="vbo-widget-history-avatar-profile" src="<?php echo strpos($history->pic, 'http') === 0 ? $history->pic : VBO_SITE_URI . 'resources/uploads/' . $history->pic; ?>" />
229 <?php
230 } else {
231 // we use an icon as fallback
232 VikBookingIcons::e('hotel', 'vbo-widget-history-avatar-icon');
233 }
234 ?>
235 </div>
236 <div class="vbo-widget-history-content">
237 <div class="vbo-widget-history-content-head">
238 <div class="vbo-widget-history-content-info-details">
239 <?php echo $ord_status; ?>
240 <h4><?php echo $nominative; ?></h4>
241 </div>
242 <div class="vbo-widget-history-content-info-booking">
243 <div class="vbo-widget-history-content-info-dates">
244 <span class="vbo-widget-history-booking-id">
245 <span class="label label-info"><?php echo $history->idorder; ?></span>
246 </span>
247 <span class="vbo-widget-history-date"><?php echo $dt_obj->format('D, d M Y H:i', true); ?></span>
248 </div>
249 <div class="vbo-widget-history-booking-checkin">
250 <span><?php echo $checkind_icn . $checkind_lbl; ?></span>
251 <span><?php echo ' - ' . $history->days . ' ' . $nights_lbl; ?></span>
252 </div>
253 </div>
254 </div>
255 <div class="vbo-widget-history-content-info-msg">
256 <span class="vbo-widget-history-content-info-msg-descr"><?php echo $history_obj->validType($history->type, true); ?></span>
257 </div>
258 </div>
259 </div>
260 <?php
261 }
262
263 // append navigation
264 ?>
265 <div class="vbo-widget-commands vbo-widget-commands-right">
266 <div class="vbo-widget-commands-main">
267 <?php
268 if ($offset > 0) {
269 // show backward navigation button
270 ?>
271 <div class="vbo-widget-command-chevron vbo-widget-command-prev">
272 <span class="vbo-widget-command-chevron-prev" onclick="vboWidgetLatestEventsNavigate('<?php echo $wrapper; ?>', -1);"><?php VikBookingIcons::e('chevron-left'); ?></span>
273 </div>
274 <?php
275 }
276 if ($has_next_page) {
277 // show forward navigation button
278 ?>
279 <div class="vbo-widget-command-chevron vbo-widget-command-next">
280 <span class="vbo-widget-command-chevron-next" onclick="vboWidgetLatestEventsNavigate('<?php echo $wrapper; ?>', 1);"><?php VikBookingIcons::e('chevron-right'); ?></span>
281 </div>
282 <?php
283 }
284 ?>
285 </div>
286 </div>
287 <?php
288
289 // get the HTML buffer
290 $html_content = ob_get_contents();
291 ob_end_clean();
292
293 // return an associative array of values
294 return array(
295 'html' => $html_content,
296 'tot_records' => count($events),
297 'next_page' => (int)$has_next_page,
298 );
299 }
300
301 public function render(?VBOMultitaskData $data = null)
302 {
303 // increase widget's instance counter
304 static::$instance_counter++;
305
306 // check whether the widget is being rendered via AJAX when adding it through the customizer
307 $is_ajax = $this->isAjaxRendering();
308
309 // check whether we are in the multitask panel
310 $is_multitask = $this->isMultitaskRendering();
311
312 // check whether the widget requires settings
313 $needs_settings = !$is_ajax;
314 $data_instance = !$is_ajax ? static::$instance_counter : '-1';
315 if ($is_multitask && $is_ajax) {
316 $guess_inst_counter = $this->guessMultitaskHistoryInstance($data);
317 if ($guess_inst_counter !== false) {
318 // force the loading of the guessed widget instance's settings
319 static::$instance_counter = $guess_inst_counter;
320 $data_instance = $guess_inst_counter;
321 $needs_settings = true;
322 }
323 }
324
325 // generate a unique ID for the sticky notes wrapper instance
326 $wrapper_instance = !$is_ajax ? static::$instance_counter : rand();
327 $wrapper_id = 'vbo-widget-latestevents-' . $wrapper_instance;
328
329 // get permissions
330 $vbo_auth_bookings = JFactory::getUser()->authorise('core.vbo.bookings', 'com_vikbooking');
331
332 // load the settings for this specific instance of the widget
333 $instance_settings = $this->getDefaultEventSettings();
334 if ($needs_settings && is_array($this->widgetSettings) && isset($this->widgetSettings[static::$instance_counter])) {
335 if (is_object($this->widgetSettings[static::$instance_counter]) && count(get_object_vars($this->widgetSettings[static::$instance_counter]))) {
336 $instance_settings = $this->widgetSettings[static::$instance_counter];
337 }
338 }
339
340 // history object
341 $history_obj = VikBooking::getBookingHistoryInstance();
342
343 // get all history types and groups
344 $history_types = $history_obj->getTypesMap();
345 $history_groups = $history_obj->getTypeGroups();
346
347 // get the current event-type filter
348 $current_evtype = '';
349 $current_evname = '';
350 if (!empty($instance_settings->evtype)) {
351 if (isset($history_types[$instance_settings->evtype])) {
352 $current_evtype = $instance_settings->evtype;
353 $current_evname = $history_types[$current_evtype];
354 } elseif (isset($history_groups[$instance_settings->evtype])) {
355 $current_evtype = $instance_settings->evtype;
356 $current_evname = JText::translate('VBO_HISTORY_GROUPS') . ' - ' . $history_groups[$current_evtype]['name'];
357 }
358 }
359
360 ?>
361 <div id="<?php echo $wrapper_id; ?>" class="vbo-admin-widget-wrapper" data-instance="<?php echo $data_instance; ?>" data-offset="0" data-evtype="<?php echo $current_evtype; ?>" data-length="<?php echo $this->events_per_page; ?>">
362 <div class="vbo-admin-widget-head">
363 <div class="vbo-admin-widget-head-inline">
364 <h4><?php echo $this->widgetIcon; ?> <span><?php echo $this->widgetName; ?></span></h4>
365 <div class="vbo-admin-widget-head-commands">
366
367 <div class="vbo-reportwidget-commands">
368 <div class="vbo-reportwidget-commands-main">
369 <div class="vbo-reportwidget-command-dates">
370 <div class="vbo-reportwidget-period-name"><?php echo JText::translate('VBOBOOKHISTORYLBLTYPE'); ?></div>
371 <div class="vbo-widget-latestevents-filttype-name"><?php echo !empty($current_evname) ? $current_evname : JText::translate('VBANYTHING'); ?></div>
372 </div>
373 </div>
374 <div class="vbo-reportwidget-command-dots">
375 <span class="vbo-widget-command-togglefilters vbo-widget-latestevents-togglefilters" onclick="vboWidgetLatestEventsToggleFilters('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('ellipsis-v'); ?></span>
376 </div>
377 </div>
378 <div class="vbo-reportwidget-filters">
379 <div class="vbo-reportwidget-filter">
380 <select class="vbo-latestevents-filttype-event">
381 <option value=""></option>
382 <optgroup label="<?php echo htmlspecialchars(JText::translate('VBO_HISTORY_GROUPS')); ?>">
383 <?php
384 foreach ($history_groups as $ev_key => $ev_data) {
385 ?>
386 <option value="<?php echo $ev_key; ?>"<?php echo !empty($instance_settings->evtype) && $instance_settings->evtype == $ev_key ? ' selected="selected"' : ''; ?>><?php echo $ev_data['name']; ?></option>
387 <?php
388 }
389 ?>
390 </optgroup>
391 <optgroup label="<?php echo htmlspecialchars(JText::translate('VBOBOOKHISTORYTAB')); ?>">
392 <?php
393 foreach ($history_types as $ev_key => $ev_name) {
394 ?>
395 <option value="<?php echo $ev_key; ?>"<?php echo !empty($instance_settings->evtype) && $instance_settings->evtype == $ev_key ? ' selected="selected"' : ''; ?>><?php echo $ev_name; ?></option>
396 <?php
397 }
398 ?>
399 </optgroup>
400 </select>
401 </div>
402 <div class="vbo-reportwidget-filter vbo-reportwidget-filter-confirm">
403 <button type="button" class="btn vbo-config-btn" onclick="vboWidgetLatestEventsFilterType('<?php echo $wrapper_id; ?>');"><?php echo JText::translate('VBADMINNOTESUPD'); ?></button>
404 </div>
405 </div>
406
407 </div>
408 </div>
409 </div>
410 <div class="vbo-widget-latestevents-wrap">
411 <div class="vbo-widget-latestevents-inner">
412 <div class="vbo-widget-latestevents-list">
413 <?php
414 for ($i = 0; $i < $this->tot_skeletons; $i++) {
415 ?>
416 <div class="vbo-dashboard-guest-activity vbo-dashboard-guest-activity-skeleton">
417 <div class="vbo-dashboard-guest-activity-avatar">
418 <div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>
419 </div>
420 <div class="vbo-dashboard-guest-activity-content">
421 <div class="vbo-dashboard-guest-activity-content-head">
422 <div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>
423 </div>
424 <div class="vbo-dashboard-guest-activity-content-info-msg">
425 <div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>
426 </div>
427 </div>
428 </div>
429 <?php
430 }
431 ?>
432 </div>
433 </div>
434 </div>
435 </div>
436 <?php
437
438 if (static::$instance_counter === 0 || $is_ajax) {
439 /**
440 * Print the JS code only once for all instances of this widget.
441 * The real rendering is made through AJAX, not when the page loads.
442 */
443 ?>
444 <a class="vbo-widget-latest-events-basenavuri" href="<?php echo VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikbooking&task=editorder&cid[]=%d#bookhistory', $xhtml = false); ?>" style="display: none;"></a>
445
446 <script type="text/javascript">
447
448 /**
449 * Open the booking details page for the clicked event
450 */
451 function vboWidgetLatestEventsOpenBooking(id) {
452 var has_perms = <?php echo (int)$vbo_auth_bookings; ?>;
453 if (!has_perms) {
454 return false;
455 }
456 var open_url = jQuery('.vbo-widget-latest-events-basenavuri').first().attr('href');
457 open_url = open_url.replace('%d', id);
458 // navigate in a new tab
459 window.open(open_url, '_blank');
460 }
461
462 /**
463 * Display the loading skeletons.
464 */
465 function vboWidgetLatestEventsSkeletons(wrapper) {
466 var widget_instance = jQuery('#' + wrapper);
467 if (!widget_instance.length) {
468 return false;
469 }
470 widget_instance.find('.vbo-widget-latestevents-list').html('');
471 for (var i = 0; i < <?php echo $this->tot_skeletons; ?>; i++) {
472 var skeleton = '';
473 skeleton += '<div class="vbo-dashboard-guest-activity vbo-dashboard-guest-activity-skeleton">';
474 skeleton += ' <div class="vbo-dashboard-guest-activity-avatar">';
475 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>';
476 skeleton += ' </div>';
477 skeleton += ' <div class="vbo-dashboard-guest-activity-content">';
478 skeleton += ' <div class="vbo-dashboard-guest-activity-content-head">';
479 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>';
480 skeleton += ' </div>';
481 skeleton += ' <div class="vbo-dashboard-guest-activity-content-info-msg">';
482 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>';
483 skeleton += ' </div>';
484 skeleton += ' </div>';
485 skeleton += '</div>';
486 // append skeleton
487 jQuery(skeleton).appendTo(widget_instance.find('.vbo-widget-latestevents-list'));
488 }
489 }
490
491 /**
492 * Toggle widget filters.
493 */
494 function vboWidgetLatestEventsToggleFilters(wrapper) {
495 var widget_instance = jQuery('#' + wrapper);
496 if (!widget_instance.length) {
497 return false;
498 }
499
500 widget_instance.find('.vbo-reportwidget-filters').toggle();
501 }
502
503 /**
504 * Perform the request to load the history events.
505 */
506 function vboWidgetLatestEventsLoad(wrapper) {
507 var widget_instance = jQuery('#' + wrapper);
508 if (!widget_instance.length) {
509 return false;
510 }
511
512 // get vars for making the request
513 var current_instance = widget_instance.attr('data-instance');
514 var current_offset = parseInt(widget_instance.attr('data-offset'));
515 var current_evtype = widget_instance.attr('data-evtype');
516 var length_per_page = parseInt(widget_instance.attr('data-length'));
517
518 // the widget method to call
519 var call_method = 'loadHistoryEvents';
520
521 // make a request to load the history events
522 VBOCore.doAjax(
523 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
524 {
525 widget_id: "<?php echo $this->getIdentifier(); ?>",
526 call: call_method,
527 return: 1,
528 instance: current_instance,
529 offset: current_offset,
530 evtype: current_evtype,
531 length: length_per_page,
532 wrapper: wrapper,
533 tmpl: "component"
534 },
535 function(response) {
536 try {
537 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
538 if (!obj_res.hasOwnProperty(call_method) || !obj_res[call_method]) {
539 console.error('Unexpected JSON response', obj_res);
540 return false;
541 }
542
543 // replace HTML with new history events
544 widget_instance.find('.vbo-widget-latestevents-list').html(obj_res[call_method]['html']);
545
546 // check results
547 var tot_records = obj_res[call_method]['tot_records'] || 0;
548 if (!isNaN(tot_records) && parseInt(tot_records) < 1) {
549 // no results can indicate the offset is invalid or too high
550 if (!isNaN(current_offset) && parseInt(current_offset) > 0) {
551 // reset offset to 0
552 widget_instance.attr('data-offset', 0);
553 // show loading skeletons
554 vboWidgetLatestEventsSkeletons(wrapper);
555 // reload the first page
556 vboWidgetLatestEventsLoad(wrapper);
557 }
558 }
559 } catch(err) {
560 console.error('could not parse JSON response', err, response);
561 }
562 },
563 function(error) {
564 // remove the skeleton loading
565 widget_instance.find('.vbo-widget-latestevents-list').find('.vbo-dashboard-guest-activity-skeleton').remove();
566 console.error(error);
567 }
568 );
569 }
570
571 /**
572 * Navigate between the various pages of the history events.
573 */
574 function vboWidgetLatestEventsNavigate(wrapper, direction) {
575 var widget_instance = jQuery('#' + wrapper);
576 if (!widget_instance.length) {
577 return false;
578 }
579
580 // show loading skeletons
581 vboWidgetLatestEventsSkeletons(wrapper);
582
583 // current offset
584 var current_offset = parseInt(widget_instance.attr('data-offset'));
585
586 // events per page per type
587 var steps = <?php echo $this->events_per_page; ?>;
588
589 // check direction and update offsets for nav
590 if (direction > 0) {
591 // navigate forward
592 widget_instance.attr('data-offset', (current_offset + steps));
593 } else {
594 // navigate backward
595 var new_offset = current_offset - steps;
596 new_offset = new_offset >= 0 ? new_offset : 0;
597 widget_instance.attr('data-offset', new_offset);
598 }
599
600 // launch navigation
601 vboWidgetLatestEventsLoad(wrapper);
602 }
603
604 /**
605 * Update the events (history) type filter
606 */
607 function vboWidgetLatestEventsFilterType(wrapper) {
608 var widget_instance = jQuery('#' + wrapper);
609 if (!widget_instance.length) {
610 return false;
611 }
612
613 // get selected event-type filter
614 var cur_evname = '';
615 var cur_evtype = widget_instance.find('select.vbo-latestevents-filttype-event').val();
616 if (!cur_evtype || !cur_evtype.length) {
617 cur_evtype = '';
618 cur_evname = Joomla.JText._('VBANYTHING');
619 } else {
620 cur_evname = widget_instance.find('select.vbo-latestevents-filttype-event').find('option:selected').text();
621 if (cur_evtype.length === 3) {
622 cur_evname = Joomla.JText._('VBO_HISTORY_GROUPS') + ' - ' + cur_evname;
623 }
624 }
625
626 // hide filters when making a new request
627 widget_instance.find('.vbo-reportwidget-filters').hide();
628
629 // update title text with the new event name
630 widget_instance.find('.vbo-widget-latestevents-filttype-name').text(cur_evname);
631
632 // update current event-type filter
633 widget_instance.attr('data-evtype', cur_evtype);
634
635 // always reset the offset to 0
636 widget_instance.attr('data-offset', 0);
637
638 // show loading skeletons
639 vboWidgetLatestEventsSkeletons(wrapper);
640
641 // reload data
642 vboWidgetLatestEventsLoad(wrapper);
643 }
644
645 </script>
646 <?php
647 }
648 ?>
649
650 <script type="text/javascript">
651
652 jQuery(function() {
653
654 // when document is ready, load history events for this widget's instance
655 vboWidgetLatestEventsLoad('<?php echo $wrapper_id; ?>');
656
657 // render select2
658 jQuery('#<?php echo $wrapper_id; ?>').find('select.vbo-latestevents-filttype-event').select2({
659 placeholder: Joomla.JText._('VBOBOOKHISTORYLBLTYPE'),
660 width: '100%',
661 allowClear: true,
662 });
663
664 });
665
666 </script>
667
668 <?php
669 }
670
671 /**
672 * Protected method to guess if the widget being rendered via AJAX in the
673 * multitask panel should load specific settings. Should be called when
674 * settings have been loaded, and if AJAX + multitask rendering is detected.
675 * It's assumed that the AJAX rendering of a multitask widget takes place one
676 * second before the AJAX event that updates the multitask map to push the widget.
677 *
678 * @param ?VBOMultitaskData $data the data object injected to the widget.
679 *
680 * @return bool|int false on failure, guessed settings index otherwise.
681 *
682 * @since 1.16.0 (J) - 1.6.0 (WP)
683 */
684 protected function guessMultitaskHistoryInstance(?VBOMultitaskData $data = null)
685 {
686 if (!is_array($this->widgetSettings) || !count($this->widgetSettings)) {
687 // nothing to guess if this widget has got no saved settings
688 return false;
689 }
690
691 if (!is_object($data)) {
692 // multitask data object must be set
693 return false;
694 }
695
696 // the page must be set in the multitask object
697 $vbo_page = $data->getPage();
698 if (empty($vbo_page)) {
699 // nothing to guess if no current page set
700 return false;
701 }
702
703 // get the map for the current page
704 $page_map = VikBooking::getAdminWidgetsInstance()->getMultitaskingMap($vbo_page, $whole = false);
705 if (!is_array($page_map) || !count($page_map)) {
706 // the multitask panel of this page has got no widgets saved, return the first index for settings
707 return 0;
708 }
709
710 // count how many widgets of this type are already on this page
711 $guessed_index = 0;
712 foreach ($page_map as $widget_type) {
713 if ($widget_type == $this->getIdentifier()) {
714 $guessed_index++;
715 }
716 }
717
718 // return the guessed index, which will load the next hypothetical instance
719 return $guessed_index;
720 }
721
722 /**
723 * Returns the default settings object for reading the latest history events.
724 *
725 * @param string $evtype optional event type requested.
726 *
727 * @return stdClass default object with default setting properties.
728 *
729 * @since 1.16.0 (J) - 1.6.0 (WP)
730 */
731 protected function getDefaultEventSettings($evtype = null)
732 {
733 $opts = new stdClass;
734 $opts->evtype = '';
735
736 if (!empty($evtype)) {
737 $opts->evtype = $evtype;
738 } elseif (!$this->isAjaxRendering() && !$this->isMultitaskRendering() && static::$instance_counter > 0) {
739 // by default, the 2nd instance of the widget will fetch a group of events
740 $opts->evtype = $this->hasChannelManager() ? 'GCM' : 'GBK';
741 }
742
743 return $opts;
744 }
745 }
746