Skip to content

Commit

Permalink
bugfix for duplicate node/link insertions; performance improvements i…
Browse files Browse the repository at this point in the history
…n data syncing
  • Loading branch information
rjohnson465 committed Aug 26, 2022
1 parent 62ae254 commit b3d5534
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
2 changes: 1 addition & 1 deletion projects/gojs-angular/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gojs-angular",
"version": "2.0.5",
"version": "2.0.6",
"peerDependencies": {
"@angular/common": ">=11.0.0",
"@angular/core": ">=11.0.0"
Expand Down
53 changes: 29 additions & 24 deletions projects/gojs-angular/src/lib/data-sync.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import * as go from 'gojs';
import produce from "immer";
import produce, { current } from "immer";

@Injectable()
export class DataSyncService {
Expand All @@ -18,6 +18,12 @@ export class DataSyncService {

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

// nodeData is immutable, modify it using the immer package's "produce" function (creates new array)
var newNodeDataArray = produce(nodeData, (draft) => {
Expand All @@ -27,12 +33,9 @@ export class DataSyncService {
// Get the value of the node key property checking wether is a function or a string
const key = model ? model.getKeyForNodeData(nd) : nd['key'];
modifiedNodesMap.set(key, nd);
for (let i = 0; i < nodeData.length; i++) {
const ndEntry = nodeData[i];
const keyNdEntry = model ? model.getKeyForNodeData(ndEntry) : ndEntry['key'];
if (keyNdEntry === key) {
draft[i] = nd;
}
const idx = keyIdxMap.get(key);
if (idx !== undefined && idx >= 0) {
draft[idx] = nd;
}
});
}
Expand All @@ -41,18 +44,18 @@ export class DataSyncService {
if (changes.insertedNodeKeys) {
changes.insertedNodeKeys.forEach((key: go.Key) => {
const nd = modifiedNodesMap.get(key);
if (nd) {
if (nd && !keyIdxMap.has(key)) {
draft.push(nd);
}
});
}

// account for removed node data
if (changes.removedNodeKeys) {
changes.removedNodeKeys.forEach(rnk => {
const idx = draft.findIndex(nd => { return model.getKeyForNodeData(nd) == rnk });
if (idx >= 0) draft.splice(idx, 1);
});
const removals = changes.removedNodeKeys.map(key => keyIdxMap.get(key)).sort();
for (let i = removals.length - 1; i >= 0; i--) {
draft.splice(removals[i], 1);
}
}
});

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

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

// linkData is immutable, modify it using the immer package's "produce" function (creates new array)
linkData = produce(linkData, draft => {
Expand All @@ -81,13 +90,9 @@ export class DataSyncService {
// Get the value of the link key
const key = model ? model.getKeyForLinkData(ld) : ld['key'];
modifiedLinksMap.set(key, ld);

for (let i = 0; i < linkData.length; i++) {
const ldEntry = linkData[i];
const keyLdEntry = model ? model.getKeyForLinkData(ldEntry) : ldEntry['key'];
if (keyLdEntry === key) {
draft[i] = ld;
}
const idx = keyIdxMap.get(key);
if (idx !== undefined && idx >= 0) {
draft[idx] = ld;
}
});
}
Expand All @@ -96,18 +101,18 @@ export class DataSyncService {
if (changes.insertedLinkKeys) {
changes.insertedLinkKeys.forEach((key: go.Key) => {
const nd = modifiedLinksMap.get(key);
if (nd) {
if (nd && !keyIdxMap.has(key)) {
draft.push(nd);
}
});
}

// account for removed link data
if (changes.removedLinkKeys) {
changes.removedLinkKeys.forEach(rlk => {
const idx = draft.findIndex(ld => { return model.getKeyForLinkData(ld) == rlk });
if (idx >= 0) draft.splice(idx, 1);
});
const removals = changes.removedLinkKeys.map(key => keyIdxMap.get(key)).sort();
for (let i = removals.length - 1; i >= 0; i--) {
draft.splice(removals[i], 1);
}
}
});

Expand Down

0 comments on commit b3d5534

Please sign in to comment.