Skip to content

Commit 3bb7641

Browse files
authored
Merge pull request #60 from daveseah/dev-bl/edit-edge-lock
Edit Edge Lock
2 parents 2554384 + ac2563c commit 3bb7641

File tree

6 files changed

+198
-68
lines changed

6 files changed

+198
-68
lines changed

build/app/assets/templates/alexander.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"label": "Label",
2121
"help": "A short title for the node",
2222
"duplicateWarning": "You’re entering a duplicate node. Do you want to View the Existing node, or Continue creating?",
23-
"sourceNodeIsLockedMessage": "This node is currently being editted by someone else, please try again later.",
23+
"sourceNodeIsLockedMessage": "This node is currently being edited by someone else, please try again later.",
2424
"_cmt4": "/// `Label` is always required and cannot be hidden"
2525
},
2626
"type": {
@@ -84,6 +84,7 @@
8484

8585

8686
"edgePrompts": {
87+
"edgeIsLockedMessage": "This edge is currently being edited by someone else, please try again later.",
8788
"source": {
8889
"label": "Source",
8990
"help": "",

build/app/unisys/server-database.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ DB.InitializeDatabase = function(options = {}) {
6565
m_locked_nodes = new Set();
6666
EDGES = m_db.getCollection("edges");
6767
if (EDGES === null) EDGES = m_db.addCollection("edges");
68+
m_locked_edges = new Set();
6869

6970
// initialize unique set manager
7071
m_dupe_set = new Set();
@@ -215,7 +216,45 @@ function m_IsInvalidNode ( nodeID ) {
215216
function m_MakeLockError( info ) {
216217
return { NOP:`ERR`, INFO:info };
217218
}
218-
219+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
220+
DB.PKT_RequestLockEdge = function (pkt) {
221+
let { edgeID } = pkt.Data();
222+
let errcode = m_IsInvalidEdge(edgeID);
223+
if (errcode) return errcode;
224+
// check if edge is already locked
225+
if (m_locked_edges.has(edgeID)) return m_MakeLockError(`edgeID ${edgeID} is already locked`);
226+
// SUCCESS
227+
// single matching edge exists and is not yet locked, so lock it
228+
m_locked_edges.add(edgeID);
229+
return { edgeID, locked: true };
230+
};
231+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
232+
DB.PKT_RequestUnlockEdge = function (pkt) {
233+
let { edgeID } = pkt.Data();
234+
let errcode = m_IsInvalidEdge(edgeID);
235+
if (errcode) return errcode;
236+
// check that edge is already locked
237+
if (m_locked_edges.has(edgeID)) {
238+
m_locked_edges.delete(edgeID);
239+
return { edgeID, unlocked: true };
240+
}
241+
// this is an error because nodeID wasn't in the lock table
242+
return m_MakeLockError(`edgeID ${edgeID} was not locked so can't unlock`);
243+
};
244+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
245+
function m_IsInvalidEdge(edgeID) {
246+
if (!edgeID) return m_MakeLockError(`undefined edgeID`);
247+
edgeID = Number.parseInt(edgeID, 10);
248+
if (isNaN(edgeID)) return m_MakeLockError(`edgeID was not a number`);
249+
if (edgeID < 0) return m_MakeLockError(`edgeID ${edgeID} must be positive integer`);
250+
if (edgeID > m_max_edgeID) return m_MakeLockError(`edgeID ${edgeID} is out of range`);
251+
// find if the node exists
252+
let matches = EDGES.find({ id: edgeID });
253+
if (matches.length === 0) return m_MakeLockError(`edgeID ${edgeID} not found`);
254+
if (matches.length > 1) return m_MakeLockError(`edgeID ${edgeID} matches multiple entries...critical error!`);
255+
// no retval is no error!
256+
return undefined;
257+
}
219258
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
220259
DB.PKT_Update = function(pkt) {
221260
let { node, edge, nodeID, replacementNodeID, edgeID } = pkt.Data();

build/app/unisys/server.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,17 @@ var UNISYS = {};
9494
return UDB.PKT_RequestUnlockNode(pkt);
9595
});
9696

97-
UNET.HandleMessage('SRV_DBGETEDGEID',function(pkt) {
97+
UNET.HandleMessage('SRV_DBLOCKEDGE', function (pkt) {
98+
if (DBG) console.log(PR, sprint_message(pkt));
99+
return UDB.PKT_RequestLockEdge(pkt);
100+
});
101+
102+
UNET.HandleMessage('SRV_DBUNLOCKEDGE', function (pkt) {
103+
if (DBG) console.log(PR, sprint_message(pkt));
104+
return UDB.PKT_RequestUnlockEdge(pkt);
105+
});
106+
107+
UNET.HandleMessage('SRV_DBGETEDGEID', function (pkt) {
98108
if (DBG) console.log(PR,sprint_message(pkt));
99109
return UDB.PKT_GetNewEdgeID(pkt);
100110
});

build/app/view/netcreate/components/EdgeEditor.jsx

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,19 @@
4949
by the EdgeEditor to determine whether it should
5050
display the edge nodes as targets or sources.
5151
52+
## STATES
5253
53-
## TECHNICAL DESCRIPTION
54+
dbIsLocked
55+
If someone else has selected the edge for editing,
56+
this flag will cause the dbIsLockedMessage
57+
to be displayed. This is only checked when
58+
the user clicks "Edit".
5459
5560
56-
## TESTING
61+
## TECHNICAL DESCRIPTION
62+
63+
64+
## TESTING
5765
5866
5967
Displaying Current Edge(s)
@@ -218,6 +226,7 @@ class EdgeEditor extends UNISYS.Component {
218226
id: ''
219227
},
220228
isLocked: true, // User has not logged in, don't allow edge edit
229+
dbIsLocked: false, // Server Database is locked because someone else is editing
221230
isEditable: false, // Form is in an edtiable state
222231
isExpanded: false, // Show EdgeEditor Component in Summary view vs Expanded view
223232
sourceIsEditable:false, // Source ndoe field is only editable when source is not parent
@@ -236,6 +245,7 @@ class EdgeEditor extends UNISYS.Component {
236245
this.onButtonClick = this.onButtonClick.bind(this);
237246
this.onDeleteButtonClick = this.onDeleteButtonClick.bind(this);
238247
this.onEditButtonClick = this.onEditButtonClick.bind(this);
248+
this.requestEdit = this.requestEdit.bind(this);
239249
this.onSwapSourceAndTarget = this.onSwapSourceAndTarget.bind(this);
240250
this.onChangeSource = this.onChangeSource.bind(this);
241251
this.onChangeTarget = this.onChangeTarget.bind(this);
@@ -304,6 +314,7 @@ class EdgeEditor extends UNISYS.Component {
304314
},
305315
isEditable: false,
306316
isExpanded: false, // Summary view vs Expanded view
317+
dbIsLocked: false,
307318
sourceIsEditable: false, // Source ndoe field is only editable when source is not parent
308319
hasValidSource: false, // Used by SwapSourceAndTarget and the Change Source button
309320
targetIsEditable: false, // Target ndoe field is only editable when target is not parent
@@ -313,7 +324,7 @@ class EdgeEditor extends UNISYS.Component {
313324
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
314325
/*/ populate formdata from D3DATA
315326
/*/ loadSourceAndTarget () {
316-
if (DBG) console.log('EdgeEditor.loadSourceAndTarget!')
327+
if (DBG) console.log('EdgeEditor.loadSourceAndTarget!')
317328

318329
let edgeID = this.props.edgeID || '';
319330
// Clean Data
@@ -327,6 +338,7 @@ class EdgeEditor extends UNISYS.Component {
327338
throw 'EdgeEditor: Passed edgeID'+edgeID+'not found!';
328339
}
329340
let edge = edges[0];
341+
if (DBG) console.log('EdgeEditor.loadSourceAndTarget: Loading edge', edge);
330342

331343
let sourceNode, sourceNodes, targetNode, targetNodes;
332344

@@ -404,7 +416,8 @@ class EdgeEditor extends UNISYS.Component {
404416
isNewEdge: false
405417
},
406418
sourceNode: sourceNode,
407-
targetNode: targetNode
419+
targetNode: targetNode,
420+
dbIsLocked: false
408421
})
409422
}
410423

@@ -417,16 +430,24 @@ class EdgeEditor extends UNISYS.Component {
417430
When a node is selected via the AutoComplete field, the SELECTION state is updated.
418431
So EdgeEditor needs to listen to the SELECTION state in order to
419432
know the target node has been selected.
433+
SELECTION is also triggered when the network updates an edge.
420434
/*/ handleSelection ( data ) {
421435
if (DBG) console.log('EdgeEditor',this.props.edgeID,'got SELECTION data',data);
422436

423-
// If edge is not being edited, ignore the selection
424-
if (!this.state.isEditable &&
425-
!(this.state.sourceIsEditable || this.state.targetIsEditable) ) return;
437+
438+
// If we're one of the edges that have been updated, and we're not currently being edited,
439+
// then update the data.
440+
// If we're not currently being edited, then if edges have been updated, update self
441+
let updatedEdge = data.edges.find((edge) => { return edge.id === this.state.formData.id; });
442+
if (!this.state.isEditable && updatedEdge!==undefined) {
443+
if (DBG) console.log('EdgeEditor: Updating edges with', updatedEdge);
444+
this.loadSourceAndTarget();
445+
return;
446+
}
426447

427448
// Technically we probably ought to also check to make sure we're the current
428-
// activeAutoCompleteId, but we wouldn't be edtiable if we weren't.
429-
if (data.nodes && data.nodes.length>0) {
449+
// activeAutoCompleteId, but we wouldn't be editable if we weren't.
450+
if (this.state.isEditable && data.nodes && data.nodes.length > 0) {
430451
// A node was selected, so load it
431452

432453
let node = data.nodes[0];
@@ -457,7 +478,7 @@ class EdgeEditor extends UNISYS.Component {
457478
// TARGET
458479
if (DBG) console.log('EdgeEditor.handleSelection:',this.props.edgeID,'setting target node to',node);
459480

460-
// Set targetNpde state
481+
// Set targetNode state
461482
this.setState({
462483
targetNode: node
463484
});
@@ -500,17 +521,13 @@ class EdgeEditor extends UNISYS.Component {
500521

501522
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
502523
/*/ Someone externally has selected an edge for editing.
503-
Usually someone has clicked a button in the EdgeList to edit an edge
524+
Usually someone has clicked a button in the EdgeTable to edit an edge
504525
/*/ handleEdgeEdit ( data ) {
505526
if (DBG) console.log('EdgeEditor',this.state.formData.id,': got state EDGE_EDIT',data,'formData is',this.state.formData);
506527

507528
if (this.state.formData.id === data.edgeID) {
508-
this.setState({
509-
isExpanded: true,
510-
isEditable: true
511-
});
529+
this.requestEdit();
512530
}
513-
this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID });
514531

515532
} // handleEdgeEdit
516533
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -542,8 +559,17 @@ class EdgeEditor extends UNISYS.Component {
542559
this.setState({ isEditable: false, targetIsEditable: false });
543560
this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID });
544561
this.AppCall('AUTOCOMPLETE_SELECT',{id:'search'});
562+
// unlock
563+
this.NetCall('SRV_DBUNLOCKEDGEE', { edgeID: this.state.formData.id })
564+
.then((data) => {
565+
if (data.NOP) {
566+
if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`);
567+
} else if (data.unlocked) {
568+
if (DBG) console.log(`SERVER SAYS: unlock success! you have released Edge ${data.edgeID}`);
569+
this.setState({ dbIsLocked: false });
570+
}
571+
});
545572
}
546-
547573
} else {
548574
// expand, but don't set the autocomplete field, since we're not editing
549575
this.setState({ isExpanded: true });
@@ -553,14 +579,13 @@ class EdgeEditor extends UNISYS.Component {
553579
/*/
554580
/*/ onDeleteButtonClick () {
555581
this.clearForm();
556-
this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID });
582+
this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); // inform NodeSelector
557583
this.AppCall('DB_UPDATE',{edgeID:this.props.edgeID});
558584
}
559585
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
560586
/*/
561587
/*/ onEditButtonClick () {
562-
this.setState({ isEditable: true });
563-
this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID });
588+
this.requestEdit(this.state.formData.id);
564589

565590
// Don't allow editing of the source or target fields.
566591
// If you want to change the edge, delete this one and create a new one.
@@ -574,6 +599,30 @@ class EdgeEditor extends UNISYS.Component {
574599
}
575600
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
576601
/*/
602+
/*/ requestEdit() {
603+
let edgeID = this.state.formData.id;
604+
if (edgeID && edgeID!=='' && !isNaN(edgeID) && (typeof edgeID ==="number")) {
605+
this.NetCall('SRV_DBLOCKEDGE', { edgeID: edgeID })
606+
.then((data) => {
607+
if (data.NOP) {
608+
// Edge is locked, can't edit
609+
if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`);
610+
this.setState({ dbIsLocked: true });
611+
} else if (data.locked) {
612+
if (DBG) console.log(`SERVER SAYS: lock success! you can edit Edge ${data.edgeID}`);
613+
if (DBG) console.log(`SERVER SAYS: unlock the edge after successful DBUPDATE`);
614+
this.setState({
615+
isEditable: true,
616+
isExpanded: true,
617+
dbIsLocked: false
618+
});
619+
this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID }); // inform NodeSelector
620+
}
621+
});
622+
}
623+
}
624+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
625+
/*/
577626
/*/ onSwapSourceAndTarget () {
578627
let formData = this.state.formData;
579628

@@ -669,12 +718,24 @@ class EdgeEditor extends UNISYS.Component {
669718
}
670719
if (DBG) console.group('EdgeEntry.onSubmit submitting',edge)
671720

672-
this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID });
721+
this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); // inform NodeSelector
673722
// pass currentAutoComplete back to nodeselector
674723
this.AppCall('AUTOCOMPLETE_SELECT',{id:'search'});
675724
this.setState({ isEditable: false, sourceIsEditable: false, targetIsEditable: false });
676-
this.AppCall('DB_UPDATE',{ edge });
677-
} // onSubmit
725+
this.AppCall('DB_UPDATE', { edge })
726+
.then(() => {
727+
this.NetCall('SRV_DBUNLOCKEDGE', { edgeID: edge.id })
728+
.then((data) => {
729+
if (data.NOP) {
730+
if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`);
731+
} else if (data.unlocked) {
732+
if (DBG) console.log(`SERVER SAYS: unlock success! you have released Edge ${data.edgeID}`);
733+
this.setState({ dbIsLocked: false });
734+
}
735+
});
736+
});
737+
738+
} // onSubmit
678739

679740

680741

@@ -814,7 +875,7 @@ class EdgeEditor extends UNISYS.Component {
814875
<Button outline size="sm"
815876
hidden={this.state.isLocked || this.state.isEditable}
816877
onClick={this.onEditButtonClick}
817-
>{this.state.isEditable?"Add New Edge":"Edit Edge"}</Button>&nbsp;
878+
>{this.state.isEditable ? "Add New Edge" : "Edit Edge"}</Button>&nbsp;
818879
<Button size="sm"
819880
outline={this.state.isEditable}
820881
onClick={this.onButtonClick}
@@ -823,6 +884,7 @@ class EdgeEditor extends UNISYS.Component {
823884
hidden={!this.state.isEditable}
824885
disabled={ !(this.state.isEditable && this.state.hasValidTarget) }
825886
>Save</Button>
887+
<p hidden={!this.state.dbIsLocked} className="small text-danger">{edgePrompts.edgeIsLockedMessage}</p>
826888
</FormGroup>
827889
</Form>
828890
</div>

0 commit comments

Comments
 (0)