add update route

This commit is contained in:
Владимир Фёдоров 2025-12-07 03:40:29 +07:00
parent 7225ce7f29
commit a62683d9ac
3 changed files with 116 additions and 79 deletions

View File

@ -2,35 +2,12 @@
import { ref, onMounted } from 'vue'
import HeaderBlock from './HeaderBlock.vue';
import { Network } from 'vis-network'
import { getGraph } from './client';
import { Network, type Data } from 'vis-network'
import { getGraph, updateNode } from './client';
import type { Graph, GraphEdge, GraphNode } from './models';
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: []
@ -46,16 +23,19 @@ const selectedNode = ref<GraphNode>({
})
let net = <Network>{}
let data = <Data>{}
onMounted(async () => {
if (!network.value) return
async function loadGraph() {
graph.value = await getGraph()
const data = {
data = {
nodes: graph.value.nodes,
edges: graph.value.edges
}
net.setData(data)
}
onMounted(async () => {
if (!network.value) return
const options = {
interaction: {
@ -85,6 +65,7 @@ onMounted(async () => {
}
});
await loadGraph()
selectNode(graph.value.nodes[0])
})
@ -103,6 +84,12 @@ function selectNode(node: GraphNode) {
net.selectNodes([selectedNode.value.id])
}
async function updateSelectedNode() {
console.log("Update node:", selectedNode.value)
await updateNode(selectedNode.value)
await loadGraph()
}
function nodeHeader(node: GraphNode): string {
return "[" + node.label + "] - " + node.name
}
@ -119,6 +106,9 @@ function nodeHeader(node: GraphNode): string {
<div class="nodes-container">
<h2>Точки</h2>
<div>Всего точек: {{ graph.nodes.length }}</div>
<div>Всего связей: {{ graph.edges.length }}</div>
<hr class="hr">
<div v-bind:key="node.id" v-for="node in graph.nodes">
<div :class="[node.id == selectedNode.id ? 'selected-node' : '']" class="node-select-button"
@ -134,22 +124,25 @@ function nodeHeader(node: GraphNode): string {
{{ nodeHeader(selectedNode) }}
</div>
<div>
{{ selectedNode.text }}
<textarea class="node-text-edit-field" rows="30" v-model="selectedNode.text"></textarea>
</div>
<div>
<h3>Приложения</h3>
<h3>Приложения: {{ selectedNode.applications.length }}</h3>
<div v-bind:key="application.name" v-for="application in selectedNode.applications">
{{ application.name }}
- {{ application.name }}
</div>
</div>
<div>
<h3>Ссылки</h3>
<h3>Ссылки: {{ selectedNode.links.length }}</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) }}
- {{ nodeHeader(node) }}
</div>
</div>
</div>
<div>
<button class="node-edit-save-button" v-on:click="updateSelectedNode()">Сохранить</button>
</div>
</div>
</template>
@ -175,7 +168,8 @@ function nodeHeader(node: GraphNode): string {
top: 55px;
height: calc(100vh - 100px);
padding: 10px 20px;
max-width: 300px;
min-width: 350px;
max-width: 400px;
}
.node-select-button {
@ -192,4 +186,27 @@ function nodeHeader(node: GraphNode): string {
color: #960000;
cursor: pointer;
}
.node-text-edit-field {
padding: 7px;
margin: 5px 0;
width: 100%;
}
.node-edit-save-button {
padding: 3px 7px;
margin: 5px;
background-color: #ffffff;
border-radius: 7px;
border: 1px solid #373737;
}
.node-edit-save-button:hover {
background-color: #dddddd;
cursor: pointer;
}
.hr {
margin: 10px 0;
}
</style>

View File

@ -1,11 +1,9 @@
import type { Game, Teams } from './models';
import { downloadData } from './qr';
import type { Game, GraphNode, Teams } from './models'
import { downloadData } from './qr'
export const apiGetTeams = async (): Promise<Teams> => {
try {
const response = await fetch(
getApiUrl("/teams")
)
const response = await fetch(getApiUrl('/teams'))
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -18,15 +16,12 @@ export const apiGetTeams = async (): Promise<Teams> => {
export const apiAddTeam = async (teamName: string) => {
try {
const response = await fetch(
getApiUrl("/teams"),
{
method: "POST",
body: JSON.stringify({
"teams": [{ "name": teamName }]
})
}
)
const response = await fetch(getApiUrl('/teams'), {
method: 'POST',
body: JSON.stringify({
teams: [{ name: teamName }],
}),
})
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -38,9 +33,7 @@ export const apiAddTeam = async (teamName: string) => {
export const apiGetGame = async (): Promise<Game> => {
try {
const response = await fetch(
getApiUrl("/game")
)
const response = await fetch(getApiUrl('/game'))
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -53,10 +46,7 @@ export const apiGetGame = async (): Promise<Game> => {
export const apiStartGame = async () => {
try {
const response = await fetch(
getApiUrl("/game/start"),
{ method: "POST" }
)
const response = await fetch(getApiUrl('/game/start'), { method: 'POST' })
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -68,10 +58,7 @@ export const apiStartGame = async () => {
export const apiStopGame = async () => {
try {
const response = await fetch(
getApiUrl("/game/stop"),
{ method: "POST" }
)
const response = await fetch(getApiUrl('/game/stop'), { method: 'POST' })
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -83,15 +70,12 @@ export const apiStopGame = async () => {
export const apiGaveApplication = async (teamId: number, id: number) => {
try {
const response = await fetch(
getApiUrl("/teams/" + teamId + "/applications"),
{
method: "POST",
body: JSON.stringify({
"applications": [{ "id": id }]
})
}
)
const response = await fetch(getApiUrl('/teams/' + teamId + '/applications'), {
method: 'POST',
body: JSON.stringify({
applications: [{ id: id }],
}),
})
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -103,13 +87,11 @@ export const apiGaveApplication = async (teamId: number, id: number) => {
export const apiDownloadQrCodesFile = async () => {
try {
const response = await fetch(
getApiUrl("/teams/pdf")
)
const response = await fetch(getApiUrl('/teams/pdf'))
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
const data = await response.json();
const data = await response.json()
downloadData(data.result)
} catch (error) {
console.error('[apiDownloadQrCodesFile] error:', error)
@ -119,9 +101,23 @@ export const apiDownloadQrCodesFile = async () => {
export const getGraph = async () => {
try {
const response = await fetch(
getApiUrl("/graph")
)
const response = await fetch(getApiUrl('/graph'))
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
return await response.json()
} catch (error) {
console.error('[apiDownloadQrCodesFile] error:', error)
throw error
}
}
export const updateNode = async (node: GraphNode) => {
try {
const response = await fetch(getApiUrl('/graph/nodes'), {
method: 'PUT',
body: JSON.stringify({ node: node }),
})
if (!response.ok) {
throw new Error(`http error status: ${response.status}`)
}
@ -133,5 +129,5 @@ export const getGraph = async () => {
}
function getApiUrl(path: string) {
return "http://" + window.location.host.split(":")[0] + ":8090" + path
return 'http://' + window.location.host.split(':')[0] + ':8090' + path
}

View File

@ -21,3 +21,27 @@ export type Game = {
startAt: string
endAt: string
}
export type Graph = {
nodes: Array<GraphNode>
edges: Array<GraphEdge>
}
export type GraphNode = {
id: number
label: string
name: string
text: string
applications: Array<GraphApplication>
links: Array<GraphNode>
}
export type GraphEdge = {
from: number
to: number
arrows: string
}
export type GraphApplication = {
name: string
}