Skip to content

Commit b3d5534

Browse files
committed
bugfix for duplicate node/link insertions; performance improvements in data syncing
1 parent 62ae254 commit b3d5534

File tree

2 files changed

+30
-25
lines changed

2 files changed

+30
-25
lines changed

projects/gojs-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gojs-angular",
3-
"version": "2.0.5",
3+
"version": "2.0.6",
44
"peerDependencies": {
55
"@angular/common": ">=11.0.0",
66
"@angular/core": ">=11.0.0"

projects/gojs-angular/src/lib/data-sync.service.ts

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import * as go from 'gojs';
3-
import produce from "immer";
3+
import produce, { current } from "immer";
44

55
@Injectable()
66
export class DataSyncService {
@@ -18,6 +18,12 @@ export class DataSyncService {
1818

1919
// maintain a map of modified nodes for fast lookup during insertion
2020
const modifiedNodesMap = new go.Map<go.Key, go.ObjectData>();
21+
// generate a map of keys -> indices for faster operations
22+
const keyIdxMap = new Map<go.Key, number>();
23+
nodeData.forEach((nd, idx) => {
24+
const key = model ? model.getKeyForNodeData(nd) : nd['key'];
25+
keyIdxMap.set(key, idx);
26+
});
2127

2228
// nodeData is immutable, modify it using the immer package's "produce" function (creates new array)
2329
var newNodeDataArray = produce(nodeData, (draft) => {
@@ -27,12 +33,9 @@ export class DataSyncService {
2733
// Get the value of the node key property checking wether is a function or a string
2834
const key = model ? model.getKeyForNodeData(nd) : nd['key'];
2935
modifiedNodesMap.set(key, nd);
30-
for (let i = 0; i < nodeData.length; i++) {
31-
const ndEntry = nodeData[i];
32-
const keyNdEntry = model ? model.getKeyForNodeData(ndEntry) : ndEntry['key'];
33-
if (keyNdEntry === key) {
34-
draft[i] = nd;
35-
}
36+
const idx = keyIdxMap.get(key);
37+
if (idx !== undefined && idx >= 0) {
38+
draft[idx] = nd;
3639
}
3740
});
3841
}
@@ -41,18 +44,18 @@ export class DataSyncService {
4144
if (changes.insertedNodeKeys) {
4245
changes.insertedNodeKeys.forEach((key: go.Key) => {
4346
const nd = modifiedNodesMap.get(key);
44-
if (nd) {
47+
if (nd && !keyIdxMap.has(key)) {
4548
draft.push(nd);
4649
}
4750
});
4851
}
4952

5053
// account for removed node data
5154
if (changes.removedNodeKeys) {
52-
changes.removedNodeKeys.forEach(rnk => {
53-
const idx = draft.findIndex(nd => { return model.getKeyForNodeData(nd) == rnk });
54-
if (idx >= 0) draft.splice(idx, 1);
55-
});
55+
const removals = changes.removedNodeKeys.map(key => keyIdxMap.get(key)).sort();
56+
for (let i = removals.length - 1; i >= 0; i--) {
57+
draft.splice(removals[i], 1);
58+
}
5659
}
5760
});
5861

@@ -72,6 +75,12 @@ export class DataSyncService {
7275

7376
// maintain a map of modified nodes for fast lookup during insertion
7477
const modifiedLinksMap = new go.Map<go.Key, go.ObjectData>();
78+
// generate a map of keys -> indices for faster operations
79+
const keyIdxMap = new Map<go.Key, number>();
80+
linkData.forEach((ld, idx) => {
81+
const key = model ? model.getKeyForLinkData(ld) : ld['key'];
82+
keyIdxMap.set(key, idx);
83+
});
7584

7685
// linkData is immutable, modify it using the immer package's "produce" function (creates new array)
7786
linkData = produce(linkData, draft => {
@@ -81,13 +90,9 @@ export class DataSyncService {
8190
// Get the value of the link key
8291
const key = model ? model.getKeyForLinkData(ld) : ld['key'];
8392
modifiedLinksMap.set(key, ld);
84-
85-
for (let i = 0; i < linkData.length; i++) {
86-
const ldEntry = linkData[i];
87-
const keyLdEntry = model ? model.getKeyForLinkData(ldEntry) : ldEntry['key'];
88-
if (keyLdEntry === key) {
89-
draft[i] = ld;
90-
}
93+
const idx = keyIdxMap.get(key);
94+
if (idx !== undefined && idx >= 0) {
95+
draft[idx] = ld;
9196
}
9297
});
9398
}
@@ -96,18 +101,18 @@ export class DataSyncService {
96101
if (changes.insertedLinkKeys) {
97102
changes.insertedLinkKeys.forEach((key: go.Key) => {
98103
const nd = modifiedLinksMap.get(key);
99-
if (nd) {
104+
if (nd && !keyIdxMap.has(key)) {
100105
draft.push(nd);
101106
}
102107
});
103108
}
104109

105110
// account for removed link data
106111
if (changes.removedLinkKeys) {
107-
changes.removedLinkKeys.forEach(rlk => {
108-
const idx = draft.findIndex(ld => { return model.getKeyForLinkData(ld) == rlk });
109-
if (idx >= 0) draft.splice(idx, 1);
110-
});
112+
const removals = changes.removedLinkKeys.map(key => keyIdxMap.get(key)).sort();
113+
for (let i = removals.length - 1; i >= 0; i--) {
114+
draft.splice(removals[i], 1);
115+
}
111116
}
112117
});
113118

0 commit comments

Comments
 (0)