/*
* Управляет и отображает историю графов чата. Предоставляет функционал для выбора
* прошлых разговоров, начала новых чатов и удаления записей графов.
*/
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 `
`;
})
.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 = '';
}
}