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.php

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

713 lines 27.5 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 JHtml::fetch('vbohtml.tmscripts.changestatus');
15
16 // access the VBO application
17 $vbo_app = VikBooking::getVboApplication();
18
19 // load context menu assets
20 $vbo_app->loadContextMenuAssets();
21
22 // access task manager
23 $taskManager = VBOFactory::getTaskManager();
24
25 // get all areas
26 $allAreas = VBOTaskModelArea::getInstance()->getItems([], 0, 0, ['id', 'name']);
27
28 // preload the chat assets
29 VBOFactory::getChatMediator()->useAssets();
30
31 JText::script('VBO_SEARCH_TASKS');
32
33 ?>
34
35 <form action="index.php?option=com_vikbooking" method="post" name="adminForm" id="adminForm"></form>
36
37 <div class="vbo-tm-settings-helper" style="display: none;">
38 <div class="vbo-tm-settings-wrapper">
39 <form method="post" id="vbo-tm-settings-form">
40 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
41 <div class="vbo-params-wrap">
42 <div class="vbo-params-container">
43 <div class="vbo-params-block">
44 <?php
45 // render all params/settings
46 echo VBOParamsRendering::getInstance(
47 [
48 'tm_op_assignment_strategy' => [
49 'type' => 'select',
50 'label' => JText::translate('VBO_TM_OP_ASSIGN_STRATEGY'),
51 'help' => JText::translate('VBO_TM_OP_ASSIGN_STRATEGY_HELP'),
52 'options' => [
53 'balanced' => JText::translate('VBO_TM_OP_ASSIGN_STRATEGY_BALANCED'),
54 'sequential' => JText::translate('VBO_TM_OP_ASSIGN_STRATEGY_SEQUENTIAL'),
55 ],
56 ],
57 ],
58 [
59 'tm_op_assignment_strategy' => VBOFactory::getConfig()->get('tm_op_assignment_strategy', 'balanced'),
60 ]
61 )->setInputName('settings')->getHtml();
62 ?>
63 </div>
64 </div>
65 </div>
66 </div>
67 </form>
68 </div>
69 </div>
70
71 <div class="vbo-tm-wrapper" style="<?php echo $allAreas ? '' : 'display: none;'; ?>">
72
73 <div class="vbo-tm-toolbar">
74
75 <div class="vbo-tm-toolbar-header">
76
77 <div class="vbo-tm-areas-ctx">
78 <?php
79 // display task manager areas context-menu
80 $layout_data = [
81 'caller' => 'taskmanager',
82 'events' => [
83 'render_task' => 'vbo-tm-area-render-task',
84 'hide_task' => 'vbo-tm-area-hide-task',
85 'update_areas' => 'vbo-tm-area-update-status',
86 ],
87 'active' => $this->activeAreas,
88 ];
89
90 echo JLayoutHelper::render('taskmanager.areas.contextmenu', $layout_data);
91 ?>
92 </div>
93
94 <div class="vbo-tm-modes">
95 <?php
96 foreach ($this->allowedModes as $mode => $mode_data) {
97 ?>
98 <span class="vbo-tm-mode mode-<?php echo $mode . ($mode == $this->mode ? ' mode-active' : ''); ?>" data-mode="<?php echo $mode; ?>"<?php echo ($mode_data['link'] ?? '') ? ' data-link="' . $mode_data['link'] . '"' : ''; ?>>
99 <?php
100 if ($mode_data['link'] ?? '') {
101 // handle the external view link differently
102 ?>
103 <a href="<?php echo $mode_data['link']; ?>"><?php VikBookingIcons::e($mode_data['icon']); ?> <?php echo $mode_data['name']; ?></a>
104 <?php
105 } else {
106 // regular taskmanager view mode
107 ?>
108 <a href="index.php?option=com_vikbooking&view=taskmanager&mode=<?php echo $mode; ?>"><?php VikBookingIcons::e($mode_data['icon']); ?> <?php echo $mode_data['name']; ?></a>
109 <?php
110 }
111 ?>
112 </span>
113 <?php
114 }
115 ?>
116 </div>
117
118 <?php
119 if ($allAreas) {
120 ?>
121 <div class="vbo-tm-newtask">
122 <button type="button" class="btn vbo-context-menu-tm-newtask">
123 <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('plus'); ?></span>
124 <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBO_NEW_TASK'); ?></span>
125 </button>
126 </div>
127 <?php
128 }
129 ?>
130
131 </div>
132
133 <div class="vbo-tm-toolbar-filters">
134
135 <div class="vbo-tm-toolbar-filter vbo-tm-statustype-ctx">
136 <?php
137 // display task manager status-types context-menu
138 $layout_data = [
139 'caller' => 'taskmanager',
140 'events' => [
141 'filter_status' => 'vbo-tm-apply-filters',
142 ],
143 'filters' => $this->filters,
144 ];
145
146 echo JLayoutHelper::render('taskmanager.statuses.contextmenu', $layout_data);
147 ?>
148 </div>
149
150 <?php
151 // display task manager color-tags context-menu
152 $layout_data = [
153 'caller' => 'taskmanager',
154 'events' => [
155 'filter_tag' => 'vbo-tm-apply-filters',
156 ],
157 'filters' => $this->filters,
158 ];
159
160 $tagsDropdown = JLayoutHelper::render('taskmanager.colortags.contextmenu', $layout_data);
161
162 if ($tagsDropdown): ?>
163 <div class="vbo-tm-toolbar-filter vbo-tm-colortags-ctx">
164 <?php echo $tagsDropdown; ?>
165 </div>
166 <?php endif; ?>
167
168 <div class="vbo-tm-toolbar-filter vbo-tm-dates-ctx">
169 <?php
170 // display task manager dates context-menu
171 $layout_data = [
172 'caller' => 'taskmanager',
173 'events' => [
174 'filter_dates' => 'vbo-tm-apply-filters',
175 ],
176 'filters' => $this->filters,
177 ];
178
179 echo JLayoutHelper::render('taskmanager.dates.contextmenu', $layout_data);
180 ?>
181 </div>
182
183 <div class="vbo-tm-toolbar-filter vbo-tm-filter-sel2 vbo-tm-filter-assignee<?php echo ($this->filters['assignee'] ?? null) ? ' vbo-tm-filter-active' : ''; ?>">
184 <div class="vbo-singleselect-inline-elems-wrap vbo-search-elems-wrap">
185 <?php
186 echo $vbo_app->renderElementsDropDown([
187 'id' => 'vbo-tm-filter-assignee',
188 'placeholder' => JText::translate('VBO_ASSIGNEE'),
189 'allow_clear' => true,
190 'attributes' => [
191 'name' => 'filters[assignee]',
192 'onchange' => "VBOCore.emitEvent('vbo-tm-apply-filters', {filters: {assignee: this.value}}); this.value ? jQuery('.vbo-tm-filter-assignee').addClass('vbo-tm-filter-active') : jQuery('.vbo-tm-filter-assignee').removeClass('vbo-tm-filter-active')",
193 ],
194 'style_selection' => true,
195 'default_selection_icon' => VikBookingIcons::i('user-tie'),
196 'selected_value' => $this->filters['assignee'] ?? null,
197 'width' => '200px',
198 ], VikBooking::getOperatorInstance()->getElements(), [
199 [
200 'text' => JText::translate('VBO_UNASSIGNED'),
201 'elements' => [
202 [
203 'id' => -1,
204 'text' => JText::translate('VBO_UNASSIGNED'),
205 ],
206 ],
207 ],
208 ]);
209 ?>
210 </div>
211 </div>
212
213 <div class="vbo-tm-toolbar-filter vbo-tm-filter-sel2 vbo-tm-filter-listing<?php echo ($this->filters['id_room'] ?? null) ? ' vbo-tm-filter-active' : ''; ?>">
214 <div class="vbo-singleselect-inline-elems-wrap vbo-search-elems-wrap">
215 <?php
216 echo $vbo_app->renderElementsDropDown([
217 'id' => 'vbo-tm-filter-idroom',
218 'elements' => 'listings',
219 'load_categories' => true,
220 'placeholder' => JText::translate('VBO_LISTING'),
221 'allow_clear' => true,
222 'attributes' => [
223 'name' => 'filters[id_room]',
224 'onchange' => "VBOCore.emitEvent('vbo-tm-apply-filters', {filters: {id_room: this.value}}); this.value ? jQuery('.vbo-tm-filter-listing').addClass('vbo-tm-filter-active') : jQuery('.vbo-tm-filter-listing').removeClass('vbo-tm-filter-active')",
225 ],
226 'style_selection' => true,
227 'default_selection_icon' => VikBookingIcons::i('bed'),
228 'selected_value' => $this->filters['id_room'] ?? null,
229 'width' => '200px',
230 ]);
231 ?>
232 </div>
233 </div>
234
235 <div class="vbo-tm-toolbar-filter vbo-tm-filter-sel2 vbo-tm-filter-booking<?php echo ($this->filters['id_order'] ?? null) ? ' vbo-tm-filter-active' : ''; ?>">
236 <div class="vbo-singleselect-inline-elems-wrap vbo-search-elems-wrap">
237 <?php
238 echo $vbo_app->renderSearchElementsDropDown([
239 'id' => 'vbo-tm-filter-idorder',
240 'elements' => 'bookings',
241 'placeholder' => JText::translate('VBO_AITOOL_SEARCH_BOOKINGS'),
242 'allow_clear' => true,
243 'attributes' => [
244 'name' => 'filters[id_order]',
245 'onchange' => "VBOCore.emitEvent('vbo-tm-apply-filters', {filters: {id_order: this.value}}); this.value ? jQuery('.vbo-tm-filter-booking').addClass('vbo-tm-filter-active') : jQuery('.vbo-tm-filter-booking').removeClass('vbo-tm-filter-active')",
246 ],
247 'style_selection' => true,
248 'selected_id' => true,
249 'selection_class' => 'vbo-sel2-selected-search-elem-full',
250 'selected_value' => $taskManager->buildBookingElement((int) ($this->filters['id_order'] ?? null)),
251 'width' => '250px',
252 ]);
253 ?>
254 </div>
255 </div>
256
257 <div class="vbo-tm-toolbar-filter vbo-tm-filter-search<?php echo ($this->filters['search'] ?? null) ? ' vbo-tm-filter-active' : ''; ?>">
258 <a href="javascript:void(0)" id="vbo-tm-filter-search">
259 <?php VikBookingIcons::e('search', 'fa-3x'); ?>
260 </a>
261 <script>
262 (function($) {
263 'use strict';
264
265 $(function() {
266 $('.vbo-tm-filter-search').on('click', function() {
267 const searchLink = $(this);
268
269 const overlay = $('<div class="vbo-tm-filter-search-overlay"></div>');
270
271 overlay.on('mousedown', (event) => {
272 if ($(event.target).is(overlay)) {
273 overlay.remove();
274 }
275 });
276
277 const handleEscape = (event) => {
278 if (event.key === 'Escape' || event.key === 'Enter') {
279 overlay.remove();
280 $(window).off('keydown', handleEscape);
281 }
282 }
283
284 $(window).on('keydown', handleEscape);
285
286 const component = $('<div class="finder-box"><?php VikBookingIcons::e('search', 'search'); ?></div>');
287 overlay.append(component);
288
289 const input = $('<input type="text" />')
290 .attr('placeholder', Joomla.JText._('VBO_SEARCH_TASKS'))
291 .val(vboTmFilters.search || '');
292
293 component.append(input);
294
295 let lastValue = input.val();
296
297 const clear = $('<?php VikBookingIcons::e('times-circle', 'clear'); ?>');
298 component.append(clear);
299
300 clear.on('click', () => {
301 input.val('').trigger('keydown');
302 handleEscape({key: 'Escape'});
303 });
304
305 if (!lastValue) {
306 clear.hide();
307 }
308
309 input.on('keydown', VBOCore.debounceEvent((event) => {
310 const newValue = input.val();
311
312 if (event.key === 'Escape') {
313 // prevent search
314 return;
315 }
316
317 if (newValue.toLowerCase().trim() == lastValue.toLowerCase().trim()) {
318 // nothing has changed
319 return;
320 }
321
322 lastValue = newValue;
323
324 VBOCore.emitEvent('vbo-tm-apply-filters', {
325 filters: {
326 search: newValue,
327 },
328 });
329
330 if (newValue) {
331 searchLink.addClass('vbo-tm-filter-active');
332 clear.show();
333 } else {
334 searchLink.removeClass('vbo-tm-filter-active');
335 clear.hide();
336 }
337 }, 300));
338
339 $('body').append(overlay);
340
341 input.focus();
342 });
343 });
344 })(jQuery);
345 </script>
346 </div>
347
348 </div>
349
350 </div>
351
352 <div class="vbo-tm-content">
353 <?php
354 /**
355 * Render the current template mode.
356 */
357 echo $this->loadTemplate($this->mode);
358 ?>
359 </div>
360
361 </div>
362
363 <?php
364 if (!$allAreas) {
365 echo JLayoutHelper::render('taskmanager.areas.blank');
366 }
367 ?>
368
369 <script type="text/javascript">
370 /**
371 * Register the global filters object.
372 */
373 const vboTmFilters = <?php echo json_encode(($this->filters ?: (new stdClass))); ?>;
374
375 /**
376 * Register all area details.
377 */
378 const vboTmAllAreas = <?php echo json_encode($allAreas); ?>;
379
380 /**
381 * Register the active area IDs.
382 */
383 const vboTmActiveAreas = <?php echo json_encode($this->activeAreas); ?>;
384
385 /**
386 * Listen to the event for applying new filters.
387 */
388 document.addEventListener('vbo-tm-apply-filters', (e) => {
389 if (!e || !e.detail || !e.detail.filters || typeof e.detail.filters !== 'object') {
390 return;
391 }
392
393 for (const [type, value] of Object.entries(e.detail.filters)) {
394 // set the requested filter value
395 vboTmFilters[type] = value;
396 }
397
398 // handle external button links with dynamic filters
399 vboTmApplyLinkFilters(vboTmFilters);
400
401 // dispatch the filters-changed event
402 VBOCore.emitEvent('vbo-tm-filters-changed', {
403 filters: vboTmFilters,
404 });
405 });
406
407 /**
408 * Listen to the event for showing a new area/project.
409 */
410 document.addEventListener('vbo-tm-area-render-task', () => {
411 // handle external button links with dynamic filters
412 vboTmApplyLinkFilters();
413 });
414
415 /**
416 * Listen to the event for hiding an area/project.
417 */
418 document.addEventListener('vbo-tm-area-hide-task', () => {
419 // handle external button links with dynamic filters
420 vboTmApplyLinkFilters();
421 });
422
423 /**
424 * Listen to the event for updating the areas/projects.
425 */
426 document.addEventListener('vbo-tm-area-update-status', () => {
427 // handle external button links with dynamic filters
428 vboTmApplyLinkFilters();
429 });
430
431 /**
432 * Register function for building external button links with dynamic filters.
433 */
434 const vboTmApplyLinkFilters = (filters) => {
435 // gather the filters to apply
436 filters = Object.assign({}, (filters || vboTmFilters));
437
438 // start the search params object
439 let searchParams = new URLSearchParams();
440
441 // iterate over all filter object properties
442 for (const [type, value] of Object.entries(filters)) {
443 // set the search param key and value
444 if (value != null && value != '') {
445 searchParams.set('tmfilters[' + type + ']', value);
446 }
447 }
448
449 // set the active areas/projects
450 if (Array.isArray(vboTmActiveAreas) && vboTmActiveAreas.length) {
451 vboTmActiveAreas.forEach((areaId) => {
452 // append the search param key and value
453 searchParams.append('tmfilters[area_ids][]', areaId);
454 });
455 }
456
457 // build the additional query string for the links
458 let queryParams = searchParams.toString();
459
460 // iterate over all button with external links
461 document.querySelectorAll('.vbo-tm-modes .vbo-tm-mode[data-link]').forEach((btnLink) => {
462 let base_link = btnLink.getAttribute('data-link');
463 let final_link = base_link + '&' + queryParams;
464 let anchor = btnLink.querySelector('a');
465 if (!anchor) {
466 return;
467 }
468 anchor.setAttribute('href', final_link);
469 });
470 };
471
472 /**
473 * Register function to silently toggle the task area active state.
474 */
475 const vboTmToggleAreaDisplay = (areaId, display) => {
476 VBOCore.doAjax(
477 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.toggleAreaDisplay'); ?>",
478 {
479 area: {
480 id: areaId,
481 display: (typeof display === 'undefined' ? -1 : display),
482 },
483 },
484 (resp) => {
485 // do nothing on success
486 },
487 (error) => {
488 // silently log the error
489 console.error(error.responseText);
490 }
491 );
492 };
493
494 /**
495 * Register listener for creating a new task.
496 */
497 document.addEventListener('vbo-tm-newtask-trigger', (e) => {
498 // obtain the area ID and filters
499 const areaId = e?.detail?.areaId;
500 const filters = e?.detail?.filters || vboTmFilters;
501
502 if (!areaId) {
503 return;
504 }
505
506 // define the modal cancel button
507 let cancel_btn = jQuery('<button></button>')
508 .attr('type', 'button')
509 .addClass('btn')
510 .text(<?php echo json_encode(JText::translate('VBANNULLA')); ?>)
511 .on('click', () => {
512 VBOCore.emitEvent('vbo-tm-newtask-dismiss');
513 });
514
515 // define the modal save button
516 let save_btn = jQuery('<button></button>')
517 .attr('type', 'button')
518 .addClass('btn btn-success')
519 .text(<?php echo json_encode(JText::translate('VBSAVE')); ?>)
520 .on('click', function() {
521 // disable button to prevent double submissions
522 let submit_btn = jQuery(this);
523 submit_btn.prop('disabled', true);
524
525 // start loading animation
526 VBOCore.emitEvent('vbo-tm-newtask-loading');
527
528 // get form data
529 const taskForm = new FormData(document.querySelector('#vbo-tm-task-manage-form'));
530
531 // build query parameters for the request
532 let qpRequest = new URLSearchParams(taskForm).toString();
533
534 // make the request
535 VBOCore.doAjax(
536 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.createTask'); ?>",
537 qpRequest,
538 (resp) => {
539 // trigger filters-changed event on success
540 VBOCore.emitEvent('vbo-tm-filters-changed', {
541 filters: vboTmFilters,
542 });
543
544 // dismiss the modal
545 VBOCore.emitEvent('vbo-tm-newtask-dismiss');
546 },
547 (error) => {
548 // display error message
549 alert(error.responseText);
550
551 // re-enable submit button
552 submit_btn.prop('disabled', false);
553
554 // stop loading
555 VBOCore.emitEvent('vbo-tm-newtask-loading');
556 }
557 );
558 });
559
560 // display modal
561 let modalBody = VBOCore.displayModal({
562 suffix: 'tm_newtask_modal',
563 title: <?php echo json_encode(JText::translate('VBO_NEW_TASK')); ?>,
564 extra_class: 'vbo-modal-rounded vbo-modal-taller vbo-modal-large',
565 body_prepend: true,
566 lock_scroll: true,
567 escape_dismiss: false,
568 footer_left: cancel_btn,
569 footer_right: save_btn,
570 loading_event: 'vbo-tm-newtask-loading',
571 dismiss_event: 'vbo-tm-newtask-dismiss',
572 });
573
574 // start loading animation
575 VBOCore.emitEvent('vbo-tm-newtask-loading');
576
577 // make the request
578 VBOCore.doAjax(
579 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
580 {
581 type: 'tasks.managetask',
582 data: {
583 area_id: areaId,
584 form_id: 'vbo-tm-task-manage-form',
585 filters: filters,
586 },
587 },
588 (resp) => {
589 // stop loading
590 VBOCore.emitEvent('vbo-tm-newtask-loading');
591
592 try {
593 // decode the response (if needed), and append the content to the modal body
594 let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
595 modalBody.append(obj_res['html']);
596 } catch (err) {
597 console.error('Error decoding the response', err, resp);
598 }
599 },
600 (error) => {
601 // display error message
602 alert(error.responseText);
603
604 // stop loading
605 VBOCore.emitEvent('vbo-tm-newtask-loading');
606 }
607 );
608 });
609
610 /**
611 * Listen to the toolbar task buttons.
612 */
613 Joomla.submitbutton = (task) => {
614 if (task === 'tm.settings') {
615 // define the modal cancel button
616 let cancel_btn = jQuery('<button></button>')
617 .attr('type', 'button')
618 .addClass('btn')
619 .text(<?php echo json_encode(JText::translate('VBANNULLA')); ?>)
620 .on('click', () => {
621 // dismiss the modal
622 VBOCore.emitEvent('vbo-tm-settings-dismiss');
623 });
624
625 // define the modal apply button
626 let apply_btn = jQuery('<button></button>')
627 .attr('type', 'button')
628 .addClass('btn btn-success')
629 .html('<?php VikBookingIcons::e('save'); ?> ' + <?php echo json_encode(JText::translate('VBSAVE')); ?>)
630 .on('click', function() {
631 // start loading
632 VBOCore.emitEvent('vbo-tm-settings-loading');
633
634 // get form data
635 const tmSettingsForm = new FormData(document.querySelector('#vbo-tm-settings-form'));
636
637 // build query parameters for the request
638 let qpRequest = new URLSearchParams(tmSettingsForm);
639
640 // make the request
641 VBOCore.doAjax(
642 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=configuration.update'); ?>",
643 qpRequest.toString(),
644 (resp) => {
645 // dismiss the modal on success
646 VBOCore.emitEvent('vbo-tm-settings-dismiss');
647 },
648 (error) => {
649 // stop loading
650 VBOCore.emitEvent('vbo-tm-settings-loading');
651 // display the error
652 alert(error.responseText || 'Generic error');
653 }
654 );
655 });
656
657 // render modal
658 let modalBody = VBOCore.displayModal({
659 suffix: 'tm_settings_modal',
660 extra_class: 'vbo-modal-rounded vbo-modal-dialog',
661 title: <?php echo json_encode(JText::translate('VBOADMINLEGENDSETTINGS')); ?>,
662 body_prepend: true,
663 lock_scroll: true,
664 footer_left: cancel_btn,
665 footer_right: apply_btn,
666 loading_event: 'vbo-tm-settings-loading',
667 dismiss_event: 'vbo-tm-settings-dismiss',
668 onDismiss: () => {
669 // move modal content back
670 jQuery('.vbo-tm-settings-wrapper').appendTo(jQuery('.vbo-tm-settings-helper'));
671 }
672 });
673
674 // set modal content
675 jQuery('.vbo-tm-settings-wrapper').appendTo(modalBody);
676 } else {
677 Joomla.submitform(task, document.adminForm);
678 }
679 };
680
681 jQuery(function() {
682
683 // build buttons for new-task context menu
684 let btns = [];
685
686 vboTmAllAreas.forEach((area) => {
687 // push area button
688 btns.push({
689 areaId: area.id,
690 class: 'vbo-context-menu-entry-secondary',
691 icon: '<?php echo VikBookingIcons::i('plus-circle'); ?>',
692 text: area.name,
693 action: (root, event) => {
694 VBOCore.emitEvent('vbo-tm-newtask-trigger', {
695 areaId: area.id,
696 filters: vboTmFilters,
697 });
698 },
699 });
700 });
701
702 // start context menu on the new task button element
703 jQuery('.vbo-context-menu-tm-newtask').vboContextMenu({
704 placement: 'bottom-right',
705 buttons: btns,
706 });
707
708 // populate external button links
709 vboTmApplyLinkFilters();
710
711 });
712 </script>
713