brief-rags-bench/static/js/ui/annotations.ui.js

245 lines
7.5 KiB
JavaScript
Raw Permalink Normal View History

2025-12-25 09:47:11 +01:00
/**
* 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
}