From 74dd20f02ed06e25495265bbf997f1229d5842e6 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 4 Feb 2017 04:13:59 +0000 Subject: [PATCH] got topic and synapse creation working --- frontend/src/ConvoAlgo/exampleObject.js | 58 +++++++ frontend/src/ConvoAlgo/index.js | 85 +--------- frontend/src/Metamaps/Cable.js | 33 ++-- frontend/src/Metamaps/Create.js | 9 - frontend/src/Metamaps/Engine.js | 36 ++-- frontend/src/Metamaps/JIT.js | 216 +++--------------------- frontend/src/Metamaps/Mouse.js | 2 +- frontend/src/Metamaps/Synapse.js | 90 ++++------ frontend/src/Metamaps/Topic.js | 115 +++++-------- frontend/src/patched/JIT.js | 1 + 10 files changed, 189 insertions(+), 456 deletions(-) create mode 100644 frontend/src/ConvoAlgo/exampleObject.js diff --git a/frontend/src/ConvoAlgo/exampleObject.js b/frontend/src/ConvoAlgo/exampleObject.js new file mode 100644 index 00000000..0f84380b --- /dev/null +++ b/frontend/src/ConvoAlgo/exampleObject.js @@ -0,0 +1,58 @@ + +// if we've placed a node into an island, we need to NOT place it in any other islands +// Every node should only appear in one island + +// the top level array represents islands +// every island has some sort of 'focal' node +/* +var example = [ + // the island that contains the focal node + { + id: 21, + parents: [ + { + id: 25, + parents: [] + }, + { + id: 25, + parents: [] + } + ], + children: [{ + id: 26, + children: [] + }] + }, + // all other islands should not contain children on the top level node + { + id: 21, + // parents may contain children + parents: [ + { + id: 100, + parents: [ + { + id: 101, + parents: [], + children: [ + { + id: 103, + children: [] + } + ] + } + ] + }, + { + id: 102, + parents: [] + } + ] + }, + { + id: 21, + parents: [] + }, +] +*/ \ No newline at end of file diff --git a/frontend/src/ConvoAlgo/index.js b/frontend/src/ConvoAlgo/index.js index fba57dc2..0d1d3288 100644 --- a/frontend/src/ConvoAlgo/index.js +++ b/frontend/src/ConvoAlgo/index.js @@ -1,10 +1,5 @@ import { findIndex, orderBy } from 'lodash' -// an array of synapses -// an array of topics - -// a focal node - /* step 1 generate an object/array that represents the intended layout @@ -13,18 +8,16 @@ generate an object/array that represents the intended layout step 2 generate x,y coordinates for every topic in the layout object -step 3 -set end states for every topic - -Step 4 -animate */ -// synapses = [{ topic1_id: 4, topic2_id: 5, direction: 'from-to' }] +// synapses = [{ topic1_id: 4, topic2_id: 5, direction: 'from-to', desc: 'has reply' }] const isEven = n => n % 2 === 0 const isOdd = n => Math.abs(n % 2) === 1 +export const X_GRID_SPACE = 250 +export const Y_GRID_SPACE = 200 +export const ISLAND_SPACING = 300 export const generateLayoutObject = (topics, synapses, focalTopicId) => { let layout = [] // will be the final output @@ -102,9 +95,6 @@ export const generateLayoutObject = (topics, synapses, focalTopicId) => { export const generateObjectCoordinates = (layoutObject, focalTopicId, focalCoords) => { const coords = {} - const X_GRID_SPACE = 250 - const Y_GRID_SPACE = 200 - const ISLAND_SPACING = 300 const traverseIsland = (island, func, parent, child) => { func(island, parent, child) @@ -165,8 +155,6 @@ export const generateObjectCoordinates = (layoutObject, focalTopicId, focalCoord coords[topic.id] = pos } - - // lay all of them out as if there were no other ones layoutObject.forEach((island, index) => { const tempPosStore = {} @@ -226,67 +214,4 @@ export const generateObjectCoordinates = (layoutObject, focalTopicId, focalCoord export const getLayoutForData = (topics, synapses, focalTopicId, focalCoords) => { return generateObjectCoordinates(generateLayoutObject(topics, synapses, focalTopicId), focalTopicId, focalCoords) -} - - - -// if we've placed a node into an island, we need to NOT place it in any other islands -// Every node should only appear in one island - -// the pseudo-focal node - - -// the top level array represents islands -// every island has some sort of 'focal' node -/* -var example = [ - // the island that contains the focal node - { - id: 21, - parents: [ - { - id: 25, - parents: [] - }, - { - id: 25, - parents: [] - } - ], - children: [{ - id: 26, - children: [] - }] - }, - // all other islands should not contain children on the top level node - { - id: 21, - // parents may contain children - parents: [ - { - id: 100, - parents: [ - { - id: 101, - parents: [], - children: [ - { - id: 103, - children: [] - } - ] - } - ] - }, - { - id: 102, - parents: [] - } - ] - }, - { - id: 21, - parents: [] - }, -] -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/frontend/src/Metamaps/Cable.js b/frontend/src/Metamaps/Cable.js index 0c4a4680..ffeb9ffb 100644 --- a/frontend/src/Metamaps/Cable.js +++ b/frontend/src/Metamaps/Cable.js @@ -46,16 +46,13 @@ const Cable = { var topic1, topic2, node1, node2, synapse, mapping, cancel, mapper function waitThenRenderSynapse() { - if (synapse && mapping && mapper) { + if (synapse && mapping && mapper && synapse.getTopic1() && synapse.getTopic2()) { topic1 = synapse.getTopic1() node1 = topic1.get('node') topic2 = synapse.getTopic2() node2 = topic2.get('node') - - Synapse.renderSynapse(mapping, synapse, node1, node2, false) - if (Create.newSynapse.focusNode === node1) { - Engine.setFocusNode(node2) - } + Synapse.renderSynapse(mapping, synapse, node1, node2, true) + Engine.runLayout() } else if (!cancel) { setTimeout(waitThenRenderSynapse, 10) } @@ -122,6 +119,7 @@ const Cable = { } DataModel.Synapses.remove(synapse) DataModel.Mappings.remove(mapping) + Engine.runLayout() } }, topicAdded: event => { @@ -130,19 +128,19 @@ const Cable = { // containing only the information we need to determine whether the active mapper // can view this topic, then if we determine it can, we make a call for the full model const t = new DataModel.Topic(event.topic) + + // refactor the heck outta this, its adding wicked wait time + var topic, mapping, mapper, cancel + function waitThenRenderTopic() { + if (topic && mapping && mapper) { + Topic.renderTopic(mapping, topic, true) + Engine.runLayout() + } else if (!cancel) { + setTimeout(waitThenRenderTopic, 10) + } + } if (t.authorizeToShow(m) && !DataModel.Topics.get(event.topic.id)) { - // refactor the heck outta this, its adding wicked wait time - var topic, mapping, mapper, cancel - - function waitThenRenderTopic() { - if (topic && mapping && mapper) { - Topic.renderTopic(mapping, topic, false) - } else if (!cancel) { - setTimeout(waitThenRenderTopic, 10) - } - } - mapper = DataModel.Mappers.get(event.topic.user_id) if (mapper === undefined) { Mapper.get(event.topic.user_id, function(m) { @@ -206,6 +204,7 @@ const Cable = { Control.hideNode(node.id) DataModel.Topics.remove(topic) DataModel.Mappings.remove(mapping) + Engine.runLayout() } }, messageCreated: event => { diff --git a/frontend/src/Metamaps/Create.js b/frontend/src/Metamaps/Create.js index 05144bc0..29877cf0 100644 --- a/frontend/src/Metamaps/Create.js +++ b/frontend/src/Metamaps/Create.js @@ -407,15 +407,6 @@ console.log(codesToSwitchToIds) if (Visualize.mGraph) Visualize.mGraph.plot() }, updateForm: function() { - // set the draw synapse start positions - Mouse.synapseStartCoordinates = [] - for (let i = Selected.Nodes.length - 1; i >= 0; i -= 1) { - const n = Selected.Nodes[i] - Mouse.synapseStartCoordinates.push({ - x: n.pos.getc().x, - y: n.pos.getc().y - }) - } let pixelPos, midpoint = {} if (Create.newSynapse.beingCreated) { Mouse.synapseEndCoordinates = { diff --git a/frontend/src/Metamaps/Engine.js b/frontend/src/Metamaps/Engine.js index 77c9c9a4..dde2e022 100644 --- a/frontend/src/Metamaps/Engine.js +++ b/frontend/src/Metamaps/Engine.js @@ -2,7 +2,7 @@ import { last, sortBy, values } from 'lodash' import $jit from '../patched/JIT' -import { getLayoutForData } from '../ConvoAlgo' +import { getLayoutForData, X_GRID_SPACE } from '../ConvoAlgo' import Active from './Active' import Create from './Create' @@ -26,52 +26,42 @@ const Engine = { }, runLayout: init => { + Visualize.mGraph.busy = true const synapses = DataModel.Synapses.map(s => s.attributes) const topics = DataModel.Topics.map(t => t.attributes) const focalNodeId = Create.newSynapse.focusNode.getData('topic').id const focalCoords = init ? { x: 0, y: 0 } : Create.newSynapse.focusNode.pos const layout = getLayoutForData(topics, synapses, focalNodeId, focalCoords) Visualize.mGraph.graph.eachNode(n => { - let calculatedCoords = layout[n.id] - if (!calculatedCoords) { - calculatedCoords = {x: 0, y: 0} - } + let calculatedCoords = layout[n.getData('topic').id] const endPos = new $jit.Complex(calculatedCoords.x, calculatedCoords.y) n.setPos(endPos, 'end') }) Visualize.mGraph.animate({ modes: ['linear'], - transition: $jit.Trans.Elastic.easeOut, - duration: 200, - onComplete: () => {} + transition: $jit.Trans.Quart.easeOut, + duration: 500, + onComplete: () => { + Visualize.mGraph.busy = false + Create.newSynapse.updateForm() + Create.newTopic.position() + } }) }, - addNode: node => { - //Engine.runLayout() - }, - removeNode: node => { - //Engine.runLayout() - }, findFocusNode: nodes => { return last(sortBy(values(nodes), n => new Date(n.getData('topic').get('created_at')))) }, - setFocusNode: (node, init) => { + setFocusNode: (node, init, dontRun) => { if (!Active.Mapper) return Create.newSynapse.focusNode = node Mouse.focusNodeCoords = node.pos Mouse.newNodeCoords = { - x: node.pos.x + 200, + x: node.pos.x + X_GRID_SPACE, y: node.pos.y } Create.newSynapse.updateForm() Create.newTopic.position() - Engine.runLayout(init) - }, - addEdge: edge => { - Engine.runLayout() - }, - removeEdge: edge => { - //Engine.runLayout() + if (!dontRun) Engine.runLayout(init) } } diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 0364f0a8..a302f3d6 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -687,6 +687,10 @@ const JIT = { onMouseMoveHandler: function(_node, eventInfo, e) { const self = JIT + if (Mouse.synapseStartCoordinates.length) { + Visualize.mGraph.plot() + } + if (Visualize.mGraph.busy) return const node = eventInfo.getNode() @@ -743,113 +747,21 @@ const JIT = { self.handleSelectionBeforeDragging(node, e) const pos = eventInfo.getPos() - const EDGE_THICKNESS = 30 - const SHIFT = 2 / Visualize.mGraph.canvas.scaleOffsetX - const PERIOD = 5 - - // self.virtualPointer = pos; - - // if it's a left click, or a touch, move the node - if (e.touches || (e.button === 0 && !e.altKey && !e.ctrlKey && (e.buttons === 0 || e.buttons === 1 || e.buttons === undefined))) { - const width = Visualize.mGraph.canvas.getSize().width - const height = Visualize.mGraph.canvas.getSize().height - const xPix = Util.coordsToPixels(Visualize.mGraph, pos).x - const yPix = Util.coordsToPixels(Visualize.mGraph, pos).y - - if (self.dragFlag === 0) { - self.mouseDownPix = Util.coordsToPixels(Visualize.mGraph, eventInfo.getPos()) - self.dragFlag = 1 - } - - if (Util.getDistance(Util.coordsToPixels(Visualize.mGraph, pos), self.mouseDownPix) > 2 && !self.dragTolerance) { - self.dragTolerance = 1 - } - - if (xPix < EDGE_THICKNESS && self.dragTolerance) { - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - self.virtualPointer = { x: Util.pixelsToCoords(Visualize.mGraph, { x: EDGE_THICKNESS, y: yPix }).x - SHIFT, y: pos.y } - Visualize.mGraph.canvas.translate(SHIFT, 0) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - - self.dragLeftEdge = setInterval(function() { - self.virtualPointer = { x: Util.pixelsToCoords(Visualize.mGraph, { x: EDGE_THICKNESS, y: yPix }).x - SHIFT, y: pos.y } - Visualize.mGraph.canvas.translate(SHIFT, 0) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - }, PERIOD) - } - if (width - xPix < EDGE_THICKNESS && self.dragTolerance) { - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - self.virtualPointer = { x: Util.pixelsToCoords(Visualize.mGraph, { x: width - EDGE_THICKNESS, y: yPix }).x + SHIFT, y: pos.y } - Visualize.mGraph.canvas.translate(-SHIFT, 0) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - - self.dragRightEdge = setInterval(function() { - self.virtualPointer = { x: Util.pixelsToCoords(Visualize.mGraph, { x: width - EDGE_THICKNESS, y: yPix }).x + SHIFT, y: pos.y } - Visualize.mGraph.canvas.translate(-SHIFT, 0) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - }, PERIOD) - } - if (yPix < EDGE_THICKNESS && self.dragTolerance) { - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - self.virtualPointer = { x: pos.x, y: Util.pixelsToCoords(Visualize.mGraph, { x: xPix, y: EDGE_THICKNESS }).y - SHIFT } - Visualize.mGraph.canvas.translate(0, SHIFT) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - - self.dragTopEdge = setInterval(function() { - self.virtualPointer = { x: pos.x, y: Util.pixelsToCoords(Visualize.mGraph, { x: xPix, y: EDGE_THICKNESS }).y - SHIFT } - Visualize.mGraph.canvas.translate(0, SHIFT) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - }, PERIOD) - } - if (height - yPix < EDGE_THICKNESS && self.dragTolerance) { - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - self.virtualPointer = { x: pos.x, y: Util.pixelsToCoords(Visualize.mGraph, { x: xPix, y: height - EDGE_THICKNESS }).y + SHIFT } - Visualize.mGraph.canvas.translate(0, -SHIFT) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - - self.dragBottomEdge = setInterval(function() { - self.virtualPointer = { x: pos.x, y: Util.pixelsToCoords(Visualize.mGraph, { x: xPix, y: height - EDGE_THICKNESS }).y + SHIFT } - Visualize.mGraph.canvas.translate(0, -SHIFT) - self.updateTopicPositions(node, self.virtualPointer) - Visualize.mGraph.plot() - }, PERIOD) - } - - if (xPix >= EDGE_THICKNESS && width - xPix >= EDGE_THICKNESS && yPix >= EDGE_THICKNESS && height - yPix >= EDGE_THICKNESS) { - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - - self.updateTopicPositions(node, pos) - Visualize.mGraph.plot() - } - } else if ((e.button === 2 || (e.button === 0 && e.altKey) || e.buttons === 2) && authorized) { - // if it's a right click or holding down alt, start synapse creation ->third option is for firefox + if ((e.button === 0 || e.buttons === 0) && authorized) { + // start synapse creation ->second option is for firefox if (JIT.tempInit === false) { JIT.tempNode = node JIT.tempInit = true - Create.newSynapse.hide() + // set the draw synapse start positions + Mouse.synapseStartCoordinates = [] + for (let i = Selected.Nodes.length - 1; i >= 0; i -= 1) { + const n = Selected.Nodes[i] + Mouse.synapseStartCoordinates.push({ + x: n.pos.getc().x, + y: n.pos.getc().y + }) + } Mouse.synapseEndCoordinates = { x: pos.x, y: pos.y @@ -859,33 +771,25 @@ const JIT = { let temp = eventInfo.getNode() if (temp !== false && temp.id !== node.id && Selected.Nodes.indexOf(temp) === -1) { // this means a Node has been returned JIT.tempNode2 = temp - Mouse.synapseEndCoordinates = { x: JIT.tempNode2.pos.getc().x, y: JIT.tempNode2.pos.getc().y } - // before making the highlighted one bigger, make sure all the others are regular size Visualize.mGraph.graph.eachNode(function(n) { n.setData('dim', 25, 'current') }) temp.setData('dim', 35, 'current') - Visualize.mGraph.plot() } else if (!temp) { JIT.tempNode2 = null - Visualize.mGraph.graph.eachNode(function(n) { - n.setData('dim', 25, 'current') - }) - Visualize.mGraph.plot() Mouse.synapseEndCoordinates = { x: pos.x, y: pos.y } + Visualize.mGraph.graph.eachNode(function(n) { + n.setData('dim', 25, 'current') + }) } - } else if ((e.button === 2 || (e.button === 0 && e.altKey) || e.buttons === 2) && Active.Topic) { - GlobalUI.notifyUser('Cannot create in Topic view.') - } else if ((e.button === 2 || (e.button === 0 && e.altKey) || e.buttons === 2) && !authorized) { - GlobalUI.notifyUser('Cannot edit this map.') } } }, // onDragMoveTopicHandler @@ -905,19 +809,6 @@ const JIT = { let pixelPos let mapping - clearInterval(self.dragLeftEdge) - clearInterval(self.dragRightEdge) - clearInterval(self.dragTopEdge) - clearInterval(self.dragBottomEdge) - - delete self.dragLeftEdge - delete self.dragRightEdge - delete self.dragTopEdge - delete self.dragBottomEdge - - self.dragFlag = 0 - self.dragTolerance = 0 - if (JIT.tempInit && JIT.tempNode2 === null) { Mouse.synapseEndCoordinates = null } else if (JIT.tempInit && JIT.tempNode2 !== null) { @@ -937,35 +828,6 @@ const JIT = { JIT.tempNode = null JIT.tempNode2 = null JIT.tempInit = false - } else if (!JIT.tempInit && node && !node.nodeFrom) { - // this means you dragged an existing node, autosave that to the database - - // check whether to save mappings - const checkWhetherToSave = function() { - const map = Active.Map - if (!map) return false - return map.authorizeToEdit(Active.Mapper) - } - - if (checkWhetherToSave()) { - mapping = node.getData('mapping') - mapping.save({ - xloc: node.getPos().x, - yloc: node.getPos().y - }) - // also save any other selected nodes that also got dragged along - const l = Selected.Nodes.length - for (var i = l - 1; i >= 0; i -= 1) { - const n = Selected.Nodes[i] - if (n !== node) { - mapping = n.getData('mapping') - mapping.save({ - xloc: n.getPos().x, - yloc: n.getPos().y - }) - } - } - } } }, // onDragEndTopicHandler canvasClickHandler: function(canvasLoc, e) { @@ -1257,43 +1119,19 @@ const JIT = { // wait a certain length of time, then check again, then run this code setTimeout(function() { if (!JIT.nodeWasDoubleClicked()) { - var nodeAlreadySelected = node.selected + if (e.button === 1 && !e.ctrlKey) { + var len = Selected.Nodes.length - if (e.button !== 1) { - if (!e.shiftKey) { - Control.deselectAllNodes() - Control.deselectAllEdges() - } + for (let i = 0; i < len; i += 1) { + let n = Selected.Nodes[i] + let result = Util.openLink(DataModel.Topics.get(n.id).attributes.link) - if (nodeAlreadySelected) { - Control.deselectNode(node) - } else { - Control.selectNode(node, e) - } - - // trigger animation to final styles - Visualize.mGraph.fx.animate({ - modes: ['edge-property:lineWidth:color:alpha'], - duration: 500 - }) - Visualize.mGraph.plot() - } else { - if (!e.ctrlKey) { - var len = Selected.Nodes.length - - for (let i = 0; i < len; i += 1) { - let n = Selected.Nodes[i] - let result = Util.openLink(DataModel.Topics.get(n.id).attributes.link) - - if (!result) { // if link failed to open - break - } - } - - if (!node.selected) { - Util.openLink(DataModel.Topics.get(node.id).attributes.link) + if (!result) { // if link failed to open + break } } + + if (!node.selected) Util.openLink(DataModel.Topics.get(node.id).attributes.link) } } }, Mouse.DOUBLE_CLICK_TOLERANCE) diff --git a/frontend/src/Metamaps/Mouse.js b/frontend/src/Metamaps/Mouse.js index b6c07ef8..2aac0135 100644 --- a/frontend/src/Metamaps/Mouse.js +++ b/frontend/src/Metamaps/Mouse.js @@ -12,7 +12,7 @@ const Mouse = { synapseEndCoordinates: null, lastNodeClick: 0, lastCanvasClick: 0, - DOUBLE_CLICK_TOLERANCE: 300 + DOUBLE_CLICK_TOLERANCE: 501 } export default Mouse diff --git a/frontend/src/Metamaps/Synapse.js b/frontend/src/Metamaps/Synapse.js index 2fd1b25c..6ce443d8 100644 --- a/frontend/src/Metamaps/Synapse.js +++ b/frontend/src/Metamaps/Synapse.js @@ -29,83 +29,52 @@ const Synapse = { } else callback(DataModel.Synapses.get(id)) }, - renderSynapse: function(mapping, synapse, node1, node2, createNewInDB, alreadyAdded) { - var edgeOnViz - var newedge - - if (!alreadyAdded) { - newedge = synapse.createEdge(mapping) - Visualize.mGraph.graph.addAdjacence(node1, node2, newedge.data) - } - edgeOnViz = Visualize.mGraph.graph.getAdjacence(node1.id, node2.id) - if (!alreadyAdded) { - Engine.addEdge(edgeOnViz) - } + renderSynapse: function(mapping, synapse, node1, node2, fromRemote) { + const newedge = synapse.createEdge(mapping) + Visualize.mGraph.graph.addAdjacence(node1, node2, newedge.data) + const edgeOnViz = Visualize.mGraph.graph.getAdjacence(node1.id, node2.id) synapse.set('edge', edgeOnViz) synapse.updateEdge() // links the synapse and the mapping to the edge - - //Control.selectEdge(edgeOnViz) - - var synapseSuccessCallback = function(synapseModel, response) { - if (Active.Map) { - mapping.save({ mappable_id: synapseModel.id }) - } - } - - if (createNewInDB) { - if (synapse.isNew()) { - synapse.save(null, { - success: synapseSuccessCallback - }) - } else if (!synapse.isNew() && Active.Map) { - mapping.save(null) - } + if (!fromRemote && synapse.isNew()) { + synapse.save(null, { + success: synapseModel => Active.Map && mapping.save({ mappable_id: synapseModel.id }) + }) + } else if (!fromRemote && !synapse.isNew() && Active.Map) { + mapping.save() } }, - createSynapseLocally: function(alreadyAdded, topic1id, topic2id) { + createSynapseLocally: function(topic1id, topic2id, manual) { var self = Synapse - let topic1 - let topic2 - let node1 - let node2 - let synapse - let mapping $(document).trigger(Map.events.editedByActiveMapper) // for each node in this array we will create a synapse going to the position2 node. - var synapsesToCreate = [] - if (alreadyAdded) { - topic2 = DataModel.Topics.get(topic2id) - node2 = topic2.get('node') - topic1 = DataModel.Topics.get(topic1id) - synapsesToCreate[0] = topic1.get('node') - } - else { - topic2 = DataModel.Topics.get(Create.newSynapse.topic2id) - node2 = topic2.get('node') - if (Selected.Nodes.length === 0) { - topic1 = DataModel.Topics.get(Create.newSynapse.topic1id) - synapsesToCreate[0] = topic1.get('node') - } else { - synapsesToCreate = Selected.Nodes - } + const synapsesToCreate = [] + const topic2 = DataModel.Topics.get(topic2id) + const node2 = topic2.get('node') + if (Selected.Nodes.length === 0) { + synapsesToCreate.push(DataModel.Topics.get(topic1id).get('node')) + } else { + synapsesToCreate.concat(Selected.Nodes) } synapsesToCreate.forEach(node1 => { - topic1 = node1.getData('topic') - synapse = new DataModel.Synapse({ + const topic1 = node1.getData('topic') + const synapse = new DataModel.Synapse({ desc: Create.newSynapse.description || '', - topic1_id: topic1.isNew() ? topic1.cid : topic1.id, - topic2_id: topic2.isNew() ? topic2.cid : topic2.id + topic1_id: topic1.id, + topic2_id: topic2.id }) DataModel.Synapses.add(synapse) - mapping = new DataModel.Mapping({ + const mapping = new DataModel.Mapping({ mappable_type: 'Synapse', mappable_id: synapse.cid }) DataModel.Mappings.add(mapping) // this function also includes the creation of the synapse in the database - self.renderSynapse(mapping, synapse, node1, node2, true, alreadyAdded) + self.renderSynapse(mapping, synapse, node1, node2) }) // for each in synapsesToCreate - Create.newSynapse.hide() + if (manual) { + Engine.runLayout() + Create.newSynapse.hide() + } }, getSynapseFromAutocomplete: function(id) { var self = Synapse @@ -121,7 +90,8 @@ const Synapse = { const topic2 = DataModel.Topics.get(Create.newSynapse.topic2id) const node2 = topic2.get('node') Create.newSynapse.hide() - self.renderSynapse(mapping, synapse, node1, node2, true) + self.renderSynapse(mapping, synapse, node1, node2) + Engine.runLayout() }) } } diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index d195b58d..7d5f1644 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -168,99 +168,66 @@ const Topic = { }) }, - renderTopic: function(mapping, topic, createNewInDB) { - var nodeOnViz - var newnode = topic.createNode() - const createSynapse = !!Create.newSynapse.focusNode && createNewInDB + renderTopic: function(mapping, topic, fromRemote) { + let nodeOnViz + const newnode = topic.createNode() + const createSynapse = !!Create.newSynapse.focusNode && !fromRemote const connectToId = createSynapse ? Create.newSynapse.focusNode.getData('topic').id : null - if (!$.isEmptyObject(Visualize.mGraph.graph.nodes)) { - // this will also add the new node - if (createSynapse) Visualize.mGraph.graph.addAdjacence(Create.newSynapse.focusNode, newnode) - else Visualize.mGraph.graph.addNode(newnode) - nodeOnViz = Visualize.mGraph.graph.getNode(newnode.id) - Engine.addNode(nodeOnViz) - if (createSynapse) Engine.addEdge(Visualize.mGraph.graph.getAdjacence(Create.newSynapse.focusNode.id, nodeOnViz.id)) - topic.set('node', nodeOnViz, {silent: true}) - topic.updateNode() // links the topic and the mapping to the node - if (createNewInDB) Engine.setFocusNode(nodeOnViz) // means this user created it - nodeOnViz.setData('dim', 1, 'start') - nodeOnViz.setData('dim', 25, 'end') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'current') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'start') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') - Visualize.mGraph.fx.animate({ - modes: ['node-property:dim'], - duration: 500 - }) + Visualize.mGraph.graph.addNode(newnode) } else { - Engine.run() Visualize.mGraph.loadJSON(newnode) - nodeOnViz = Visualize.mGraph.graph.getNode(newnode.id) - Engine.addNode(nodeOnViz) - topic.set('node', nodeOnViz, {silent: true}) - topic.updateNode() // links the topic and the mapping to the node - Engine.setFocusNode(nodeOnViz) - nodeOnViz.setData('dim', 1, 'start') - nodeOnViz.setData('dim', 25, 'end') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'current') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'start') - nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') - Visualize.mGraph.fx.plotNode(nodeOnViz, Visualize.mGraph.canvas) - Visualize.mGraph.fx.animate({ - modes: ['node-property:dim'], - duration: 500 + } + nodeOnViz = Visualize.mGraph.graph.getNode(newnode.id) + topic.set('node', nodeOnViz, {silent: true}) + topic.updateNode() // links the topic and the mapping to the node + nodeOnViz.setData('dim', 1, 'start') + nodeOnViz.setData('dim', 25, 'end') + nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'current') + nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'start') + nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') + Visualize.mGraph.fx.plotNode(nodeOnViz, Visualize.mGraph.canvas) + Visualize.mGraph.fx.animate({ + modes: ['node-property:dim'], + duration: 200 + }) + if (!fromRemote && topic.isNew()) { + topic.save(null, { + success: topicModel => { + Active.Map && mapping.save({ mappable_id: topicModel.id }) + createSynapse && Synapse.createSynapseLocally(connectToId, topicModel.id) + } }) - } - - var topicSuccessCallback = function(topicModel, response) { - if (Active.Map) { - mapping.save({ mappable_id: topicModel.id }) - } - createSynapse && Synapse.createSynapseLocally(true, connectToId, topicModel.id) - } - - if (createNewInDB) { - if (topic.isNew()) { - topic.save(null, { - success: topicSuccessCallback - }) - } else if (!topic.isNew() && Active.Map) { - mapping.save(null) - } + } else if (!fromRemote && !topic.isNew()) { + Active.Map && mapping.save() + createSynapse && Synapse.createSynapseLocally(connectToId, topic.id) } }, createTopicLocally: function() { var self = Topic - if (Create.newTopic.name === '') { GlobalUI.notifyUser('Please enter a topic title...') return } - $(document).trigger(Map.events.editedByActiveMapper) - var metacode = DataModel.Metacodes.get(Create.newTopic.metacode) - var topic = new DataModel.Topic({ name: Create.newTopic.name, metacode_id: metacode.id, defer_to_map_id: Active.Map.id }) DataModel.Topics.add(topic) - var mapping = new DataModel.Mapping({ - xloc: Mouse.newNodeCoords.x, + xloc: Mouse.newNodeCoords.x, yloc: Mouse.newNodeCoords.y, mappable_id: topic.cid, mappable_type: 'Topic' }) DataModel.Mappings.add(mapping) - - // these can't happen until the value is retrieved, which happens in the line above + // these can't happen until the new topic values are retrieved Create.newTopic.reset() - - self.renderTopic(mapping, topic, true) // this function also includes the creation of the topic in the database + self.renderTopic(mapping, topic) + Engine.setFocusNode(topic.get('node'), false, true) }, getTopicFromAutocomplete: function(id) { var self = Topic @@ -274,14 +241,13 @@ const Topic = { mappable_id: topic.id }) DataModel.Mappings.add(mapping) - self.renderTopic(mapping, topic, true) + self.renderTopic(mapping, topic) + Engine.setFocusNode(topic.get('node'), false, true) }) }, getMapFromAutocomplete: function(data) { var self = Topic - $(document).trigger(Map.events.editedByActiveMapper) - var metacode = DataModel.Metacodes.findWhere({ name: 'Metamap' }) var topic = new DataModel.Topic({ name: data.name, @@ -290,7 +256,6 @@ const Topic = { link: window.location.origin + '/maps/' + data.id }) DataModel.Topics.add(topic) - var mapping = new DataModel.Mapping({ xloc: Mouse.newNodeCoords.x, yloc: Mouse.newNodeCoords.y, @@ -298,17 +263,13 @@ const Topic = { mappable_type: 'Topic' }) DataModel.Mappings.add(mapping) - - // these can't happen until the value is retrieved, which happens in the line above Create.newTopic.reset() - - self.renderTopic(mapping, topic, true) // this function also includes the creation of the topic in the database + self.renderTopic(mapping, topic) + Engine.setFocusNode(topic.get('node'), false, true) }, getTopicFromSearch: function(event, id) { var self = Topic - $(document).trigger(Map.events.editedByActiveMapper) - self.get(id, (topic) => { var nextCoords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings }) var mapping = new DataModel.Mapping({ @@ -318,10 +279,10 @@ const Topic = { mappable_id: topic.id }) DataModel.Mappings.add(mapping) - self.renderTopic(mapping, topic, true) + self.renderTopic(mapping, topic) + Engine.runLayout() GlobalUI.notifyUser('Topic was added to your map') }) - event.stopPropagation() event.preventDefault() return false diff --git a/frontend/src/patched/JIT.js b/frontend/src/patched/JIT.js index 99d9fd93..4675d4d9 100644 --- a/frontend/src/patched/JIT.js +++ b/frontend/src/patched/JIT.js @@ -2564,6 +2564,7 @@ Extras.Classes.Navigation = new Class({ x: eventInfo.getPos().x, y: eventInfo.getPos().y } + Metamaps.Visualize.mGraph.plot() //console.log('mouse move'); return; }