@things-factory/integration-ui 9.0.0-beta.7 → 9.0.0-beta.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/client/analysis/graph-viewer.ts +1 -1
  2. package/client/analysis/node.ts +2 -2
  3. package/client/analysis/relationship.ts +1 -1
  4. package/client/bootstrap.ts +10 -6
  5. package/client/editors/entity-editor.ts +2 -2
  6. package/client/editors/property-editor.ts +5 -5
  7. package/client/editors/things-editor-entity-selector.ts +1 -1
  8. package/client/grist/connection-selector.ts +1 -1
  9. package/client/grist/connector-selector.ts +1 -1
  10. package/client/pages/connection.ts +2 -2
  11. package/client/pages/integration-analysis.ts +3 -3
  12. package/client/pages/integration-monitor.ts +4 -4
  13. package/client/pages/scenario-detail.ts +1 -1
  14. package/client/pages/scenario.ts +3 -3
  15. package/client/pages/state-register.ts +1 -1
  16. package/client/viewparts/scenario-instance-log-view.ts +1 -1
  17. package/client/viewparts/scenario-instance-monitor.ts +7 -5
  18. package/client/viewparts/scenario-instance-view.ts +2 -2
  19. package/client/viewparts/scenario-monitor.ts +5 -3
  20. package/client/viewparts/scenarios-monitor.ts +1 -1
  21. package/dist-client/analysis/graph-viewer.d.ts +1 -1
  22. package/dist-client/analysis/graph-viewer.js.map +1 -1
  23. package/dist-client/analysis/node.d.ts +1 -1
  24. package/dist-client/analysis/node.js +1 -1
  25. package/dist-client/analysis/node.js.map +1 -1
  26. package/dist-client/analysis/relationship.d.ts +1 -1
  27. package/dist-client/analysis/relationship.js.map +1 -1
  28. package/dist-client/bootstrap.d.ts +2 -2
  29. package/dist-client/bootstrap.js +5 -5
  30. package/dist-client/bootstrap.js.map +1 -1
  31. package/dist-client/editors/entity-editor.d.ts +1 -1
  32. package/dist-client/editors/entity-editor.js +2 -2
  33. package/dist-client/editors/entity-editor.js.map +1 -1
  34. package/dist-client/editors/property-editor.d.ts +5 -5
  35. package/dist-client/editors/property-editor.js +5 -5
  36. package/dist-client/editors/property-editor.js.map +1 -1
  37. package/dist-client/editors/things-editor-entity-selector.d.ts +1 -1
  38. package/dist-client/editors/things-editor-entity-selector.js +1 -1
  39. package/dist-client/editors/things-editor-entity-selector.js.map +1 -1
  40. package/dist-client/grist/connection-selector.d.ts +1 -1
  41. package/dist-client/grist/connection-selector.js +1 -1
  42. package/dist-client/grist/connection-selector.js.map +1 -1
  43. package/dist-client/grist/connector-selector.d.ts +1 -1
  44. package/dist-client/grist/connector-selector.js +1 -1
  45. package/dist-client/grist/connector-selector.js.map +1 -1
  46. package/dist-client/pages/connection.d.ts +1 -1
  47. package/dist-client/pages/connection.js +2 -2
  48. package/dist-client/pages/connection.js.map +1 -1
  49. package/dist-client/pages/integration-analysis.d.ts +1 -1
  50. package/dist-client/pages/integration-analysis.js +2 -2
  51. package/dist-client/pages/integration-analysis.js.map +1 -1
  52. package/dist-client/pages/integration-monitor.d.ts +4 -4
  53. package/dist-client/pages/integration-monitor.js +4 -4
  54. package/dist-client/pages/integration-monitor.js.map +1 -1
  55. package/dist-client/pages/scenario-detail.js +1 -1
  56. package/dist-client/pages/scenario-detail.js.map +1 -1
  57. package/dist-client/pages/scenario.d.ts +2 -2
  58. package/dist-client/pages/scenario.js +3 -3
  59. package/dist-client/pages/scenario.js.map +1 -1
  60. package/dist-client/pages/state-register.js +1 -1
  61. package/dist-client/pages/state-register.js.map +1 -1
  62. package/dist-client/tsconfig.tsbuildinfo +1 -1
  63. package/dist-client/viewparts/scenario-instance-log-view.js +1 -1
  64. package/dist-client/viewparts/scenario-instance-log-view.js.map +1 -1
  65. package/dist-client/viewparts/scenario-instance-monitor.d.ts +1 -1
  66. package/dist-client/viewparts/scenario-instance-monitor.js +7 -5
  67. package/dist-client/viewparts/scenario-instance-monitor.js.map +1 -1
  68. package/dist-client/viewparts/scenario-instance-view.d.ts +1 -1
  69. package/dist-client/viewparts/scenario-instance-view.js +2 -2
  70. package/dist-client/viewparts/scenario-instance-view.js.map +1 -1
  71. package/dist-client/viewparts/scenario-monitor.d.ts +1 -1
  72. package/dist-client/viewparts/scenario-monitor.js +5 -3
  73. package/dist-client/viewparts/scenario-monitor.js.map +1 -1
  74. package/dist-client/viewparts/scenarios-monitor.d.ts +1 -1
  75. package/dist-client/viewparts/scenarios-monitor.js +1 -1
  76. package/dist-client/viewparts/scenarios-monitor.js.map +1 -1
  77. package/dist-server/tsconfig.tsbuildinfo +1 -1
  78. package/package.json +6 -6
  79. package/client/analysis/graph-viewer-old.ts +0 -1097
  80. package/dist-client/analysis/graph-viewer-old.d.ts +0 -110
  81. package/dist-client/analysis/graph-viewer-old.js +0 -808
  82. package/dist-client/analysis/graph-viewer-old.js.map +0 -1
