File "default_board.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/vikbooking/admin/views/taskmanager/tmpl/default_board.php
File size: 15.5 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* @package VikBooking
* @subpackage core
* @author E4J s.r.l.
* @copyright Copyright (C) 2025 E4J s.r.l. All Rights Reserved.
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
* @link https://vikwp.com
*/
// No direct access
defined('ABSPATH') or die('No script kiddies please!');
?>
<div class="vbo-tm-board-areas-list">
<?php
foreach ($this->visibleAreas as $areaRecord) {
// wrap the area record into a task area object
$taskArea = VBOTaskArea::getInstance((array) $areaRecord);
?>
<div class="vbo-tm-board-area-container" data-area-id="<?php echo $taskArea->getID(); ?>">
<?php
// build layout data
$layout_data = [
'data' => [
'taskArea' => $taskArea,
'filters' => $this->filters,
],
];
// render task list area
echo JLayoutHelper::render('taskmanager.board.area', $layout_data);
?>
</div>
<?php
}
?>
</div>
<script type="text/javascript">
/**
* Register function for rendering a task area.
*/
const vboTmBoardRenderArea = (areaId) => {
let areaContainer = jQuery('<div></div>')
.addClass('vbo-tm-board-area-container')
.attr('data-area-id', areaId);
areaContainer.append(
jQuery('<div></div>')
.addClass('vbo-tm-board-area-loading')
.html('<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>')
);
areaContainer.appendTo('.vbo-tm-board-areas-list');
// make the request to display the requested task area
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
{
type: 'board.area',
data: {
area_id: areaId,
filters: vboTmFilters || {},
},
},
(resp) => {
try {
// decode the response (if needed)
let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
// set HTML response (use jQuery rather than plain JS to avoid issues with injected scripts execution)
areaContainer.html(obj_res['html']);
// silently update task area status
vboTmToggleAreaDisplay(areaId, 1);
// load area tasks list
vboTmBoardRenderAreaTasks(areaId);
} catch (err) {
console.error('Error decoding the response', err, resp);
}
},
(error) => {
// display error message
alert(error.responseText);
// dispatch the event for updating the active areas
VBOCore.emitEvent('vbo-tm-area-update-status');
}
);
};
/**
* Register function for rendering the given area tasks with filters and start offset.
*/
const vboTmBoardRenderAreaTasks = (areaId, filters, start) => {
let tasksList;
let loadingList;
let nextPage = false;
if (start) {
// existing tasks list for loading a new page
tasksList = jQuery('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.find('.vbo-tm-board-area-tasks-list');
if (tasksList.length) {
// set the current loading list
loadingList = document
.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.querySelector('.vbo-tm-board-area-tasks-list');
// populate loading skeletons
vboTmBoardSetSkeletons(areaId, 10);
} else {
// start a new list
tasksList = null;
}
}
if (!tasksList) {
// load the first page of tasks
tasksList = jQuery('<div></div>')
.addClass('vbo-tm-board-area-tasks-list');
tasksList.append(
jQuery('<div></div>')
.addClass('vbo-tm-board-area-tasks-loading')
.html('<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>')
);
tasksList.appendTo('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]');
} else {
// turn flag on for loading a next page
nextPage = true;
}
// make the request to display the requested task area
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
{
type: 'board.tasks',
data: {
area_id: areaId,
filters: filters || vboTmFilters || {},
start: start || 0,
limit: 10,
},
},
(resp) => {
try {
// decode the response (if needed)
let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
// set HTML response (use jQuery rather than plain JS to avoid issues with injected scripts execution)
if (!nextPage) {
// set the loading result for the first page of tasks
tasksList.html(obj_res['html']);
} else {
if (loadingList) {
// turn flag off for loading a new page
loadingList.pageLoading = false;
// delete loading skeletons
vboTmBoardUnsetSkeletons(areaId);
}
if ((obj_res['html'] + '').indexOf('data-no-results="1"') < 0 || !tasksList.find('[data-no-results="1"]').length) {
// append the loading result of the next tasks by preventing multiple "no-results" elements due to infinite scroll loading
tasksList.append(obj_res['html']);
}
}
// dispatch event for TM contents loaded
VBOCore.emitEvent('vbo-tm-contents-loaded', {
element: tasksList,
});
} catch (err) {
console.error('Error decoding the response', err, resp);
}
},
(error) => {
// display error message
alert(error.responseText);
if (loadingList) {
// turn flag off for loading a new page
loadingList.pageLoading = false;
}
}
);
};
/**
* Register function to set some task loading skeletons.
*/
const vboTmBoardSetSkeletons = (areaId, quantity) => {
let container = document.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]');
let tasksList = container ? container.querySelector('.vbo-tm-board-area-tasks-list') : null;
if (!tasksList) {
return;
}
// ensure the quantity is a valid number greater than zero
quantity = !isNaN(quantity) && quantity > 0 ? quantity : 1;
// build skeleton HTML string
let skeletonHtml = '';
skeletonHtml += '<div class="vbo-tm-board-area-task-wrap vbo-tm-board-area-task-wrap-skeleton">';
skeletonHtml += ' <div class="vbo-tm-board-area-task-head">';
skeletonHtml += ' <div class="vbo-skeleton-loading vbo-tm-board-area-task-title"></div>';
skeletonHtml += ' <div class="vbo-tm-board-area-task-notes">';
skeletonHtml += ' <div class="vbo-skeleton-loading vbo-tm-board-area-task-notes-line"></div>';
skeletonHtml += ' <div class="vbo-skeleton-loading vbo-tm-board-area-task-notes-line"></div>';
skeletonHtml += ' </div>';
skeletonHtml += ' </div>';
skeletonHtml += ' <div class="vbo-tm-board-area-task-body">';
skeletonHtml += ' <div class="vbo-tm-board-area-task-status">';
skeletonHtml += ' <span class="vbo-skeleton-loading vbo-tm-board-area-task-status-badge"></span>';
skeletonHtml += ' </div>';
skeletonHtml += ' <div class="vbo-tm-board-area-task-assignees">';
skeletonHtml += ' <span class="vbo-skeleton-loading vbo-tm-board-area-task-assignee"></span>';
skeletonHtml += ' <span class="vbo-skeleton-loading vbo-tm-board-area-task-assignee"></span>';
skeletonHtml += ' </div>';
skeletonHtml += ' </div>';
skeletonHtml += '</div>';
for (let i = 1; i <= quantity; i++) {
tasksList.insertAdjacentHTML('beforeend', skeletonHtml);
}
};
/**
* Register function to unset the task loading skeletons.
*/
const vboTmBoardUnsetSkeletons = (areaId) => {
let container = document.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]');
let tasksList = container ? container.querySelector('.vbo-tm-board-area-tasks-list') : null;
if (!tasksList) {
return;
}
tasksList
.querySelectorAll('.vbo-tm-board-area-task-wrap.vbo-tm-board-area-task-wrap-skeleton')
.forEach((skeleton) => {
skeleton.remove();
});
};
/**
* Register function for hiding a task area.
*/
const vboTmBoardHideArea = (areaId) => {
// remove element blocks from DOM
document
.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.remove();
// silently update task area status
vboTmToggleAreaDisplay(areaId, 0);
};
/**
* Register function for hiding the given area tasks.
*/
const vboTmBoardHideAreaTasks = (areaId) => {
// remove tasks list element from DOM
let list = document
.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.querySelector('.vbo-tm-board-area-tasks-list');
if (list) {
list.remove();
}
};
/**
* Register function for setting up the infinite scroll loading for an area.
*/
const vboTmBoardSetupInfiniteScroll = (areaId, start, count) => {
let tasksList = document
.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.querySelector('.vbo-tm-board-area-tasks-list');
if (!tasksList) {
return;
}
if (count < 10) {
// no extra loading needed
tasksList
.removeEventListener('scroll', vboTmBoardHandleInfiniteScroll);
return;
}
// get wrapper dimensions
let listViewHeight = tasksList.offsetHeight;
let listGlobHeight = tasksList.scrollHeight;
if (listViewHeight >= listGlobHeight) {
// no scrolling detected
return;
}
// inject/update custom object properties
tasksList.areaId = areaId;
tasksList.offsetStart = start;
if (!start && !tasksList.scrollListener) {
// inject custom object property to identify the scroll event listener
tasksList.scrollListener = true;
// register infinite scroll event handler
tasksList
.addEventListener('scroll', vboTmBoardHandleInfiniteScroll);
}
};
/**
* Register function for infinite scroll loading handler.
*/
const vboTmBoardHandleInfiniteScroll = (e) => {
// access the injected area ID property
let areaId = e.currentTarget.areaId;
if (!areaId) {
return;
}
// access the involved tasks list
let tasksList = document
.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')
.querySelector('.vbo-tm-board-area-tasks-list');
if (!tasksList) {
return;
}
// make sure the loading of a next page isn't running
if (tasksList.pageLoading) {
// abort
return;
}
// register throttling callback
VBOCore.throttleTimer(() => {
// get wrapper dimensions
let listViewHeight = tasksList.offsetHeight;
let listGlobHeight = tasksList.scrollHeight;
let listScrollTop = tasksList.scrollTop;
if (!listScrollTop || listViewHeight >= listGlobHeight) {
// no scrolling detected at all
return;
}
// calculate missing distance to the end of the list
let listEndDistance = listGlobHeight - (listViewHeight + listScrollTop);
if (listEndDistance < 140) {
// inject custom property to identify a next page is loading
tasksList.pageLoading = true;
// load the next page of notifications
vboTmBoardRenderAreaTasks(areaId, (vboTmFilters || {}), (tasksList.offsetStart || 0) + 10);
}
}, 100);
};
jQuery(function() {
/**
* Load all area tasks upon page loading.
*/
document.querySelectorAll('.vbo-tm-board-area-container').forEach((area) => {
let areaId = area.getAttribute('data-area-id');
// render area tasks
vboTmBoardRenderAreaTasks(areaId);
});
/**
* Register to the event for rendering a task area.
*/
document.addEventListener('vbo-tm-area-render-task', (e) => {
if (!e || !e?.detail?.areaId) {
return;
}
let areaId = e.detail.areaId;
vboTmBoardRenderArea(areaId);
});
/**
* Register to the event for hiding a task area.
*/
document.addEventListener('vbo-tm-area-hide-task', (e) => {
if (!e || !e?.detail?.areaId) {
return;
}
let areaId = e.detail.areaId;
vboTmBoardHideArea(areaId);
});
/**
* Register listener for the filters changed event.
*/
document.addEventListener('vbo-tm-filters-changed', (e) => {
// obtain the global filters
let filters = e?.detail?.filters;
// iterate over all the visible areas
document.querySelectorAll('.vbo-tm-board-area-container').forEach((area) => {
// get area ID
let areaId = area.getAttribute('data-area-id');
// hide the area tasks
vboTmBoardHideAreaTasks(areaId);
// re-render area tasks
vboTmBoardRenderAreaTasks(areaId, filters);
});
});
/**
* Register listener for the tasks loaded event to configure the infinite scroll loading.
*/
document.addEventListener('vbo-tm-board-tasks-loaded', (e) => {
let areaId = e?.detail?.areaId || 0;
let start = e?.detail?.start || 0;
let count = e?.detail?.count || 0;
if (document.querySelector('.vbo-tm-board-area-container[data-area-id="' + areaId + '"]')) {
// setup infinite scroll loading for the current area
vboTmBoardSetupInfiniteScroll(areaId, start, count);
}
});
});
</script>