Automate Your CAD Workflow for Just $400 With Industry Leader AutoCAD

Automate Your CAD Workflow for Just $400 With Industry Leader AutoCAD

/Business News/Tech
See All
${reply?.comment_author}${reply?.eln_tier_label ? “ : ”}

${reply?.comment_relative_time}
${reply?.comment_content?.trim()}

`;
}

function createComment(comment, replies, isLastComment) {
const commentListDiv = document.getElementById(PublicCommentSelectors.LIST);

if (!commentListDiv) {
return;
}

const borderClasses = isLastComment ? ” : ‘tw:border-b tw:border-slate-200’;

const currentUser = window?.tp?.pianoId?.getUser() ?? null;
const currentUserInitials = currentUser
? getInitials(`${currentUser?.firstName ?? ”} ${currentUser?.lastName ?? ”}`)
: ”;

const repliesHTML = replies.length ? `
${replies.map(buildReplyHTML).join(”)}

` : ”;

const replyButtonHTML = allowsComments ? `

` : ”;

const replyFormHTML = allowsComments ? `

` : ”;

const commentDiv = `
${comment?.comment_author}${comment?.eln_tier_label ? “ : ”}

${comment?.comment_relative_time}
${comment?.comment_content?.trim()}

${replyButtonHTML}

${repliesHTML}
${replyFormHTML}

