Change to show graph title in graph panel
This commit is contained in:
parent
47cff8a121
commit
b0d802241b
|
|
@ -24,6 +24,7 @@ export class GraphView extends ItemView {
|
||||||
graphsList: any[];
|
graphsList: any[];
|
||||||
selectedGraphId: string | null;
|
selectedGraphId: string | null;
|
||||||
selectedNodeIds: Set<string>; // Добавляем Set для хранения ID выделенных узлов
|
selectedNodeIds: Set<string>; // Добавляем Set для хранения ID выделенных узлов
|
||||||
|
selectedGraphTitle: string | null;
|
||||||
|
|
||||||
// UI Elements
|
// UI Elements
|
||||||
historyPanel: HistoryPanel | null;
|
historyPanel: HistoryPanel | null;
|
||||||
|
|
@ -33,9 +34,9 @@ export class GraphView extends ItemView {
|
||||||
toggleButton: HTMLButtonElement;
|
toggleButton: HTMLButtonElement;
|
||||||
isHistoryCollapsed: boolean;
|
isHistoryCollapsed: boolean;
|
||||||
|
|
||||||
// Глобальные кнопки действий
|
// Глобальные кнопки действий
|
||||||
copySelectedButton: HTMLButtonElement | null = null;
|
copySelectedButton: HTMLButtonElement | null = null;
|
||||||
deleteSelectedButton: HTMLButtonElement | null = null;
|
deleteSelectedButton: HTMLButtonElement | null = null;
|
||||||
|
|
||||||
constructor(leaf: WorkspaceLeaf, plugin: LLMAgentPlugin) {
|
constructor(leaf: WorkspaceLeaf, plugin: LLMAgentPlugin) {
|
||||||
super(leaf);
|
super(leaf);
|
||||||
|
|
@ -47,7 +48,8 @@ export class GraphView extends ItemView {
|
||||||
this.historyPanel = null;
|
this.historyPanel = null;
|
||||||
this.reactRoot = null;
|
this.reactRoot = null;
|
||||||
this.isHistoryCollapsed = true;
|
this.isHistoryCollapsed = true;
|
||||||
this.selectedNodeIds = new Set<string>(); // Инициализируем Set
|
this.selectedNodeIds = new Set<string>(); // Инициализируем Set
|
||||||
|
this.selectedGraphTitle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,7 +63,7 @@ export class GraphView extends ItemView {
|
||||||
* @returns {string} Отображаемое имя представления.
|
* @returns {string} Отображаемое имя представления.
|
||||||
*/
|
*/
|
||||||
getDisplayText(): string {
|
getDisplayText(): string {
|
||||||
return 'LLM Agent Graph';
|
return this.selectedGraphTitle || 'LLM Agent Graph';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -106,9 +108,9 @@ export class GraphView extends ItemView {
|
||||||
eventBus: this.plugin.eventBus
|
eventBus: this.plugin.eventBus
|
||||||
});
|
});
|
||||||
|
|
||||||
// Создаем кнопки переключения и глобальные кнопки действий
|
// Создаем кнопки переключения и глобальные кнопки действий
|
||||||
this.addToggleButton();
|
this.addToggleButton();
|
||||||
this.addGlobalActionButtons(); // Добавляем вызов новой функции
|
this.addGlobalActionButtons(); // Добавляем вызов новой функции
|
||||||
|
|
||||||
// Инициализируем React Flow
|
// Инициализируем React Flow
|
||||||
this.initializeGraphPanel();
|
this.initializeGraphPanel();
|
||||||
|
|
@ -116,7 +118,7 @@ export class GraphView extends ItemView {
|
||||||
// Подписываемся на события
|
// Подписываемся на события
|
||||||
this.plugin.eventBus.on('new-chat', this.handleNewChat.bind(this));
|
this.plugin.eventBus.on('new-chat', this.handleNewChat.bind(this));
|
||||||
this.plugin.eventBus.on('graph-selected', this.handleGraphSelected.bind(this));
|
this.plugin.eventBus.on('graph-selected', this.handleGraphSelected.bind(this));
|
||||||
this.plugin.eventBus.on('delete-node', this.handleDeleteNodeFromChat.bind(this)); // Слушаем событие из ChatPanel
|
this.plugin.eventBus.on('delete-node', this.handleDeleteNodeFromChat.bind(this)); // Слушаем событие из ChatPanel
|
||||||
|
|
||||||
// Загружаем список графов
|
// Загружаем список графов
|
||||||
await this.fetchGraphsList();
|
await this.fetchGraphsList();
|
||||||
|
|
@ -140,9 +142,23 @@ export class GraphView extends ItemView {
|
||||||
|
|
||||||
this.plugin.eventBus.off('new-chat', this.handleNewChat);
|
this.plugin.eventBus.off('new-chat', this.handleNewChat);
|
||||||
this.plugin.eventBus.off('graph-selected', this.handleGraphSelected);
|
this.plugin.eventBus.off('graph-selected', this.handleGraphSelected);
|
||||||
this.plugin.eventBus.off('delete-node', this.handleDeleteNodeFromChat);
|
this.plugin.eventBus.off('delete-node', this.handleDeleteNodeFromChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------- Custom Title Update ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Обновляет текстовое содержимое заголовка представления.
|
||||||
|
* Этот метод должен быть вызван для динамического изменения заголовка
|
||||||
|
* после первоначальной отрисовки представления.
|
||||||
|
*/
|
||||||
|
updateTitle(): void {
|
||||||
|
const titleElement = this.containerEl.querySelector('.view-header-title');
|
||||||
|
if (titleElement) {
|
||||||
|
titleElement.textContent = this.selectedGraphTitle || 'LLM Agent Graph';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------- History Panel Toggle --------------------------------------------------
|
// ----------------------------------------------- History Panel Toggle --------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -164,37 +180,37 @@ export class GraphView extends ItemView {
|
||||||
|
|
||||||
// ----------------------------------------------- Graph Panel Integration --------------------------------------------------
|
// ----------------------------------------------- Graph Panel Integration --------------------------------------------------
|
||||||
|
|
||||||
addToggleButton(): void {
|
addToggleButton(): void {
|
||||||
const buttonWrapper = this.graphContainer.createDiv({ cls: 'graph-view-toolbar' }); // Создаем контейнер для кнопок
|
const buttonWrapper = this.graphContainer.createDiv({ cls: 'graph-view-toolbar' }); // Создаем контейнер для кнопок
|
||||||
this.toggleButton = buttonWrapper.createEl('button', { cls: 'global-action-button' }); // history-toggle-button
|
this.toggleButton = buttonWrapper.createEl('button', { cls: 'global-action-button' }); // history-toggle-button
|
||||||
this.toggleButton.textContent = this.isHistoryCollapsed ? '📋' : '❌';
|
this.toggleButton.textContent = this.isHistoryCollapsed ? '📋' : '❌';
|
||||||
this.toggleButton.addEventListener('click', this.toggleHistoryPanel.bind(this));
|
this.toggleButton.addEventListener('click', this.toggleHistoryPanel.bind(this));
|
||||||
console.log('Toggle button created and appended:', this.toggleButton);
|
console.log('Toggle button created and appended:', this.toggleButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Добавляет глобальные кнопки действий для выделенных узлов.
|
* Добавляет глобальные кнопки действий для выделенных узлов.
|
||||||
*/
|
*/
|
||||||
addGlobalActionButtons(): void {
|
addGlobalActionButtons(): void {
|
||||||
const toolbar = this.graphContainer.querySelector('.graph-view-toolbar');
|
const toolbar = this.graphContainer.querySelector('.graph-view-toolbar');
|
||||||
if (!toolbar) return;
|
if (!toolbar) return;
|
||||||
|
|
||||||
// Кнопка "Копировать выделенные"
|
// Кнопка "Копировать выделенные"
|
||||||
this.copySelectedButton = toolbar.createEl('button', {
|
this.copySelectedButton = toolbar.createEl('button', {
|
||||||
cls: 'global-action-button',
|
cls: 'global-action-button',
|
||||||
attr: { 'aria-label': 'Копировать выделенные узлы', 'data-tooltip': 'Копировать выделенные узлы' },
|
attr: { 'aria-label': 'Копировать выделенные узлы', 'data-tooltip': 'Копировать выделенные узлы' },
|
||||||
text: '📄'
|
text: '📄'
|
||||||
});
|
});
|
||||||
this.copySelectedButton.addEventListener('click', this.handleCopySelectedNodes.bind(this));
|
this.copySelectedButton.addEventListener('click', this.handleCopySelectedNodes.bind(this));
|
||||||
|
|
||||||
// Кнопка "Удалить выделенные"
|
// Кнопка "Удалить выделенные"
|
||||||
this.deleteSelectedButton = toolbar.createEl('button', {
|
this.deleteSelectedButton = toolbar.createEl('button', {
|
||||||
cls: 'global-action-button',
|
cls: 'global-action-button',
|
||||||
attr: { 'aria-label': 'Удалить выделенные узлы', 'data-tooltip': 'Удалить выделенные узлы' },
|
attr: { 'aria-label': 'Удалить выделенные узлы', 'data-tooltip': 'Удалить выделенные узлы' },
|
||||||
text: '🗑️'
|
text: '🗑️'
|
||||||
});
|
});
|
||||||
this.deleteSelectedButton.addEventListener('click', this.handleDeleteSelectedNodes.bind(this));
|
this.deleteSelectedButton.addEventListener('click', this.handleDeleteSelectedNodes.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------- Graph Panel Integration --------------------------------------------------
|
// ----------------------------------------------- Graph Panel Integration --------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -204,9 +220,9 @@ export class GraphView extends ItemView {
|
||||||
*/
|
*/
|
||||||
initializeGraphPanel(): void {
|
initializeGraphPanel(): void {
|
||||||
this.graphContainer.empty();
|
this.graphContainer.empty();
|
||||||
// Перемещаем кнопки обратно после очистки, если они были частью graphContainer
|
// Перемещаем кнопки обратно после очистки, если они были частью graphContainer
|
||||||
this.addToggleButton();
|
this.addToggleButton();
|
||||||
this.addGlobalActionButtons();
|
this.addGlobalActionButtons();
|
||||||
|
|
||||||
const wrapper = this.graphContainer.createDiv();
|
const wrapper = this.graphContainer.createDiv();
|
||||||
wrapper.style.cssText = 'width: 100%; height: 100%;';
|
wrapper.style.cssText = 'width: 100%; height: 100%;';
|
||||||
|
|
@ -236,10 +252,10 @@ export class GraphView extends ItemView {
|
||||||
edges: this.graphData.edges
|
edges: this.graphData.edges
|
||||||
},
|
},
|
||||||
onNodeClick: this.handleNodeClick.bind(this),
|
onNodeClick: this.handleNodeClick.bind(this),
|
||||||
onNodeSelectionChange: this.handleNodeSelectionChange.bind(this), // Передаем обработчик изменения выделения
|
onNodeSelectionChange: this.handleNodeSelectionChange.bind(this), // Передаем обработчик изменения выделения
|
||||||
onNodeDelete: this.handleDeleteNode.bind(this), // Передаем колбэк для удаления одиночного узла
|
onNodeDelete: this.handleDeleteNode.bind(this), // Передаем колбэк для удаления одиночного узла
|
||||||
selectedNodeIds: this.selectedNodeIds, // Передаем Set выделенных узлов
|
selectedNodeIds: this.selectedNodeIds, // Передаем Set выделенных узлов
|
||||||
app: this.plugin.app
|
app: this.plugin.app
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -272,87 +288,92 @@ export class GraphView extends ItemView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Загружает данные конкретного графа по его ID.
|
* Загружает данные конкретного графа по его ID.
|
||||||
* @param {string} graphId - ID графа для загрузки.
|
* @param {string} graphId - ID графа для загрузки.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async fetchGraphData(graphId: string): Promise<void> {
|
async fetchGraphData(graphId: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (!graphId) {
|
if (!graphId) {
|
||||||
this.graphData = { nodes: [], edges: [] };
|
this.graphData = { nodes: [], edges: [] };
|
||||||
this.currentNode = null;
|
this.currentNode = null;
|
||||||
this.selectedNodeIds.clear(); // Очищаем выделения
|
this.selectedNodeIds.clear(); // Очищаем выделения
|
||||||
this.renderGraphPanel();
|
this.selectedGraphTitle = null; // Сброс заголовка
|
||||||
this.plugin.eventBus.emit('chat-history-updated', { graphId: null, messages: [], current_node_id: null });
|
this.updateTitle(); // Обновляем заголовок
|
||||||
return;
|
this.renderGraphPanel();
|
||||||
}
|
this.plugin.eventBus.emit('chat-history-updated', { graphId: null, messages: [], current_node_id: null });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${graphId}`);
|
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${graphId}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
throw new Error(`Ошибка загрузки данных графа: ${response.status} - ${errorText}`);
|
throw new Error(`Ошибка загрузки данных графа: ${response.status} - ${errorText}`);
|
||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
this.graphData = {
|
this.graphData = {
|
||||||
nodes: data.graph_nodes || [],
|
nodes: data.graph_nodes || [],
|
||||||
edges: data.graph_edges || []
|
edges: data.graph_edges || []
|
||||||
};
|
};
|
||||||
this.currentNode = data.current_node_id;
|
this.currentNode = data.current_node_id;
|
||||||
|
|
||||||
// Перерендериваем граф
|
// Устанавливаем заголовок графа
|
||||||
this.renderGraphPanel();
|
this.selectedGraphTitle = data.title || data.first_message || `Граф ${graphId.substring(0, 8)}...`;
|
||||||
|
this.updateTitle(); // Обновляем заголовок
|
||||||
// Также обновляем ChatView с полученными сообщениями и текущим узлом
|
// Перерендериваем граф
|
||||||
this.plugin.eventBus.emit('chat-history-updated', {
|
this.renderGraphPanel();
|
||||||
graphId: graphId,
|
|
||||||
messages: data.messages || [],
|
|
||||||
current_node_id: data.current_node_id // Передаем актуальный current_node_id
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
// Также обновляем ChatView с полученными сообщениями и текущим узлом
|
||||||
console.error('Ошибка загрузки данных графа:', error);
|
this.plugin.eventBus.emit('chat-history-updated', {
|
||||||
// Optionally: show a notice to the user
|
graphId: graphId,
|
||||||
// new Notice(`Ошибка загрузки данных графа: ${error.message}`);
|
messages: data.messages || [],
|
||||||
}
|
current_node_id: data.current_node_id // Передаем актуальный current_node_id
|
||||||
}
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка загрузки данных графа:', error);
|
||||||
|
this.selectedGraphTitle = null;
|
||||||
|
this.updateTitle(); // Обновляем заголовок
|
||||||
|
// Optionally: show a notice to the user
|
||||||
|
// new Notice(`Ошибка загрузки данных графа: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Удаляет узел графа по его ID.
|
* Удаляет узел графа по его ID.
|
||||||
* @param {string} graphId - ID графа.
|
* @param {string} graphId - ID графа.
|
||||||
* @param {string} nodeId - ID узла для удаления.
|
* @param {string} nodeId - ID узла для удаления.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async handleDeleteNode(nodeId: string): Promise<void> {
|
async handleDeleteNode(nodeId: string): Promise<void> {
|
||||||
if (!this.selectedGraphId) {
|
if (!this.selectedGraphId) {
|
||||||
new Notice('Не выбран граф для удаления узла.', 3000);
|
new Notice('Не выбран граф для удаления узла.', 3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${this.selectedGraphId}/nodes/${nodeId}`, {
|
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${this.selectedGraphId}/nodes/${nodeId}`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
throw new Error(`Ошибка удаления узла: ${response.status} - ${errorText}`);
|
throw new Error(`Ошибка удаления узла: ${response.status} - ${errorText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Notice('Узел успешно удален.', 2000);
|
new Notice('Узел успешно удален.', 2000);
|
||||||
// После удаления узла, нужно обновить данные графа и перерисовать его.
|
// После удаления узла, нужно обновить данные графа и перерисовать его.
|
||||||
// Это также обновит ChatPanel, если удаленное сообщение было частью текущей ветки.
|
// Это также обновит ChatPanel, если удаленное сообщение было частью текущей ветки.
|
||||||
await this.fetchGraphData(this.selectedGraphId);
|
await this.fetchGraphData(this.selectedGraphId);
|
||||||
|
|
||||||
// Сбрасываем выделение, если удаленный узел был выделен
|
// Сбрасываем выделение, если удаленный узел был выделен
|
||||||
this.selectedNodeIds.delete(nodeId);
|
this.selectedNodeIds.delete(nodeId);
|
||||||
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error(`Ошибка при удалении узла ${nodeId}:`, error);
|
||||||
console.error(`Ошибка при удалении узла ${nodeId}:`, error);
|
new Notice(`Ошибка при удалении узла: ${error.message}`, 5000);
|
||||||
new Notice(`Ошибка при удалении узла: ${error.message}`, 5000);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------- Event Handlers ------------------------------------------------------------
|
// ----------------------------------------------- Event Handlers ------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -363,26 +384,26 @@ export class GraphView extends ItemView {
|
||||||
*/
|
*/
|
||||||
handleNodeClick(nodeId: string): void {
|
handleNodeClick(nodeId: string): void {
|
||||||
this.currentNode = nodeId;
|
this.currentNode = nodeId;
|
||||||
// Очищаем предыдущие выделения при обычном клике
|
// Очищаем предыдущие выделения при обычном клике
|
||||||
if (this.selectedNodeIds.size > 0) {
|
if (this.selectedNodeIds.size > 0) {
|
||||||
this.selectedNodeIds.clear();
|
this.selectedNodeIds.clear();
|
||||||
}
|
}
|
||||||
this.plugin.eventBus.emit('node-selected', { nodeId, graphId: this.selectedGraphId });
|
this.plugin.eventBus.emit('node-selected', { nodeId, graphId: this.selectedGraphId });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик изменения состояния выделения узла.
|
* Обработчик изменения состояния выделения узла.
|
||||||
* @param {string} nodeId - ID узла.
|
* @param {string} nodeId - ID узла.
|
||||||
* @param {boolean} isSelected - Новое состояние выделения.
|
* @param {boolean} isSelected - Новое состояние выделения.
|
||||||
*/
|
*/
|
||||||
handleNodeSelectionChange(nodeId: string, isSelected: boolean): void {
|
handleNodeSelectionChange(nodeId: string, isSelected: boolean): void {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
this.selectedNodeIds.add(nodeId);
|
this.selectedNodeIds.add(nodeId);
|
||||||
} else {
|
} else {
|
||||||
this.selectedNodeIds.delete(nodeId);
|
this.selectedNodeIds.delete(nodeId);
|
||||||
}
|
}
|
||||||
this.renderGraphPanel(); // Перерендериваем для обновления визуального состояния выделения
|
this.renderGraphPanel(); // Перерендериваем для обновления визуального состояния выделения
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик начала нового чата.
|
* Обработчик начала нового чата.
|
||||||
|
|
@ -393,7 +414,9 @@ export class GraphView extends ItemView {
|
||||||
this.currentNode = null;
|
this.currentNode = null;
|
||||||
this.selectedGraphId = null;
|
this.selectedGraphId = null;
|
||||||
this.selectedNodeIds.clear(); // Очищаем выделения
|
this.selectedNodeIds.clear(); // Очищаем выделения
|
||||||
this.renderGraphPanel();
|
this.selectedGraphTitle = null; // Сброс заголовка при новом чате
|
||||||
|
this.updateTitle(); // Обновляем заголовок
|
||||||
|
this.renderGraphPanel();
|
||||||
this.fetchGraphsList(); // Обновить список графов, чтобы показать новый пустой чат
|
this.fetchGraphsList(); // Обновить список графов, чтобы показать новый пустой чат
|
||||||
this.plugin.eventBus.emit('chat-history-updated', { graphId: null, messages: [], current_node_id: null });
|
this.plugin.eventBus.emit('chat-history-updated', { graphId: null, messages: [], current_node_id: null });
|
||||||
}
|
}
|
||||||
|
|
@ -406,100 +429,100 @@ export class GraphView extends ItemView {
|
||||||
*/
|
*/
|
||||||
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
||||||
this.selectedGraphId = data.graphId;
|
this.selectedGraphId = data.graphId;
|
||||||
this.selectedNodeIds.clear(); // Очищаем выделения при смене графа
|
this.selectedNodeIds.clear(); // Очищаем выделения при смене графа
|
||||||
await this.fetchGraphData(data.graphId);
|
await this.fetchGraphData(data.graphId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик события удаления узла из ChatPanel.
|
* Обработчик события удаления узла из ChatPanel.
|
||||||
* @param {{ graphId: string, nodeId: string }} data - Данные об удаляемом узле.
|
* @param {{ graphId: string, nodeId: string }} data - Данные об удаляемом узле.
|
||||||
*/
|
*/
|
||||||
async handleDeleteNodeFromChat(data: { graphId: string, nodeId: string }): Promise<void> {
|
async handleDeleteNodeFromChat(data: { graphId: string, nodeId: string }): Promise<void> {
|
||||||
if (data.graphId === this.selectedGraphId) {
|
if (data.graphId === this.selectedGraphId) {
|
||||||
await this.handleDeleteNode(data.nodeId);
|
await this.handleDeleteNode(data.nodeId);
|
||||||
} else {
|
} else {
|
||||||
new Notice('Сообщение относится к другому графу. Удаление невозможно из текущего контекста.', 3000);
|
new Notice('Сообщение относится к другому графу. Удаление невозможно из текущего контекста.', 3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик для кнопки "Копировать выделенные узлы".
|
* Обработчик для кнопки "Копировать выделенные узлы".
|
||||||
*/
|
*/
|
||||||
async handleCopySelectedNodes(): Promise<void> {
|
async handleCopySelectedNodes(): Promise<void> {
|
||||||
if (this.selectedNodeIds.size === 0) {
|
if (this.selectedNodeIds.size === 0) {
|
||||||
new Notice('Выберите узлы для копирования.', 2000);
|
new Notice('Выберите узлы для копирования.', 2000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messagesToCopy: string[] = [];
|
const messagesToCopy: string[] = [];
|
||||||
// Собираем сообщения в порядке выделения
|
// Собираем сообщения в порядке выделения
|
||||||
// Необходимо пройтись по nodes в graphData, чтобы получить актуальные данные сообщений
|
// Необходимо пройтись по nodes в graphData, чтобы получить актуальные данные сообщений
|
||||||
const orderedNodeIds = Array.from(this.selectedNodeIds); // Сохраняем порядок
|
const orderedNodeIds = Array.from(this.selectedNodeIds); // Сохраняем порядок
|
||||||
for (const nodeId of orderedNodeIds) {
|
for (const nodeId of orderedNodeIds) {
|
||||||
const node = this.graphData.nodes.find(n => n.id === nodeId);
|
const node = this.graphData.nodes.find(n => n.id === nodeId);
|
||||||
if (node && node.data && node.data.message && node.data.message.content) {
|
if (node && node.data && node.data.message && node.data.message.content) {
|
||||||
messagesToCopy.push(node.data.message.content);
|
messagesToCopy.push(node.data.message.content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messagesToCopy.length > 0) {
|
if (messagesToCopy.length > 0) {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(messagesToCopy.join('\n\n--- Разделитель --- \n\n'));
|
await navigator.clipboard.writeText(messagesToCopy.join('\n\n--- Разделитель --- \n\n'));
|
||||||
new Notice(`Скопировано ${messagesToCopy.length} сообщений.`, 2000);
|
new Notice(`Скопировано ${messagesToCopy.length} сообщений.`, 2000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Не удалось скопировать сообщения:', err);
|
console.error('Не удалось скопировать сообщения:', err);
|
||||||
new Notice('Ошибка при копировании сообщений.', 3000);
|
new Notice('Ошибка при копировании сообщений.', 3000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new Notice('Нет содержимого для копирования в выделенных узлах.', 2000);
|
new Notice('Нет содержимого для копирования в выделенных узлах.', 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик для кнопки "Удалить выделенные узлы".
|
* Обработчик для кнопки "Удалить выделенные узлы".
|
||||||
*/
|
*/
|
||||||
async handleDeleteSelectedNodes(): Promise<void> {
|
async handleDeleteSelectedNodes(): Promise<void> {
|
||||||
if (this.selectedNodeIds.size === 0) {
|
if (this.selectedNodeIds.size === 0) {
|
||||||
new Notice('Выберите узлы для удаления.', 2000);
|
new Notice('Выберите узлы для удаления.', 2000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.selectedGraphId) {
|
if (!this.selectedGraphId) {
|
||||||
new Notice('Не выбран граф для удаления узлов.', 3000);
|
new Notice('Не выбран граф для удаления узлов.', 3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmed = await Dialog.confirm(
|
const confirmed = await Dialog.confirm(
|
||||||
this.plugin.app,
|
this.plugin.app,
|
||||||
`Вы уверены, что хотите удалить ${this.selectedNodeIds.size} выделенных узлов?`
|
`Вы уверены, что хотите удалить ${this.selectedNodeIds.size} выделенных узлов?`
|
||||||
);
|
);
|
||||||
if (!confirmed)
|
if (!confirmed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new Notice(`Начинаю удаление ${this.selectedNodeIds.size} узлов...`, 2000);
|
new Notice(`Начинаю удаление ${this.selectedNodeIds.size} узлов...`, 2000);
|
||||||
const nodesToDelete = Array.from(this.selectedNodeIds); // Сохраняем порядок выделения
|
const nodesToDelete = Array.from(this.selectedNodeIds); // Сохраняем порядок выделения
|
||||||
|
|
||||||
for (const nodeId of nodesToDelete) {
|
for (const nodeId of nodesToDelete) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${this.selectedGraphId}/nodes/${nodeId}`, {
|
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/graphs/${this.selectedGraphId}/nodes/${nodeId}`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
throw new Error(`Ошибка удаления узла ${nodeId}: ${response.status} - ${errorText}`);
|
throw new Error(`Ошибка удаления узла ${nodeId}: ${response.status} - ${errorText}`);
|
||||||
}
|
}
|
||||||
new Notice(`Узел ${nodeId.substring(0, 8)}... успешно удален.`, 1000);
|
new Notice(`Узел ${nodeId.substring(0, 8)}... успешно удален.`, 1000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Ошибка при удалении узла ${nodeId}:`, error);
|
console.error(`Ошибка при удалении узла ${nodeId}:`, error);
|
||||||
new Notice(`Ошибка при удалении узла ${nodeId.substring(0, 8)}...: ${error.message}`, 5000);
|
new Notice(`Ошибка при удалении узла ${nodeId.substring(0, 8)}...: ${error.message}`, 5000);
|
||||||
// Продолжаем попытки удаления остальных узлов, но фиксируем ошибку
|
// Продолжаем попытки удаления остальных узлов, но фиксируем ошибку
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// После всех удалений очищаем выделение и обновляем граф полностью
|
// После всех удалений очищаем выделение и обновляем граф полностью
|
||||||
this.selectedNodeIds.clear();
|
this.selectedNodeIds.clear();
|
||||||
await this.fetchGraphData(this.selectedGraphId); // Полностью обновляем граф и чат-панель
|
await this.fetchGraphData(this.selectedGraphId); // Полностью обновляем граф и чат-панель
|
||||||
new Notice('Операция удаления завершена.', 2000);
|
new Notice('Операция удаления завершена.', 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user