PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.12
VikBooking Hotel Booking Engine & PMS v1.8.12
1.8.16 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 All 37 releases
vikbooking / admin / layouts / taskmanager / tasks / managetask.php

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

537 lines 25.8 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 task management form.
18 */
19 extract($displayData);
20
21 // access the task manager object
22 $taskManager = VBOFactory::getTaskManager();
23
24 // wrap the task record, if editing, into a registry
25 $task = VBOTaskTaskregistry::getRecordInstance(($data['task_id'] ?? 0));
26 if (!empty($data['task_id']) && !$task->getID()) {
27 // raise an error
28 throw new RuntimeException('Could not load task record object.', 404);
29 }
30
31 // get the current area/project ID
32 $areaId = $task->getAreaID() ?: $data['area_id'] ?? 0;
33
34 // get the current task area object wrapper
35 $taskArea = VBOTaskArea::getRecordInstance($areaId);
36
37 // inject current area in task registry wrapper
38 $task->setArea($taskArea);
39
40 // get the task area driver
41 $taskDriver = $taskManager->getDriverInstance($taskArea->getType(), [$taskArea]);
42
43 // get the current filters
44 $filters = (array) ($data['filters'] ?? []);
45
46 // get VBO application
47 $vbo_app = VikBooking::getVboApplication();
48
49 // load visual editor assets
50 $vbo_app->loadVisualEditorAssets();
51
52 if (!empty($data['task_id'])) {
53 // fetch task activities history
54 $history = (new VBOHistoryModelDatabase(
55 new VBOTaskHistoryContext((int) $data['task_id'])
56 ))->getItems();
57 } else {
58 $history = [];
59 }
60
61 ?>
62
63 <form method="post" action="#" id="<?php echo $data['form_id'] ?? ''; ?>" class="vbo-managetask-modal-form">
64 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
65 <div class="vbo-params-wrap">
66 <div class="vbo-params-container vbo-tm-task-params-container">
67
68 <?php
69 if (!empty($data['task_id'])) {
70 ?>
71 <input type="hidden" name="data[id]" value="<?php echo $task->getID(); ?>" />
72 <?php
73 }
74 ?>
75 <input type="hidden" name="data[id_area]" value="<?php echo $task->getAreaID(); ?>" />
76
77 <div class="vbo-param-container" style="margin-top: 0; position: relative;">
78 <div class="vbo-param-setting vbo-param-setting-tm-task-title-wrap">
79 <input
80 type="text"
81 name="data[title]"
82 class="vbo-param-setting-tm-task-title-inp"
83 placeholder="<?php echo JHtml::fetch('esc_attr', JText::translate('VBO_ADD_TITLE')); ?>"
84 value="<?php echo JHtml::fetch('esc_attr', $task->get('title', '')); ?>"
85 maxlength="128"
86 />
87 </div>
88
89 <?php if (!empty($data['task_id'])): ?>
90 <a href="javascript:void(0)" class="tm-switch-main-panel" data-unread="0">
91 <?php VikBookingIcons::e('comment') ?>
92 </a>
93 <?php endif; ?>
94 </div>
95
96 <div class="vbo-tm-panel">
97
98 <div class="vbo-tm-panel-editor">
99
100 <div class="vbo-tm-editor-panel vbo-visualeditor-transparent">
101 <?php
102 echo $vbo_app->renderVisualEditor(
103 'data[notes]',
104 $task->get('notes', ''),
105 [
106 'class' => 'vbo-tm-managetask-notes',
107 'style' => 'width: 96%; height: 150px;',
108 ],
109 [
110 'modes' => [
111 'visual',
112 'text',
113 ],
114 'hide_modes' => true,
115 'list_check' => true,
116 'unset_buttons' => [
117 'mailwrapper',
118 'preview',
119 'homelogo',
120 ],
121 'gen_ai' => [
122 'environment' => 'taskmanager',
123 ],
124 ],
125 []
126 );
127 ?>
128 </div>
129
130 <?php if (!empty($data['task_id'])): ?>
131 <div class="vbo-tm-chat-panel" style="display: none; height: 0;">
132 <?php
133 $chat = VBOFactory::getChatMediator();
134
135 echo $chat->render($chat->createContext('task', $data['task_id']), [
136 'assets' => false,
137 'autoread' => false,
138 ]);
139 ?>
140 </div>
141 <?php endif; ?>
142
143 <?php if (count($history) > 1): ?>
144 <div class="vbo-tm-history-panel" style="display: none;">
145 <?php
146 echo JLayoutHelper::render('history.timeline', [
147 'history' => $history,
148 ]);
149 ?>
150 </div>
151 <?php endif; ?>
152
153 </div>
154
155 <div class="vbo-tm-panel-controls">
156
157 <?php
158 if (!empty($data['task_id'])) {
159 ?>
160 <div class="vbo-param-container">
161 <div class="vbo-param-label vbo-param-label-icn-wrap" style="display: flex; justify-content: space-between; align-items: start; margin-right: 0;">
162 <span>
163 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('hashtag'); ?></span>
164 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_TASK'); ?></span>
165 </span>
166 <?php if (count($history) > 1): ?>
167 <a href="javascript:void(0)" class="tm-toggle-history-timeline">
168 <?php VikBookingIcons::e('history') ?>
169 <span><?php echo JText::translate('VBO_HISTORY_SHOW_ACTIVITIES'); ?></span>
170 </a>
171 <?php endif; ?>
172 </div>
173 <div class="vbo-param-setting">
174 <span class="badge badge-info"><?php echo $task->getID(); ?></span>
175 <?php
176 if ($task->isAI()) {
177 ?>
178 <span class="badge badge-ai"><?php echo JText::translate('VBO_AI_LABEL_DEF'); ?></span>
179 <?php
180 }
181 ?>
182 <span class="badge badge"><?php echo $task->getAreaName($task->getAreaID()); ?></span>
183 </div>
184 </div>
185 <?php
186 }
187 ?>
188
189 <div class="vbo-param-container">
190 <div class="vbo-param-label vbo-param-label-icn-wrap">
191 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('calendar'); ?></span>
192 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_DUE_DATE'); ?></span>
193 </div>
194 <div class="vbo-param-setting">
195 <?php
196 $activeDtime = ($filters['calendar_day'] ?? '') ?: ($filters['calendar_month'] ?? '');
197 if ($activeDtime && preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', (string) $activeDtime)) {
198 if (!preg_match('/[0-9]{2}:[0-9]{2}$/', $activeDtime)) {
199 // time not provided
200 $defaultTime = $filters['calendar_time'] ?? '00:00';
201 $activeDtime = date('Y-m-d ' . $defaultTime, strtotime($activeDtime));
202 }
203 } else {
204 $activeDtime = '';
205 }
206 echo $vbo_app->renderDateTimePicker([
207 'name' => 'data[dueon]',
208 'value' => ($task->getDueDate(true, 'Y-m-d H:i') ?: $activeDtime ?: date('Y-m-d 00:00')),
209 ]);
210 ?>
211 </div>
212 </div>
213
214 <?php
215 if (!empty($data['task_id']) && ($task->getBeginDate() || !$task->isFuture())) {
216 // allow to edit the began and finished date-time values
217 ?>
218 <div class="vbo-param-container">
219 <div class="vbo-param-label vbo-param-label-icn-wrap">
220 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('stopwatch'); ?></span>
221 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_BEGIN_DATE'); ?></span>
222 </div>
223 <div class="vbo-param-setting">
224 <?php
225 echo $vbo_app->renderDateTimePicker([
226 'name' => 'data[beganon]',
227 'value' => $task->getBeginDate(true, 'Y-m-d H:i'),
228 ]);
229 ?>
230 </div>
231 </div>
232
233 <div class="vbo-param-container">
234 <div class="vbo-param-label vbo-param-label-icn-wrap">
235 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('calendar-check'); ?></span>
236 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_FINISH_DATE'); ?></span>
237 </div>
238 <div class="vbo-param-setting">
239 <?php
240 echo $vbo_app->renderDateTimePicker([
241 'name' => 'data[finishedon]',
242 'value' => $task->getFinishDate(true, 'Y-m-d H:i'),
243 ]);
244 ?>
245 </div>
246 </div>
247 <?php
248 }
249 ?>
250
251 <div class="vbo-param-container">
252 <div class="vbo-param-label vbo-param-label-icn-wrap">
253 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('clipboard-check'); ?></span>
254 <span class="vbo-param-label-txt"><?php echo JText::translate('VBRENTALORD'); ?></span>
255 </div>
256 <div class="vbo-param-setting">
257 <div class="vbo-singleselect-inline-elems-wrap vbo-search-elems-wrap">
258 <?php
259 echo $vbo_app->renderSearchElementsDropDown([
260 'id' => 'vbo-tm-managetask-idorder',
261 'elements' => 'bookings',
262 'placeholder' => JText::translate('VBO_AITOOL_SEARCH_BOOKINGS'),
263 'allow_clear' => true,
264 'attributes' => [
265 'name' => 'data[id_order]',
266 ],
267 'style_selection' => true,
268 'selected_id' => true,
269 'selection_class' => 'vbo-sel2-selected-search-elem-full',
270 'selected_value' => $task->buildBookingElement((int) ($filters['id_order'] ?? 0)),
271 'selection_click_widget' => 'booking_details',
272 ]);
273 ?>
274 </div>
275 </div>
276 </div>
277
278 <div class="vbo-param-container">
279 <div class="vbo-param-label vbo-param-label-icn-wrap">
280 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('bed'); ?></span>
281 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_LISTING'); ?></span>
282 </div>
283 <div class="vbo-param-setting">
284 <?php
285 echo $vbo_app->renderElementsDropDown([
286 'id' => 'vbo-tm-managetask-idroom',
287 'elements' => 'listings',
288 'element_ids' => $taskDriver->getListingIds(),
289 'placeholder' => JText::translate('VBO_LISTING'),
290 'allow_clear' => true,
291 'attributes' => [
292 'name' => 'data[id_room]',
293 ],
294 'selected_value' => $task->getRoomId() ?: $filters['id_room'] ?? 0,
295 'style_selection' => true,
296 ]);
297 ?>
298 </div>
299 </div>
300
301 <div class="vbo-param-container">
302 <div class="vbo-param-label vbo-param-label-icn-wrap">
303 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('bullseye'); ?></span>
304 <span class="vbo-param-label-txt"><?php echo JText::translate('VBSTATUS'); ?></span>
305 </div>
306 <div class="vbo-param-setting">
307 <div class="vbo-singleselect-inline-elems-wrap vbo-tagcolors-elems-wrap vbo-statuscolors-elems-wrap">
308 <?php
309 echo $vbo_app->renderTagsDropDown([
310 'id' => 'vbo-tm-managetask-status',
311 'placeholder' => JText::translate('VBSTATUS'),
312 'allow_clear' => false,
313 'allow_tags' => false,
314 'attributes' => [
315 'name' => 'data[status_enum]',
316 ],
317 'style_selection' => true,
318 'selected_value' => $task->getStatus(),
319 ], [], $taskArea->getStatusElements($task->getStatus()));
320 ?>
321 </div>
322 </div>
323 </div>
324
325 <div class="vbo-param-container vbo-param-container-full-setting">
326 <div class="vbo-param-label vbo-param-label-icn-wrap">
327 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('users'); ?></span>
328 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_ASSIGNEES'); ?></span>
329 </div>
330 <div class="vbo-param-setting">
331 <div class="vbo-multiselect-inline-elems-wrap">
332 <?php
333 $activeAssignees = ($filters['assignee'] ?? null) ? [(int) $filters['assignee']] : [];
334 echo $vbo_app->renderElementsDropDown([
335 'id' => 'vbo-tm-managetask-assignees',
336 'placeholder' => JText::translate('VBO_ASSIGNEES'),
337 'allow_clear' => false,
338 'attributes' => [
339 'name' => 'data[assignees][]',
340 'multiple' => 'multiple',
341 ],
342 'style_selection' => true,
343 'default_selection_icon' => VikBookingIcons::i('user-tie'),
344 'selected_values' => $task->getAssigneeIds() ?: $activeAssignees,
345 ], $taskDriver->getOperators($elements = true, $activeAssignees));
346 ?>
347 </div>
348 </div>
349 </div>
350
351 <div class="vbo-param-container vbo-param-container-full-setting">
352 <div class="vbo-param-label vbo-param-label-icn-wrap">
353 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('tags'); ?></span>
354 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_TAGS'); ?></span>
355 <span class="vbo-inline-genai-btn">
356 <button type="button" class="btn btn-small vbo-genai-task-tags"><?php echo JText::translate('VBO_AI_LABEL_DEF'); ?></button>
357 </span>
358 </div>
359 <div class="vbo-param-setting">
360 <div class="vbo-multiselect-inline-elems-wrap vbo-tagcolors-elems-wrap">
361 <?php
362 echo $vbo_app->renderTagsDropDown([
363 'id' => 'vbo-tm-managetask-tags',
364 'placeholder' => JText::translate('VBO_TAGS'),
365 'allow_clear' => false,
366 'allow_tags' => false,
367 'attributes' => [
368 'name' => 'data[tags][]',
369 'multiple' => 'multiple',
370 ],
371 'style_selection' => true,
372 'selected_values' => $task->getTags(),
373 ], $taskArea->getTagRecords());
374 ?>
375 </div>
376 </div>
377 </div>
378
379 </div>
380
381 </div>
382
383 </div>
384 </div>
385 </div>
386
387 </form>
388
389 <script>
390 (function($) {
391 'use strict';
392
393 <?php if (!empty($data['task_id'])): ?>
394
395 const refreshBadgeCount = (chat) => {
396 // observe only the current chat
397 if (chat.data.environment.context.alias != 'task' || chat.data.environment.context.id != <?php echo (int) $data['task_id']; ?>) {
398 return;
399 }
400
401 $('.tm-switch-main-panel').attr('data-unread', chat.getUnreadMessagesCount());
402 }
403
404 window.addEventListener('chat.sync', (event) => {
405 refreshBadgeCount(event.detail.chat);
406 });
407
408 window.addEventListener('chat.read', (event) => {
409 refreshBadgeCount(event.detail.chat);
410 });
411
412 $(function() {
413 $('.vbo-tm-chat-panel .chat-input-footer').css('padding', '0 10px');
414
415 refreshBadgeCount(VBOChat.getInstance());
416
417 $('.tm-switch-main-panel').on('click', function() {
418 $('.vbo-tm-history-panel').hide();
419 $('.tm-toggle-history-timeline').find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_SHOW_ACTIVITIES')); ?>);
420
421 const chat = VBOChat.getInstance();
422
423 if ($('.vbo-tm-editor-panel').is(':visible')) {
424 $('.vbo-tm-editor-panel').hide();
425 $('.vbo-tm-chat-panel').show();
426
427 $(this).find('i').attr('class', '<?php echo VikBookingIcons::i('comment-slash'); ?>');
428
429 $('.vbo-tm-chat-panel').css('max-height', ($('.vbo-tm-panel-controls').outerHeight()) + 'px');
430 $('.vbo-tm-chat-panel').css('height', ($('.vbo-tm-panel-controls').outerHeight()) + 'px');
431
432 // scroll chat
433 chat.scrollToBottom();
434
435 // auto-read messages again
436 chat.data.environment.options.autoread = true;
437 chat.readNotifications();
438
439 // auto-scroll modal too
440 $('.vbo-modal-overlay-content-body-scroll').scrollTop($('.vbo-modal-overlay-content-body-scroll')[0].scrollHeight + 200);
441 } else {
442 $('.vbo-tm-editor-panel').show();
443 $('.vbo-tm-chat-panel').hide();
444
445 $(this).find('i').attr('class', '<?php echo VikBookingIcons::i('comment'); ?>');
446
447 // stop auto-reading messages when the chat hasn't the focus
448 chat.data.environment.options.autoread = false;
449 }
450 });
451
452 $('.tm-toggle-history-timeline').on('click', function() {
453 if ($('.vbo-tm-history-panel').is(':visible')) {
454 $(this).find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_SHOW_ACTIVITIES')); ?>);
455 $('.tm-switch-main-panel').trigger('click');
456 } else {
457 $(this).find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_HIDE_ACTIVITIES')); ?>);
458 $('.vbo-tm-editor-panel, .vbo-tm-chat-panel').hide();
459 $('.vbo-tm-history-panel').show();
460 }
461 });
462
463 document.addEventListener('vbo-modal-dismissed', (event) => {
464 VBOChat.getInstance().destroy();
465 }, {
466 once: true,
467 });
468
469 });
470
471 <?php endif; ?>
472
473 $(function() {
474 <?php if (!$task->get('title', '')): ?>
475 $('.vbo-param-setting-tm-task-title-inp').focus();
476 <?php endif; ?>
477
478 document.querySelector('.vbo-genai-task-tags').addEventListener('click', (e) => {
479 let btn = e.target;
480
481 // get button default text
482 let btnDefText = btn.innerText;
483
484 // prevent double submissions
485 btn.disabled = true;
486
487 // set icon loading animation
488 btn.innerHTML = '<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>';
489
490 VBOCore.doAjax(
491 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=ai.extractTaskTags'); ?>",
492 {
493 area_id: '<?php echo $areaId; ?>',
494 task_id: '<?php echo (int) ($data['task_id'] ?? 0); ?>',
495 task_title: document.querySelector('.vbo-param-setting-tm-task-title-inp')?.value,
496 task_notes: document.querySelector('.vbo-tm-managetask-notes')?.value,
497 booking_id: document.querySelector('#vbo-tm-managetask-idorder')?.value,
498 listing_id: document.querySelector('#vbo-tm-managetask-idroom')?.value,
499 },
500 (resp) => {
501 let tagsElement = document.querySelector('#vbo-tm-managetask-tags');
502
503 if (Array.isArray(resp?.tags)) {
504 resp.tags.forEach((tag) => {
505 Array.from(tagsElement.options).forEach((tagOpt) => {
506 if (tagOpt.value == tag?.id) {
507 tagOpt.selected = true;
508 }
509 });
510 });
511
512 tagsElement.dispatchEvent(new Event('change'));
513 }
514
515 // restore button text
516 btn.innerHTML = '';
517 btn.innerText = btnDefText;
518
519 // restore the button
520 btn.disabled = false;
521 },
522 (error) => {
523 // display the error
524 alert(error.responseText || 'An error occurred');
525
526 // restore button text
527 btn.innerHTML = '';
528 btn.innerText = btnDefText;
529
530 // restore the button
531 btn.disabled = false;
532 }
533 );
534 });
535 });
536 })(jQuery);
537 </script>