From b321c763909e2519c7a4b9e113a9f482fc6eb5ab Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 7 Feb 2016 16:56:03 +0800 Subject: [PATCH 1/6] bare minimum topic import functionality - use by Ctrl+V onto the map canvas itself --- app/assets/javascripts/application.js | 3 +- .../javascripts/src/Metamaps.Import.js.erb | 104 ++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/src/Metamaps.Import.js.erb diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index e0fad224..2d2ead0d 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -22,7 +22,8 @@ //= require ./src/Metamaps.Views //= require ./src/JIT //= require ./src/Metamaps +//= require ./src/Metamaps.Import //= require ./src/Metamaps.JIT //= require_directory ./shims //= require_directory ./require -//= require_directory ./famous \ No newline at end of file +//= require_directory ./famous diff --git a/app/assets/javascripts/src/Metamaps.Import.js.erb b/app/assets/javascripts/src/Metamaps.Import.js.erb new file mode 100644 index 00000000..d17077ae --- /dev/null +++ b/app/assets/javascripts/src/Metamaps.Import.js.erb @@ -0,0 +1,104 @@ +/* + * Example tab-separated input: + * Some fields will be ignored + * + * id name metacode desc link user.name permission synapses + * 1 topic1 Catalyst admin commons 1->7 + * 2 topic2 Event admin commons + * 5 topic Action admin commons + * 6 topic6 Action admin commons 6->7 + * 7 topic7 Action admin commons 7->8 7<-6 7<-1 + * 8 topic8 Action admin commons 8<-7 + */ + +Metamaps.Import = { + headersWhitelist: [ + 'name', 'metacode', 'desc', 'link', 'permission' + ], + + init: function() { + var self = Metamaps.Import; + $('body').bind('paste', function(e) { + var text = e.originalEvent.clipboardData.getData('text/plain'); + var parsed = self.parseTabbedString(text); + + if (confirm("Are you sure you want to create " + parsed.length + " new topics?")) { + self.importTopics(parsed); + }//if + }); + }, + + importTopics: function(parsedTopics) { + var self = Metamaps.Import; + + var x = -200; + var y = -200; + parsedTopics.forEach(function(topic) { + self.createTopicWithParameters( + topic.name, topic.metacode, topic.permission, + topic.desc, topic.link, x, y + ); + + // update positions of topics + x += 50; + if (x > 200) { + y += 50; + x = -200; + }//if + }); + }, + + parseTabbedString: function(text) { + var self = Metamaps.Import; + + // determine line ending and split lines + var delim = "\n"; + if (text.indexOf("\r\n") !== -1) { + delim = "\r\n"; + }//if + var lines = text.split(delim); + + // get csv-style headers to name the object fields + var headers = lines[0].split(' '); //tab character + + var results = []; + lines.forEach(function(line, index) { + if (index === 0) return; + if (line == "") return; + + var topic = {}; + line.split(" ").forEach(function(field, index) { + if (self.headersWhitelist.indexOf(headers[index]) === -1) return; + topic[headers[index]] = field; + }); + results.push(topic); + }); + return results; + }, + + createTopicWithParameters: function(name, metacode_name, permission, desc, link, xloc, yloc) { + var self = Metamaps.Topic; + + var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null; + if (metacode === null) return console.error("metacode not found"); + + var topic = new Metamaps.Backbone.Topic({ + name: name, + metacode_id: metacode.id, + permission: permission || Metamaps.Active.Map.get('permission'), + desc: desc, + link: link + }); + Metamaps.Topics.add(topic); + + var mapping = new Metamaps.Backbone.Mapping({ + xloc: xloc, + yloc: yloc, + mappable_id: topic.cid, + mappable_type: "Topic", + }); + Metamaps.Mappings.add(mapping); + + self.renderTopic(mapping, topic, true, true); // this function also includes the creation of the topic in the database + }, +}; From 669c3c7e44b5a615a1df437d249313f85cd05d31 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 7 Feb 2016 17:51:01 +0800 Subject: [PATCH 2/6] don't ask about adding 0 topics --- app/assets/javascripts/src/Metamaps.Import.js.erb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.Import.js.erb b/app/assets/javascripts/src/Metamaps.Import.js.erb index d17077ae..14612247 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js.erb +++ b/app/assets/javascripts/src/Metamaps.Import.js.erb @@ -22,7 +22,9 @@ Metamaps.Import = { var text = e.originalEvent.clipboardData.getData('text/plain'); var parsed = self.parseTabbedString(text); - if (confirm("Are you sure you want to create " + parsed.length + " new topics?")) { + if (parsed.length > 0 && + confirm("Are you sure you want to create " + parsed.length + + " new topics?")) { self.importTopics(parsed); }//if }); @@ -76,7 +78,8 @@ Metamaps.Import = { return results; }, - createTopicWithParameters: function(name, metacode_name, permission, desc, link, xloc, yloc) { + createTopicWithParameters: function(name, metacode_name, permission, desc, + link, xloc, yloc) { var self = Metamaps.Topic; var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null; @@ -99,6 +102,7 @@ Metamaps.Import = { }); Metamaps.Mappings.add(mapping); - self.renderTopic(mapping, topic, true, true); // this function also includes the creation of the topic in the database + // this function also includes the creation of the topic in the database + self.renderTopic(mapping, topic, true, true); }, }; From 85e9486b50928f2059690deaaf0cee5bd8fb01ae Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 14 Feb 2016 22:39:29 +0800 Subject: [PATCH 3/6] use state machine to implement smarter topic/synapse import also include better auto-layout of new topics if x/y not specified --- .../javascripts/src/Metamaps.Import.js.erb | 237 ++++++++++++++---- 1 file changed, 194 insertions(+), 43 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.Import.js.erb b/app/assets/javascripts/src/Metamaps.Import.js.erb index 14612247..b604e970 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js.erb +++ b/app/assets/javascripts/src/Metamaps.Import.js.erb @@ -12,42 +12,34 @@ */ Metamaps.Import = { - headersWhitelist: [ - 'name', 'metacode', 'desc', 'link', 'permission' + topicWhitelist: [ + 'name', 'metacode', 'description', 'link', 'permission' ], + synapseWhitelist: [ + 'desc', 'description', 'category', 'topic1', 'topic2', 'permission' + ], init: function() { var self = Metamaps.Import; $('body').bind('paste', function(e) { var text = e.originalEvent.clipboardData.getData('text/plain'); - var parsed = self.parseTabbedString(text); - if (parsed.length > 0 && - confirm("Are you sure you want to create " + parsed.length + - " new topics?")) { - self.importTopics(parsed); + var results = self.parseTabbedString(text); + var topics = results.topics; + var synapses = results.synapses; + + if (topics.length > 0 || synapses.length > 0) { + if (confirm("Are you sure you want to create " + topics.length + + " new topics and " + synapses.length + " new synapses?")) { + self.importTopics(topics); + self.importSynapses(synapses); + }//if }//if }); }, - importTopics: function(parsedTopics) { - var self = Metamaps.Import; - - var x = -200; - var y = -200; - parsedTopics.forEach(function(topic) { - self.createTopicWithParameters( - topic.name, topic.metacode, topic.permission, - topic.desc, topic.link, x, y - ); - - // update positions of topics - x += 50; - if (x > 200) { - y += 50; - x = -200; - }//if - }); + abort: function(message) { + console.error(message); }, parseTabbedString: function(text) { @@ -58,30 +50,162 @@ Metamaps.Import = { if (text.indexOf("\r\n") !== -1) { delim = "\r\n"; }//if + + var STATES = { + UNKNOWN: 0, + TOPICS_NEED_HEADERS: 1, + SYNAPSES_NEED_HEADERS: 2, + TOPICS: 3, + SYNAPSES: 4, + }; + + // state & lines determine parser behaviour + var state = STATES.UNKNOWN; var lines = text.split(delim); + var results = { topics: [], synapses: [] } + var topicHeaders = []; + var synapseHeaders = []; - // get csv-style headers to name the object fields - var headers = lines[0].split(' '); //tab character - - var results = []; - lines.forEach(function(line, index) { - if (index === 0) return; - if (line == "") return; - - var topic = {}; - line.split(" ").forEach(function(field, index) { - if (self.headersWhitelist.indexOf(headers[index]) === -1) return; - topic[headers[index]] = field; + lines.forEach(function(line_raw, index) { + var line = line_raw.split(' '); // tab character + var noblanks = line.filter(function(elt) { + return elt !== ""; }); - results.push(topic); + switch(state) { + case STATES.UNKNOWN: + if (noblanks.length === 0) { + state = STATES.UNKNOWN; + break; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { + state = STATES.TOPICS_NEED_HEADERS; + break; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { + state = STATES.SYNAPSES_NEED_HEADERS; + break; + } + state = STATES.TOPICS_NEED_HEADERS; + // FALL THROUGH - if we're not sure what to do, pretend + // we're on the TOPICS_NEED_HEADERS state and parse some headers + + case STATES.TOPICS_NEED_HEADERS: + if (noblanks.length < 2) { + return self.abort("Not enough topic headers on line " + index); + } + topicHeaders = line.map(function(header, index) { + return header.toLowerCase().replace('description', 'desc'); + }); + state = STATES.TOPICS; + break; + + case STATES.SYNAPSES_NEED_HEADERS: + if (noblanks.length < 2) { + return self.abort("Not enough synapse headers on line " + index); + } + synapseHeaders = line.map(function(header, index) { + return header.toLowerCase().replace('description', 'desc'); + }); + state = STATES.SYNAPSES; + break; + + case STATES.TOPICS: + if (noblanks.length === 0) { + state = STATES.UNKNOWN; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { + state = STATES.TOPICS_NEED_HEADERS; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { + state = STATES.SYNAPSES_NEED_HEADERS; + } else { + var topic = {}; + line.forEach(function(field, index) { + var header = topicHeaders[index]; + if (self.topicWhitelist.indexOf(header) === -1) return; + topic[header] = field; + if (header === 'x' || header === 'y') { + topic[header] = parseInt(topic[header]); + }//if + }); + results.topics.push(topic); + } + break; + + case STATES.SYNAPSES: + if (noblanks.length === 0) { + state = STATES.UNKNOWN; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { + state = STATES.TOPICS_NEED_HEADERS; + } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { + state = STATES.SYNAPSES_NEED_HEADERS; + } else { + var synapse = {}; + line.forEach(function(field, index) { + var header = synapseHeaders[index]; + if (self.synapseWhitelist.indexOf(header) === -1) return; + synapse[header] = field; + if (header === 'topic1' || header === 'topic2') { + synapse[header] = parseInt(header); + }//if + }); + results.synapses.push(synapse); + } + break; + + default: + return self.abort("Invalid state while parsing import data. " + + "Check code."); + } }); + return results; }, - createTopicWithParameters: function(name, metacode_name, permission, desc, - link, xloc, yloc) { - var self = Metamaps.Topic; + importTopics: function(parsedTopics) { + var self = Metamaps.Import; + + // up to 25 topics: scale 100 + // up to 81 topics: scale 200 + // up to 169 topics: scale 300 + var scale = Math.floor((Math.sqrt(parsedTopics.length) - 1) / 4) * 100; + if (scale < 100) scale = 100; + var autoX = -scale; + var autoY = -scale; + + parsedTopics.forEach(function(topic) { + var x, y; + if (topic.x && topic.y) { + x = topic.x; + y = topic.y; + } else { + x = autoX; + y = autoY; + autoX += 50; + if (autoX > scale) { + autoY += 50; + autoX = -scale; + } + } + + self.createTopicWithParameters( + topic.name, topic.metacode, topic.permission, + topic.desc, topic.link, x, y, topic.id + ); + }); + }, + + importSynapses: function(parsedSynapses) { + var self = Metamaps.Import; + + parsedSynapses.forEach(function(synapse) { + self.createSynapseWithParameters( + synapse.desc, synapse.category, synapse.permission, + synapse.topic1, synapse.topic2 + ); + }); + }, + + createTopicWithParameters: function(name, metacode_name, permission, desc, + link, xloc, yloc, import_id) { + $(document).trigger(Metamaps.Map.events.editedByActiveMapper); var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null; if (metacode === null) return console.error("metacode not found"); @@ -90,7 +214,8 @@ Metamaps.Import = { metacode_id: metacode.id, permission: permission || Metamaps.Active.Map.get('permission'), desc: desc, - link: link + link: link, + import_id: import_id }); Metamaps.Topics.add(topic); @@ -103,6 +228,32 @@ Metamaps.Import = { Metamaps.Mappings.add(mapping); // this function also includes the creation of the topic in the database - self.renderTopic(mapping, topic, true, true); + Metamaps.Topic.renderTopic(mapping, topic, true, true); + + Metamaps.Famous.viz.hideInstructions(); + }, + + createSynapseWithParameters: function(description, category, permission, + node1_id, node2_id) { + var topic1 = Metamaps.Topics.where({import_id: node1_id}); + var topic2 = Metamaps.Topics.where({import_id: node2_id}); + var node1 = topic1.get('node'); + var node2 = topic2.get('node'); + // TODO check if topic1 and topic2 were sucessfully found... + + var synapse = new Metamaps.Backbone.Synapse({ + desc: description, + category: category, + permission: permission, + node1_id: node1_id, + node2_id: node2_id, + }); + + var mapping = new Metamaps.Backbone.Mapping({ + mappable_type: "Synapse", + mappable_id: synapse.cid, + }); + + Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true); }, }; From 7d73da7f7b463cfdffffcd88e17c2a8f499cc6c1 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 21 Feb 2016 16:28:31 +0800 Subject: [PATCH 4/6] import fixes - better abort logic & messaging - handle \r line delim - better example format at top --- .../javascripts/src/Metamaps.Import.js.erb | 64 ++++++++++++++----- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.Import.js.erb b/app/assets/javascripts/src/Metamaps.Import.js.erb index b604e970..8a366560 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js.erb +++ b/app/assets/javascripts/src/Metamaps.Import.js.erb @@ -2,19 +2,30 @@ * Example tab-separated input: * Some fields will be ignored * - * id name metacode desc link user.name permission synapses - * 1 topic1 Catalyst admin commons 1->7 - * 2 topic2 Event admin commons - * 5 topic Action admin commons - * 6 topic6 Action admin commons 6->7 - * 7 topic7 Action admin commons 7->8 7<-6 7<-1 - * 8 topic8 Action admin commons 8<-7 + * Topics + * Id Name Metacode X Y Description Link User Permission + * 8 topic8 Action -231 131 admin commons + * 5 topic Action -229 -131 admin commons + * 7 topic7.1 Action -470 -55 hey admin commons + * 2 topic2 Event -57 -63 admin commons + * 1 topic1 Catalyst -51 50 admin commons + * 6 topic6 Action -425 63 admin commons + * + * Synapses + * Id Description Category Topic1 Topic2 User Permission + * 43 from-to 6 2 admin commons + * 44 from-to 6 1 admin commons + * 45 from-to 6 5 admin commons + * 46 from-to 2 7 admin commons + * 47 from-to 8 6 admin commons + * 48 from-to 8 1 admin commons + * */ Metamaps.Import = { topicWhitelist: [ 'name', 'metacode', 'description', 'link', 'permission' - ], + ], synapseWhitelist: [ 'desc', 'description', 'category', 'topic1', 'topic2', 'permission' ], @@ -25,6 +36,8 @@ Metamaps.Import = { var text = e.originalEvent.clipboardData.getData('text/plain'); var results = self.parseTabbedString(text); + if (results === false) return; + var topics = results.topics; var synapses = results.synapses; @@ -39,9 +52,16 @@ Metamaps.Import = { }, abort: function(message) { + alert("Sorry, something went wrong!\n\n" + message); console.error(message); }, + simplify: function(string) { + return string + .replace(/(^\s*|\s*$)/g, '') + .toLowerCase(); + }, + parseTabbedString: function(text) { var self = Metamaps.Import; @@ -49,9 +69,12 @@ Metamaps.Import = { var delim = "\n"; if (text.indexOf("\r\n") !== -1) { delim = "\r\n"; + } else if (text.indexOf("\r") !== -1) { + delim = "\r"; }//if var STATES = { + ABORT: -1, UNKNOWN: 0, TOPICS_NEED_HEADERS: 1, SYNAPSES_NEED_HEADERS: 2, @@ -67,7 +90,7 @@ Metamaps.Import = { var synapseHeaders = []; lines.forEach(function(line_raw, index) { - var line = line_raw.split(' '); // tab character + var line = line_raw.split("\t"); var noblanks = line.filter(function(elt) { return elt !== ""; }); @@ -76,10 +99,10 @@ Metamaps.Import = { if (noblanks.length === 0) { state = STATES.UNKNOWN; break; - } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { + } else if (noblanks.length === 1 && self.simplify(line[0]) === 'topics') { state = STATES.TOPICS_NEED_HEADERS; break; - } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { + } else if (noblanks.length === 1 && self.simplify(line[0]) === 'synapses') { state = STATES.SYNAPSES_NEED_HEADERS; break; } @@ -89,7 +112,8 @@ Metamaps.Import = { case STATES.TOPICS_NEED_HEADERS: if (noblanks.length < 2) { - return self.abort("Not enough topic headers on line " + index); + self.abort("Not enough topic headers on line " + index); + state = STATES.ABORT; } topicHeaders = line.map(function(header, index) { return header.toLowerCase().replace('description', 'desc'); @@ -99,7 +123,8 @@ Metamaps.Import = { case STATES.SYNAPSES_NEED_HEADERS: if (noblanks.length < 2) { - return self.abort("Not enough synapse headers on line " + index); + self.abort("Not enough synapse headers on line " + index); + state = STATES.ABORT; } synapseHeaders = line.map(function(header, index) { return header.toLowerCase().replace('description', 'desc'); @@ -148,14 +173,19 @@ Metamaps.Import = { results.synapses.push(synapse); } break; - + case STATES.ABORT: + ; default: - return self.abort("Invalid state while parsing import data. " + - "Check code."); + self.abort("Invalid state while parsing import data. Check code."); + state = STATES.ABORT; } }); - return results; + if (state === STATES.ABORT) { + return false; + } else { + return results; + } }, From 1f1cd37553449de4cf6e019f5f00e0014ca0f17b Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 21 Feb 2016 17:02:37 +0800 Subject: [PATCH 5/6] fix a bug with synapses and use cid to link new topics with synapses Synapses are now created client-side, but still rejected server-side --- .../javascripts/src/Metamaps.Import.js.erb | 26 +++++++++++-------- app/assets/javascripts/src/Metamaps.js.erb | 6 ++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.Import.js.erb b/app/assets/javascripts/src/Metamaps.Import.js.erb index 8a366560..8d6b3867 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js.erb +++ b/app/assets/javascripts/src/Metamaps.Import.js.erb @@ -24,11 +24,12 @@ Metamaps.Import = { topicWhitelist: [ - 'name', 'metacode', 'description', 'link', 'permission' + 'id', 'name', 'metacode', 'description', 'link', 'permission' ], synapseWhitelist: [ - 'desc', 'description', 'category', 'topic1', 'topic2', 'permission' + 'id', 'desc', 'description', 'category', 'topic1', 'topic2', 'permission' ], + cidMappings: {}, //to be filled by import_id => cid mappings init: function() { var self = Metamaps.Import; @@ -145,7 +146,7 @@ Metamaps.Import = { var header = topicHeaders[index]; if (self.topicWhitelist.indexOf(header) === -1) return; topic[header] = field; - if (header === 'x' || header === 'y') { + if (['id', 'x', 'y'].indexOf(header) !== -1) { topic[header] = parseInt(topic[header]); }//if }); @@ -166,8 +167,8 @@ Metamaps.Import = { var header = synapseHeaders[index]; if (self.synapseWhitelist.indexOf(header) === -1) return; synapse[header] = field; - if (header === 'topic1' || header === 'topic2') { - synapse[header] = parseInt(header); + if (['id', 'topic1', 'topic2'].indexOf(header) !== -1) { + synapse[header] = parseInt(synapse[header]); }//if }); results.synapses.push(synapse); @@ -235,6 +236,7 @@ Metamaps.Import = { createTopicWithParameters: function(name, metacode_name, permission, desc, link, xloc, yloc, import_id) { + var self = Metamaps.Import; $(document).trigger(Metamaps.Map.events.editedByActiveMapper); var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null; if (metacode === null) return console.error("metacode not found"); @@ -245,9 +247,9 @@ Metamaps.Import = { permission: permission || Metamaps.Active.Map.get('permission'), desc: desc, link: link, - import_id: import_id }); Metamaps.Topics.add(topic); + self.cidMappings[import_id] = topic.cid; var mapping = new Metamaps.Backbone.Mapping({ xloc: xloc, @@ -260,13 +262,15 @@ Metamaps.Import = { // this function also includes the creation of the topic in the database Metamaps.Topic.renderTopic(mapping, topic, true, true); + Metamaps.Famous.viz.hideInstructions(); }, createSynapseWithParameters: function(description, category, permission, node1_id, node2_id) { - var topic1 = Metamaps.Topics.where({import_id: node1_id}); - var topic2 = Metamaps.Topics.where({import_id: node2_id}); + var self = Metamaps.Import; + var topic1 = Metamaps.Topics.get(self.cidMappings[node1_id]); + var topic2 = Metamaps.Topics.get(self.cidMappings[node2_id]); var node1 = topic1.get('node'); var node2 = topic2.get('node'); // TODO check if topic1 and topic2 were sucessfully found... @@ -275,13 +279,13 @@ Metamaps.Import = { desc: description, category: category, permission: permission, - node1_id: node1_id, - node2_id: node2_id, + node1_id: node1.id, + node2_id: node2.id, }); var mapping = new Metamaps.Backbone.Mapping({ mappable_type: "Synapse", - mappable_id: synapse.cid, + mappable_id: synapse.id, }); Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true); diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index 82b033ca..febbd219 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -375,7 +375,7 @@ Metamaps.Backbone.init = function () { mappable_id: this.isNew() ? this.cid : this.id }); }, - createEdge: function () { + createEdge: function (providedMapping) { var mapping, mappingID; var synapseID = this.isNew() ? this.cid : this.id; @@ -389,7 +389,7 @@ Metamaps.Backbone.init = function () { }; if (Metamaps.Active.Map) { - mapping = this.getMapping(); + mapping = providedMapping || this.getMapping(); mappingID = mapping.isNew() ? mapping.cid : mapping.id; edge.data.$mappings = []; edge.data.$mappingIDs = [mappingID]; @@ -4233,7 +4233,7 @@ Metamaps.Synapse = { var edgeOnViz; - var newedge = synapse.createEdge(); + var newedge = synapse.createEdge(mapping); Metamaps.Visualize.mGraph.graph.addAdjacence(node1, node2, newedge.data); edgeOnViz = Metamaps.Visualize.mGraph.graph.getAdjacence(node1.id, node2.id); From 5b47527f461008ed795ecb0b9c8559f6057757f3 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 21 Feb 2016 17:25:39 +0800 Subject: [PATCH 6/6] don't need xloc or yloc for Synapse mappings --- app/models/mapping.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/mapping.rb b/app/models/mapping.rb index 425f358d..d034de1c 100644 --- a/app/models/mapping.rb +++ b/app/models/mapping.rb @@ -7,8 +7,10 @@ class Mapping < ActiveRecord::Base belongs_to :map, :class_name => "Map", :foreign_key => "map_id", touch: true belongs_to :user - validates :xloc, presence: true - validates :yloc, presence: true + validates :xloc, presence: true, + unless: Proc.new { |m| m.mappable_type == 'Synapse' } + validates :yloc, presence: true, + unless: Proc.new { |m| m.mappable_type == 'Synapse' } validates :map, presence: true validates :mappable, presence: true