`;

commentListDiv.innerHTML += commentDiv;
}

function displayComments() {
// Empty out the comment list container before refreshing comments.
const commentListDiv = document.getElementById(PublicCommentSelectors.LIST);
commentListDiv.innerHTML = ”;

const comments = state?.comments ?? [];

if (!comments.length) {
return;
}

// Build a threaded structure: separate top-level from replies.
const repliesByParent = {};
const topLevelComments = [];

comments.forEach(comment => {
if (comment.comment_parent === 0) {
topLevelComments.push(comment);
} else {
const parentId = comment.comment_parent;
if (!repliesByParent[parentId]) {
repliesByParent[parentId] = [];
}
repliesByParent[parentId].push(comment);
}
});

// Apply top-level sort order. Server returns DESC; reverse for oldest-first.
if (state.sortOrder === ‘oldest’) {
topLevelComments.reverse();
}

// Replies always show oldest first within a thread (server returns DESC, so reverse).
Object.keys(repliesByParent).forEach(parentId => {
repliesByParent[parentId].reverse();
});

topLevelComments.forEach((comment, index) => {
const isLastComment = index === topLevelComments.length – 1;
const replies = repliesByParent[comment.comment_ID] ?? [];
createComment(comment, replies, isLastComment);
});

createCommentAvatars();
}

function updateCommentCount() {
const countDiv = document.getElementById(PublicCommentSelectors.COMMENT_COUNT);
const sortControls = document.getElementById(PublicCommentSelectors.SORT_CONTROLS);

if (!countDiv) {
return;
}

const count = state?.comments?.length ?? 0;

// Do not display if there are no comments.
if (count === 0) {
return;
}

countDiv.innerHTML = `${count} Comment${count > 1 ? ‘s’ : ”}`;

if (sortControls) {
sortControls.classList.remove(‘tw:hidden’);
sortControls.classList.add(‘tw:flex’);
}
}

function displayLoader(show) {
const loader = document.getElementById(PublicCommentSelectors.BUTTON_LOADER);
const text = document.getElementById(PublicCommentSelectors.BUTTON_TEXT);

if (!loader || !text) {
return;
}

// Show or hide the loader.
if (show) {
loader.classList.remove(‘tw:hidden’);
text.classList.add(‘tw:hidden’);
} else {
loader.classList.add(‘tw:hidden’);
text.classList.remove(‘tw:hidden’);
}
}

function displayError(error) {
const errorDiv = document.getElementById(PublicCommentSelectors.ERROR);

if (!errorDiv) {
return;
}

if (error) {
errorDiv.classList.add(‘tw:block’);
errorDiv.classList.remove(‘tw:hidden’);
errorDiv.textContent = `Comment submission error: ${error}`;
} else {
errorDiv.classList.remove(‘tw:block’);
errorDiv.classList.add(‘tw:hidden’);
errorDiv.textContent = ”;
}
}

function clearCommentInput() {
const commentField = document.getElementById(PublicCommentSelectors.INPUT);

if (!commentField) {
return;
}

commentField.value = ”;
}

function updateComments(comments = []) {
state.comments = comments;
displayComments();
updateCommentCount();
}

function runCommentProcess(type) {
if (type === ‘postComment’) {
const comment = document.getElementById(PublicCommentSelectors.INPUT);

if (!comment || !comment?.value) {
return;
}

// Hide errors, show loader.
displayError();
displayLoader(true);
}

const data = {
type,
postId: 444112,
};

// Get a fresh nonce and either fetch comments or post comment.
fetch(`${adminAjaxUrl}?action=ep_get_public_comment_nonce`, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((response) => {
// Handle errors.
if (!response.success) {
displayLoader(false);
console.error(‘Error getting nonce: ‘, response?.data?.message);
return;
}

const nonce = response?.data?.nonce;

// Get comments.
if (type === ‘getComments’) {
getComments(nonce);
return;
}

// Post comment.
if (type === ‘postComment’) {
postComment(nonce);
}
})
.catch((e) => {
displayLoader(false);
console.error(`Error running comment process ${type}: `, e);
});
}

function getComments(nonce) {
const data = {
nonce,
postId: 444112,
};

// Fetch comments.
fetch(`${adminAjaxUrl}?action=ep_get_public_comments`, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((response) => {
// Handle errors.
if (!response.success) {
displayLoader(false);
console.error(‘Error getting comments: ‘, response?.data?.message);
return;
}

updateComments(response?.data?.comments);
displayLoader(false);
})
.catch((e) => {
displayLoader(false);
console.error(‘Error getting comments: ‘, e);
});
}

function postComment(nonce) {
const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user || !user?.uid) {
console.error(‘Error posting comment: Unauthorized. Submission aborted.’);
return;
}

const comment = document.getElementById(PublicCommentSelectors.INPUT);

if (!comment || !comment?.value) {
return;
}

const data = {
nonce,
comment: comment.value,
commentParent: 0,
postId: 444112,
uid: user?.uid,
};

// Post the comment.
fetch(`${adminAjaxUrl}?action=ep_create_public_comment`, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
credentials: ‘include’,
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((response) => {
// Handle errors.
if (!response.success) {
displayLoader(false);
displayError(response?.data?.message, true);
console.error(‘Error posting comment: ‘, response?.data?.message);
return;
}

// Handle success.
clearCommentInput();
runCommentProcess(‘getComments’);
})
.catch((e) => {
displayLoader(false);
displayError(e);
console.error(‘Error posting comment: ‘, e);
});
}

function toggleReplyForm(commentId) {
// Close any other open reply forms.
document.querySelectorAll(‘.ep-reply-form’).forEach(function(form) {
if (form.dataset.parentId !== String(commentId)) {
form.classList.add(‘tw:hidden’);
}
});

// Toggle the targeted reply form.
const targetForm = document.querySelector(‘.ep-reply-form[data-parent-id=”‘ + commentId + ‘”]’);

if (targetForm) {
targetForm.classList.toggle(‘tw:hidden’);

if (!targetForm.classList.contains(‘tw:hidden’)) {
targetForm.querySelector(‘.ep-reply-input’)?.focus();
}
}
}

function setReplyLoading(formEl, isLoading) {
const btn = formEl.querySelector(‘.ep-reply-submit’);
const btnText = formEl.querySelector(‘.ep-reply-button-text’);

if (!btn || !btnText) {
return;
}

if (isLoading) {
btnText.textContent = ‘Posting…’;
btn.disabled = true;
} else {
btnText.textContent = ‘Post Reply’;
btn.disabled = false;
}
}

function displayReplyError(formEl, error) {
const errorDiv = formEl.querySelector(‘.ep-reply-error’);

if (!errorDiv || !error) {
return;
}

errorDiv.textContent = ‘Reply error: ‘ + error;
errorDiv.classList.remove(‘tw:hidden’);
errorDiv.classList.add(‘tw:block’);
}

function clearReplyError(formEl) {
const errorDiv = formEl.querySelector(‘.ep-reply-error’);

if (!errorDiv) {
return;
}

errorDiv.textContent = ”;
errorDiv.classList.add(‘tw:hidden’);
errorDiv.classList.remove(‘tw:block’);
}

function postReply(nonce, parentId, replyText, formEl) {
const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user || !user?.uid) {
setReplyLoading(formEl, false);
return;
}

const data = {
nonce,
comment: replyText,
commentParent: parentId,
postId: 444112,
uid: user?.uid,
};

fetch(`${adminAjaxUrl}?action=ep_create_public_comment`, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
credentials: ‘include’,
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((response) => {
setReplyLoading(formEl, false);

if (!response.success) {
displayReplyError(formEl, response?.data?.message);
console.error(‘Error posting reply: ‘, response?.data?.message);
return;
}

formEl.querySelector(‘.ep-reply-input’).value = ”;
formEl.classList.add(‘tw:hidden’);
runCommentProcess(‘getComments’);
})
.catch((e) => {
setReplyLoading(formEl, false);
displayReplyError(formEl, ‘Network error. Please try again.’);
console.error(‘Error posting reply: ‘, e);
});
}

function submitReply(parentId, formEl) {
const input = formEl.querySelector(‘.ep-reply-input’);

if (!input || !input.value.trim()) {
return;
}

const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user || !user?.uid) {
openLoginModal();
return;
}

setReplyLoading(formEl, true);
clearReplyError(formEl);

const data = {
type: ‘postComment’,
postId: 444112,
};

fetch(`${adminAjaxUrl}?action=ep_get_public_comment_nonce`, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify(data),
})
.then((r) => r.json())
.then((response) => {
if (!response.success) {
setReplyLoading(formEl, false);
displayReplyError(formEl, response?.data?.message);
return;
}

postReply(response?.data?.nonce, parseInt(parentId, 10), input.value.trim(), formEl);
})
.catch((e) => {
setReplyLoading(formEl, false);
displayReplyError(formEl, ‘Network error. Please try again.’);
console.error(‘Error getting nonce for reply: ‘, e);
});
}

function setupCommentListDelegation() {
const commentListDiv = document.getElementById(PublicCommentSelectors.LIST);

if (!commentListDiv) {
return;
}

commentListDiv.addEventListener(‘click’, function(e) {
// Reply button: toggle the inline reply form.
const replyButton = e.target.closest(‘.’ + PublicCommentSelectors.REPLY_BUTTON);
if (replyButton) {
const commentId = replyButton.dataset.commentId;
const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user) {
openLoginModal();
return;
}

toggleReplyForm(commentId);
return;
}

// Reply cancel: hide the reply form.
const replyCancel = e.target.closest(‘.ep-reply-cancel’);
if (replyCancel) {
const parentId = replyCancel.dataset.parentId;
const form = document.querySelector(‘.ep-reply-form[data-parent-id=”‘ + parentId + ‘”]’);
if (form) {
form.classList.add(‘tw:hidden’);
}
return;
}

// Reply submit: post the reply.
const replySubmit = e.target.closest(‘.ep-reply-submit’);
if (replySubmit) {
const parentId = replySubmit.dataset.parentId;
const form = document.querySelector(‘.ep-reply-form[data-parent-id=”‘ + parentId + ‘”]’);
if (form) {
submitReply(parentId, form);
}
}
});
}

function setupUserAvatar() {
const usernameDiv = document.getElementById(PublicCommentSelectors.USERNAME);
const userAvatar = document.getElementById(PublicCommentSelectors.USER_AVATAR);

if (!usernameDiv || !userAvatar) {
return;
}

const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user) {
return;
}

const fullName = `${user?.firstName ?? ”} ${user?.lastName ?? ”}`;

usernameDiv.innerHTML = fullName;
userAvatar.innerHTML = getInitials(fullName);
}

function openLoginModal() {
window?.tp?.pianoId?.show({ displayMode: ‘modal’, screen: ‘login’ });
}

function setupCommentSubmitButton() {
const submitButton = document.getElementById(PublicCommentSelectors.SUBMIT);

if (!submitButton || state.submitCommentButtonRegistered) {
return;
}

// Register a single click handler that checks auth state at click time.
submitButton.addEventListener(‘click’, function() {
const user = window?.tp?.pianoId?.getUser() ?? null;

if (!user) {
openLoginModal();
return;
}

runCommentProcess(‘postComment’);
});

state.submitCommentButtonRegistered = true;
}

function setSortOrder(order) {
state.sortOrder = order;

const newestBtn = document.getElementById(PublicCommentSelectors.SORT_NEWEST);
const oldestBtn = document.getElementById(PublicCommentSelectors.SORT_OLDEST);

if (newestBtn && oldestBtn) {
const activeClasses = [‘tw:font-bold’, ‘tw:text-blue-800’];
const inactiveClasses = [‘tw:font-normal’, ‘tw:text-slate-500’];

if (order === ‘newest’) {
newestBtn.classList.add(…activeClasses);
newestBtn.classList.remove(…inactiveClasses);
oldestBtn.classList.add(…inactiveClasses);
oldestBtn.classList.remove(…activeClasses);
} else {
oldestBtn.classList.add(…activeClasses);
oldestBtn.classList.remove(…inactiveClasses);
newestBtn.classList.add(…inactiveClasses);
newestBtn.classList.remove(…activeClasses);
}
}

displayComments();
}

function setupSortControls() {
const newestBtn = document.getElementById(PublicCommentSelectors.SORT_NEWEST);
const oldestBtn = document.getElementById(PublicCommentSelectors.SORT_OLDEST);

if (newestBtn) {
newestBtn.addEventListener(‘click’, function() {
setSortOrder(‘newest’);
});
}

if (oldestBtn) {
oldestBtn.addEventListener(‘click’, function() {
setSortOrder(‘oldest’);
});
}
}

runCommentProcess(‘getComments’);
listenForPianoLogin();
setupCommentSubmitButton();
setupCommentListDelegation();
setupSortControls();
});

By Simon Moser
By Entrepreneur Store
By Ben Angel
By Entrepreneur Store
By Jonathan Small
By Jonathan Small

Related:

Digital Automation Training Benin: 5 Winning Skills Employers Demand in 2026

<a href="https://yoursite.com/automation-africa/" title="WhatsApp Marketing Automation Africa: 6 Dangerous Mistakes Brands Make in Nigeria”>
WhatsApp Marketing Automation Africa: 6 Dangerous Mistakes Brands Make in Nigeria

Want to learn this practically?

Join Justfine Infotech and build real digital skills in AI, automation, web development, digital marketing, office productivity, e-commerce, freelancing and cybersecurity.

Available Programmes:
6 Weeks Certificate • 3 Months Professional Certificate • 6 Months Diploma • Full Professional Diploma

WhatsApp:
+229 01 57 57 99 15
+229 01 66 68 11 60

Enroll Now

Source: www.entrepreneur.com

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top