File "guest_messaging.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/vikbooking/site/layouts/tools/guest_messaging.php
File size: 25.75 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* @package VikBooking
* @subpackage com_vikbooking
* @author Alessio Gaggii - E4J srl
* @copyright Copyright (C) 2025 E4J srl. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
* @link https://vikwp.com
*/
defined('ABSPATH') or die('No script kiddies please!');
/**
* Obtain vars from arguments received in the layout file.
* This is the layout file for the "guest_messaging" operator tool.
*
* @var string $tool The tool identifier.
* @var array $operator The operator record accessing the tool.
* @var object $permissions The operator-tool permissions registry.
* @var string $tool_uri The base URI for rendering this tool.
*/
extract($displayData);
// messages per page
$messages_per_page = 20;
// distance threshold in pixels between the current scroll position and the end of the list
$px_distance_threshold = 140;
// get listings assigned to the current operator (no listings equals to all listings)
$listings = array_filter(
array_map('intval', (array) $permissions->get('rooms', []))
);
// attempt to require the chat handler from VCM
try {
VikBooking::getVcmChatInstance($oid = 0, $channel = null);
} catch (Throwable $e) {
// propagate the error code
VBOHttpDocument::getInstance()->close($e->getCode(), 'Channel Manager not available.');
}
// make sure VCM is available and up to date
if (!class_exists('VCMChatHandler') || !method_exists('VCMChatHandler', 'loadChatAssets')) {
// raise an error
VBOHttpDocument::getInstance()->close(500, 'Channel Manager not available.');
}
/**
* Load the VBOCore JS class and chat assets from VCM.
*/
VikBooking::getVboApplication()->loadCoreJS();
VCMChatHandler::loadChatAssets();
// load JS lang definitions
JText::script('VBTODAY');
JText::script('VBSTANDBY');
JText::script('VBCONFIRMED');
JText::script('VBCANCELLED');
JText::script('VBOCHECKEDSTATUSIN');
JText::script('VBOCHECKEDSTATUSOUT');
JText::script('VBOCHECKEDSTATUSNOS');
JText::script('VBO_REPLY');
JText::script('VBO_NO_MORE_MESSAGES');
JText::script('VBO_NO_REPLY_NEEDED');
JText::script('VBO_WANT_PROCEED');
JText::script('VBO_NEW_MESSAGES');
?>
<div class="vbo-optool-gmessaging-wrap">
<div class="vbo-optool-gmessaging-inner">
<div class="vbo-optool-gmessaging-list-container" data-offset="0">
<?php
for ($i = 0; $i < $messages_per_page; $i++) {
?>
<div class="vbo-optool-gmessaging-guest-activity vbo-optool-gmessaging-guest-activity-skeleton">
<div class="vbo-optool-gmessaging-guest-activity-avatar">
<div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>
</div>
<div class="vbo-optool-gmessaging-guest-activity-content">
<div class="vbo-optool-gmessaging-guest-activity-content-head">
<div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>
</div>
<div class="vbo-optool-gmessaging-guest-activity-content-info-msg">
<div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>
</div>
</div>
</div>
<?php
}
?>
</div>
<div class="vbo-optool-gmessaging-inboxstyle-chat"></div>
</div>
</div>
<script type="text/javascript">
const vbo_media_base_uri = '<?php echo VBO_SITE_URI . 'resources/uploads/'; ?>';
/**
* Loads and renders the chat for a given booking ID.
*
* @note do NOT use an arrow function because the clicked message is passed as "thisArg".
*/
const vbo_optool_gmessaging_load_chat_fn = function(bid) {
// define the clicked message
let clickedMessage = this;
// gather thread id
let threadId = 0;
try {
threadId = clickedMessage.getAttribute('data-idthread');
} catch(err) {
// silently catch the error
console.error(err);
}
// empty current chat
let chatContainer = document.querySelector('.vbo-optool-gmessaging-inboxstyle-chat');
if (typeof VCMChat !== 'undefined') {
VCMChat.getInstance().destroy();
}
chatContainer.innerHTML = '';
// start loading
let loadingElement = document.createElement('div');
loadingElement.classList.add('vbo-optool-gmessaging-chat-loading');
loadingElement.innerHTML = '<span><?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?></span>';
chatContainer.append(loadingElement);
// make the request to the controller
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operatortool.renderGuestBookingChat') ?>",
{
bid: bid,
},
(response) => {
response = typeof response === 'string' ? JSON.parse(response) : response;
// remove loading element
loadingElement.remove();
// create chat head element
let chatHead = document.createElement('div');
chatHead.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head');
// build chat head-inner element
let chatHeadInner = document.createElement('div');
try {
// clone and set avatar
let guestAvatar = clickedMessage.querySelector('.vbo-optool-gmessaging-message-avatar').cloneNode(true);
chatHeadInner.append(guestAvatar);
// build head details element
let chatHeadDetails = document.createElement('div');
chatHeadDetails.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head-details');
// get guest name
let guestName = clickedMessage.querySelector('.vbo-optool-gmessaging-message-guestname-txt').innerText;
// build head info element
let chatHeadInfo = document.createElement('div');
chatHeadInfo.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head-info');
// append guest name
let guestNameEl = document.createElement('span');
guestNameEl.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head-info-gname');
guestNameEl.innerText = guestName;
chatHeadInfo.append(guestNameEl);
// append booking ID
let bidEl = document.createElement('span');
bidEl.classList.add('vbo-badge');
bidEl.classList.add('badge-info');
bidEl.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head-info-bid');
bidEl.innerText = bid;
chatHeadInfo.append(bidEl);
// set head info
chatHeadDetails.append(chatHeadInfo);
// build head summary element
let chatHeadSummary = document.createElement('div');
chatHeadSummary.classList.add('vbo-optool-gmessaging-inboxstyle-chat-head-summary');
// clone and build booking summary
let bookingSummary = clickedMessage.querySelector('.vbo-optool-gmessaging-message-bookinginfo').cloneNode(true);
// listing details
let listingDetails = document.createElement('span');
listingDetails.classList.add('vbo-optool-gmessaging-message-listings');
bookingSummary.append(listingDetails);
vbo_optool_gmessaging_set_listingdets_fn(bid, listingDetails);
// no-reply needed
let noReplyNeededEl = document.createElement('a');
noReplyNeededEl.classList.add('vbo-label');
noReplyNeededEl.classList.add('vbo-optool-gmessaging-message-noreplyneeded');
noReplyNeededEl.innerText = Joomla.JText._('VBO_NO_REPLY_NEEDED');
noReplyNeededEl.addEventListener('click', () => {
if (confirm(Joomla.JText._('VBO_WANT_PROCEED'))) {
// get no-reply-needed status on thread
let threadNoReplyNeededStatus = clickedMessage ? (clickedMessage.getAttribute('data-noreply-needed') || 0) : 0;
// toggle no-reply-needed status on thread
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operatortool.toggleGuestThreadNoReplyNeeded') ?>",
{
bid: bid,
status: threadNoReplyNeededStatus,
id_thread: threadId,
},
(response) => {
if (threadNoReplyNeededStatus == 1) {
noReplyNeededEl.classList.remove('label-danger');
clickedMessage.setAttribute('data-noreply-needed', '0');
} else {
noReplyNeededEl.classList.add('label-danger');
clickedMessage.setAttribute('data-noreply-needed', '1');
}
},
(error) => {
console.error(error);
}
);
}
});
bookingSummary.append(noReplyNeededEl);
// set booking summary
chatHeadSummary.append(bookingSummary);
// set head summary
chatHeadDetails.append(chatHeadSummary);
// set the whole head details block
chatHeadInner.append(chatHeadDetails);
} catch(err) {
// silently catch the error
console.error(err);
}
// append chat head
chatHead.append(chatHeadInner);
chatContainer.append(chatHead);
// create chat body element
let chatBody = document.createElement('div');
chatBody.classList.add('vbo-optool-gmessaging-inboxstyle-chat-body');
// append chat body
chatContainer.append(chatBody);
// render chat through jQuery
jQuery('.vbo-optool-gmessaging-inboxstyle-chat-body').html(response.html);
// rendering through pure JS will NOT work
// chatContainer.setHTMLUnsafe(response['html']);
// register scroll to bottom with a small delay
setTimeout(() => {
if (typeof VCMChat !== 'undefined') {
VCMChat.getInstance().scrollToBottom();
}
}, 150);
},
(error) => {
// log and display error
console.error(error);
alert(error.responseText || 'Unknown error');
// abort loading
loadingElement.remove();
}
);
};
/**
* Loads the listing details for a booking.
*/
const vbo_optool_gmessaging_set_listingdets_fn = (bid, detailsNode) => {
// perform the request
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operatortool.loadGuestBookingListings') ?>",
{
bid: bid,
},
(response) => {
response = typeof response === 'string' ? JSON.parse(response) : response;
if (!detailsNode) {
detailsNode = document.querySelector('.vbo-optool-gmessaging-message-listings');
}
detailsNode.innerHTML = '<?php VikBookingIcons::e('home'); ?> ' + response.listings.join(', ');
},
(error) => {
console.error(error);
}
);
};
/**
* Loads a pagination of thread messages.
*/
const vbo_optool_gmessaging_load_threads_fn = (offset, limit) => {
// validate offset and limit
offset = parseInt((isNaN(offset) ? 0 : offset));
limit = parseInt((isNaN(limit) || limit < 1 ? <?php echo $messages_per_page; ?> : limit));
// perform the request
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operatortool.loadGuestThreads') ?>",
{
start: offset,
limit: limit,
},
(response) => {
let threads = typeof response === 'string' ? JSON.parse(response) : response;
let container = document.querySelector('.vbo-optool-gmessaging-list-container');
let messagesList = container.querySelector('.vbo-optool-gmessaging-messages-list');
let lastMessage = container.querySelector('.vbo-optool-gmessaging-message-last');
if (lastMessage && threads.length) {
// remove the "last message" class
lastMessage.classList.remove('vbo-optool-gmessaging-message-last');
}
if (!offset) {
// first page loading will clean up the container with the skeletons
container.innerHTML = '';
if (threads.length) {
// first page loading should also set the most recent message (thread) date
container.setAttribute('data-last-updated', (threads[0]?.last_updated || ''));
}
} else {
// scan and remove all skeletons
container.querySelectorAll('.vbo-optool-gmessaging-guest-activity-skeleton').forEach((skeleton) => {
skeleton.remove();
});
}
// update offset for next page loading
container.setAttribute('data-offset', offset + limit);
if (!threads.length) {
if (offset > 0) {
// attempt to destroy the infinite scroll loading
vbo_optool_gmessaging_destroy_infinite_scroll_fn();
}
// display the "no more messages" element
let noMessagesEl = document.createElement('p');
noMessagesEl.classList.add('info');
noMessagesEl.setAttribute('data-no-messages', '1');
noMessagesEl.innerText = Joomla.JText._('VBO_NO_MORE_MESSAGES');
if (messagesList && !messagesList.querySelector('.info[data-no-messages="1"]')) {
// no more messages
messagesList.append(noMessagesEl);
} else if (!messagesList) {
// no messages at all
container.append(noMessagesEl);
}
}
if (!messagesList) {
// create the messages list element
messagesList = document.createElement('div');
messagesList.classList.add('vbo-optool-gmessaging-messages-list');
} else {
// turn custom property off for the page loading
container.pageLoading = false;
}
// scan all thread messages
threads.forEach((thread, index) => {
// create message element
let messageElement = document.createElement('div');
messageElement.classList.add('vbo-optool-gmessaging-message');
if (!thread?.read_dt && (thread?.sender_type + '').toLowerCase() == 'guest') {
messageElement.classList.add('vbo-optool-gmessaging-message-new');
}
if (thread?.replied == 0 && (thread?.sender_type + '').toLowerCase() == 'guest') {
messageElement.classList.add('vbo-optool-gmessaging-message-unreplied');
}
if (!offset && !index) {
messageElement.classList.add('vbo-optool-gmessaging-message-first');
} else if (offset && (index + 1) == threads.length) {
messageElement.classList.add('vbo-optool-gmessaging-message-last');
}
// set attributes
messageElement.setAttribute('data-idorder', thread.idorder);
messageElement.setAttribute('data-idthread', thread.id_thread);
messageElement.setAttribute('data-idmessage', thread.id_message);
messageElement.setAttribute('data-noreply-needed', (thread?.no_reply_needed || 0));
// register click event
messageElement.addEventListener('click', () => {
document.querySelectorAll('.vbo-optool-gmessaging-message-active').forEach((activeMess) => {
activeMess.classList.remove('vbo-optool-gmessaging-message-active');
});
vbo_optool_gmessaging_load_chat_fn.call(messageElement, thread.idorder);
messageElement.classList.add('vbo-optool-gmessaging-message-active');
messageElement.classList.remove('vbo-optool-gmessaging-message-new');
messageElement.classList.remove('vbo-optool-gmessaging-message-unreplied');
let unrepliedIcn = messageElement.querySelector('.message-unreplied');
if (unrepliedIcn) {
unrepliedIcn.remove();
}
});
// build message avatar
let avatarPic = '';
let avatarPicEl = document.createElement('div');
let messageAvatar = document.createElement('div');
messageAvatar.classList.add('vbo-optool-gmessaging-message-avatar');
if (thread?.pic) {
avatarPic = thread.pic.indexOf('http') === 0 ? thread.pic : vbo_media_base_uri + thread.pic;
} else if (thread?.channel_logo) {
avatarPic = thread.channel_logo;
}
if (!avatarPic) {
avatarPicEl.classList.add('vbo-optool-gmessaging-message-avatar-icon');
avatarPicEl.innerHTML = '<?php VikBookingIcons::e('user'); ?>';
} else {
let avatarPicImg = document.createElement('img');
avatarPicImg.setAttribute('src', avatarPic);
avatarPicEl.classList.add('vbo-optool-gmessaging-message-avatar-profile');
avatarPicEl.append(avatarPicImg);
}
messageAvatar.append(avatarPicEl);
// build message content elements
let messageContent = document.createElement('div');
messageContent.classList.add('vbo-optool-gmessaging-message-content');
let messContHead = document.createElement('div');
messContHead.classList.add('vbo-optool-gmessaging-message-content-head');
// message content head details
let messHeadDetails = document.createElement('div');
messHeadDetails.classList.add('vbo-optool-gmessaging-message-content-details');
let messGuestName = document.createElement('div');
messGuestName.classList.add('vbo-optool-gmessaging-message-guestname');
let fullGuestName = ((thread?.first_name || '') + ' ' + (thread?.last_name || '')).trim();
if (!fullGuestName.length) {
fullGuestName = 'Guest';
}
let fullGuestNameEl = document.createElement('span');
fullGuestNameEl.classList.add('vbo-optool-gmessaging-message-guestname-txt');
fullGuestNameEl.innerText = fullGuestName;
messGuestName.append(fullGuestNameEl);
if (thread?.replied == 0 && (thread?.sender_type + '').toLowerCase() == 'guest') {
let unrepliedEl = document.createElement('span');
unrepliedEl.classList.add('label');
unrepliedEl.classList.add('label-small');
unrepliedEl.classList.add('message-unreplied');
unrepliedEl.innerHTML = '<?php VikBookingIcons::e('comments', 'message-reply') ?> ' + Joomla.JText._('VBO_REPLY');
messGuestName.append(unrepliedEl);
}
messHeadDetails.append(messGuestName);
let messageBookInfo = document.createElement('div');
messageBookInfo.classList.add('vbo-optool-gmessaging-message-bookinginfo');
let bookStatus = document.createElement('span');
bookStatus.classList.add('vbo-badge');
if (thread?.b_status) {
if (thread.b_status == 'standby') {
bookStatus.classList.add('badge-warning');
bookStatus.innerText = Joomla.JText._('VBSTANDBY');
} else if (thread.b_status == 'cancelled') {
bookStatus.classList.add('badge-danger');
bookStatus.innerText = Joomla.JText._('VBCANCELLED');
} else {
bookStatus.classList.add('badge-success');
if (thread?.b_checkout && thread.b_checkout < thread.message_info.current_ts) {
bookStatus.innerText = Joomla.JText._('VBOCHECKEDSTATUSOUT');
} else {
bookStatus.innerText = Joomla.JText._('VBCONFIRMED');
}
}
}
messageBookInfo.append(bookStatus);
let stayDates = document.createElement('span');
stayDates.classList.add('vbo-optool-gmessaging-message-staydates');
let stayDatesIn = document.createElement('span');
stayDatesIn.classList.add('vbo-optool-gmessaging-message-stayin');
stayDatesIn.innerText = thread.message_info.str_checkin;
let stayDatesSep = document.createElement('span');
stayDatesSep.classList.add('vbo-optool-gmessaging-message-staysep');
stayDatesSep.innerText = ' - ';
let stayDatesOut = document.createElement('span');
stayDatesOut.classList.add('vbo-optool-gmessaging-message-stayout');
stayDatesOut.innerText = thread.message_info.str_checkout;
stayDates.append(stayDatesIn);
stayDates.append(stayDatesSep);
stayDates.append(stayDatesOut);
messageBookInfo.append(stayDates);
messHeadDetails.append(messageBookInfo);
// message content head date
let messHeadDate = document.createElement('div');
messHeadDate.classList.add('vbo-optool-gmessaging-message-content-date');
let messHeadTimeSpan = document.createElement('span');
messHeadTimeSpan.innerText = thread.message_info.time;
messHeadDate.append(messHeadTimeSpan);
let messHeadDateSpan = document.createElement('span');
messHeadDateSpan.innerText = thread.message_info.is_today ? Joomla.JText._('VBTODAY') : thread.message_info.date;
messHeadDate.append(messHeadDateSpan);
// finalize head element
messContHead.append(messHeadDetails);
messContHead.append(messHeadDate);
// message content text element
let messContMess = document.createElement('div');
messContMess.classList.add('vbo-optool-gmessaging-message-content-msg');
let messContMsg = document.createElement('p');
messContMsg.innerHTML = (thread.content + '').substring(0, 90);
if ((thread.content + '').length > 90) {
messContMsg.innerText = messContMsg.innerText + '...';
}
messContMess.append(messContMsg);
// append message content elements
messageContent.append(messContHead);
messageContent.append(messContMess);
// append message elements
messageElement.append(messageAvatar);
messageElement.append(messageContent);
// append message element to list
messagesList.append(messageElement);
});
if (!container.querySelector('.vbo-optool-gmessaging-messages-list')) {
// messages list element must be appended to main container
container.append(messagesList);
}
if (!offset && threads.length) {
// attempt to register the infinite scroll loading
setTimeout(() => {
vbo_optool_gmessaging_setup_infinite_scroll_fn();
}, 150);
}
},
(error) => {
// log and display error
console.error(error);
alert(error.responseText || 'Unknown error');
}
);
};
/**
* Destroys the infinite scroll loading.
*/
const vbo_optool_gmessaging_destroy_infinite_scroll_fn = () => {
let messagesList = document.querySelector('.vbo-optool-gmessaging-list-container');
// un-register infinite scroll event handler
messagesList.removeEventListener('scroll', vbo_optool_gmessaging_handle_infinite_scroll_fn);
};
/**
* Sets up the infinite scroll loading.
*/
const vbo_optool_gmessaging_setup_infinite_scroll_fn = () => {
let messagesList = document.querySelector('.vbo-optool-gmessaging-list-container');
// get wrapper dimensions
let listViewHeight = messagesList.offsetHeight;
let listGlobHeight = messagesList.scrollHeight;
if (listViewHeight >= listGlobHeight) {
// no scrolling detected, probably because of too few messages
return;
}
// register infinite scroll event handler
messagesList.addEventListener('scroll', vbo_optool_gmessaging_handle_infinite_scroll_fn);
};
/**
* Handles the infinite scroll loading.
*/
const vbo_optool_gmessaging_handle_infinite_scroll_fn = (e) => {
// register throttling callback
VBOCore.throttleTimer(() => {
// access the current messages container
let messagesList = document.querySelector('.vbo-optool-gmessaging-list-container');
// make sure the loading of a next page isn't running
if (messagesList.pageLoading) {
// abort
return;
}
// get wrapper dimensions
let listViewHeight = messagesList.offsetHeight;
let listGlobHeight = messagesList.scrollHeight;
let listScrollTop = messagesList.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 < <?php echo $px_distance_threshold; ?>) {
// inject custom property to identify a next page is loading
messagesList.pageLoading = true;
// show that we are loading more messages
vbo_optool_gmessaging_draw_skeletons_fn(3);
// load the next page of messages
vbo_optool_gmessaging_load_more_fn();
}
}, 500);
};
/**
* Draws skeletons in the messages list container.
*/
const vbo_optool_gmessaging_draw_skeletons_fn = (num) => {
let messagesPool = document.querySelector('.vbo-optool-gmessaging-messages-list');
if (!messagesPool) {
return;
}
num = parseInt((isNaN(num) || num < 1 ? 3 : num));
for (let i = 0; i < num; i++) {
let skeleton = '';
skeleton += '<div class="vbo-optool-gmessaging-guest-activity vbo-optool-gmessaging-guest-activity-skeleton">';
skeleton += ' <div class="vbo-optool-gmessaging-guest-activity-avatar">';
skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>';
skeleton += ' </div>';
skeleton += ' <div class="vbo-optool-gmessaging-guest-activity-content">';
skeleton += ' <div class="vbo-optool-gmessaging-guest-activity-content-head">';
skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>';
skeleton += ' </div>';
skeleton += ' <div class="vbo-optool-gmessaging-guest-activity-content-info-msg">';
skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>';
skeleton += ' </div>';
skeleton += ' </div>';
skeleton += '</div>';
messagesPool.insertAdjacentHTML('beforeend', skeleton);
}
};
/**
* Loads the next page of messages.
*/
const vbo_optool_gmessaging_load_more_fn = () => {
// access the current messages container
let messagesList = document.querySelector('.vbo-optool-gmessaging-list-container');
// get the current offset to load a new page of messages
let offset = messagesList.getAttribute('data-offset');
// load the next page of thread messages
vbo_optool_gmessaging_load_threads_fn(offset, <?php echo $messages_per_page; ?>);
};
/**
* Checks for new thread messages.
*/
const vbo_optool_gmessaging_check_new_threads_fn = () => {
let container = document.querySelector('.vbo-optool-gmessaging-list-container');
let last_date = container.getAttribute('data-last-updated');
// perform the request
VBOCore.doAjax(
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operatortool.checkNewGuestThreads') ?>",
{
last_date: last_date,
},
(response) => {
response = typeof response === 'string' ? JSON.parse(response) : response;
if (response.newThreads.length) {
if (!container.querySelector('.info[data-new-messages="1"]')) {
// display message
let newMessEl = document.createElement('p');
newMessEl.classList.add('info');
newMessEl.setAttribute('data-new-messages', '1');
let reloadLink = document.createElement('a');
reloadLink.setAttribute('href', '<?php echo $tool_uri; ?>');
reloadLink.innerText = Joomla.JText._('VBO_NEW_MESSAGES');
newMessEl.append(reloadLink);
container.prepend(newMessEl);
}
// update attribute
container.setAttribute('data-last-updated', (response.newThreads[0]?.last_updated || last_date));
}
},
(error) => {
console.error(error);
}
);
};
/**
* Configure the DOM-ready execution.
*/
jQuery(function() {
// load the first page of threads on page load
vbo_optool_gmessaging_load_threads_fn(0, <?php echo $messages_per_page; ?>);
// register a periodic interval to watch for new messages
setInterval(() => {
vbo_optool_gmessaging_check_new_threads_fn();
}, 120000);
});
</script>