-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.ts
138 lines (120 loc) · 4.32 KB
/
app.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import {
Class,
DefaultLabelStyle,
GraphBuilder,
GraphComponent,
GraphViewerInputMode,
HierarchicLayout,
IGraph,
INode,
InteriorStretchLabelModel,
LayoutExecutor,
License,
PolylineEdgeStyle,
ShapeNodeStyle,
Size
} from 'yfiles'
import LicenseContent from '../../license.json'
License.value = LicenseContent;
Class.ensure(LayoutExecutor)
let gc: GraphComponent;
let graph: IGraph;
type PersonHierarchy = {
nodes: Person[]
links: Link[]
}
type Person = {
id: number
firstName: string
lastName: string
}
type PersonAddress = {
addressLine: string,
zip: string,
city: string,
country: string
}
type Link = {
from: number
to: number
}
(window as any).initializeGraph = async (selector: string) => {
gc = new GraphComponent(selector);
graph = gc.graph;
// load the whole person hierarchy as JSON
const jsonGraph = await load()
buildGraph(graph, jsonGraph)
// this enables selection of nodes
gc.inputMode = new GraphViewerInputMode();
// add a listener to detect selection and deselection of nodes
gc.selection.addItemSelectionChangedListener((_, evt) => {
if (evt.item instanceof INode) {
if (evt.itemSelected) {
// fetch information about person and update details panal
updateDetails(evt.item.tag)
} else {
// reset and hide details panel
updateDetailsPanel(null)
}
}
})
graph.applyLayout(new HierarchicLayout({ orthogonalRouting: true }))
gc.fitGraphBounds()
}
(window as any).initializeGraph("#designDiv");
async function load(): Promise<PersonHierarchy> {
const response = await fetch("API/GetHierarchy/0")
return response.json()
}
function buildGraph(graph: IGraph, jsonGraph: PersonHierarchy) {
// styling
graph.nodeDefaults.size = new Size(75, 40)
graph.nodeDefaults.style = new ShapeNodeStyle({
fill: '#67b7dc',
stroke: '#294958',
shape: "round-rectangle"
})
graph.edgeDefaults.style = new PolylineEdgeStyle({
stroke: '#294958',
targetArrow: "#294958 medium triangle"
})
graph.nodeDefaults.labels.layoutParameter = InteriorStretchLabelModel.CENTER
graph.nodeDefaults.labels.style = new DefaultLabelStyle({
horizontalTextAlignment: "center",
verticalTextAlignment: "center"
})
const builder = new GraphBuilder(graph)
const nodesSource = builder.createNodesSource(jsonGraph.nodes, node => node.id)
const nodeLabelsSource = nodesSource.nodeCreator.createLabelsSource(node => [node])
nodeLabelsSource.labelCreator.textProvider = label => label.firstName + '\n' + label.lastName
builder.createEdgesSource(jsonGraph.links, link => link.from, link => link.to);
builder.buildGraph()
}
async function updateDetails(person: Person): Promise<void> {
const id = person.id
const [personData, addressData] = await Promise.all([
fetch("API/GetPerson/" + id).then(resp => resp.json()),
fetch("API/GetPersonAddress/" + id).then(resp => resp.json())
])
updateDetailsPanel({person: personData, address: addressData})
}
function updateDetailsPanel(data: { person: Person, address: PersonAddress } | null): void {
// update text in divs and show/hide the details panel by setting the css display property
if (data === null) {
document.getElementById("FirstName")!.innerText = ""
document.getElementById("LastName")!.innerText = ""
document.getElementById("Address")!.innerText = ""
document.getElementById("City")!.innerText = ""
document.getElementById("Zip")!.innerText = ""
document.getElementById("Country")!.innerText = ""
document.getElementById("detailsPanel")!.style.display = "none"
} else {
document.getElementById("FirstName")!.innerText = data.person.firstName
document.getElementById("LastName")!.innerText = data.person.lastName
document.getElementById("Address")!.innerText = data.address.addressLine
document.getElementById("City")!.innerText = data.address.city
document.getElementById("Zip")!.innerText = data.address.zip
document.getElementById("Country")!.innerText = data.address.country
document.getElementById("detailsPanel")!.style.display = "block"
}
}