/**
* @fileoverview Request Comments Handler - управление комментариями к заявкам
* Загрузка, отображение и добавление комментариев через AJAX
* @module components/requestCommentsHandler
*/
import { esc } from '../utils/stringUtils.js';
/**
* Инициализирует обработчик комментариев к заявкам
*
* @param {Object} options - Опции инициализации
* @param {string} options.commentsUrlTemplate - URL шаблон для получения комментариев (с /0/)
* @param {string} options.addCommentUrlTemplate - URL шаблон для добавления комментария (с /0/)
* @param {string} [options.collapseSelector='[data-comments-collapse]'] - Селектор collapse элементов
* @param {boolean} [options.autoloadCounts=true] - Автозагрузка счётчиков комментариев
* @returns {Object} API обработчика
*/
export function initRequestCommentsHandler(options) {
const {
commentsUrlTemplate,
addCommentUrlTemplate,
collapseSelector = '[data-comments-collapse]',
autoloadCounts = true
} = options;
if (!commentsUrlTemplate || !addCommentUrlTemplate) {
console.warn('RequestCommentsHandler: URL templates are required');
return null;
}
/**
* Рендерит HTML комментария
* @param {Object} comment - Объект комментария
* @returns {string} HTML строка
*/
function renderComment(comment) {
const author = (comment.author &&
(comment.author.full_name || comment.author.display_name || comment.author.username)) || '—';
return `
`;
}
/**
* Обновляет счётчик комментариев для заявки
* @param {string} reqId - ID заявки
* @param {number} count - Количество комментариев
*/
function updateCount(reqId, count) {
const btn = document.querySelector(`[data-bs-target="#rcoll-${reqId}"] [data-role="count"]`) ||
document.querySelector(`#req-${reqId} [data-role="count"]`);
if (btn) {
btn.textContent = count;
}
}
/**
* Загружает комментарии для заявки
* @param {HTMLElement} collapseEl - Collapse элемент
*/
async function loadComments(collapseEl) {
const reqId = collapseEl.getAttribute('data-request-id');
const block = collapseEl.querySelector('.comments-block');
const listEl = block.querySelector('[data-role=list]');
const spinner = block.querySelector('.spinner-border');
// Проверяем, загружены ли уже комментарии
if (collapseEl.dataset.loaded === '1') return;
spinner.style.display = 'inline-block';
try {
const url = commentsUrlTemplate.replace('/0/', `/${reqId}/`);
const resp = await fetch(url, {
headers: { 'Accept': 'application/json' }
});
if (!resp.ok) throw new Error('HTTP ' + resp.status);
const data = await resp.json();
// Рендерим комментарии
if (data.length) {
listEl.innerHTML = data.map(renderComment).join('');
} else {
listEl.innerHTML = 'Комментариев нет.
';
}
collapseEl.dataset.loaded = '1';
updateCount(reqId, data.length);
} catch (e) {
listEl.innerHTML = 'Не удалось загрузить.
';
console.error('Failed to load comments:', e);
} finally {
spinner.style.display = 'none';
}
}
/**
* Отправляет новый комментарий
* @param {HTMLElement} block - Блок комментариев
* @param {string} text - Текст комментария
* @returns {Promise