/** * Annotations UI * * UI компонент для работы с аннотациями ответов. */ import appState from '../state/appState.js' import { getInputValue, setInputValue } from '../utils/dom.utils.js' /** * Инициализировать аннотацию для ответа * @param {number} index - Индекс ответа */ export function initForAnswer(index) { const env = appState.getCurrentEnv() if (!env.annotations[index]) { env.annotations[index] = { overall: { rating: '', comment: '' }, body_research: { issues: [], comment: '' }, body_analytical_hub: { issues: [], comment: '' }, docs_from_vectorstore: { research: {}, analytical_hub: {} }, docs_to_llm: { research: {}, analytical_hub: {} } } } } /** * Загрузить аннотации для ответа * @param {number} index - Индекс ответа */ export function loadForAnswer(index) { initForAnswer(index) const env = appState.getCurrentEnv() const annotation = env.annotations[index] // Load overall rating const ratingSelect = document.getElementById('overall-rating') const overallComment = document.getElementById('overall-comment') if (ratingSelect) { ratingSelect.value = annotation.overall.rating || '' } if (overallComment) { setInputValue(overallComment, annotation.overall.comment || '') } // Load body annotations loadSection('body_research', annotation.body_research) loadSection('body_analytical_hub', annotation.body_analytical_hub) // Load document annotations loadDocuments('docs_from_vectorstore', 'research', annotation.docs_from_vectorstore?.research) loadDocuments('docs_from_vectorstore', 'analytical_hub', annotation.docs_from_vectorstore?.analytical_hub) loadDocuments('docs_to_llm', 'research', annotation.docs_to_llm?.research) loadDocuments('docs_to_llm', 'analytical_hub', annotation.docs_to_llm?.analytical_hub) // Setup event listeners for current answer setupListeners() } /** * Загрузить аннотацию секции (body) * @param {string} section - Название секции * @param {object} data - Данные аннотации */ export function loadSection(section, data) { // Load checkboxes document.querySelectorAll(`input[data-section="${section}"]`).forEach(checkbox => { if (checkbox.type === 'checkbox') { const issue = checkbox.dataset.issue checkbox.checked = data.issues.includes(issue) updateCheckboxStyle(checkbox) } }) // Load comment const textarea = document.querySelector(`textarea[data-section="${section}"]:not([data-doc-index])`) if (textarea) { setInputValue(textarea, data.comment || '') } } /** * Загрузить аннотации документов * @param {string} section - Секция (docs_from_vectorstore, docs_to_llm) * @param {string} subsection - Подсекция (research, analytical_hub) * @param {object} docs - Объект с аннотациями документов */ export function loadDocuments(section, subsection, docs) { if (!docs) return Object.keys(docs).forEach(docIndex => { const data = docs[docIndex] // Load checkboxes document.querySelectorAll( `input[data-section="${section}"][data-subsection="${subsection}"][data-doc-index="${docIndex}"]` ).forEach(checkbox => { if (checkbox.type === 'checkbox') { const issue = checkbox.dataset.issue checkbox.checked = data.issues?.includes(issue) || false updateCheckboxStyle(checkbox) } }) // Load comment const textarea = document.querySelector( `textarea[data-section="${section}"][data-subsection="${subsection}"][data-doc-index="${docIndex}"]` ) if (textarea) { setInputValue(textarea, data.comment || '') } }) } /** * Настроить обработчики событий для аннотаций */ export function setupListeners() { const env = appState.getCurrentEnv() const index = env.currentAnswerIndex // Overall rating const ratingSelect = document.getElementById('overall-rating') const overallComment = document.getElementById('overall-comment') if (ratingSelect) { ratingSelect.onchange = (e) => { env.annotations[index].overall.rating = e.target.value saveDraft() } } if (overallComment) { overallComment.oninput = (e) => { env.annotations[index].overall.comment = getInputValue(e.target) saveDraft() } } // Section checkboxes and textareas document.querySelectorAll('input.checkbox, textarea').forEach(element => { const section = element.dataset.section const subsection = element.dataset.subsection const docIndex = element.dataset.docIndex if (!section) return if (element.type === 'checkbox') { element.onchange = (e) => { const issue = e.target.dataset.issue if (docIndex !== undefined) { // Document annotation if (!env.annotations[index][section]) { env.annotations[index][section] = { research: {}, analytical_hub: {} } } if (!env.annotations[index][section][subsection]) { env.annotations[index][section][subsection] = {} } if (!env.annotations[index][section][subsection][docIndex]) { env.annotations[index][section][subsection][docIndex] = { issues: [], comment: '' } } const issues = env.annotations[index][section][subsection][docIndex].issues if (e.target.checked) { if (!issues.includes(issue)) issues.push(issue) } else { const idx = issues.indexOf(issue) if (idx > -1) issues.splice(idx, 1) } } else { // Body annotation const issues = env.annotations[index][section].issues if (e.target.checked) { if (!issues.includes(issue)) issues.push(issue) } else { const idx = issues.indexOf(issue) if (idx > -1) issues.splice(idx, 1) } } updateCheckboxStyle(e.target) saveDraft() } } else if (element.tagName === 'TEXTAREA') { element.oninput = (e) => { const value = getInputValue(e.target) if (docIndex !== undefined) { // Document annotation if (!env.annotations[index][section][subsection][docIndex]) { env.annotations[index][section][subsection][docIndex] = { issues: [], comment: '' } } env.annotations[index][section][subsection][docIndex].comment = value } else if (section !== 'overall') { // Body annotation env.annotations[index][section].comment = value } saveDraft() } } }) } /** * Обновить стиль чекбокса (добавить checked класс к label) * @param {HTMLElement} checkbox - Чекбокс элемент */ export function updateCheckboxStyle(checkbox) { const label = checkbox.closest('.issue-checkbox') if (label) { if (checkbox.checked) { label.classList.add('checked') } else { label.classList.remove('checked') } } } /** * Сохранить черновик аннотаций в localStorage */ export function saveDraft() { const currentEnv = appState.getCurrentEnvironment() appState.saveEnvironmentToStorage(currentEnv) } // Export as default object export default { initForAnswer, loadForAnswer, loadSection, loadDocuments, setupListeners, updateCheckboxStyle, saveDraft }