Metamaps.Import standard style
This commit is contained in:
parent
d2d67d5d6c
commit
5a3ab025b7
1 changed files with 178 additions and 189 deletions
|
@ -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 = {
|
||||||
|
@ -30,61 +22,61 @@ Metamaps.Import = {
|
||||||
synapseWhitelist: [
|
synapseWhitelist: [
|
||||||
'topic1', 'topic2', 'category', 'desc', 'description', 'permission'
|
'topic1', 'topic2', 'category', 'desc', 'description', 'permission'
|
||||||
],
|
],
|
||||||
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 = {
|
||||||
ABORT: -1,
|
ABORT: -1,
|
||||||
|
@ -92,226 +84,223 @@ 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
|
||||||
topic1.once('sync', function() {
|
topic1.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
|
||||||
});
|
})
|
||||||
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({
|
||||||
desc: description,
|
desc: description,
|
||||||
|
@ -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)
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
Loading…
Reference in a new issue