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 / taskmanager / tmpl / default_list.php

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

285 lines 10.7 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 core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2025 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 // collect a list of active area IDs
15 $activeAreaIds = [];
16
17 foreach ($this->visibleAreas as $areaRecord) {
18 // wrap the area record into a task area object
19 $taskArea = VBOTaskArea::getInstance((array) $areaRecord);
20
21 // push active area ID
22 $activeAreaIds[] = $taskArea->getID();
23 }
24
25 ?>
26
27 <div class="vbo-tm-list-tasks-wrap">
28 <div class="vbo-tm-list-tasks-container">
29 <div class="vbo-tm-list-tasks-columns">
30 <div class="vbo-tm-list-tasks-column" data-type="id">
31 <span><?php echo JText::translate('VBO_TASK'); ?></span>
32 </div>
33 <div class="vbo-tm-list-tasks-column" data-type="title">
34 <span><?php echo JText::translate('VBO_TITLE'); ?></span>
35 </div>
36 <div class="vbo-tm-list-tasks-column" data-type="assignees">
37 <span><?php echo JText::translate('VBO_ASSIGNEES'); ?></span>
38 </div>
39 <div class="vbo-tm-list-tasks-column" data-type="due">
40 <span><?php echo JText::translate('VBO_REMINDER_DUE_DATE'); ?></span>
41 </div>
42 <div class="vbo-tm-list-tasks-column" data-type="status">
43 <span><?php echo JText::translate('VBSTATUS'); ?></span>
44 </div>
45 <div class="vbo-tm-list-tasks-column" data-type="id_order">
46 <span><?php echo JText::translate('VBRENTALORD'); ?></span>
47 </div>
48 <div class="vbo-tm-list-tasks-column" data-type="id_area">
49 <span><?php echo JText::translate('VBO_PROJECT_AREA'); ?></span>
50 </div>
51 <div class="vbo-tm-list-tasks-column" data-type="tags">
52 <span><?php echo JText::translate('VBO_TAGS'); ?></span>
53 </div>
54 </div>
55 <div class="vbo-tm-list-tasks-body"></div>
56 </div>
57 <div class="vbo-tm-list-tasks-footer">
58 <div class="vbo-tm-list-tasks-loadmore" style="display: none;">
59 <button type="button" class="btn btn-secondary vbo-tm-list-tasks-loadmore-btn"><?php VikBookingIcons::e('ellipsis-h'); ?> <?php echo JText::translate('VBO_LOAD_MORE'); ?></button>
60 </div>
61 </div>
62 </div>
63
64 <script type="text/javascript">
65 /**
66 * Register the global active area IDs.
67 */
68 const vboTmListAreaIds = <?php echo json_encode($activeAreaIds); ?>;
69
70 /**
71 * Register function to load the area tasks.
72 */
73 const vboTmListLoadTasks = (start, filters) => {
74 let tasksBody = document.querySelector('.vbo-tm-list-tasks-body');
75 let hasTasks = tasksBody.querySelectorAll('.vbo-tm-list-task-row').length;
76
77 // inject custom object property
78 tasksBody.offsetStart = start || 0;
79
80 if (!start) {
81 // empty the tasks body element
82 tasksBody.innerHTML = '';
83
84 // reset flag
85 hasTasks = 0;
86
87 // hide button to load more tasks
88 jQuery('.vbo-tm-list-tasks-loadmore').hide();
89 }
90
91 // populate loading skeletons
92 vboTmListSetSkeletons(10);
93
94 // make the request for loading the tasks
95 VBOCore.doAjax(
96 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
97 {
98 type: 'list.tasks',
99 data: {
100 area_ids: vboTmListAreaIds,
101 filters: filters || vboTmFilters || {},
102 start: start || 0,
103 limit: 20,
104 },
105 },
106 (resp) => {
107 try {
108 // decode the response (if needed)
109 let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
110
111 // set HTML response (use jQuery rather than plain JS to avoid issues with injected scripts execution)
112 if (!hasTasks) {
113 // set the loading result for the first page of tasks
114 jQuery(tasksBody).html(obj_res['html']);
115 } else {
116 // delete loading skeletons
117 vboTmListUnsetSkeletons();
118
119 // append the loading result of the next tasks
120 jQuery(tasksBody).append(obj_res['html']);
121 }
122
123 if ((obj_res['html'] + '').indexOf('data-no-results="1"') < 0 && (tasksBody.querySelectorAll('.vbo-tm-list-task-row').length - hasTasks) >= 20) {
124 // show button to load more tasks
125 jQuery('.vbo-tm-list-tasks-loadmore').show();
126 } else {
127 // hide button to load more tasks
128 jQuery('.vbo-tm-list-tasks-loadmore').hide();
129 }
130
131 // dispatch event for TM contents loaded
132 VBOCore.emitEvent('vbo-tm-contents-loaded', {
133 element: tasksBody,
134 });
135 } catch (err) {
136 console.error('Error decoding the response', err, resp);
137 }
138 },
139 (error) => {
140 // display error message
141 alert(error.responseText);
142 }
143 );
144 };
145
146 /**
147 * Register function to set some task loading skeletons.
148 */
149 const vboTmListSetSkeletons = (quantity) => {
150 let tasksBody = document.querySelector('.vbo-tm-list-tasks-body');
151
152 if (!tasksBody) {
153 return;
154 }
155
156 // ensure the quantity is a valid number greater than zero
157 quantity = !isNaN(quantity) && quantity > 0 ? quantity : 1;
158
159 for (let i = 1; i <= quantity; i++) {
160 // build skeleton HTML string
161 let skeletonHtml = '';
162 skeletonHtml += '<div class="vbo-tm-list-task-row vbo-tm-list-task-row-skeleton">\n';
163 skeletonHtml += ' <div class="vbo-tm-list-task-cell vbo-skeleton-loading" data-type="id"></div>\n';
164 skeletonHtml += ' <div class="vbo-tm-list-task-cell vbo-skeleton-loading" data-type="title" style="width:' + (Math.floor(Math.random() * 45) + 50) + '%;"></div>\n';
165 skeletonHtml += ' <div class="vbo-tm-list-task-cell" data-type="assignees">\n';
166 skeletonHtml += ' <span class="vbo-skeleton-loading vbo-tm-board-area-task-assignee"></span>\n'.repeat(Math.floor(Math.random() * 3) + 1);
167 skeletonHtml += ' </div>\n';
168 skeletonHtml += ' <div class="vbo-tm-list-task-cell vbo-skeleton-loading" data-type="due"></div>\n';
169 skeletonHtml += ' <div class="vbo-tm-list-task-cell vbo-skeleton-loading" data-type="status"></div>\n';
170 skeletonHtml += ' <div class="vbo-tm-list-task-cell" data-type="id_order">\n';
171 skeletonHtml += ' <span class="vbo-skeleton-loading vbo-tm-board-area-task-assignee"></span>\n';
172 skeletonHtml += ' <div class="order-room-booking-wrapper">\n';
173 skeletonHtml += ' <div class="vbo-skeleton-loading room-info"></div>\n';
174 skeletonHtml += ' <div class="vbo-skeleton-loading booking-info"></div>\n';
175 skeletonHtml += ' </div>\n';
176 skeletonHtml += ' </div>\n';
177 skeletonHtml += ' <div class="vbo-tm-list-task-cell vbo-skeleton-loading" data-type="id_area"></div>\n';
178 skeletonHtml += ' <div class="vbo-tm-list-task-cell" data-type="tags">\n';
179 skeletonHtml += ' <span class="vbo-skeleton-loading"></span>\n'.repeat(Math.floor(Math.random() * 3) + 1);
180 skeletonHtml += ' </div>\n';
181 skeletonHtml += '</div>';
182
183 tasksBody.insertAdjacentHTML('beforeend', skeletonHtml);
184 }
185 };
186
187 /**
188 * Register function to unset the task loading skeletons.
189 */
190 const vboTmListUnsetSkeletons = (areaId) => {
191 let tasksBody = document.querySelector('.vbo-tm-list-tasks-body');
192
193 if (!tasksBody) {
194 return;
195 }
196
197 tasksBody
198 .querySelectorAll('.vbo-tm-list-task-row.vbo-tm-list-task-row-skeleton')
199 .forEach((skeleton) => {
200 skeleton.remove();
201 });
202 };
203
204 jQuery(function() {
205
206 /**
207 * Load all area tasks upon page loading.
208 */
209 vboTmListLoadTasks(0);
210
211 /**
212 * Register click event on the button to load more tasks.
213 */
214 document
215 .querySelector('button.vbo-tm-list-tasks-loadmore-btn')
216 .addEventListener('click', function() {
217 let tasksBody = document.querySelector('.vbo-tm-list-tasks-body');
218
219 // get current offset
220 let nextStart = (tasksBody.offsetStart || 0) + 20;
221
222 // hide button
223 this.parentNode.style.display = 'none';
224
225 // load more tasks
226 vboTmListLoadTasks(nextStart);
227 });
228
229 /**
230 * Register to the event for rendering the tasks of an area.
231 */
232 document.addEventListener('vbo-tm-area-render-task', (e) => {
233 if (!e || !e?.detail?.areaId) {
234 return;
235 }
236
237 let areaId = parseInt(e.detail.areaId);
238
239 if (!vboTmListAreaIds.includes(areaId)) {
240 // push new area ID
241 vboTmListAreaIds.push(areaId);
242 }
243
244 // reload tasks
245 vboTmListLoadTasks(0);
246 // toggle area visibility
247 vboTmToggleAreaDisplay(areaId, 1);
248 });
249
250 /**
251 * Register to the event for hiding the tasks of an area.
252 */
253 document.addEventListener('vbo-tm-area-hide-task', (e) => {
254 if (!e || !e?.detail?.areaId) {
255 return;
256 }
257
258 let areaId = parseInt(e.detail.areaId);
259
260 let index = vboTmListAreaIds.indexOf(areaId);
261 if (index >= 0) {
262 // remove the requested area ID
263 vboTmListAreaIds.splice(index, 1);
264 }
265
266 // reload tasks
267 vboTmListLoadTasks(0);
268 // toggle area visibility
269 vboTmToggleAreaDisplay(areaId, 0);
270 });
271
272 /**
273 * Register listener for the filters changed event.
274 */
275 document.addEventListener('vbo-tm-filters-changed', (e) => {
276 // obtain the global filters
277 let filters = e?.detail?.filters;
278
279 // re-render tasks list
280 vboTmListLoadTasks(0, filters);
281 });
282
283 });
284 </script>
285