Metamaps.Import standard style

This commit is contained in:
Devin Howard 2016-03-27 19:43:30 +08:00
parent d2d67d5d6c
commit 5a3ab025b7

View file

@ -1,25 +1,17 @@
/* global Metamaps, $ */
/* /*
* Example tab-separated input: * Metamaps.Import.js.erb
* Some fields will be ignored
*
* 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
* Topic1 Topic2 Category Description User Permission
* 6 2 from-to admin commons
* 6 1 from-to admin commons
* 6 5 from-to admin commons
* 2 7 from-to admin commons
* 8 6 from-to admin commons
* 8 1 from-to admin commons
* *
* Dependencies:
* - Metamaps.Active
* - Metamaps.Backbone
* - Metamaps.Famous // TODO remove dependency
* - Metamaps.Map
* - Metamaps.Mappings
* - Metamaps.Metacodes
* - Metamaps.Synapses
* - Metamaps.Topics
*/ */
Metamaps.Import = { Metamaps.Import = {
@ -33,57 +25,57 @@ Metamaps.Import = {
cidMappings: {}, // to be filled by import_id => cid mappings cidMappings: {}, // to be filled by import_id => cid mappings
init: function () { init: function () {
var self = Metamaps.Import; var self = Metamaps.Import
$('body').bind('paste', function (e) { $('body').bind('paste', function (e) {
if (e.target.tagName === "INPUT") return; if (e.target.tagName === 'INPUT') return
var text = e.originalEvent.clipboardData.getData('text/plain'); var text = e.originalEvent.clipboardData.getData('text/plain')
var results; var results
if (text.trimLeft()[0] === '{') { if (text.trimLeft()[0] === '{') {
try { try {
results = JSON.parse(text); results = JSON.parse(text)
} catch (e) { } catch (e) {
results = false; results = false
} }
} else { } else {
results = self.parseTabbedString(text); results = self.parseTabbedString(text)
} }
if (results === false) return; if (results === false) return
var topics = results.topics; var topics = results.topics
var synapses = results.synapses; var synapses = results.synapses
if (topics.length > 0 || synapses.length > 0) { if (topics.length > 0 || synapses.length > 0) {
if (confirm("Are you sure you want to create " + topics.length + if (window.confirm('Are you sure you want to create ' + topics.length +
" new topics and " + synapses.length + " new synapses?")) { ' new topics and ' + synapses.length + ' new synapses?')) {
self.importTopics(topics); self.importTopics(topics)
self.importSynapses(synapses); self.importSynapses(synapses)
} // if } // if
} // if } // if
}); })
}, },
abort: function (message) { abort: function (message) {
console.error(message); console.error(message)
}, },
simplify: function (string) { simplify: function (string) {
return string return string
.replace(/(^\s*|\s*$)/g, '') .replace(/(^\s*|\s*$)/g, '')
.toLowerCase(); .toLowerCase()
}, },
parseTabbedString: function (text) { parseTabbedString: function (text) {
var self = Metamaps.Import; var self = Metamaps.Import
// determine line ending and split lines // determine line ending and split lines
var delim = "\n"; var delim = '\n'
if (text.indexOf("\r\n") !== -1) { if (text.indexOf('\r\n') !== -1) {
delim = "\r\n"; delim = '\r\n'
} else if (text.indexOf("\r") !== -1) { } else if (text.indexOf('\r') !== -1) {
delim = "\r"; delim = '\r'
} // if } // if
var STATES = { var STATES = {
@ -92,160 +84,159 @@ Metamaps.Import = {
TOPICS_NEED_HEADERS: 1, TOPICS_NEED_HEADERS: 1,
SYNAPSES_NEED_HEADERS: 2, SYNAPSES_NEED_HEADERS: 2,
TOPICS: 3, TOPICS: 3,
SYNAPSES: 4, SYNAPSES: 4
}; }
// state & lines determine parser behaviour // state & lines determine parser behaviour
var state = STATES.UNKNOWN; var state = STATES.UNKNOWN
var lines = text.split(delim); var lines = text.split(delim)
var results = { topics: [], synapses: [] } var results = { topics: [], synapses: [] }
var topicHeaders = []; var topicHeaders = []
var synapseHeaders = []; var synapseHeaders = []
lines.forEach(function (line_raw, index) { lines.forEach(function (line_raw, index) {
var line = line_raw.split("\t"); var line = line_raw.split('\t')
var noblanks = line.filter(function (elt) { var noblanks = line.filter(function (elt) {
return elt !== ""; return elt !== ''
}); })
switch (state) { switch (state) {
case STATES.UNKNOWN: case STATES.UNKNOWN:
if (noblanks.length === 0) { if (noblanks.length === 0) {
state = STATES.UNKNOWN; state = STATES.UNKNOWN
break; break
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'topics') { } else if (noblanks.length === 1 && self.simplify(line[0]) === 'topics') {
state = STATES.TOPICS_NEED_HEADERS; state = STATES.TOPICS_NEED_HEADERS
break; break
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'synapses') { } else if (noblanks.length === 1 && self.simplify(line[0]) === 'synapses') {
state = STATES.SYNAPSES_NEED_HEADERS; state = STATES.SYNAPSES_NEED_HEADERS
break; break
} }
state = STATES.TOPICS_NEED_HEADERS; state = STATES.TOPICS_NEED_HEADERS
// FALL THROUGH - if we're not sure what to do, pretend // FALL THROUGH - if we're not sure what to do, pretend
// we're on the TOPICS_NEED_HEADERS state and parse some headers // we're on the TOPICS_NEED_HEADERS state and parse some headers
case STATES.TOPICS_NEED_HEADERS: case STATES.TOPICS_NEED_HEADERS: // eslint-disable-line
if (noblanks.length < 2) { if (noblanks.length < 2) {
self.abort("Not enough topic headers on line " + index); self.abort('Not enough topic headers on line ' + index)
state = STATES.ABORT; state = STATES.ABORT
} }
topicHeaders = line.map(function (header, index) { topicHeaders = line.map(function (header, index) {
return header.toLowerCase().replace('description', 'desc'); return header.toLowerCase().replace('description', 'desc')
}); })
state = STATES.TOPICS; state = STATES.TOPICS
break; break
case STATES.SYNAPSES_NEED_HEADERS: case STATES.SYNAPSES_NEED_HEADERS:
if (noblanks.length < 2) { if (noblanks.length < 2) {
self.abort("Not enough synapse headers on line " + index); self.abort('Not enough synapse headers on line ' + index)
state = STATES.ABORT; state = STATES.ABORT
} }
synapseHeaders = line.map(function (header, index) { synapseHeaders = line.map(function (header, index) {
return header.toLowerCase().replace('description', 'desc'); return header.toLowerCase().replace('description', 'desc')
}); })
state = STATES.SYNAPSES; state = STATES.SYNAPSES
break; break
case STATES.TOPICS: case STATES.TOPICS:
if (noblanks.length === 0) { if (noblanks.length === 0) {
state = STATES.UNKNOWN; state = STATES.UNKNOWN
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
state = STATES.TOPICS_NEED_HEADERS; state = STATES.TOPICS_NEED_HEADERS
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
state = STATES.SYNAPSES_NEED_HEADERS; state = STATES.SYNAPSES_NEED_HEADERS
} else { } else {
var topic = {}; var topic = {}
line.forEach(function (field, index) { line.forEach(function (field, index) {
var header = topicHeaders[index]; var header = topicHeaders[index]
if (self.topicWhitelist.indexOf(header) === -1) return; if (self.topicWhitelist.indexOf(header) === -1) return
topic[header] = field; topic[header] = field
if (['id', 'x', 'y'].indexOf(header) !== -1) { if (['id', 'x', 'y'].indexOf(header) !== -1) {
topic[header] = parseInt(topic[header]); topic[header] = parseInt(topic[header])
} // if } // if
}); })
results.topics.push(topic); results.topics.push(topic)
} }
break; break
case STATES.SYNAPSES: case STATES.SYNAPSES:
if (noblanks.length === 0) { if (noblanks.length === 0) {
state = STATES.UNKNOWN; state = STATES.UNKNOWN
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') { } else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
state = STATES.TOPICS_NEED_HEADERS; state = STATES.TOPICS_NEED_HEADERS
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') { } else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
state = STATES.SYNAPSES_NEED_HEADERS; state = STATES.SYNAPSES_NEED_HEADERS
} else { } else {
var synapse = {}; var synapse = {}
line.forEach(function (field, index) { line.forEach(function (field, index) {
var header = synapseHeaders[index]; var header = synapseHeaders[index]
if (self.synapseWhitelist.indexOf(header) === -1) return; if (self.synapseWhitelist.indexOf(header) === -1) return
synapse[header] = field; synapse[header] = field
if (['id', 'topic1', 'topic2'].indexOf(header) !== -1) { if (['id', 'topic1', 'topic2'].indexOf(header) !== -1) {
synapse[header] = parseInt(synapse[header]); synapse[header] = parseInt(synapse[header])
} // if } // if
}); })
results.synapses.push(synapse); results.synapses.push(synapse)
} }
break; break
case STATES.ABORT: case STATES.ABORT:
;
default: default:
self.abort("Invalid state while parsing import data. Check code."); self.abort('Invalid state while parsing import data. Check code.')
state = STATES.ABORT; state = STATES.ABORT
} }
}); })
if (state === STATES.ABORT) { if (state === STATES.ABORT) {
return false; return false
} else { } else {
return results; return results
} }
}, },
importTopics: function (parsedTopics) { importTopics: function (parsedTopics) {
var self = Metamaps.Import; var self = Metamaps.Import
// up to 25 topics: scale 100 // up to 25 topics: scale 100
// up to 81 topics: scale 200 // up to 81 topics: scale 200
// up to 169 topics: scale 300 // up to 169 topics: scale 300
var scale = Math.floor((Math.sqrt(parsedTopics.length) - 1) / 4) * 100; var scale = Math.floor((Math.sqrt(parsedTopics.length) - 1) / 4) * 100
if (scale < 100) scale = 100; if (scale < 100) scale = 100
var autoX = -scale; var autoX = -scale
var autoY = -scale; var autoY = -scale
parsedTopics.forEach(function (topic) { parsedTopics.forEach(function (topic) {
var x, y; var x, y
if (topic.x && topic.y) { if (topic.x && topic.y) {
x = topic.x; x = topic.x
y = topic.y; y = topic.y
} else { } else {
x = autoX; x = autoX
y = autoY; y = autoY
autoX += 50; autoX += 50
if (autoX > scale) { if (autoX > scale) {
autoY += 50; autoY += 50
autoX = -scale; autoX = -scale
} }
} }
self.createTopicWithParameters( self.createTopicWithParameters(
topic.name, topic.metacode, topic.permission, topic.name, topic.metacode, topic.permission,
topic.desc, topic.link, x, y, topic.id topic.desc, topic.link, x, y, topic.id
); )
}); })
}, },
importSynapses: function (parsedSynapses) { importSynapses: function (parsedSynapses) {
var self = Metamaps.Import; var self = Metamaps.Import
parsedSynapses.forEach(function(synapse) { parsedSynapses.forEach(function(synapse) {
// only createSynapseWithParameters once both topics are persisted // only createSynapseWithParameters once both topics are persisted
var topic1 = Metamaps.Topics.get(self.cidMappings[synapse.topic1]); var topic1 = Metamaps.Topics.get(self.cidMappings[synapse.topic1])
var topic2 = Metamaps.Topics.get(self.cidMappings[synapse.topic2]); var topic2 = Metamaps.Topics.get(self.cidMappings[synapse.topic2])
if (!topic1 || !topic2) { if (!topic1 || !topic2) {
console.error("One of the two topics doesn't exist!") console.error("One of the two topics doesn't exist!")
console.error(synapse) console.error(synapse)
return true; return true
} }
var synapse_created = false var synapse_created = false
@ -255,62 +246,60 @@ Metamaps.Import = {
self.createSynapseWithParameters( self.createSynapseWithParameters(
synapse.desc, synapse.category, synapse.permission, synapse.desc, synapse.category, synapse.permission,
topic1, topic2 topic1, topic2
); )
} // if } // if
}); })
topic2.once('sync', function () { topic2.once('sync', function () {
if (topic1.id && topic2.id && !synapse_created) { if (topic1.id && topic2.id && !synapse_created) {
synapse_created = true synapse_created = true
self.createSynapseWithParameters( self.createSynapseWithParameters(
synapse.desc, synapse.category, synapse.permission, synapse.desc, synapse.category, synapse.permission,
topic1, topic2 topic1, topic2
); )
} // if } // if
}); })
}); })
}, },
createTopicWithParameters: function (name, metacode_name, permission, desc, createTopicWithParameters: function (name, metacode_name, permission, desc,
link, xloc, yloc, import_id) { link, xloc, yloc, import_id) {
var self = Metamaps.Import; var self = Metamaps.Import
$(document).trigger(Metamaps.Map.events.editedByActiveMapper); $(document).trigger(Metamaps.Map.events.editedByActiveMapper)
var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null; var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null
if (metacode === null) return console.error("metacode not found"); if (metacode === null) return console.error('metacode not found')
var topic = new Metamaps.Backbone.Topic({ var topic = new Metamaps.Backbone.Topic({
name: name, name: name,
metacode_id: metacode.id, metacode_id: metacode.id,
permission: permission || Metamaps.Active.Map.get('permission'), permission: permission || Metamaps.Active.Map.get('permission'),
desc: desc, desc: desc,
link: link, link: link
}); })
Metamaps.Topics.add(topic); Metamaps.Topics.add(topic)
self.cidMappings[import_id] = topic.cid; self.cidMappings[import_id] = topic.cid
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
xloc: xloc, xloc: xloc,
yloc: yloc, yloc: yloc,
mappable_id: topic.cid, mappable_id: topic.cid,
mappable_type: "Topic", mappable_type: 'Topic'
}); })
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping)
// this function also includes the creation of the topic in the database // this function also includes the creation of the topic in the database
Metamaps.Topic.renderTopic(mapping, topic, true, true); Metamaps.Topic.renderTopic(mapping, topic, true, true)
Metamaps.Famous.viz.hideInstructions()
Metamaps.Famous.viz.hideInstructions();
}, },
createSynapseWithParameters: function (description, category, permission, createSynapseWithParameters: function (description, category, permission,
topic1, topic2) { topic1, topic2) {
var self = Metamaps.Import; var node1 = topic1.get('node')
var node1 = topic1.get('node'); var node2 = topic2.get('node')
var node2 = topic2.get('node');
if (!topic1.id || !topic2.id) { if (!topic1.id || !topic2.id) {
console.error("missing topic id when creating synapse") console.error('missing topic id when creating synapse')
return; return
} // if } // if
var synapse = new Metamaps.Backbone.Synapse({ var synapse = new Metamaps.Backbone.Synapse({
@ -319,15 +308,15 @@ Metamaps.Import = {
permission: permission, permission: permission,
node1_id: topic1.id, node1_id: topic1.id,
node2_id: topic2.id node2_id: topic2.id
}); })
Metamaps.Synapses.add(synapse); Metamaps.Synapses.add(synapse)
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
mappable_type: "Synapse", mappable_type: 'Synapse',
mappable_id: synapse.cid, mappable_id: synapse.cid
}); })
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping)
Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true); Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true)
}, }
}; }