/** * Questions List UI * * UI компонент для списка вопросов. */ import appState from '../state/appState.js' import { escapeHtml, formatTime, pluralize } from '../utils/format.utils.js' import { setElementText, setElementHTML } from '../utils/dom.utils.js' /** * Проверить наличие аннотаций в секции документов * @param {object} docsSection - Секция документов * @returns {boolean} True если есть аннотации */ export function hasAnnotationsInDocs(docsSection) { if (!docsSection) return false // Check research documents if (docsSection.research) { for (const docIndex in docsSection.research) { const doc = docsSection.research[docIndex] if (doc.issues?.length > 0 || doc.comment) { return true } } } // Check analytical_hub documents if (docsSection.analytical_hub) { for (const docIndex in docsSection.analytical_hub) { const doc = docsSection.analytical_hub[docIndex] if (doc.issues?.length > 0 || doc.comment) { return true } } } return false } /** * Отрендерить список вопросов */ export function render() { const container = document.getElementById('questions-list') const countElement = document.getElementById('questions-count') if (!container) { console.error('Questions list container not found') return } const env = appState.getCurrentEnv() const response = env.currentResponse if (!response || !response.answers || response.answers.length === 0) { setElementHTML(container, `
question_answer
Нет данных
Отправьте запрос к RAG бэкенду
`) if (countElement) { setElementText(countElement, '0 вопросов') } return } // Update count if (countElement) { const count = response.answers.length const text = `${count} ${pluralize(count, 'вопрос', 'вопроса', 'вопросов')}` setElementText(countElement, text) } // Render questions const html = response.answers.map((answer, index) => { const isActive = index === env.currentAnswerIndex const annotation = env.annotations[index] // Check for annotations in body sections const hasBodyAnnotations = annotation && ( annotation.overall?.comment || annotation.body_research?.issues?.length > 0 || annotation.body_analytical_hub?.issues?.length > 0 ) // Check for annotations in documents const hasDocAnnotations = annotation && ( hasAnnotationsInDocs(annotation.docs_from_vectorstore) || hasAnnotationsInDocs(annotation.docs_to_llm) ) const hasAnyAnnotations = hasBodyAnnotations || hasDocAnnotations // Get rating indicator const rating = annotation?.overall?.rating let ratingIndicator = '' if (rating === 'correct') { ratingIndicator = 'check_circle' } else if (rating === 'partial') { ratingIndicator = 'error' } else if (rating === 'incorrect') { ratingIndicator = 'cancel' } // Get annotation bookmark indicator (separate from rating) const annotationIndicator = hasAnyAnnotations ? 'bookmark' : '' return `
#${index + 1}
${ratingIndicator} ${annotationIndicator}
${escapeHtml(answer.question)}
${formatTime(answer.processing_time_sec)}
` }).join('') setElementHTML(container, html) } /** * Выбрать ответ по индексу * @param {number} index - Индекс ответа * @param {Function} onSelect - Callback при выборе */ export function selectAnswer(index, onSelect) { const env = appState.getCurrentEnv() env.currentAnswerIndex = index // Re-render questions list to update active state render() // Call callback if provided if (typeof onSelect === 'function') { onSelect(index) } } // Export as default object export default { render, selectAnswer, hasAnnotationsInDocs }