feat: graph-page
ci-front / build (push) Successful in 1m58s

This commit is contained in:
nikita
2026-04-04 12:14:17 +03:00
parent 26ca7c0d51
commit aac3fa3758
14 changed files with 757 additions and 537 deletions
@@ -0,0 +1,113 @@
import { create } from "zustand";
import type { GraphData, GraphNode, GraphLink } from "../types";
interface GraphState {
data: GraphData;
highlightNodes: Set<string>;
highlightLinks: Set<GraphLink>;
isLinkMode: boolean;
selectedNode: GraphNode | null;
// Действия с данными
setData: (data: GraphData) => void;
addNode: (node: GraphNode) => void;
removeNode: (nodeId: string) => void;
addLink: (link: GraphLink) => void;
removeLink: (link: GraphLink) => void;
// Подсветка
setHighlight: (nodeIds: Set<string>, links: Set<GraphLink>) => void;
// Режим связи
toggleLinkMode: () => void;
setSelectedNode: (node: GraphNode | null) => void;
createLink: (sourceId: string, targetId: string) => void;
// Экспорт
exportData: () => void;
}
export const useGraphStore = create<GraphState>((set, get) => ({
data: { nodes: [], links: [] },
highlightNodes: new Set(),
highlightLinks: new Set(),
isLinkMode: false,
selectedNode: null,
setData: (data) => set({ data }),
addNode: (node) => {
set((state) => ({
data: {
...state.data,
nodes: [...state.data.nodes, node],
},
}));
},
removeNode: (nodeId) => {
set((state) => ({
data: {
nodes: state.data.nodes.filter((n) => n.id !== nodeId),
links: state.data.links.filter(
(l) => l.source !== nodeId && l.target !== nodeId,
),
},
}));
},
addLink: (link) => {
set((state) => ({
data: {
...state.data,
links: [...state.data.links, link],
},
}));
},
removeLink: (linkToRemove) => {
set((state) => ({
data: {
...state.data,
links: state.data.links.filter((l) => l !== linkToRemove),
},
}));
},
setHighlight: (nodeIds, links) =>
set({ highlightNodes: nodeIds, highlightLinks: links }),
toggleLinkMode: () =>
set((state) => ({
isLinkMode: !state.isLinkMode,
selectedNode: null,
})),
setSelectedNode: (node) => set({ selectedNode: node }),
createLink: (sourceId, targetId) => {
const { data, addLink } = get();
const linkExists = data.links.some(
(link) =>
(link.source === sourceId && link.target === targetId) ||
(link.source === targetId && link.target === sourceId),
);
if (!linkExists) {
addLink({ source: sourceId, target: targetId, type: "custom" });
}
},
exportData: () => {
const { data } = get();
const dataStr = JSON.stringify(data, null, 2);
const blob = new Blob([dataStr], { type: "application/json" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "graph-data.json";
link.click();
URL.revokeObjectURL(url);
},
}));