From eafce2496888543ceb2ff2bf997f4697c349f341 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Mon, 28 Jan 2019 19:40:01 -0800 Subject: [PATCH 1/3] dev-bl/edit-edge-lock: Lock edge on db when being edited. --- build/app/assets/templates/alexander.json | 3 +- build/app/unisys/server-database.js | 41 ++++++++- build/app/unisys/server.js | 12 ++- .../view/netcreate/components/EdgeEditor.jsx | 87 +++++++++++++++---- 4 files changed, 123 insertions(+), 20 deletions(-) diff --git a/build/app/assets/templates/alexander.json b/build/app/assets/templates/alexander.json index dd1a26296..287b6672a 100644 --- a/build/app/assets/templates/alexander.json +++ b/build/app/assets/templates/alexander.json @@ -20,7 +20,7 @@ "label": "Label", "help": "A short title for the node", "duplicateWarning": "You’re entering a duplicate node. Do you want to View the Existing node, or Continue creating?", - "sourceNodeIsLockedMessage": "This node is currently being editted by someone else, please try again later.", + "sourceNodeIsLockedMessage": "This node is currently being edited by someone else, please try again later.", "_cmt4": "/// `Label` is always required and cannot be hidden" }, "type": { @@ -84,6 +84,7 @@ "edgePrompts": { + "edgeIsLockedMessage": "This edge is currently being edited by someone else, please try again later.", "source": { "label": "Source", "help": "", diff --git a/build/app/unisys/server-database.js b/build/app/unisys/server-database.js index 48567912e..9b44d2611 100644 --- a/build/app/unisys/server-database.js +++ b/build/app/unisys/server-database.js @@ -65,6 +65,7 @@ DB.InitializeDatabase = function(options = {}) { m_locked_nodes = new Set(); EDGES = m_db.getCollection("edges"); if (EDGES === null) EDGES = m_db.addCollection("edges"); + m_locked_edges = new Set(); // initialize unique set manager m_dupe_set = new Set(); @@ -215,7 +216,45 @@ function m_IsInvalidNode ( nodeID ) { function m_MakeLockError( info ) { return { NOP:`ERR`, INFO:info }; } - +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +DB.PKT_RequestLockEdge = function (pkt) { + let { edgeID } = pkt.Data(); + let errcode = m_IsInvalidEdge(edgeID); + if (errcode) return errcode; + // check if edge is already locked + if (m_locked_edges.has(edgeID)) return m_MakeLockError(`edgeID ${edgeID} is already locked`); + // SUCCESS + // single matching edge exists and is not yet locked, so lock it + m_locked_edges.add(edgeID); + return { edgeID, locked: true }; +}; +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +DB.PKT_RequestUnlockEdge = function (pkt) { + let { edgeID } = pkt.Data(); + let errcode = m_IsInvalidEdge(edgeID); + if (errcode) return errcode; + // check that edge is already locked + if (m_locked_edges.has(edgeID)) { + m_locked_edges.delete(edgeID); + return { edgeID, unlocked: true }; + } + // this is an error because nodeID wasn't in the lock table + return m_MakeLockError(`edgeID ${edgeID} was not locked so can't unlock`); +}; +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +function m_IsInvalidEdge(edgeID) { + if (!edgeID) return m_MakeLockError(`undefined edgeID`); + edgeID = Number.parseInt(edgeID, 10); + if (isNaN(edgeID)) return m_MakeLockError(`edgeID was not a number`); + if (edgeID < 0) return m_MakeLockError(`edgeID ${edgeID} must be positive integer`); + if (edgeID > m_max_edgeID) return m_MakeLockError(`edgeID ${edgeID} is out of range`); + // find if the node exists + let matches = EDGES.find({ id: edgeID }); + if (matches.length === 0) return m_MakeLockError(`edgeID ${edgeID} not found`); + if (matches.length > 1) return m_MakeLockError(`edgeID ${edgeID} matches multiple entries...critical error!`); + // no retval is no error! + return undefined; +} /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DB.PKT_Update = function(pkt) { let { node, edge, nodeID, replacementNodeID, edgeID } = pkt.Data(); diff --git a/build/app/unisys/server.js b/build/app/unisys/server.js index ca05c59ed..478fde973 100644 --- a/build/app/unisys/server.js +++ b/build/app/unisys/server.js @@ -94,7 +94,17 @@ var UNISYS = {}; return UDB.PKT_RequestUnlockNode(pkt); }); - UNET.HandleMessage('SRV_DBGETEDGEID',function(pkt) { + UNET.HandleMessage('SRV_DBLOCKEDGE', function (pkt) { + if (DBG) console.log(PR, sprint_message(pkt)); + return UDB.PKT_RequestLockEdge(pkt); + }); + + UNET.HandleMessage('SRV_DBUNLOCKEDGE', function (pkt) { + if (DBG) console.log(PR, sprint_message(pkt)); + return UDB.PKT_RequestUnlockEdge(pkt); + }); + + UNET.HandleMessage('SRV_DBGETEDGEID', function (pkt) { if (DBG) console.log(PR,sprint_message(pkt)); return UDB.PKT_GetNewEdgeID(pkt); }); diff --git a/build/app/view/netcreate/components/EdgeEditor.jsx b/build/app/view/netcreate/components/EdgeEditor.jsx index 2f6781019..53e988345 100644 --- a/build/app/view/netcreate/components/EdgeEditor.jsx +++ b/build/app/view/netcreate/components/EdgeEditor.jsx @@ -49,11 +49,19 @@ by the EdgeEditor to determine whether it should display the edge nodes as targets or sources. + ## STATES - ## TECHNICAL DESCRIPTION + dbIsLocked + If someone else has selected the edge for editing, + this flag will cause the dbIsLockedMessage + to be displayed. This is only checked when + the user clicks "Edit". - ## TESTING + ## TECHNICAL DESCRIPTION + + + ## TESTING Displaying Current Edge(s) @@ -218,6 +226,7 @@ class EdgeEditor extends UNISYS.Component { id: '' }, isLocked: true, // User has not logged in, don't allow edge edit + dbIsLocked: false, // Server Database is locked because someone else is editing isEditable: false, // Form is in an edtiable state isExpanded: false, // Show EdgeEditor Component in Summary view vs Expanded view sourceIsEditable:false, // Source ndoe field is only editable when source is not parent @@ -236,6 +245,7 @@ class EdgeEditor extends UNISYS.Component { this.onButtonClick = this.onButtonClick.bind(this); this.onDeleteButtonClick = this.onDeleteButtonClick.bind(this); this.onEditButtonClick = this.onEditButtonClick.bind(this); + this.requestEdit = this.requestEdit.bind(this); this.onSwapSourceAndTarget = this.onSwapSourceAndTarget.bind(this); this.onChangeSource = this.onChangeSource.bind(this); this.onChangeTarget = this.onChangeTarget.bind(this); @@ -304,6 +314,7 @@ class EdgeEditor extends UNISYS.Component { }, isEditable: false, isExpanded: false, // Summary view vs Expanded view + dbIsLocked: false, sourceIsEditable: false, // Source ndoe field is only editable when source is not parent hasValidSource: false, // Used by SwapSourceAndTarget and the Change Source button targetIsEditable: false, // Target ndoe field is only editable when target is not parent @@ -404,7 +415,8 @@ class EdgeEditor extends UNISYS.Component { isNewEdge: false }, sourceNode: sourceNode, - targetNode: targetNode + targetNode: targetNode, + dbIsLocked: false }) } @@ -500,17 +512,13 @@ class EdgeEditor extends UNISYS.Component { /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ Someone externally has selected an edge for editing. - Usually someone has clicked a button in the EdgeList to edit an edge + Usually someone has clicked a button in the EdgeTable to edit an edge /*/ handleEdgeEdit ( data ) { if (DBG) console.log('EdgeEditor',this.state.formData.id,': got state EDGE_EDIT',data,'formData is',this.state.formData); if (this.state.formData.id === data.edgeID) { - this.setState({ - isExpanded: true, - isEditable: true - }); + this.requestEdit(); } - this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID }); } // handleEdgeEdit /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -542,8 +550,17 @@ class EdgeEditor extends UNISYS.Component { this.setState({ isEditable: false, targetIsEditable: false }); this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); this.AppCall('AUTOCOMPLETE_SELECT',{id:'search'}); + // unlock + this.NetCall('SRV_DBUNLOCKEDGEE', { edgeID: this.state.formData.id }) + .then((data) => { + if (data.NOP) { + if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); + } else if (data.unlocked) { + if (DBG) console.log(`SERVER SAYS: unlock success! you have released Edge ${data.edgeID}`); + this.setState({ dbIsLocked: false }); + } + }); } - } else { // expand, but don't set the autocomplete field, since we're not editing this.setState({ isExpanded: true }); @@ -553,14 +570,13 @@ class EdgeEditor extends UNISYS.Component { /*/ /*/ onDeleteButtonClick () { this.clearForm(); - this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); + this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); // inform NodeSelector this.AppCall('DB_UPDATE',{edgeID:this.props.edgeID}); } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ /*/ onEditButtonClick () { - this.setState({ isEditable: true }); - this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID }); + this.requestEdit(this.state.formData.id); // Don't allow editing of the source or target fields. // If you want to change the edge, delete this one and create a new one. @@ -574,6 +590,30 @@ class EdgeEditor extends UNISYS.Component { } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ +/*/ requestEdit() { + let edgeID = this.state.formData.id; + if (edgeID && edgeID!=='' && !isNaN(edgeID) && (typeof edgeID ==="number")) { + this.NetCall('SRV_DBLOCKEDGE', { edgeID: edgeID }) + .then((data) => { + if (data.NOP) { + // Edge is locked, can't edit + if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); + this.setState({ dbIsLocked: true }); + } else if (data.locked) { + if (DBG) console.log(`SERVER SAYS: lock success! you can edit Edge ${data.edgeID}`); + if (DBG) console.log(`SERVER SAYS: unlock the edge after successful DBUPDATE`); + this.setState({ + isEditable: true, + isExpanded: true, + dbIsLocked: false + }); + this.AppCall('EDGEEDIT_LOCK', { edgeID: this.props.edgeID }); // inform NodeSelector + } + }); + } + } +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*/ /*/ onSwapSourceAndTarget () { let formData = this.state.formData; @@ -669,12 +709,24 @@ class EdgeEditor extends UNISYS.Component { } if (DBG) console.group('EdgeEntry.onSubmit submitting',edge) - this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); + this.AppCall('EDGEEDIT_UNLOCK', { edgeID: this.props.edgeID }); // inform NodeSelector // pass currentAutoComplete back to nodeselector this.AppCall('AUTOCOMPLETE_SELECT',{id:'search'}); this.setState({ isEditable: false, sourceIsEditable: false, targetIsEditable: false }); - this.AppCall('DB_UPDATE',{ edge }); - } // onSubmit + this.AppCall('DB_UPDATE', { edge }) + .then(() => { + this.NetCall('SRV_DBUNLOCKEDGE', { edgeID: edge.id }) + .then((data) => { + if (data.NOP) { + if (DBG) console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); + } else if (data.unlocked) { + if (DBG) console.log(`SERVER SAYS: unlock success! you have released Edge ${data.edgeID}`); + this.setState({ dbIsLocked: false }); + } + }); + }); + + } // onSubmit @@ -814,7 +866,7 @@ class EdgeEditor extends UNISYS.Component {   + >{this.state.isEditable ? "Add New Edge" : "Edit Edge"}  + From 84a2e2b230097494dd7e32fad3197f216d02bf5c Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 29 Jan 2019 09:54:42 -0800 Subject: [PATCH 2/3] dev-bl/edit-edge-lock: Rename `sourceNodeIsLocked' to 'dbIsLocked' --- .../netcreate/components/NodeSelector.jsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/build/app/view/netcreate/components/NodeSelector.jsx b/build/app/view/netcreate/components/NodeSelector.jsx index 9951708c8..e189da6be 100644 --- a/build/app/view/netcreate/components/NodeSelector.jsx +++ b/build/app/view/netcreate/components/NodeSelector.jsx @@ -58,9 +58,9 @@ isEditable If true, form fields are enabled for editing If false, form is readonly - sourceNodeIsLocked + dbIsLocked If someone else has selected the node for editing, - this flag will cause the sourceNodeIsLockedMessage + this flag will cause the dbIsLockedMessage to be displayed. This is only checked when the user clicks "Edit". @@ -151,7 +151,7 @@ class NodeSelector extends UNISYS.Component { edges: [], isLocked: true, edgesAreLocked: false, - sourceNodeIsLocked: false, + dbIsLocked: false, isEditable: false, isValid: false, isDuplicateNodeLabel: false, @@ -269,7 +269,7 @@ class NodeSelector extends UNISYS.Component { isNewNode: true }, edges: [], - sourceNodeIsLocked: false, + dbIsLocked: false, isEditable: false, isValid: false, isDuplicateNodeLabel: false, @@ -366,7 +366,7 @@ class NodeSelector extends UNISYS.Component { // * force exit? // * prevent load? // * prevent selection? - if (DBG) console.error('NodeSelector: Already editing, ignoring SELECTION'); + if (DBG) console.log('NodeSelector: Already editing, ignoring SELECTION'); } this.validateForm(); @@ -453,7 +453,7 @@ class NodeSelector extends UNISYS.Component { id: node.id, isNewNode: false }, - sourceNodeIsLocked: false, + dbIsLocked: false, isEditable: false, isDuplicateNodeLabel: false }); @@ -590,11 +590,11 @@ class NodeSelector extends UNISYS.Component { .then((data)=>{ if (data.NOP) { console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); - this.setState({ sourceNodeIsLocked: true }); + this.setState({ dbIsLocked: true }); } else if (data.locked) { console.log(`SERVER SAYS: lock success! you can edit Node ${data.nodeID}`); console.log(`SERVER SAYS: unlock the node after successful DBUPDATE`); - this.setState({ sourceNodeIsLocked: false }); + this.setState({ dbIsLocked: false }); this.editNode(); } }); @@ -664,7 +664,7 @@ class NodeSelector extends UNISYS.Component { console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); } else if (data.unlocked) { console.log(`SERVER SAYS: unlock success! you have released Node ${data.nodeID}`); - this.setState({ sourceNodeIsLocked: false }); + this.setState({ dbIsLocked: false }); } }); } @@ -726,7 +726,7 @@ class NodeSelector extends UNISYS.Component { console.log(`SERVER SAYS: ${data.NOP} ${data.INFO}`); } else if (data.unlocked) { console.log(`SERVER SAYS: unlock success! you have released Node ${data.nodeID}`); - this.setState({ sourceNodeIsLocked: false }); + this.setState({ dbIsLocked: false }); } }); }); @@ -817,7 +817,7 @@ class NodeSelector extends UNISYS.Component { hidden={this.state.isLocked || this.state.isEditable || (this.state.formData.id==='') } onClick={this.onEditButtonClick} >Edit Node - +