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 / layouts / taskmanager / board / tasks.php

tasks.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/layouts/taskmanager/board/tasks.php

323 lines 13.4 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 /**
15 * Obtain vars from arguments received in the layout file.
16 *
17 * @var array $data The data for rendering the tasks of a given area within the board.
18 */
19 extract($displayData);
20
21 // get the task area object
22 if (($data['taskArea'] ?? null) && $data['taskArea'] instanceof VBOTaskArea) {
23 // rendering during page loading
24 $taskArea = $data['taskArea'];
25 } elseif ($data['area_id'] ?? null) {
26 // probably rendering through AJAX
27 $taskArea = VBOTaskArea::getRecordInstance((int) $data['area_id']);
28 } else {
29 // raise an error
30 throw new InvalidArgumentException('Could not load task area object.', 400);
31 }
32
33 // get fetching start and limit values
34 $start = abs(intval($data['start'] ?? 0));
35 $limit = abs(intval($data['limit'] ?? 10));
36
37 // get the filters for rendering the area tasks
38 $filters = (array) ($data['filters'] ?? []);
39
40 // save current filters in the user state
41 JFactory::getApplication()->setUserState('vbo.tm.filters', $filters);
42
43 // access the task manager object
44 $taskManager = VBOFactory::getTaskManager();
45
46 // get the first area tasks according to filters, by always forcing/injecting the area ID
47 $tasks = VBOTaskModelTask::getInstance()->filterItems(array_merge($filters, ['id_area' => $taskArea->getID()]), $start, $limit);
48
49 foreach ($tasks as $taskRecord) {
50 // wrap task record into a registry
51 $task = VBOTaskTaskregistry::getInstance((array) $taskRecord);
52
53 // load task tags
54 $tags = $task->getTags() ? $task->getTagRecords() : [];
55 ?>
56 <div class="vbo-tm-board-area-task-wrap" data-task-id="<?php echo $task->getID(); ?>">
57 <div class="vbo-tm-board-area-task-head">
58 <?php
59 if ($tags) {
60 ?>
61 <div class="vbo-tm-board-area-task-tags">
62 <?php
63 foreach ($tags as $tag) {
64 $tag = (array) $tag;
65 ?>
66 <span class="vbo-tm-board-area-task-tag vbo-tm-task-tag vbo-tm-color <?php echo $tag['color']; ?>"><?php echo $tag['name']; ?></span>
67 <?php
68 }
69 ?>
70 </div>
71 <?php
72 }
73 ?>
74 <div class="vbo-tm-board-area-task-title">
75 <?php echo $task->getTitle(); ?>
76
77 <?php if ($task->get('hasUnreadMessages', false)): ?>
78 <span class="unread-message-dot">
79 <?php VikBookingIcons::e('comment'); ?>
80 </span>
81 <?php endif; ?>
82 </div>
83 <div class="vbo-tm-board-area-task-notes"><?php echo JHtml::fetch('vikbooking.shorten', $task->getNotes(), 120); ?></div>
84 <div class="vbo-tm-board-area-task-due">
85 <?php VikBookingIcons::e('clock'); ?>
86 <span><?php echo $task->getDueDate(true); ?></span>
87 </div>
88 </div>
89 <div class="vbo-tm-board-area-task-body">
90 <div class="vbo-tm-board-area-task-status">
91 <?php
92 if ($taskManager->statusTypeExists($task->getStatus())) {
93 $status = $taskManager->getStatusTypeInstance($task->getStatus());
94 echo JHtml::fetch('vbohtml.taskmanager.status', $status);
95 }
96 ?>
97 </div>
98 <div class="vbo-tm-board-area-task-assignees">
99 <?php
100 foreach ($task->getAssigneeDetails() as $operator) {
101 ?>
102 <span class="vbo-tm-board-area-task-assignee vbo-tm-task-assignee">
103 <span class="vbo-tm-board-area-task-assignee-avatar vbo-tm-task-assignee-avatar" title="<?php echo JHtml::fetch('esc_attr', $operator['name']); ?>">
104 <?php
105 if (!empty($operator['img_uri'])) {
106 ?>
107 <img src="<?php echo $operator['img_uri']; ?>" alt="<?php echo JHtml::fetch('esc_attr', $operator['initials']); ?>" decoding="async" loading="lazy" />
108 <?php
109 } else {
110 ?>
111 <span><?php echo $operator['initials']; ?></span>
112 <?php
113 }
114 ?>
115 </span>
116 </span>
117 <?php
118 }
119 ?>
120 </div>
121 </div>
122 </div>
123 <?php
124 }
125
126 if (!$tasks) {
127 ?>
128 <p class="info" data-no-results="1"><?php echo !$start ? JText::translate('VBO_NO_RECORDS_FOUND') : JText::translate('VBO_NO_MORE_RECORDS'); ?></p>
129 <?php
130 }
131 ?>
132
133 <script type="text/javascript">
134
135 jQuery(function() {
136
137 /**
138 * Register listener for editing an existing task.
139 */
140 document
141 .querySelector('.vbo-tm-board-area-container[data-area-id="<?php echo $taskArea->getID(); ?>"]')
142 .querySelectorAll('.vbo-tm-board-area-task-title')
143 .forEach((taskElement) => {
144 if (taskElement.clickListener) {
145 // listener added already
146 return;
147 }
148
149 taskElement.addEventListener('click', () => {
150 // get the clicked task ID
151 const taskId = taskElement.closest('.vbo-tm-board-area-task-wrap').getAttribute('data-task-id');
152
153 // define the modal delete button
154 let delete_btn = jQuery('<button></button>')
155 .attr('type', 'button')
156 .addClass('btn btn-danger')
157 .text(<?php echo json_encode(JText::translate('VBELIMINA')); ?>)
158 .on('click', function() {
159 if (!confirm(<?php echo json_encode(JText::translate('VBDELCONFIRM')); ?>)) {
160 return false;
161 }
162
163 // disable button to prevent double submissions
164 let submit_btn = jQuery(this);
165 submit_btn.prop('disabled', true);
166
167 // start loading animation
168 VBOCore.emitEvent('vbo-tm-edittask-loading');
169
170 // make the request
171 VBOCore.doAjax(
172 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.deleteTask'); ?>",
173 {
174 data: {
175 id: taskId,
176 },
177 },
178 (resp) => {
179 // trigger filters-changed event on success
180 VBOCore.emitEvent('vbo-tm-filters-changed', {
181 filters: vboTmFilters,
182 });
183
184 // dismiss the modal
185 VBOCore.emitEvent('vbo-tm-edittask-dismiss');
186 },
187 (error) => {
188 // display error message
189 alert(error.responseText);
190
191 // re-enable submit button
192 submit_btn.prop('disabled', false);
193
194 // stop loading
195 VBOCore.emitEvent('vbo-tm-edittask-loading');
196 }
197 );
198 });
199
200 // define the modal save button
201 let save_btn = jQuery('<button></button>')
202 .attr('type', 'button')
203 .addClass('btn btn-success')
204 .text(<?php echo json_encode(JText::translate('VBSAVE')); ?>)
205 .on('click', function() {
206 // disable button to prevent double submissions
207 let submit_btn = jQuery(this);
208 submit_btn.prop('disabled', true);
209
210 // start loading animation
211 VBOCore.emitEvent('vbo-tm-edittask-loading');
212
213 // get form data
214 const taskForm = new FormData(document.querySelector('#vbo-tm-task-manage-form'));
215
216 // build query parameters for the request
217 let qpRequest = new URLSearchParams(taskForm);
218
219 // make sure the request always includes the assignees query parameter, even if the list is empty
220 if (!qpRequest.has('data[assignees][]')) {
221 qpRequest.append('data[assignees][]', []);
222 }
223
224 // make sure the request always includes the tags query parameter, even if the list is empty
225 if (!qpRequest.has('data[tags][]')) {
226 qpRequest.append('data[tags][]', []);
227 }
228
229 // make the request
230 VBOCore.doAjax(
231 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.updateTask'); ?>",
232 qpRequest.toString(),
233 (resp) => {
234 // trigger filters-changed event on success
235 VBOCore.emitEvent('vbo-tm-filters-changed', {
236 filters: vboTmFilters,
237 });
238
239 // dismiss the modal
240 VBOCore.emitEvent('vbo-tm-edittask-dismiss');
241 },
242 (error) => {
243 // display error message
244 alert(error.responseText);
245
246 // re-enable submit button
247 submit_btn.prop('disabled', false);
248
249 // stop loading
250 VBOCore.emitEvent('vbo-tm-edittask-loading');
251 }
252 );
253 });
254
255 // display modal
256 let modalBody = VBOCore.displayModal({
257 suffix: 'tm_edittask_modal',
258 title: <?php echo json_encode(JText::translate('VBO_TASK')); ?> + ' #' + taskId,
259 extra_class: 'vbo-modal-rounded vbo-modal-taller vbo-modal-large',
260 body_prepend: true,
261 lock_scroll: true,
262 escape_dismiss: false,
263 footer_left: delete_btn,
264 footer_right: save_btn,
265 loading_event: 'vbo-tm-edittask-loading',
266 dismiss_event: 'vbo-tm-edittask-dismiss',
267 });
268
269 // start loading animation
270 VBOCore.emitEvent('vbo-tm-edittask-loading');
271
272 // make the request
273 VBOCore.doAjax(
274 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
275 {
276 type: 'tasks.managetask',
277 data: {
278 task_id: taskId,
279 area_id: <?php echo $taskArea->getID(); ?>,
280 form_id: 'vbo-tm-task-manage-form',
281 },
282 },
283 (resp) => {
284 // stop loading
285 VBOCore.emitEvent('vbo-tm-edittask-loading');
286
287 try {
288 // decode the response (if needed), and append the content to the modal body
289 let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
290 modalBody.append(obj_res['html']);
291 } catch (err) {
292 console.error('Error decoding the response', err, resp);
293 }
294 },
295 (error) => {
296 // display error message
297 alert(error.responseText);
298
299 // stop loading
300 VBOCore.emitEvent('vbo-tm-edittask-loading');
301 }
302 );
303 });
304
305 // turn flag on for listener set
306 taskElement.clickListener = true;
307 });
308
309 /**
310 * Dispatch the delayed event to setup the infinite scroll loading.
311 */
312 setTimeout(() => {
313 VBOCore.emitEvent('vbo-tm-board-tasks-loaded', {
314 areaId: <?php echo $taskArea->getID(); ?>,
315 start: <?php echo $start; ?>,
316 limit: <?php echo $limit; ?>,
317 count: <?php echo count($tasks); ?>,
318 });
319 }, 0);
320 });
321
322 </script>
323