196 lines
4.0 KiB
Vue
196 lines
4.0 KiB
Vue
<script setup lang="ts">
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
import HeaderBlock from './HeaderBlock.vue';
|
|
import { Network } from 'vis-network'
|
|
import { getGraph } from './client';
|
|
|
|
const network = ref<HTMLElement>()
|
|
|
|
type GraphApplication = {
|
|
name: string,
|
|
}
|
|
|
|
type GraphNode = {
|
|
id: number,
|
|
label: string,
|
|
name: string,
|
|
text: string,
|
|
applications: Array<GraphApplication>,
|
|
links: Array<GraphNode>,
|
|
};
|
|
|
|
type GraphEdge = {
|
|
from: number,
|
|
to: number,
|
|
arrows: string,
|
|
};
|
|
|
|
type Graph = {
|
|
nodes: Array<GraphNode>;
|
|
edges: Array<GraphEdge>;
|
|
};
|
|
|
|
const graph = ref<Graph>({
|
|
nodes: [],
|
|
edges: []
|
|
})
|
|
|
|
const selectedNode = ref<GraphNode>({
|
|
id: 0,
|
|
label: "",
|
|
name: "",
|
|
text: "",
|
|
applications: [],
|
|
links: [],
|
|
})
|
|
|
|
let net = <Network>{}
|
|
|
|
onMounted(async () => {
|
|
if (!network.value) return
|
|
|
|
graph.value = await getGraph()
|
|
|
|
const data = {
|
|
nodes: graph.value.nodes,
|
|
edges: graph.value.edges
|
|
}
|
|
|
|
const options = {
|
|
interaction: {
|
|
selectable: true,
|
|
},
|
|
nodes: {
|
|
color: {
|
|
border: '#2B7CE9', // Normal border color
|
|
background: '#97C2FC', // Normal background color
|
|
highlight: { // Selection state
|
|
border: '#960000',
|
|
background: '#ff9494'
|
|
},
|
|
hover: { // Hover state
|
|
border: '#2B7CE9',
|
|
background: '#D2E5FF'
|
|
}
|
|
}
|
|
},
|
|
}
|
|
net = new Network(network.value, data, options)
|
|
net.on("click", function (params) {
|
|
if (params.nodes.length > 0) {
|
|
selectNode(graph.value.nodes[params.nodes[0]])
|
|
} else if (params.edges.length > 0) {
|
|
console.log("Clicked edge:", params.edges[0]);
|
|
}
|
|
});
|
|
|
|
selectNode(graph.value.nodes[0])
|
|
})
|
|
|
|
function selectNode(node: GraphNode) {
|
|
console.log("Select node:", node.id)
|
|
selectedNode.value = node
|
|
const links = graph.value.edges.filter(function (it: GraphEdge) {
|
|
return it.from == node.id
|
|
}).map(function (it: GraphEdge): GraphNode {
|
|
const id = it.to
|
|
const linkNode = graph.value.nodes.filter(function (it: GraphNode) { return it.id == id })
|
|
return linkNode[0]
|
|
})
|
|
|
|
selectedNode.value.links = links
|
|
net.selectNodes([selectedNode.value.id])
|
|
}
|
|
|
|
function nodeHeader(node: GraphNode): string {
|
|
return "[" + node.label + "] - " + node.name
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<HeaderBlock>
|
|
<div>
|
|
Редактор сценариев
|
|
</div>
|
|
</HeaderBlock>
|
|
|
|
<div ref="network" class="graph-container"></div>
|
|
|
|
<div class="nodes-container">
|
|
<h2>Точки</h2>
|
|
|
|
<div v-bind:key="node.id" v-for="node in graph.nodes">
|
|
<div :class="[node.id == selectedNode.id ? 'selected-node' : '']" class="node-select-button"
|
|
v-on:click="selectNode(node)">
|
|
{{ nodeHeader(node) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="edit-node-container">
|
|
<h2>Редактирование точки</h2>
|
|
<div>
|
|
{{ nodeHeader(selectedNode) }}
|
|
</div>
|
|
<div>
|
|
{{ selectedNode.text }}
|
|
</div>
|
|
<div>
|
|
<h3>Приложения</h3>
|
|
<div v-bind:key="application.name" v-for="application in selectedNode.applications">
|
|
{{ application.name }}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h3>Ссылки</h3>
|
|
<div v-bind:key="node.id" v-for="node in selectedNode.links">
|
|
<div class="node-select-button" v-on:click="selectNode(node)">
|
|
{{ nodeHeader(node) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.graph-container {
|
|
width: 100%;
|
|
height: calc(100vh - 50px);
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.nodes-container {
|
|
position: fixed;
|
|
left: 5px;
|
|
top: 55px;
|
|
height: calc(100vh - 100px);
|
|
padding: 10px 20px;
|
|
}
|
|
|
|
.edit-node-container {
|
|
position: fixed;
|
|
right: 5px;
|
|
top: 55px;
|
|
height: calc(100vh - 100px);
|
|
padding: 10px 20px;
|
|
max-width: 300px;
|
|
}
|
|
|
|
.node-select-button {
|
|
color: #373737;
|
|
}
|
|
|
|
.node-select-button:hover {
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.selected-node {
|
|
font-weight: bold;
|
|
color: #960000;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|