add update route
This commit is contained in:
parent
7225ce7f29
commit
a62683d9ac
@ -2,35 +2,12 @@
|
|||||||
|
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import HeaderBlock from './HeaderBlock.vue';
|
import HeaderBlock from './HeaderBlock.vue';
|
||||||
import { Network } from 'vis-network'
|
import { Network, type Data } from 'vis-network'
|
||||||
import { getGraph } from './client';
|
import { getGraph, updateNode } from './client';
|
||||||
|
import type { Graph, GraphEdge, GraphNode } from './models';
|
||||||
|
|
||||||
const network = ref<HTMLElement>()
|
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>({
|
const graph = ref<Graph>({
|
||||||
nodes: [],
|
nodes: [],
|
||||||
edges: []
|
edges: []
|
||||||
@ -46,16 +23,19 @@ const selectedNode = ref<GraphNode>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
let net = <Network>{}
|
let net = <Network>{}
|
||||||
|
let data = <Data>{}
|
||||||
|
|
||||||
onMounted(async () => {
|
async function loadGraph() {
|
||||||
if (!network.value) return
|
|
||||||
|
|
||||||
graph.value = await getGraph()
|
graph.value = await getGraph()
|
||||||
|
data = {
|
||||||
const data = {
|
|
||||||
nodes: graph.value.nodes,
|
nodes: graph.value.nodes,
|
||||||
edges: graph.value.edges
|
edges: graph.value.edges
|
||||||
}
|
}
|
||||||
|
net.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (!network.value) return
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
interaction: {
|
interaction: {
|
||||||
@ -85,6 +65,7 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await loadGraph()
|
||||||
selectNode(graph.value.nodes[0])
|
selectNode(graph.value.nodes[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -103,6 +84,12 @@ function selectNode(node: GraphNode) {
|
|||||||
net.selectNodes([selectedNode.value.id])
|
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 {
|
function nodeHeader(node: GraphNode): string {
|
||||||
return "[" + node.label + "] - " + node.name
|
return "[" + node.label + "] - " + node.name
|
||||||
}
|
}
|
||||||
@ -119,6 +106,9 @@ function nodeHeader(node: GraphNode): string {
|
|||||||
|
|
||||||
<div class="nodes-container">
|
<div class="nodes-container">
|
||||||
<h2>Точки</h2>
|
<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 v-bind:key="node.id" v-for="node in graph.nodes">
|
||||||
<div :class="[node.id == selectedNode.id ? 'selected-node' : '']" class="node-select-button"
|
<div :class="[node.id == selectedNode.id ? 'selected-node' : '']" class="node-select-button"
|
||||||
@ -134,22 +124,25 @@ function nodeHeader(node: GraphNode): string {
|
|||||||
{{ nodeHeader(selectedNode) }}
|
{{ nodeHeader(selectedNode) }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{ selectedNode.text }}
|
<textarea class="node-text-edit-field" rows="30" v-model="selectedNode.text"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3>Приложения</h3>
|
<h3>Приложения: {{ selectedNode.applications.length }}</h3>
|
||||||
<div v-bind:key="application.name" v-for="application in selectedNode.applications">
|
<div v-bind:key="application.name" v-for="application in selectedNode.applications">
|
||||||
{{ application.name }}
|
- {{ application.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3>Ссылки</h3>
|
<h3>Ссылки: {{ selectedNode.links.length }}</h3>
|
||||||
<div v-bind:key="node.id" v-for="node in selectedNode.links">
|
<div v-bind:key="node.id" v-for="node in selectedNode.links">
|
||||||
<div class="node-select-button" v-on:click="selectNode(node)">
|
<div class="node-select-button" v-on:click="selectNode(node)">
|
||||||
{{ nodeHeader(node) }}
|
- {{ nodeHeader(node) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button class="node-edit-save-button" v-on:click="updateSelectedNode()">Сохранить</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -175,7 +168,8 @@ function nodeHeader(node: GraphNode): string {
|
|||||||
top: 55px;
|
top: 55px;
|
||||||
height: calc(100vh - 100px);
|
height: calc(100vh - 100px);
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
max-width: 300px;
|
min-width: 350px;
|
||||||
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-select-button {
|
.node-select-button {
|
||||||
@ -192,4 +186,27 @@ function nodeHeader(node: GraphNode): string {
|
|||||||
color: #960000;
|
color: #960000;
|
||||||
cursor: pointer;
|
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>
|
</style>
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
import type { Game, Teams } from './models';
|
import type { Game, GraphNode, Teams } from './models'
|
||||||
import { downloadData } from './qr';
|
import { downloadData } from './qr'
|
||||||
|
|
||||||
export const apiGetTeams = async (): Promise<Teams> => {
|
export const apiGetTeams = async (): Promise<Teams> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/teams'))
|
||||||
getApiUrl("/teams")
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -18,15 +16,12 @@ export const apiGetTeams = async (): Promise<Teams> => {
|
|||||||
|
|
||||||
export const apiAddTeam = async (teamName: string) => {
|
export const apiAddTeam = async (teamName: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/teams'), {
|
||||||
getApiUrl("/teams"),
|
method: 'POST',
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
"teams": [{ "name": teamName }]
|
teams: [{ name: teamName }],
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -38,9 +33,7 @@ export const apiAddTeam = async (teamName: string) => {
|
|||||||
|
|
||||||
export const apiGetGame = async (): Promise<Game> => {
|
export const apiGetGame = async (): Promise<Game> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/game'))
|
||||||
getApiUrl("/game")
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -53,10 +46,7 @@ export const apiGetGame = async (): Promise<Game> => {
|
|||||||
|
|
||||||
export const apiStartGame = async () => {
|
export const apiStartGame = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/game/start'), { method: 'POST' })
|
||||||
getApiUrl("/game/start"),
|
|
||||||
{ method: "POST" }
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -68,10 +58,7 @@ export const apiStartGame = async () => {
|
|||||||
|
|
||||||
export const apiStopGame = async () => {
|
export const apiStopGame = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/game/stop'), { method: 'POST' })
|
||||||
getApiUrl("/game/stop"),
|
|
||||||
{ method: "POST" }
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -83,15 +70,12 @@ export const apiStopGame = async () => {
|
|||||||
|
|
||||||
export const apiGaveApplication = async (teamId: number, id: number) => {
|
export const apiGaveApplication = async (teamId: number, id: number) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/teams/' + teamId + '/applications'), {
|
||||||
getApiUrl("/teams/" + teamId + "/applications"),
|
method: 'POST',
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
"applications": [{ "id": id }]
|
applications: [{ id: id }],
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -103,13 +87,11 @@ export const apiGaveApplication = async (teamId: number, id: number) => {
|
|||||||
|
|
||||||
export const apiDownloadQrCodesFile = async () => {
|
export const apiDownloadQrCodesFile = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/teams/pdf'))
|
||||||
getApiUrl("/teams/pdf")
|
|
||||||
)
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json()
|
||||||
downloadData(data.result)
|
downloadData(data.result)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[apiDownloadQrCodesFile] error:', error)
|
console.error('[apiDownloadQrCodesFile] error:', error)
|
||||||
@ -119,9 +101,23 @@ export const apiDownloadQrCodesFile = async () => {
|
|||||||
|
|
||||||
export const getGraph = async () => {
|
export const getGraph = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(getApiUrl('/graph'))
|
||||||
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) {
|
if (!response.ok) {
|
||||||
throw new Error(`http error status: ${response.status}`)
|
throw new Error(`http error status: ${response.status}`)
|
||||||
}
|
}
|
||||||
@ -133,5 +129,5 @@ export const getGraph = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getApiUrl(path: string) {
|
function getApiUrl(path: string) {
|
||||||
return "http://" + window.location.host.split(":")[0] + ":8090" + path
|
return 'http://' + window.location.host.split(':')[0] + ':8090' + path
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,3 +21,27 @@ export type Game = {
|
|||||||
startAt: string
|
startAt: string
|
||||||
endAt: 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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user