/* * Управляет и отображает историю графов чата. Предоставляет функционал для выбора * прошлых разговоров, начала новых чатов и удаления записей графов. */ import { EventBus } from '../utils/EventBus'; export class HistoryPanel { container: HTMLElement; props: { graphs: any[]; eventBus: EventBus; }; graphs: any[]; newChatButton: HTMLButtonElement; chatList: HTMLElement; contextMenu: HTMLElement; deleteButton: HTMLButtonElement; contextMenuGraphId: string | null; constructor( container: HTMLElement, props: { graphs: any[]; eventBus: EventBus; } ) { this.container = container; this.props = props; this.graphs = props.graphs || []; this.init(); } init(): void { this.container.innerHTML = `

История диалогов

`; this.newChatButton = this.container.querySelector('#new-chat-button') as HTMLButtonElement; this.chatList = this.container.querySelector('#chat-list') as HTMLElement; this.contextMenu = this.container.querySelector('#context-menu') as HTMLElement; this.deleteButton = this.container.querySelector('#delete-graph-button') as HTMLButtonElement; this.setupEventListeners(); this.renderGraphs(); } setupEventListeners(): void { this.newChatButton.addEventListener('click', () => { this.props.eventBus.emit('new-chat'); }); this.deleteButton.addEventListener('click', () => { if (this.contextMenuGraphId) { this.handleDeleteGraph(this.contextMenuGraphId); } }); // Закрытие контекстного меню при клике вне его document.addEventListener('click', (e) => { if (!this.contextMenu.contains(e.target as Node)) { this.contextMenu.style.display = 'none'; } }); } renderGraphs(): void { this.chatList.innerHTML = this.graphs .map((graph) => { const titleClass = graph.title_generated ? 'graph-title-generated' : 'graph-title-pending'; const displayTitle = graph.title || graph.first_message || `Граф ${graph.id}`; return `
${displayTitle}
`; }) .join(''); // Добавляем обработчики событий this.chatList.querySelectorAll('.chat-list-item').forEach((item) => { item.addEventListener('click', (e) => { if (!(e.target as HTMLElement).classList.contains('chat-item-options-button')) { const graphId = (item as HTMLElement).dataset.graphId; if (graphId) { this.props.eventBus.emit('graph-selected', { graphId: graphId, currentNode: null }); } } }); }); this.chatList.querySelectorAll('.chat-item-options-button').forEach((button) => { button.addEventListener('click', (e) => { e.stopPropagation(); this.showContextMenu(e, (button as HTMLElement).dataset.graphId || ''); }); }); } showContextMenu(event: Event, graphId: string): void { this.contextMenuGraphId = graphId; this.contextMenu.style.display = 'block'; this.contextMenu.style.left = `${(event as MouseEvent).clientX}px`; this.contextMenu.style.top = `${(event as MouseEvent).clientY}px`; } async handleDeleteGraph(graphId: string): Promise { try { const response = await fetch(`http://localhost:5000/api/graphs/${graphId}`, { method: 'DELETE' }); if (!response.ok) { throw new Error(`HTTP ошибка! статус: ${response.status}`); } // Обновляем список графов this.graphs = this.graphs.filter((graph) => graph.id !== graphId); this.renderGraphs(); this.contextMenu.style.display = 'none'; } catch (error) { console.error('Ошибка удаления графа:', error); } } updateGraphs(newGraphs: any[]): void { this.graphs = newGraphs; this.renderGraphs(); } destroy(): void { this.container.innerHTML = ''; } }