@@ -1,1097 +0,0 @@
1
- import * as d3 from 'd3'
2
-
3
- export class GraphViewer {
4
- public simulation
5
-
6
- private container
7
- private info
8
- private node
9
- private nodes
10
- private relationship
11
- private relationshipOutline
12
- private relationshipOverlay
13
- private relationshipText
14
- private relationships
15
- private selector
16
- private svg
17
- private svgNodes
18
- private svgRelationships
19
- private svgScale
20
- private svgTranslate: any
21
- private classes2colors = {}
22
- private justLoaded = false
23
- private numClasses = 0
24
- private options = {
25
- arrowSize: 4,
26
- colors: this.colors(),
27
- highlight: undefined,
28
- infoPanel: true,
29
- minCollision: undefined,
30
- graphData: undefined,
31
- dataUrl: undefined,
32
- nodeOutlineFillColor: undefined,
33
- nodeRadius: 25,
34
- relationshipColor: '#a5abb6',
35
- zoomFit: false
36
- } as any
37
-
38
- constructor(_selector: any, _options: any) {
39
- this.init(_selector, _options)
40
- }
41
-
42
- appendGraph(container) {
43
- this.svg = container
44
- .append('svg')
45
- .attr('width', '100%')
46
- .attr('height', '100%')
47
- .attr('class', 'graph-viewer')
48
- .call(
49
- d3.zoom().on('zoom', (event, d) => {
50
- var scale = event.transform.k,
51
- translate = [event.transform.x, event.transform.y]
52
-
53
- if (this.svgTranslate) {
54
- translate[0] += this.svgTranslate[0]
55
- translate[1] += this.svgTranslate[1]
56
- }
57
-
58
- if (this.svgScale) {
59
- scale *= this.svgScale
60
- }
61
-
62
- this.svg.attr('transform', 'translate(' + translate[0] + ', ' + translate[1] + ') scale(' + scale + ')')
63
- })
64
- )
65
- .on('dblclick.zoom', null)
66
- .append('g')
67
- .attr('width', '100%')
68
- .attr('height', '100%')
69
-
70
- this.svgRelationships = this.svg.append('g').attr('class', 'relationships')
71
-
72
- this.svgNodes = this.svg.append('g').attr('class', 'nodes')
73
- }
74
-
75
- appendImageToNode(node) {
76
- return node
77
- .append('image')
78
- .attr('height', d => {
79
- return this.icon(d) ? '24px' : '30px'
80
- })
81
- .attr('x', d => {
82
- return this.icon(d) ? '5px' : '-15px'
83
- })
84
- .attr('xlink:href', d => {
85
- return this.image(d)
86
- })
87
- .attr('y', d => {
88
- return this.icon(d) ? '5px' : '-16px'
89
- })
90
- .attr('width', d => {
91
- return this.icon(d) ? '24px' : '30px'
92
- })
93
- }
94
-
95
- appendInfoPanel(container) {
96
- return container.append('div').attr('class', 'graph-info')
97
- }
98
-
99
- appendInfoElement(cls, isNode, property, value?: any) {
100
- var elem = this.info.append('a')
101
-
102
- elem
103
- .attr('href', '#')
104
- .attr('class', cls)
105
- .html('<strong>' + property + '</strong>' + (value ? ': ' + value : ''))
106
-
107
- if (!value) {
108
- elem
109
- .style('background-color', d => {
110
- return this.options.nodeOutlineFillColor
111
- ? this.options.nodeOutlineFillColor
112
- : isNode
113
- ? this.class2color(property)
114
- : this.defaultColor()
115
- })
116
- .style('border-color', d => {
117
- return this.options.nodeOutlineFillColor
118
- ? this.class2darkenColor(this.options.nodeOutlineFillColor)
119
- : isNode
120
- ? this.class2darkenColor(property)
121
- : this.defaultDarkenColor()
122
- })
123
- .style('color', d => {
124
- return this.options.nodeOutlineFillColor ? this.class2darkenColor(this.options.nodeOutlineFillColor) : '#fff'
125
- })
126
- }
127
- }
128
-
129
- appendInfoElementClass(cls, node) {
130
- this.appendInfoElement(cls, true, node)
131
- }
132
-
133
- appendInfoElementProperty(cls, property, value) {
134
- this.appendInfoElement(cls, false, property, value)
135
- }
136
-
137
- appendInfoElementRelationship(cls, relationship) {
138
- this.appendInfoElement(cls, false, relationship)
139
- }
140
-
141
- appendNode() {
142
- return this.node
143
- .enter()
144
- .append('g')
145
- .attr('class', d => {
146
- var highlight,
147
- i,
148
- classes = 'node',
149
- label = d.labels[0]
150
-
151
- if (this.icon(d)) {
152
- classes += ' node-icon'
153
- }
154
-
155
- if (this.image(d)) {
156
- classes += ' node-image'
157
- }
158
-
159
- if (this.options.highlight) {
160
- for (i = 0; i < this.options.highlight.length; i++) {
161
- highlight = this.options.highlight[i]
162
-
163
- if (d.labels[0] === highlight.class && d.properties[highlight.property] === highlight.value) {
164
- classes += ' node-highlighted'
165
- break
166
- }
167
- }
168
- }
169
-
170
- return classes
171
- })
172
- .on('click', (event, d) => {
173
- d.fx = d.fy = null
174
-
175
- if (typeof this.options.onNodeClick === 'function') {
176
- this.options.onNodeClick(d)
177
- }
178
- })
179
- .on('dblclick', (event, d) => {
180
- this.stickNode(event, d)
181
-
182
- if (typeof this.options.onNodeDoubleClick === 'function') {
183
- this.options.onNodeDoubleClick(d)
184
- }
185
- })
186
- .on('mouseenter', (event, d) => {
187
- if (this.info) {
188
- this.updateInfo(d)
189
- }
190
-
191
- if (typeof this.options.onNodeMouseEnter === 'function') {
192
- this.options.onNodeMouseEnter(d)
193
- }
194
- })
195
- .on('mouseleave', (event, d) => {
196
- if (this.info) {
197
- this.clearInfo()
198
- }
199
-
200
- if (typeof this.options.onNodeMouseLeave === 'function') {
201
- this.options.onNodeMouseLeave(d)
202
- }
203
- })
204
- .call(
205
- d3
206
- .drag()
207
- .on('start', this.dragStarted.bind(this))
208
- .on('drag', this.dragged.bind(this))
209
- .on('end', this.dragEnded.bind(this))
210
- )
211
- }
212
-
213
- appendNodeToGraph() {
214
- var n = this.appendNode()
215
-
216
- this.appendRingToNode(n)
217
- // this.appendBoxToNode(n)
218
- this.appendOutlineToNode(n)
219
-
220
- if (this.options.icons) {
221
- this.appendTextToNode(n)
222
- }
223
-
224
- if (this.options.images) {
225
- this.appendImageToNode(n)
226
- }
227
-
228
- return n
229
- }
230
-
231
- appendOutlineToNode(node) {
232
- const outline = node
233
- .append('circle')
234
- .attr('class', 'outline')
235
- .attr('r', this.options.nodeRadius)
236
- .style('fill', d => {
237
- return this.options.nodeOutlineFillColor ? this.options.nodeOutlineFillColor : this.class2color(d.labels[0])
238
- })
239
- .style('stroke', d => {
240
- return this.options.nodeOutlineFillColor
241
- ? this.class2darkenColor(this.options.nodeOutlineFillColor)
242
- : this.class2darkenColor(d.labels[0])
243
- })
244
- .append('title')
245
- .text(d => {
246
- return this.toString(d)
247
- })
248
-
249
- node
250
- .append('text')
251
- .attr('class', 'node-text')
252
- .attr('x', 0)
253
- .attr('y', 52)
254
- .attr('text-anchor', 'middle') // 텍스트 중앙 정렬
255
- .attr('fill', 'black') // 텍스트 색상을 검은색으로 변경
256
- .text(d => d.text)
257
-
258
- return outline
259
- }
260
-
261
- appendBoxToNode(node) {
262
- const rect = node
263
- .append('rect')
264
- .attr('class', 'node-rect')
265
- .attr('width', 160) // 사각형의 너비
266
- .attr('height', 30) // 사각형의 높이
267
- .attr('x', -80) // 사각형의 중심을 기준으로 x 위치 조정
268
- .attr('y', -15) // 사각형의 중심을 기준으로 y 위치 조정
269
- .style('fill', d => {
270
- return this.options.nodeOutlineFillColor ? this.options.nodeOutlineFillColor : this.class2color(d.labels[0])
271
- })
272
- .style('stroke', d => {
273
- return this.options.nodeOutlineFillColor
274
- ? this.class2darkenColor(this.options.nodeOutlineFillColor)
275
- : this.class2darkenColor(d.labels[0])
276
- })
277
- .append('title')
278
- .text(d => {
279
- return this.toString(d)
280
- })
281
-
282
- node
283
- .append('text')
284
- .attr('class', 'node-text')
285
- .attr('x', 0)
286
- .attr('y', 4)
287
- .attr('text-anchor', 'middle') // 텍스트 중앙 정렬
288
- .attr('fill', 'black') // 텍스트 색상을 검은색으로 변경
289
- .text(d => d.text)
290
-
291
- return rect
292
- }
293
-
294
- appendRingToNode(node) {
295
- return node
296
- .append('circle')
297
- .attr('class', 'ring')
298
- .attr('r', this.options.nodeRadius * 1.16)
299
- .append('title')
300
- .text(d => {
301
- return this.toString(d)
302
- })
303
- }
304
-
305
- appendTextToNode(node) {
306
- return node
307
- .append('text')
308
- .attr('fill', '#ffffff')
309
- .attr('pointer-events', 'none')
310
- .attr('text-anchor', 'middle')
311
- .attr('y', '24px')
312
- .attr('font-family', 'Material Symbols Outlined')
313
- .attr('font-size', '48px')
314
- .attr('text-anchor', 'middle')
315
- .attr('alignment-baseline', 'top')
316
- .text(d => this.icon(d))
317
- }
318
-
319
- appendRelationship() {
320
- return this.relationship
321
- .enter()
322
- .append('g')
323
- .attr('class', 'relationship')
324
- .on('dblclick', (event, d) => {
325
- if (typeof this.options.onRelationshipDoubleClick === 'function') {
326
- this.options.onRelationshipDoubleClick(d)
327
- }
328
- })
329
- .on('mouseenter', (event, d) => {
330
- if (this.info) {
331
- this.updateInfo(d)
332
- }
333
- })
334
- }
335
-
336
- appendOutlineToRelationship(r) {
337
- return r.append('path').attr('class', 'outline').attr('fill', '#a5abb6').attr('stroke', 'none')
338
- }
339
-
340
- appendOverlayToRelationship(r) {
341
- return r.append('path').attr('class', 'overlay')
342
- }
343
-
344
- appendTextToRelationship(r) {
345
- return r
346
- .append('text')
347
- .attr('class', 'text')
348
- .attr('fill', '#000000')
349
- .attr('font-size', '8px')
350
- .attr('pointer-events', 'none')
351
- .attr('text-anchor', 'middle')
352
- .text(d => {
353
- return d.type
354
- })
355
- }
356
-
357
- appendRelationshipToGraph() {
358
- var relationship = this.appendRelationship(),
359
- text = this.appendTextToRelationship(relationship),
360
- outline = this.appendOutlineToRelationship(relationship),
361
- overlay = this.appendOverlayToRelationship(relationship)
362
-
363
- return {
364
- outline: outline,
365
- overlay: overlay,
366
- relationship: relationship,
367
- text: text
368
- }
369
- }
370
-
371
- class2color(cls) {
372
- var color = this.classes2colors[cls]
373
-
374
- if (!color) {
375
- // color = this.options.colors[Math.min(numClasses, this.options.colors.length - 1)];
376
- color = this.options.colors[this.numClasses % this.options.colors.length]
377
- this.classes2colors[cls] = color
378
- this.numClasses++
379
- }
380
-
381
- return color
382
- }
383
-
384
- class2darkenColor(cls) {
385
- return d3.rgb(this.class2color(cls)).darker(1)
386
- }
387
-
388
- clearInfo() {
389
- this.info.html('')
390
- }
391
-
392
- color() {
393
- return this.options.colors[(this.options.colors.length * Math.random()) << 0]
394
- }
395
-
396
- colors() {
397
- // d3.schemeCategory10,
398
- // d3.schemeCategory20,
399
- return [
400
- '#68bdf6', // light blue
401
- '#6dce9e', // green #1
402
- '#faafc2', // light pink
403
- '#f2baf6', // purple
404
- '#ff928c', // light red
405
- '#fcea7e', // light yellow
406
- '#ffc766', // light orange
407
- '#405f9e', // navy blue
408
- '#a5abb6', // dark gray
409
- '#78cecb', // green #2,
410
- '#b88cbb', // dark purple
411
- '#ced2d9', // light gray
412
- '#e84646', // dark red
413
- '#fa5f86', // dark pink
414
- '#ffab1a', // dark orange
415
- '#fcda19', // dark yellow
416
- '#797b80', // black
417
- '#c9d96f', // pistacchio
418
- '#47991f', // green #3
419
- '#70edee', // turquoise
420
- '#ff75ea' // pink
421
- ]
422
- }
423
-
424
- contains(array, id) {
425
- var filter = array.filter(function (elem) {
426
- return elem.id === id
427
- })
428
-
429
- return filter.length > 0
430
- }
431
-
432
- defaultColor() {
433
- return this.options.relationshipColor
434
- }
435
-
436
- defaultDarkenColor() {
437
- return d3.rgb(this.options.colors[this.options.colors.length - 1]).darker(1)
438
- }
439
-
440
- dragEnded(event, d) {
441
- if (!event.active) {
442
- this.simulation.alphaTarget(0)
443
- }
444
-
445
- if (typeof this.options.onNodeDragEnd === 'function') {
446
- this.options.onNodeDragEnd(d)
447
- }
448
- }
449
-
450
- dragged(event, d) {
451
- this.stickNode(event, d)
452
- }
453
-
454
- dragStarted(event, d) {
455
- if (!event.active) {
456
- this.simulation.alphaTarget(0.3).restart()
457
- }
458
-
459
- d.fx = d.x
460
- d.fy = d.y
461
-
462
- if (typeof this.options.onNodeDragStart === 'function') {
463
- this.options.onNodeDragStart(d)
464
- }
465
- }
466
-
467
- extend(obj1, obj2) {
468
- var obj = {}
469
-
470
- this.merge(obj, obj1)
471
- this.merge(obj, obj2)
472
-
473
- return obj
474
- }
475
-
476
- icon(d) {
477
- return d.icon
478
- }
479
-
480
- image(d) {
481
- var i, imagesForLabel, img, imgLevel, label, labelPropertyValue, property, value
482
-
483
- if (this.options.images) {
484
- imagesForLabel = this.options.imageMap[d.labels[0]]
485
-
486
- if (imagesForLabel) {
487
- imgLevel = 0
488
-
489
- for (i = 0; i < imagesForLabel.length; i++) {
490
- labelPropertyValue = imagesForLabel[i].split('|')
491
-
492
- switch (labelPropertyValue.length) {
493
- case 3:
494
- value = labelPropertyValue[2]
495
- /* falls through */
496
- case 2:
497
- property = labelPropertyValue[1]
498
- /* falls through */
499
- case 1:
500
- label = labelPropertyValue[0]
501
- }
502
-
503
- if (
504
- d.labels[0] === label &&
505
- (!property || d.properties[property] !== undefined) &&
506
- (!value || d.properties[property] === value)
507
- ) {
508
- if (labelPropertyValue.length > imgLevel) {
509
- img = this.options.images[imagesForLabel[i]]
510
- imgLevel = labelPropertyValue.length
511
- }
512
- }
513
- }
514
- }
515
- }
516
-
517
- return img
518
- }
519
-
520
- init(_selector, _options) {
521
- this.merge(this.options, _options)
522
-
523
- if (this.options.icons) {
524
- this.options.showIcons = true
525
- }
526
-
527
- if (!this.options.minCollision) {
528
- this.options.minCollision = this.options.nodeRadius * 2
529
- }
530
-
531
- this.selector = _selector
532
-
533
- this.container = d3.select(this.selector)
534
-
535
- // this.container.attr('class', 'graph-container').html('')
536
-
537
- if (this.options.infoPanel) {
538
- this.info = this.appendInfoPanel(this.container)
539
- }
540
-
541
- this.appendGraph(this.container)
542
-
543
- this.simulation = this.initSimulation()
544
-
545
- if (this.options.graphData) {
546
- this.loadGraphData()
547
- } else if (this.options.dataUrl) {
548
- this.loadGraphDataFromUrl(this.options.dataUrl)
549
- } else {
550
- console.error('Error: both graphData and dataUrl are empty!')
551
- }
552
- }
553
-
554
- initSimulation() {
555
- const x = this.svg.node().parentElement.parentElement.clientWidth / 2
556
- const y = this.svg.node().parentElement.parentElement.clientHeight / 2
557
-
558
- var simulation = d3
559
- .forceSimulation()
560
- .force(
561
- 'collide',
562
- d3
563
- .forceCollide()
564
- .radius(d => {
565
- return this.options.minCollision
566
- })
567
- .iterations(2)
568
- )
569
- .force('charge', d3.forceManyBody())
570
- .force(
571
- 'link',
572
- d3.forceLink().id(d => {
573
- return d.id
574
- })
575
- )
576
- .force('center', d3.forceCenter(x, y))
577
- .on('tick', () => {
578
- this.tick()
579
- })
580
- .on('end', () => {
581
- if (this.options.zoomFit && !this.justLoaded) {
582
- this.justLoaded = true
583
- this.zoomFit(2)
584
- }
585
- })
586
-
587
- return simulation
588
- }
589
-
590
- loadGraphData() {
591
- this.nodes = []
592
- this.relationships = []
593
-
594
- this.updateWithGraphData(this.options.graphData)
595
- }
596
-
597
- loadGraphDataFromUrl(dataUrl) {
598
- this.nodes = []
599
- this.relationships = []
600
-
601
- d3.json(dataUrl, (error, data) => {
602
- if (error) {
603
- throw error
604
- }
605
-
606
- this.updateWithGraphData(data)
607
- })
608
- }
609
-
610
- merge(target, source) {
611
- Object.keys(source).forEach(property => {
612
- target[property] = source[property]
613
- })
614
- }
615
-
616
- graphDataToD3Data(data) {
617
- var graph = {
618
- nodes: [] as any[],
619
- relationships: [] as any[]
620
- }
621
-
622
- data.results.forEach(result => {
623
- result.data.forEach(data => {
624
- data.graph.nodes.forEach(node => {
625
- if (!this.contains(graph.nodes, node.id)) {
626
- graph.nodes.push(node)
627
- }
628
- })
629
-
630
- data.graph.relationships.forEach(function (relationship) {
631
- relationship.source = relationship.startNode
632
- relationship.target = relationship.endNode
633
- graph.relationships.push(relationship)
634
- })
635
-
636
- data.graph.relationships.sort(function (a, b) {
637
- if (a.source > b.source) {
638
- return 1
639
- } else if (a.source < b.source) {
640
- return -1
641
- } else {
642
- if (a.target > b.target) {
643
- return 1
644
- }
645
-
646
- if (a.target < b.target) {
647
- return -1
648
- } else {
649
- return 0
650
- }
651
- }
652
- })
653
-
654
- for (var i = 0; i < data.graph.relationships.length; i++) {
655
- if (
656
- i !== 0 &&
657
- data.graph.relationships[i].source === data.graph.relationships[i - 1].source &&
658
- data.graph.relationships[i].target === data.graph.relationships[i - 1].target
659
- ) {
660
- data.graph.relationships[i].linknum = data.graph.relationships[i - 1].linknum + 1
661
- } else {
662
- data.graph.relationships[i].linknum = 1
663
- }
664
- }
665
- })
666
- })
667
-
668
- return graph
669
- }
670
-
671
- randomD3Data(d, maxNodesToGenerate) {
672
- var data = {
673
- nodes: [] as any[],
674
- relationships: [] as any[]
675
- },
676
- i,
677
- label,
678
- node,
679
- numNodes = ((maxNodesToGenerate * Math.random()) << 0) + 1,
680
- relationship,
681
- s = this.size()
682
-
683
- for (i = 0; i < numNodes; i++) {
684
- label = this.randomLabel()
685
-
686
- node = {
687
- id: s.nodes + 1 + i,
688
- labels: [label],
689
- properties: {
690
- random: label
691
- },
692
- x: d.x,
693
- y: d.y
694
- }
695
-
696
- data.nodes[data.nodes.length] = node
697
-
698
- relationship = {
699
- id: s.relationships + 1 + i,
700
- type: label.toUpperCase(),
701
- startNode: d.id,
702
- endNode: s.nodes + 1 + i,
703
- properties: {
704
- from: Date.now()
705
- },
706
- source: d.id,
707
- target: s.nodes + 1 + i,
708
- linknum: s.relationships + 1 + i
709
- }
710
-
711
- data.relationships[data.relationships.length] = relationship
712
- }
713
-
714
- return data
715
- }
716
-
717
- randomLabel() {
718
- var icons = Object.keys(this.options.iconMap)
719
- return icons[(icons.length * Math.random()) << 0]
720
- }
721
-
722
- rotate(cx, cy, x, y, angle) {
723
- var radians = (Math.PI / 180) * angle,
724
- cos = Math.cos(radians),
725
- sin = Math.sin(radians),
726
- nx = cos * (x - cx) + sin * (y - cy) + cx,
727
- ny = cos * (y - cy) - sin * (x - cx) + cy
728
-
729
- return { x: nx, y: ny }
730
- }
731
-
732
- rotatePoint(c, p, angle) {
733
- return this.rotate(c.x, c.y, p.x, p.y, angle)
734
- }
735
-
736
- rotation(source, target) {
737
- return (Math.atan2(target.y - source.y, target.x - source.x) * 180) / Math.PI
738
- }
739
-
740
- size() {
741
- return {
742
- nodes: this.nodes.length,
743
- relationships: this.relationships.length
744
- }
745
- }
746
-
747
- stickNode(event, d) {
748
- d.fx = event.x
749
- d.fy = event.y
750
- }
751
-
752
- tick() {
753
- this.tickNodes()
754
- this.tickRelationships()
755
- }
756
-
757
- tickNodes() {
758
- if (this.node) {
759
- this.node.attr('transform', d => {
760
- return 'translate(' + d.x + ', ' + d.y + ')'
761
- })
762
- }
763
- }
764
-
765
- tickRelationships() {
766
- if (this.relationship) {
767
- this.relationship.attr('transform', d => {
768
- var angle = this.rotation(d.source, d.target)
769
- return 'translate(' + d.source.x + ', ' + d.source.y + ') rotate(' + angle + ')'
770
- })
771
-
772
- this.tickRelationshipsTexts()
773
- this.tickRelationshipsOutlines()
774
- this.tickRelationshipsOverlays()
775
- }
776
- }
777
-
778
- tickRelationshipsOutlines() {
779
- const self = this
780
- this.relationship.each(function (this, relationship) {
781
- var rel = d3.select(this)
782
- var outline = rel.select('.outline'),
783
- text = rel.select('.text'),
784
- bbox = text.node().getBBox(),
785
- padding = 3
786
-
787
- outline.attr('d', d => {
788
- var center = { x: 0, y: 0 },
789
- angle = self.rotation(d.source, d.target),
790
- textBoundingBox = text.node().getBBox(),
791
- textPadding = 5,
792
- u = self.unitaryVector(d.source, d.target),
793
- textMargin = {
794
- x: (d.target.x - d.source.x - (textBoundingBox.width + textPadding) * u.x) * 0.5,
795
- y: (d.target.y - d.source.y - (textBoundingBox.width + textPadding) * u.y) * 0.5
796
- },
797
- n = self.unitaryNormalVector(d.source, d.target),
798
- rotatedPointA1 = self.rotatePoint(
799
- center,
800
- { x: 0 + (self.options.nodeRadius + 1) * u.x - n.x, y: 0 + (self.options.nodeRadius + 1) * u.y - n.y },
801
- angle
802
- ),
803
- rotatedPointB1 = self.rotatePoint(center, { x: textMargin.x - n.x, y: textMargin.y - n.y }, angle),
804
- rotatedPointC1 = self.rotatePoint(center, { x: textMargin.x, y: textMargin.y }, angle),
805
- rotatedPointD1 = self.rotatePoint(
806
- center,
807
- { x: 0 + (self.options.nodeRadius + 1) * u.x, y: 0 + (self.options.nodeRadius + 1) * u.y },
808
- angle
809
- ),
810
- rotatedPointA2 = self.rotatePoint(
811
- center,
812
- { x: d.target.x - d.source.x - textMargin.x - n.x, y: d.target.y - d.source.y - textMargin.y - n.y },
813
- angle
814
- ),
815
- rotatedPointB2 = self.rotatePoint(
816
- center,
817
- {
818
- x: d.target.x - d.source.x - (self.options.nodeRadius + 1) * u.x - n.x - u.x * self.options.arrowSize,
819
- y: d.target.y - d.source.y - (self.options.nodeRadius + 1) * u.y - n.y - u.y * self.options.arrowSize
820
- },
821
- angle
822
- ),
823
- rotatedPointC2 = self.rotatePoint(
824
- center,
825
- {
826
- x:
827
- d.target.x -
828
- d.source.x -
829
- (self.options.nodeRadius + 1) * u.x -
830
- n.x +
831
- (n.x - u.x) * self.options.arrowSize,
832
- y:
833
- d.target.y -
834
- d.source.y -
835
- (self.options.nodeRadius + 1) * u.y -
836
- n.y +
837
- (n.y - u.y) * self.options.arrowSize
838
- },
839
- angle
840
- ),
841
- rotatedPointD2 = self.rotatePoint(
842
- center,
843
- {
844
- x: d.target.x - d.source.x - (self.options.nodeRadius + 1) * u.x,
845
- y: d.target.y - d.source.y - (self.options.nodeRadius + 1) * u.y
846
- },
847
- angle
848
- ),
849
- rotatedPointE2 = self.rotatePoint(
850
- center,
851
- {
852
- x: d.target.x - d.source.x - (self.options.nodeRadius + 1) * u.x + (-n.x - u.x) * self.options.arrowSize,
853
- y: d.target.y - d.source.y - (self.options.nodeRadius + 1) * u.y + (-n.y - u.y) * self.options.arrowSize
854
- },
855
- angle
856
- ),
857
- rotatedPointF2 = self.rotatePoint(
858
- center,
859
- {
860
- x: d.target.x - d.source.x - (self.options.nodeRadius + 1) * u.x - u.x * self.options.arrowSize,
861
- y: d.target.y - d.source.y - (self.options.nodeRadius + 1) * u.y - u.y * self.options.arrowSize
862
- },
863
- angle
864
- ),
865
- rotatedPointG2 = self.rotatePoint(
866
- center,
867
- { x: d.target.x - d.source.x - textMargin.x, y: d.target.y - d.source.y - textMargin.y },
868
- angle
869
- )
870
-
871
- return (
872
- 'M ' +
873
- rotatedPointA1.x +
874
- ' ' +
875
- rotatedPointA1.y +
876
- ' L ' +
877
- rotatedPointB1.x +
878
- ' ' +
879
- rotatedPointB1.y +
880
- ' L ' +
881
- rotatedPointC1.x +
882
- ' ' +
883
- rotatedPointC1.y +
884
- ' L ' +
885
- rotatedPointD1.x +
886
- ' ' +
887
- rotatedPointD1.y +
888
- ' Z M ' +
889
- rotatedPointA2.x +
890
- ' ' +
891
- rotatedPointA2.y +
892
- ' L ' +
893
- rotatedPointB2.x +
894
- ' ' +
895
- rotatedPointB2.y +
896
- ' L ' +
897
- rotatedPointC2.x +
898
- ' ' +
899
- rotatedPointC2.y +
900
- ' L ' +
901
- rotatedPointD2.x +
902
- ' ' +
903
- rotatedPointD2.y +
904
- ' L ' +
905
- rotatedPointE2.x +
906
- ' ' +
907
- rotatedPointE2.y +
908
- ' L ' +
909
- rotatedPointF2.x +
910
- ' ' +
911
- rotatedPointF2.y +
912
- ' L ' +
913
- rotatedPointG2.x +
914
- ' ' +
915
- rotatedPointG2.y +
916
- ' Z'
917
- )
918
- })
919
- })
920
- }
921
-
922
- tickRelationshipsOverlays() {
923
- this.relationshipOverlay.attr('d', d => {
924
- var center = { x: 0, y: 0 },
925
- angle = this.rotation(d.source, d.target),
926
- n1 = this.unitaryNormalVector(d.source, d.target),
927
- n = this.unitaryNormalVector(d.source, d.target, 50),
928
- rotatedPointA = this.rotatePoint(center, { x: 0 - n.x, y: 0 - n.y }, angle),
929
- rotatedPointB = this.rotatePoint(
930
- center,
931
- { x: d.target.x - d.source.x - n.x, y: d.target.y - d.source.y - n.y },
932
- angle
933
- ),
934
- rotatedPointC = this.rotatePoint(
935
- center,
936
- { x: d.target.x - d.source.x + n.x - n1.x, y: d.target.y - d.source.y + n.y - n1.y },
937
- angle
938
- ),
939
- rotatedPointD = this.rotatePoint(center, { x: 0 + n.x - n1.x, y: 0 + n.y - n1.y }, angle)
940
-
941
- return (
942
- 'M ' +
943
- rotatedPointA.x +
944
- ' ' +
945
- rotatedPointA.y +
946
- ' L ' +
947
- rotatedPointB.x +
948
- ' ' +
949
- rotatedPointB.y +
950
- ' L ' +
951
- rotatedPointC.x +
952
- ' ' +
953
- rotatedPointC.y +
954
- ' L ' +
955
- rotatedPointD.x +
956
- ' ' +
957
- rotatedPointD.y +
958
- ' Z'
959
- )
960
- })
961
- }
962
-
963
- tickRelationshipsTexts() {
964
- this.relationshipText.attr('transform', d => {
965
- var angle = (this.rotation(d.source, d.target) + 360) % 360,
966
- mirror = angle > 90 && angle < 270,
967
- center = { x: 0, y: 0 },
968
- n = this.unitaryNormalVector(d.source, d.target),
969
- nWeight = mirror ? 2 : -3,
970
- point = {
971
- x: (d.target.x - d.source.x) * 0.5 + n.x * nWeight,
972
- y: (d.target.y - d.source.y) * 0.5 + n.y * nWeight
973
- },
974
- rotatedPoint = this.rotatePoint(center, point, angle)
975
-
976
- return 'translate(' + rotatedPoint.x + ', ' + rotatedPoint.y + ') rotate(' + (mirror ? 180 : 0) + ')'
977
- })
978
- }
979
-
980
- toString(d) {
981
- var s = d.labels ? d.labels[0] : d.type
982
-
983
- s += ' (<id>: ' + d.id
984
-
985
- Object.keys(d.properties).forEach(function (property) {
986
- s += ', ' + property + ': ' + JSON.stringify(d.properties[property])
987
- })
988
-
989
- s += ')'
990
-
991
- return s
992
- }
993
-
994
- unitaryNormalVector(source, target, newLength?: any) {
995
- var center = { x: 0, y: 0 },
996
- vector = this.unitaryVector(source, target, newLength)
997
-
998
- return this.rotatePoint(center, vector, 90)
999
- }
1000
-
1001
- unitaryVector(source, target, newLength?: any) {
1002
- var length =
1003
- Math.sqrt(Math.pow(target.x - source.x, 2) + Math.pow(target.y - source.y, 2)) / Math.sqrt(newLength || 1)
1004
-
1005
- return {
1006
- x: (target.x - source.x) / length,
1007
- y: (target.y - source.y) / length
1008
- }
1009
- }
1010
-
1011
- updateWithD3Data(d3Data) {
1012
- this.updateNodesAndRelationships(d3Data.nodes, d3Data.relationships)
1013
- }
1014
-
1015
- updateWithGraphData(graphData) {
1016
- var d3Data = this.graphDataToD3Data(graphData)
1017
- this.updateWithD3Data(d3Data)
1018
- }
1019
-
1020
- updateInfo(d) {
1021
- this.clearInfo()
1022
-
1023
- if (d.labels) {
1024
- this.appendInfoElementClass('class', d.labels[0])
1025
- } else {
1026
- this.appendInfoElementRelationship('class', d.type)
1027
- }
1028
-
1029
- this.appendInfoElementProperty('property', '&lt;id&gt;', d.id)
1030
-
1031
- Object.keys(d.properties).forEach(property => {
1032
- this.appendInfoElementProperty('property', property, JSON.stringify(d.properties[property]))
1033
- })
1034
- }
1035
-
1036
- updateNodes(n) {
1037
- Array.prototype.push.apply(this.nodes, n)
1038
-
1039
- this.node = this.svgNodes.selectAll('.node').data(this.nodes, d => {
1040
- return d.id
1041
- })
1042
- var nodeEnter = this.appendNodeToGraph()
1043
- this.node = nodeEnter.merge(this.node)
1044
- }
1045
-
1046
- updateNodesAndRelationships(n, r) {
1047
- this.updateRelationships(r)
1048
- this.updateNodes(n)
1049
-
1050
- this.simulation.nodes(this.nodes)
1051
- this.simulation.force('link').links(this.relationships)
1052
- }
1053
-
1054
- updateRelationships(r) {
1055
- Array.prototype.push.apply(this.relationships, r)
1056
-
1057
- this.relationship = this.svgRelationships.selectAll('.relationship').data(this.relationships, d => {
1058
- return d.id
1059
- })
1060
-
1061
- var relationshipEnter = this.appendRelationshipToGraph()
1062
-
1063
- this.relationship = relationshipEnter.relationship.merge(this.relationship)
1064
-
1065
- this.relationshipOutline = this.svg.selectAll('.relationship .outline')
1066
- this.relationshipOutline = relationshipEnter.outline.merge(this.relationshipOutline)
1067
-
1068
- this.relationshipOverlay = this.svg.selectAll('.relationship .overlay')
1069
- this.relationshipOverlay = relationshipEnter.overlay.merge(this.relationshipOverlay)
1070
-
1071
- this.relationshipText = this.svg.selectAll('.relationship .text')
1072
- this.relationshipText = relationshipEnter.text.merge(this.relationshipText)
1073
- }
1074
-
1075
- zoomFit(transitionDuration) {
1076
- var bounds = this.svg.node().getBBox(),
1077
- parent = this.svg.node().parentElement.parentElement,
1078
- fullWidth = parent.clientWidth,
1079
- fullHeight = parent.clientHeight,
1080
- width = bounds.width,
1081
- height = bounds.height,
1082
- midX = bounds.x + width / 2,
1083
- midY = bounds.y + height / 2
1084
-
1085
- if (width === 0 || height === 0) {
1086
- return // nothing to fit
1087
- }
1088
-
1089
- this.svgScale = 0.85 / Math.max(width / fullWidth, height / fullHeight)
1090
- this.svgTranslate = [fullWidth / 2 - this.svgScale * midX, fullHeight / 2 - this.svgScale * midY]
1091
-
1092
- this.svg.attr(
1093
- 'transform',
1094
- 'translate(' + this.svgTranslate[0] + ', ' + this.svgTranslate[1] + ') scale(' + this.svgScale + ')'
1095
- )
1096
- }
1097
- }