PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
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.16, at admin/layouts/taskmanager/tasks/managetask.php

540 lines 26.0 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 <?php echo $taskDriver->onManageTask('sidebar.details', $task, $taskArea); ?>
185 </div>
186 <?php
187 }
188 ?>
189
190 <div class="vbo-param-container">
191 <div class="vbo-param-label vbo-param-label-icn-wrap">
192 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('calendar'); ?></span>
193 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_DUE_DATE'); ?></span>
194 </div>
195 <div class="vbo-param-setting">
196 <?php
197 $activeDtime = ($filters['calendar_day'] ?? '') ?: ($filters['calendar_month'] ?? '');
198 if ($activeDtime && preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', (string) $activeDtime)) {
199 if (!preg_match('/[0-9]{2}:[0-9]{2}$/', $activeDtime)) {
200 // time not provided
201 $defaultTime = $filters['calendar_time'] ?? '00:00';
202 $activeDtime = date('Y-m-d ' . $defaultTime, strtotime($activeDtime));
203 }
204 } else {
205 $activeDtime = '';
206 }
207 echo $vbo_app->renderDateTimePicker([
208 'name' => 'data[dueon]',
209 'value' => ($task->getDueDate(true, 'Y-m-d H:i') ?: $activeDtime ?: date('Y-m-d 00:00')),
210 ]);
211 ?>
212 </div>
213 </div>
214
215 <?php
216 if (!empty($data['task_id']) && ($task->getBeginDate() || !$task->isFuture())) {
217 // allow to edit the began and finished date-time values
218 ?>
219 <div class="vbo-param-container">
220 <div class="vbo-param-label vbo-param-label-icn-wrap">
221 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('stopwatch'); ?></span>
222 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_BEGIN_DATE'); ?></span>
223 </div>
224 <div class="vbo-param-setting">
225 <?php
226 echo $vbo_app->renderDateTimePicker([
227 'name' => 'data[beganon]',
228 'value' => $task->getBeginDate(true, 'Y-m-d H:i'),
229 ]);
230 ?>
231 </div>
232 </div>
233
234 <div class="vbo-param-container">
235 <div class="vbo-param-label vbo-param-label-icn-wrap">
236 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('calendar-check'); ?></span>
237 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_FINISH_DATE'); ?></span>
238 </div>
239 <div class="vbo-param-setting">
240 <?php
241 echo $vbo_app->renderDateTimePicker([
242 'name' => 'data[finishedon]',
243 'value' => $task->getFinishDate(true, 'Y-m-d H:i'),
244 ]);
245 ?>
246 </div>
247 </div>
248 <?php
249 }
250 ?>
251
252 <div class="vbo-param-container">
253 <div class="vbo-param-label vbo-param-label-icn-wrap">
254 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('clipboard-check'); ?></span>
255 <span class="vbo-param-label-txt"><?php echo JText::translate('VBRENTALORD'); ?></span>
256 </div>
257 <div class="vbo-param-setting">
258 <div class="vbo-singleselect-inline-elems-wrap vbo-search-elems-wrap">
259 <?php
260 echo $vbo_app->renderSearchElementsDropDown([
261 'id' => 'vbo-tm-managetask-idorder',
262 'elements' => 'bookings',
263 'placeholder' => JText::translate('VBO_AITOOL_SEARCH_BOOKINGS'),
264 'allow_clear' => true,
265 'attributes' => [
266 'name' => 'data[id_order]',
267 ],
268 'style_selection' => true,
269 'selected_id' => true,
270 'selection_class' => 'vbo-sel2-selected-search-elem-full',
271 'selected_value' => $task->buildBookingElement((int) ($filters['id_order'] ?? 0)),
272 'selection_click_widget' => 'booking_details',
273 ]);
274 ?>
275 </div>
276 </div>
277 </div>
278
279 <div class="vbo-param-container">
280 <div class="vbo-param-label vbo-param-label-icn-wrap">
281 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('bed'); ?></span>
282 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_LISTING'); ?></span>
283 </div>
284 <div class="vbo-param-setting">
285 <?php
286 echo $vbo_app->renderElementsDropDown([
287 'id' => 'vbo-tm-managetask-idroom',
288 'elements' => 'listings',
289 'element_ids' => $taskDriver->getListingIds(),
290 'placeholder' => JText::translate('VBO_LISTING'),
291 'allow_clear' => true,
292 'attributes' => [
293 'name' => 'data[id_room]',
294 ],
295 'selected_value' => $task->getRoomId() ?: $filters['id_room'] ?? 0,
296 'style_selection' => true,
297 ]);
298 ?>
299 </div>
300 </div>
301
302 <div class="vbo-param-container">
303 <div class="vbo-param-label vbo-param-label-icn-wrap">
304 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('bullseye'); ?></span>
305 <span class="vbo-param-label-txt"><?php echo JText::translate('VBSTATUS'); ?></span>
306 </div>
307 <div class="vbo-param-setting">
308 <div class="vbo-singleselect-inline-elems-wrap vbo-tagcolors-elems-wrap vbo-statuscolors-elems-wrap">
309 <?php
310 echo $vbo_app->renderTagsDropDown([
311 'id' => 'vbo-tm-managetask-status',
312 'placeholder' => JText::translate('VBSTATUS'),
313 'allow_clear' => false,
314 'allow_tags' => false,
315 'attributes' => [
316 'name' => 'data[status_enum]',
317 ],
318 'style_selection' => true,
319 'selected_value' => $task->getStatus(),
320 ], [], $taskArea->getStatusElements($task->getStatus()));
321 ?>
322 </div>
323 </div>
324 </div>
325
326 <div class="vbo-param-container vbo-param-container-full-setting">
327 <div class="vbo-param-label vbo-param-label-icn-wrap">
328 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('users'); ?></span>
329 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_ASSIGNEES'); ?></span>
330 </div>
331 <div class="vbo-param-setting">
332 <div class="vbo-multiselect-inline-elems-wrap">
333 <?php
334 $activeAssignees = ($filters['assignee'] ?? null) ? [(int) $filters['assignee']] : [];
335 echo $vbo_app->renderElementsDropDown([
336 'id' => 'vbo-tm-managetask-assignees',
337 'placeholder' => JText::translate('VBO_ASSIGNEES'),
338 'allow_clear' => false,
339 'attributes' => [
340 'name' => 'data[assignees][]',
341 'multiple' => 'multiple',
342 ],
343 'style_selection' => true,
344 'default_selection_icon' => VikBookingIcons::i('user-tie'),
345 'selected_values' => $task->getAssigneeIds() ?: $activeAssignees,
346 ], $taskDriver->getOperators($elements = true, $activeAssignees));
347 ?>
348 </div>
349 </div>
350 </div>
351
352 <div class="vbo-param-container vbo-param-container-full-setting">
353 <div class="vbo-param-label vbo-param-label-icn-wrap">
354 <span class="vbo-param-label-icn"><?php VikBookingIcons::e('tags'); ?></span>
355 <span class="vbo-param-label-txt"><?php echo JText::translate('VBO_TAGS'); ?></span>
356 <span class="vbo-inline-genai-btn">
357 <button type="button" class="btn btn-small vbo-genai-task-tags"><?php echo JText::translate('VBO_AI_LABEL_DEF'); ?></button>
358 </span>
359 </div>
360 <div class="vbo-param-setting">
361 <div class="vbo-multiselect-inline-elems-wrap vbo-tagcolors-elems-wrap">
362 <?php
363 echo $vbo_app->renderTagsDropDown([
364 'id' => 'vbo-tm-managetask-tags',
365 'placeholder' => JText::translate('VBO_TAGS'),
366 'allow_clear' => false,
367 'allow_tags' => false,
368 'attributes' => [
369 'name' => 'data[tags][]',
370 'multiple' => 'multiple',
371 ],
372 'style_selection' => true,
373 'selected_values' => $task->getTags(),
374 ], $taskArea->getTagRecords());
375 ?>
376 </div>
377 </div>
378 </div>
379
380 <?php echo $taskDriver->onManageTask('sidebar.bottom', $task, $taskArea); ?>
381
382 </div>
383
384 </div>
385
386 </div>
387 </div>
388 </div>
389
390 </form>
391
392 <script>
393 (function($) {
394 'use strict';
395
396 <?php if (!empty($data['task_id'])): ?>
397
398 const refreshBadgeCount = (chat) => {
399 // observe only the current chat
400 if (chat.data.environment.context.alias != 'task' || chat.data.environment.context.id != <?php echo (int) $data['task_id']; ?>) {
401 return;
402 }
403
404 $('.tm-switch-main-panel').attr('data-unread', chat.getUnreadMessagesCount());
405 }
406
407 window.addEventListener('chat.sync', (event) => {
408 refreshBadgeCount(event.detail.chat);
409 });
410
411 window.addEventListener('chat.read', (event) => {
412 refreshBadgeCount(event.detail.chat);
413 });
414
415 $(function() {
416 $('.vbo-tm-chat-panel .chat-input-footer').css('padding', '0 10px');
417
418 refreshBadgeCount(VBOChat.getInstance());
419
420 $('.tm-switch-main-panel').on('click', function() {
421 $('.vbo-tm-history-panel').hide();
422 $('.tm-toggle-history-timeline').find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_SHOW_ACTIVITIES')); ?>);
423
424 const chat = VBOChat.getInstance();
425
426 if ($('.vbo-tm-editor-panel').is(':visible')) {
427 $('.vbo-tm-editor-panel').hide();
428 $('.vbo-tm-chat-panel').show();
429
430 $(this).find('i').attr('class', '<?php echo VikBookingIcons::i('comment-slash'); ?>');
431
432 $('.vbo-tm-chat-panel').css('max-height', ($('.vbo-tm-panel-controls').outerHeight()) + 'px');
433 $('.vbo-tm-chat-panel').css('height', ($('.vbo-tm-panel-controls').outerHeight()) + 'px');
434
435 // scroll chat
436 chat.scrollToBottom();
437
438 // auto-read messages again
439 chat.data.environment.options.autoread = true;
440 chat.readNotifications();
441
442 // auto-scroll modal too
443 $('.vbo-modal-overlay-content-body-scroll').scrollTop($('.vbo-modal-overlay-content-body-scroll')[0].scrollHeight + 200);
444 } else {
445 $('.vbo-tm-editor-panel').show();
446 $('.vbo-tm-chat-panel').hide();
447
448 $(this).find('i').attr('class', '<?php echo VikBookingIcons::i('comment'); ?>');
449
450 // stop auto-reading messages when the chat hasn't the focus
451 chat.data.environment.options.autoread = false;
452 }
453 });
454
455 $('.tm-toggle-history-timeline').on('click', function() {
456 if ($('.vbo-tm-history-panel').is(':visible')) {
457 $(this).find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_SHOW_ACTIVITIES')); ?>);
458 $('.tm-switch-main-panel').trigger('click');
459 } else {
460 $(this).find('span').text(<?php echo json_encode(JText::translate('VBO_HISTORY_HIDE_ACTIVITIES')); ?>);
461 $('.vbo-tm-editor-panel, .vbo-tm-chat-panel').hide();
462 $('.vbo-tm-history-panel').show();
463 }
464 });
465
466 document.addEventListener('vbo-modal-dismissed', (event) => {
467 VBOChat.getInstance().destroy();
468 }, {
469 once: true,
470 });
471
472 });
473
474 <?php endif; ?>
475
476 $(function() {
477 <?php if (!$task->get('title', '')): ?>
478 $('.vbo-param-setting-tm-task-title-inp').focus();
479 <?php endif; ?>
480
481 document.querySelector('.vbo-genai-task-tags').addEventListener('click', (e) => {
482 let btn = e.target;
483
484 // get button default text
485 let btnDefText = btn.innerText;
486
487 // prevent double submissions
488 btn.disabled = true;
489
490 // set icon loading animation
491 btn.innerHTML = '<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>';
492
493 VBOCore.doAjax(
494 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=ai.extractTaskTags'); ?>",
495 {
496 area_id: '<?php echo $areaId; ?>',
497 task_id: '<?php echo (int) ($data['task_id'] ?? 0); ?>',
498 task_title: document.querySelector('.vbo-param-setting-tm-task-title-inp')?.value,
499 task_notes: document.querySelector('.vbo-tm-managetask-notes')?.value,
500 booking_id: document.querySelector('#vbo-tm-managetask-idorder')?.value,
501 listing_id: document.querySelector('#vbo-tm-managetask-idroom')?.value,
502 },
503 (resp) => {
504 let tagsElement = document.querySelector('#vbo-tm-managetask-tags');
505
506 if (Array.isArray(resp?.tags)) {
507 resp.tags.forEach((tag) => {
508 Array.from(tagsElement.options).forEach((tagOpt) => {
509 if (tagOpt.value == tag?.id) {
510 tagOpt.selected = true;
511 }
512 });
513 });
514
515 tagsElement.dispatchEvent(new Event('change'));
516 }
517
518 // restore button text
519 btn.innerHTML = '';
520 btn.innerText = btnDefText;
521
522 // restore the button
523 btn.disabled = false;
524 },
525 (error) => {
526 // display the error
527 alert(error.responseText || 'An error occurred');
528
529 // restore button text
530 btn.innerHTML = '';
531 btn.innerText = btnDefText;
532
533 // restore the button
534 btn.disabled = false;
535 }
536 );
537 });
538 });
539 })(jQuery);
540 </script>