2016-10-02 22:28:00 +08:00
|
|
|
/* global $ */
|
2016-03-27 19:43:30 +08:00
|
|
|
|
2016-09-24 15:22:42 +08:00
|
|
|
import parse from 'csv-parse'
|
|
|
|
import _ from 'lodash'
|
|
|
|
|
2016-09-22 17:36:47 +08:00
|
|
|
import Active from './Active'
|
2016-10-01 12:43:02 +08:00
|
|
|
import AutoLayout from './AutoLayout'
|
2016-10-03 08:32:37 +08:00
|
|
|
import DataModel from './DataModel'
|
2016-09-22 17:36:47 +08:00
|
|
|
import Map from './Map'
|
2016-09-22 18:31:56 +08:00
|
|
|
import Synapse from './Synapse'
|
|
|
|
import Topic from './Topic'
|
2016-09-22 17:36:47 +08:00
|
|
|
|
2016-09-22 15:21:59 +08:00
|
|
|
const Import = {
|
2016-03-26 12:49:26 +08:00
|
|
|
// note that user is not imported
|
2016-02-14 22:39:29 +08:00
|
|
|
topicWhitelist: [
|
2016-03-26 12:49:26 +08:00
|
|
|
'id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission'
|
2016-02-21 16:28:31 +08:00
|
|
|
],
|
2016-02-14 22:39:29 +08:00
|
|
|
synapseWhitelist: [
|
2016-10-06 12:02:14 +08:00
|
|
|
'topic1', 'topic2', 'category', 'direction', 'desc', 'description', 'permission'
|
2016-02-14 22:39:29 +08:00
|
|
|
],
|
2016-11-07 15:25:08 -05:00
|
|
|
cidMappings: {}, // to be filled by importId => cid mappings
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
handleTSV: function(text) {
|
2016-09-30 22:31:24 +08:00
|
|
|
const results = Import.parseTabbedString(text)
|
|
|
|
Import.handle(results)
|
2016-09-13 21:02:55 +08:00
|
|
|
},
|
2016-03-27 11:46:58 +08:00
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
handleCSV: function(text, parserOpts = {}) {
|
2016-09-30 22:31:24 +08:00
|
|
|
const self = Import
|
2016-09-24 15:22:42 +08:00
|
|
|
|
2017-03-06 22:49:46 -05:00
|
|
|
const topicsRegex = /("?Topics"?[, \t"]*)([\s\S]*)/mi
|
|
|
|
const synapsesRegex = /("?Synapses"?[, \t"]*)([\s\S]*)/mi
|
2016-10-01 12:43:02 +08:00
|
|
|
let topicsText = text.match(topicsRegex) || ''
|
2016-09-24 15:22:42 +08:00
|
|
|
if (topicsText) topicsText = topicsText[2].replace(synapsesRegex, '')
|
2016-10-01 12:43:02 +08:00
|
|
|
let synapsesText = text.match(synapsesRegex) || ''
|
2016-09-24 15:22:42 +08:00
|
|
|
if (synapsesText) synapsesText = synapsesText[2].replace(topicsRegex, '')
|
|
|
|
|
|
|
|
// merge default options and extra options passed in parserOpts argument
|
2016-11-07 15:25:08 -05:00
|
|
|
const csvParserOptions = Object.assign({
|
2016-09-24 15:22:42 +08:00
|
|
|
columns: true, // get headers
|
|
|
|
relax_column_count: true,
|
|
|
|
skip_empty_lines: true
|
|
|
|
}, parserOpts)
|
|
|
|
|
|
|
|
const topicsPromise = $.Deferred()
|
2016-11-07 15:25:08 -05:00
|
|
|
parse(topicsText, csvParserOptions, (err, data) => {
|
2016-10-01 12:14:38 +08:00
|
|
|
if (err) {
|
|
|
|
console.warn(err)
|
|
|
|
return topicsPromise.resolve([])
|
|
|
|
}
|
2016-10-06 12:02:14 +08:00
|
|
|
topicsPromise.resolve(data)
|
2016-09-24 15:22:42 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
const synapsesPromise = $.Deferred()
|
2016-11-07 15:25:08 -05:00
|
|
|
parse(synapsesText, csvParserOptions, (err, data) => {
|
2016-10-01 12:14:38 +08:00
|
|
|
if (err) {
|
|
|
|
console.warn(err)
|
|
|
|
return synapsesPromise.resolve([])
|
|
|
|
}
|
2016-10-06 12:02:14 +08:00
|
|
|
synapsesPromise.resolve(data)
|
2016-09-24 15:22:42 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
$.when(topicsPromise, synapsesPromise).done((topics, synapses) => {
|
2016-11-07 15:25:08 -05:00
|
|
|
self.handle({ topics, synapses })
|
2016-09-24 15:22:42 +08:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
handleJSON: function(text) {
|
2016-09-30 22:31:24 +08:00
|
|
|
const results = JSON.parse(text)
|
|
|
|
Import.handle(results)
|
2016-09-13 21:02:55 +08:00
|
|
|
},
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-09-13 21:02:55 +08:00
|
|
|
handle: function(results) {
|
2016-09-22 15:21:59 +08:00
|
|
|
var self = Import
|
2016-10-06 12:02:14 +08:00
|
|
|
var topics = results.topics.map(topic => self.normalizeKeys(topic))
|
|
|
|
var synapses = results.synapses.map(synapse => self.normalizeKeys(synapse))
|
2016-09-13 21:02:55 +08:00
|
|
|
|
|
|
|
if (topics.length > 0 || synapses.length > 0) {
|
|
|
|
if (window.confirm('Are you sure you want to create ' + topics.length +
|
|
|
|
' new topics and ' + synapses.length + ' new synapses?')) {
|
|
|
|
self.importTopics(topics)
|
2016-11-07 15:25:08 -05:00
|
|
|
// window.setTimeout(() => self.importSynapses(synapses), 5000)
|
2016-10-27 14:03:18 +08:00
|
|
|
self.importSynapses(synapses)
|
2016-03-27 19:43:30 +08:00
|
|
|
} // if
|
2016-09-13 21:02:55 +08:00
|
|
|
} // if
|
2016-02-07 16:56:03 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
parseTabbedString: function(text) {
|
2016-09-22 15:21:59 +08:00
|
|
|
var self = Import
|
2016-02-07 16:56:03 +08:00
|
|
|
|
|
|
|
// determine line ending and split lines
|
2016-03-27 19:43:30 +08:00
|
|
|
var delim = '\n'
|
|
|
|
if (text.indexOf('\r\n') !== -1) {
|
|
|
|
delim = '\r\n'
|
|
|
|
} else if (text.indexOf('\r') !== -1) {
|
|
|
|
delim = '\r'
|
|
|
|
} // if
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-02-14 22:39:29 +08:00
|
|
|
var STATES = {
|
2016-02-21 16:28:31 +08:00
|
|
|
ABORT: -1,
|
2016-02-14 22:39:29 +08:00
|
|
|
UNKNOWN: 0,
|
|
|
|
TOPICS_NEED_HEADERS: 1,
|
|
|
|
SYNAPSES_NEED_HEADERS: 2,
|
|
|
|
TOPICS: 3,
|
2016-03-27 19:43:30 +08:00
|
|
|
SYNAPSES: 4
|
|
|
|
}
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-02-14 22:39:29 +08:00
|
|
|
// state & lines determine parser behaviour
|
2016-03-27 19:43:30 +08:00
|
|
|
var state = STATES.UNKNOWN
|
|
|
|
var lines = text.split(delim)
|
2016-02-14 22:39:29 +08:00
|
|
|
var results = { topics: [], synapses: [] }
|
2016-03-27 19:43:30 +08:00
|
|
|
var topicHeaders = []
|
|
|
|
var synapseHeaders = []
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
lines.forEach(function(lineRaw, index) {
|
|
|
|
const line = lineRaw.split('\t')
|
|
|
|
var noblanks = line.filter(function(elt) {
|
2016-03-27 19:43:30 +08:00
|
|
|
return elt !== ''
|
|
|
|
})
|
|
|
|
switch (state) {
|
2016-02-14 22:39:29 +08:00
|
|
|
case STATES.UNKNOWN:
|
|
|
|
if (noblanks.length === 0) {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.UNKNOWN
|
|
|
|
break
|
2016-02-21 16:28:31 +08:00
|
|
|
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'topics') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.TOPICS_NEED_HEADERS
|
|
|
|
break
|
2016-02-21 16:28:31 +08:00
|
|
|
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'synapses') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.SYNAPSES_NEED_HEADERS
|
|
|
|
break
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.TOPICS_NEED_HEADERS
|
2016-02-14 22:39:29 +08:00
|
|
|
// FALL THROUGH - if we're not sure what to do, pretend
|
|
|
|
// we're on the TOPICS_NEED_HEADERS state and parse some headers
|
|
|
|
|
2016-10-04 23:38:32 +08:00
|
|
|
case STATES.TOPICS_NEED_HEADERS: // eslint-disable-line no-fallthrough
|
2016-02-14 22:39:29 +08:00
|
|
|
if (noblanks.length < 2) {
|
2016-03-27 19:43:30 +08:00
|
|
|
self.abort('Not enough topic headers on line ' + index)
|
|
|
|
state = STATES.ABORT
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-11-07 15:25:08 -05:00
|
|
|
topicHeaders = line.map(function(header, index) {
|
2016-10-06 12:02:14 +08:00
|
|
|
return self.normalizeKey(header)
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
|
|
|
state = STATES.TOPICS
|
|
|
|
break
|
2016-02-14 22:39:29 +08:00
|
|
|
|
|
|
|
case STATES.SYNAPSES_NEED_HEADERS:
|
|
|
|
if (noblanks.length < 2) {
|
2016-03-27 19:43:30 +08:00
|
|
|
self.abort('Not enough synapse headers on line ' + index)
|
|
|
|
state = STATES.ABORT
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-11-07 15:25:08 -05:00
|
|
|
synapseHeaders = line.map(function(header, index) {
|
2016-10-06 12:02:14 +08:00
|
|
|
return self.normalizeKey(header)
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
|
|
|
state = STATES.SYNAPSES
|
|
|
|
break
|
2016-02-14 22:39:29 +08:00
|
|
|
|
|
|
|
case STATES.TOPICS:
|
|
|
|
if (noblanks.length === 0) {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.UNKNOWN
|
2016-02-14 22:39:29 +08:00
|
|
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.TOPICS_NEED_HEADERS
|
2016-02-14 22:39:29 +08:00
|
|
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.SYNAPSES_NEED_HEADERS
|
2016-02-14 22:39:29 +08:00
|
|
|
} else {
|
2016-03-27 19:43:30 +08:00
|
|
|
var topic = {}
|
2016-11-07 15:25:08 -05:00
|
|
|
line.forEach(function(field, index) {
|
2016-03-27 19:43:30 +08:00
|
|
|
var header = topicHeaders[index]
|
|
|
|
if (self.topicWhitelist.indexOf(header) === -1) return
|
|
|
|
topic[header] = field
|
2016-02-21 17:02:37 +08:00
|
|
|
if (['id', 'x', 'y'].indexOf(header) !== -1) {
|
2016-03-27 19:43:30 +08:00
|
|
|
topic[header] = parseInt(topic[header])
|
|
|
|
} // if
|
|
|
|
})
|
|
|
|
results.topics.push(topic)
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-03-27 19:43:30 +08:00
|
|
|
break
|
2016-02-14 22:39:29 +08:00
|
|
|
|
|
|
|
case STATES.SYNAPSES:
|
|
|
|
if (noblanks.length === 0) {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.UNKNOWN
|
2016-02-14 22:39:29 +08:00
|
|
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.TOPICS_NEED_HEADERS
|
2016-02-14 22:39:29 +08:00
|
|
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
|
2016-03-27 19:43:30 +08:00
|
|
|
state = STATES.SYNAPSES_NEED_HEADERS
|
2016-02-14 22:39:29 +08:00
|
|
|
} else {
|
2016-03-27 19:43:30 +08:00
|
|
|
var synapse = {}
|
2016-11-07 15:25:08 -05:00
|
|
|
line.forEach(function(field, index) {
|
2016-03-27 19:43:30 +08:00
|
|
|
var header = synapseHeaders[index]
|
|
|
|
if (self.synapseWhitelist.indexOf(header) === -1) return
|
|
|
|
synapse[header] = field
|
2016-02-21 17:02:37 +08:00
|
|
|
if (['id', 'topic1', 'topic2'].indexOf(header) !== -1) {
|
2016-03-27 19:43:30 +08:00
|
|
|
synapse[header] = parseInt(synapse[header])
|
|
|
|
} // if
|
|
|
|
})
|
|
|
|
results.synapses.push(synapse)
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-03-27 19:43:30 +08:00
|
|
|
break
|
2016-02-21 16:28:31 +08:00
|
|
|
case STATES.ABORT:
|
2016-10-04 23:38:32 +08:00
|
|
|
// FALL THROUGH
|
|
|
|
default: // eslint-disable-line no-fallthrough
|
2016-03-27 19:43:30 +08:00
|
|
|
self.abort('Invalid state while parsing import data. Check code.')
|
|
|
|
state = STATES.ABORT
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-02-21 16:28:31 +08:00
|
|
|
if (state === STATES.ABORT) {
|
2016-03-27 19:43:30 +08:00
|
|
|
return false
|
2016-02-21 16:28:31 +08:00
|
|
|
} else {
|
2016-03-27 19:43:30 +08:00
|
|
|
return results
|
2016-02-21 16:28:31 +08:00
|
|
|
}
|
2016-02-07 16:56:03 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
importTopics: function(parsedTopics) {
|
2016-09-22 15:21:59 +08:00
|
|
|
var self = Import
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-10-26 20:34:22 +08:00
|
|
|
parsedTopics.forEach(topic => {
|
2016-10-01 12:57:19 +08:00
|
|
|
let coords = { x: topic.x, y: topic.y }
|
|
|
|
if (!coords.x || !coords.y) {
|
2016-10-03 08:32:37 +08:00
|
|
|
coords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings })
|
2016-02-14 22:39:29 +08:00
|
|
|
}
|
|
|
|
|
2016-10-01 12:57:19 +08:00
|
|
|
if (!topic.name && topic.link ||
|
|
|
|
topic.name && topic.link && !topic.metacode) {
|
|
|
|
self.handleURL(topic.link, {
|
|
|
|
coords,
|
|
|
|
name: topic.name,
|
|
|
|
permission: topic.permission,
|
2016-11-07 15:25:08 -05:00
|
|
|
importId: topic.id
|
2016-10-01 12:57:19 +08:00
|
|
|
})
|
|
|
|
return // "continue"
|
2016-10-01 12:14:38 +08:00
|
|
|
}
|
|
|
|
|
2016-02-14 22:39:29 +08:00
|
|
|
self.createTopicWithParameters(
|
|
|
|
topic.name, topic.metacode, topic.permission,
|
2016-10-01 12:57:19 +08:00
|
|
|
topic.desc, topic.link, coords.x, coords.y, topic.id
|
2016-03-27 19:43:30 +08:00
|
|
|
)
|
|
|
|
})
|
2016-02-14 22:39:29 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
importSynapses: function(parsedSynapses) {
|
2016-09-22 15:21:59 +08:00
|
|
|
var self = Import
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
parsedSynapses.forEach(function(synapse) {
|
2016-03-27 19:43:30 +08:00
|
|
|
// only createSynapseWithParameters once both topics are persisted
|
2016-10-06 11:52:05 +08:00
|
|
|
// if there isn't a cidMapping, check by topic name instead
|
2016-10-02 22:28:00 +08:00
|
|
|
var topic1 = DataModel.Topics.get(self.cidMappings[synapse.topic1])
|
|
|
|
if (!topic1) topic1 = DataModel.Topics.findWhere({ name: synapse.topic1 })
|
|
|
|
var topic2 = DataModel.Topics.get(self.cidMappings[synapse.topic2])
|
|
|
|
if (!topic2) topic2 = DataModel.Topics.findWhere({ name: synapse.topic2 })
|
2016-10-06 11:52:05 +08:00
|
|
|
|
2016-03-31 09:25:14 +08:00
|
|
|
if (!topic1 || !topic2) {
|
|
|
|
console.error("One of the two topics doesn't exist!")
|
|
|
|
console.error(synapse)
|
2016-10-06 11:52:05 +08:00
|
|
|
return // next
|
2016-03-31 09:25:14 +08:00
|
|
|
}
|
|
|
|
|
2016-10-27 14:03:18 +08:00
|
|
|
const topic1Promise = $.Deferred()
|
|
|
|
if (topic1.id) {
|
|
|
|
topic1Promise.resolve()
|
|
|
|
} else {
|
|
|
|
topic1.on('sync', () => topic1Promise.resolve())
|
|
|
|
}
|
|
|
|
const topic2Promise = $.Deferred()
|
|
|
|
if (topic2.id) {
|
|
|
|
topic2Promise.resolve()
|
|
|
|
} else {
|
|
|
|
topic2.on('sync', () => topic2Promise.resolve())
|
|
|
|
}
|
|
|
|
$.when(topic1Promise, topic2Promise).done(() => {
|
|
|
|
self.createSynapseWithParameters(
|
|
|
|
synapse.desc, synapse.category, synapse.permission,
|
|
|
|
topic1, topic2
|
|
|
|
)
|
|
|
|
})
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
2016-02-14 22:39:29 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
createTopicWithParameters: function(name, metacodeName, permission, desc,
|
|
|
|
link, xloc, yloc, importId, opts = {}) {
|
2016-09-22 15:21:59 +08:00
|
|
|
var self = Import
|
2016-09-22 17:36:47 +08:00
|
|
|
$(document).trigger(Map.events.editedByActiveMapper)
|
2016-11-07 15:25:08 -05:00
|
|
|
var metacode = DataModel.Metacodes.where({name: metacodeName})[0] || null
|
2016-07-03 13:31:04 +08:00
|
|
|
if (metacode === null) {
|
2016-10-02 22:28:00 +08:00
|
|
|
metacode = DataModel.Metacodes.where({ name: 'Wildcard' })[0]
|
2016-11-07 15:25:08 -05:00
|
|
|
console.warn("Couldn't find metacode " + metacodeName + ' so used Wildcard instead.')
|
2016-07-03 13:31:04 +08:00
|
|
|
}
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
const topicPermision = permission || Active.Map.get('permission')
|
|
|
|
var deferToMapId = permission === topicPermision ? Active.Map.get('id') : null
|
2016-10-02 22:28:00 +08:00
|
|
|
var topic = new DataModel.Topic({
|
2016-02-07 16:56:03 +08:00
|
|
|
name: name,
|
|
|
|
metacode_id: metacode.id,
|
2016-11-07 15:25:08 -05:00
|
|
|
permission: topicPermision,
|
|
|
|
defer_to_map_id: deferToMapId,
|
2016-10-13 16:48:46 +08:00
|
|
|
desc: desc || '',
|
2016-12-06 16:46:46 -05:00
|
|
|
link: link || ''
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
2016-10-02 22:28:00 +08:00
|
|
|
DataModel.Topics.add(topic)
|
2016-09-13 21:02:55 +08:00
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
if (importId !== null && importId !== undefined) {
|
|
|
|
self.cidMappings[importId] = topic.cid
|
2016-09-13 21:02:55 +08:00
|
|
|
}
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-10-02 22:28:00 +08:00
|
|
|
var mapping = new DataModel.Mapping({
|
2016-03-27 19:43:30 +08:00
|
|
|
xloc: xloc,
|
|
|
|
yloc: yloc,
|
|
|
|
mappable_id: topic.cid,
|
|
|
|
mappable_type: 'Topic'
|
|
|
|
})
|
2016-10-02 22:28:00 +08:00
|
|
|
DataModel.Mappings.add(mapping)
|
2016-02-07 16:56:03 +08:00
|
|
|
|
2016-02-07 17:51:01 +08:00
|
|
|
// this function also includes the creation of the topic in the database
|
2016-09-22 18:31:56 +08:00
|
|
|
Topic.renderTopic(mapping, topic, true, true, {
|
2016-09-21 14:27:49 +08:00
|
|
|
success: opts.success
|
|
|
|
})
|
2016-02-21 17:02:37 +08:00
|
|
|
|
2017-03-16 17:58:56 -04:00
|
|
|
Map.setHasLearnedTopicCreation(true)
|
2016-02-14 22:39:29 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
createSynapseWithParameters: function(desc, category, permission,
|
2016-03-27 19:43:30 +08:00
|
|
|
topic1, topic2) {
|
|
|
|
var node1 = topic1.get('node')
|
|
|
|
var node2 = topic2.get('node')
|
2016-03-27 11:46:58 +08:00
|
|
|
|
2016-03-27 15:20:09 +08:00
|
|
|
if (!topic1.id || !topic2.id) {
|
2016-03-27 19:43:30 +08:00
|
|
|
console.error('missing topic id when creating synapse')
|
|
|
|
return
|
|
|
|
} // if
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-10-02 22:28:00 +08:00
|
|
|
var synapse = new DataModel.Synapse({
|
2016-10-13 16:48:46 +08:00
|
|
|
desc: desc || '',
|
2016-10-13 14:23:55 +08:00
|
|
|
category: category || 'from-to',
|
2016-02-14 22:39:29 +08:00
|
|
|
permission: permission,
|
2016-09-28 10:32:28 +08:00
|
|
|
topic1_id: topic1.id,
|
|
|
|
topic2_id: topic2.id
|
2016-03-27 19:43:30 +08:00
|
|
|
})
|
2016-10-02 22:28:00 +08:00
|
|
|
DataModel.Synapses.add(synapse)
|
2016-02-14 22:39:29 +08:00
|
|
|
|
2016-10-02 22:28:00 +08:00
|
|
|
var mapping = new DataModel.Mapping({
|
2016-03-27 19:43:30 +08:00
|
|
|
mappable_type: 'Synapse',
|
|
|
|
mappable_id: synapse.cid
|
|
|
|
})
|
2016-10-02 22:28:00 +08:00
|
|
|
DataModel.Mappings.add(mapping)
|
2016-03-27 19:43:30 +08:00
|
|
|
|
2016-09-22 18:31:56 +08:00
|
|
|
Synapse.renderSynapse(mapping, synapse, node1, node2, true)
|
2016-09-24 15:22:42 +08:00
|
|
|
},
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
handleURL: function(url, opts = {}) {
|
2016-10-01 12:57:19 +08:00
|
|
|
let coords = opts.coords
|
|
|
|
if (!coords || coords.x === undefined || coords.y === undefined) {
|
2016-10-03 08:32:37 +08:00
|
|
|
coords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings })
|
2016-10-01 12:57:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const name = opts.name || 'Link'
|
|
|
|
const metacode = opts.metacode || 'Reference'
|
2016-11-07 15:25:08 -05:00
|
|
|
const importId = opts.importId || null // don't store a cidMapping
|
2016-10-01 12:57:19 +08:00
|
|
|
const permission = opts.permission || null // use default
|
|
|
|
const desc = opts.desc || url
|
|
|
|
|
|
|
|
Import.createTopicWithParameters(
|
|
|
|
name,
|
|
|
|
metacode,
|
|
|
|
permission,
|
|
|
|
desc,
|
|
|
|
url,
|
|
|
|
coords.x,
|
|
|
|
coords.y,
|
2016-11-07 15:25:08 -05:00
|
|
|
importId,
|
2016-10-01 12:57:19 +08:00
|
|
|
{
|
|
|
|
success: function(topic) {
|
|
|
|
if (topic.get('name') !== 'Link') return
|
2018-03-03 22:51:16 -05:00
|
|
|
$.get('/hacks/load_url_title', {
|
2016-10-01 12:57:19 +08:00
|
|
|
url
|
|
|
|
}, function success(data, textStatus) {
|
2017-02-01 12:37:50 -05:00
|
|
|
if (typeof data === 'string' && data.trim() === '') return
|
2017-03-22 19:22:38 -04:00
|
|
|
var selector = '.showcard #topic_' + topic.get('id') + ' .best_in_place'
|
2016-10-01 12:57:19 +08:00
|
|
|
if ($(selector).find('form').length > 0) {
|
|
|
|
$(selector).find('textarea, input').val(data.title)
|
|
|
|
} else {
|
|
|
|
$(selector).html(data.title)
|
|
|
|
}
|
|
|
|
topic.set('name', data.title)
|
|
|
|
topic.save()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
2017-04-11 11:51:22 -04:00
|
|
|
handleText: function(text, opts = {}) {
|
|
|
|
let coords = opts.coords
|
|
|
|
if (!coords || coords.x === undefined || coords.y === undefined) {
|
|
|
|
coords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings })
|
|
|
|
}
|
|
|
|
|
|
|
|
const name = text
|
|
|
|
const url = ''
|
|
|
|
const metacode = opts.metacode || 'Wildcard'
|
|
|
|
const importId = opts.importId || null // don't store a cidMapping
|
|
|
|
const permission = opts.permission || null // use default
|
|
|
|
const desc = opts.desc || ''
|
|
|
|
|
|
|
|
Import.createTopicWithParameters(
|
|
|
|
name,
|
|
|
|
metacode,
|
|
|
|
permission,
|
|
|
|
desc,
|
|
|
|
url,
|
|
|
|
coords.x,
|
|
|
|
coords.y,
|
|
|
|
importId
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
2016-09-24 15:22:42 +08:00
|
|
|
/*
|
|
|
|
* helper functions
|
|
|
|
*/
|
|
|
|
|
2016-11-07 15:25:08 -05:00
|
|
|
abort: function(message) {
|
2016-09-24 15:22:42 +08:00
|
|
|
console.error(message)
|
|
|
|
},
|
|
|
|
|
2016-10-01 12:57:19 +08:00
|
|
|
// TODO investigate replacing with es6 (?) trim()
|
2016-11-07 15:25:08 -05:00
|
|
|
simplify: function(string) {
|
2016-09-24 15:22:42 +08:00
|
|
|
return string
|
|
|
|
.replace(/(^\s*|\s*$)/g, '')
|
|
|
|
.toLowerCase()
|
|
|
|
},
|
|
|
|
|
2016-10-06 12:02:14 +08:00
|
|
|
normalizeKey: function(key) {
|
|
|
|
let newKey = key.toLowerCase()
|
|
|
|
newKey = newKey.replace(/\s/g, '') // remove whitespace
|
|
|
|
if (newKey === 'url') newKey = 'link'
|
|
|
|
if (newKey === 'title') newKey = 'name'
|
2016-09-25 00:27:04 +08:00
|
|
|
if (newKey === 'label') newKey = 'desc'
|
2016-10-06 12:02:14 +08:00
|
|
|
if (newKey === 'description') newKey = 'desc'
|
|
|
|
if (newKey === 'direction') newKey = 'category'
|
|
|
|
return newKey
|
|
|
|
},
|
2016-09-24 15:22:42 +08:00
|
|
|
|
|
|
|
// thanks to http://stackoverflow.com/a/25290114/5332286
|
2016-10-01 12:57:19 +08:00
|
|
|
normalizeKeys: function(obj) {
|
2016-09-24 15:22:42 +08:00
|
|
|
return _.transform(obj, (result, val, key) => {
|
2016-10-06 12:02:14 +08:00
|
|
|
const newKey = Import.normalizeKey(key)
|
2016-10-01 12:57:19 +08:00
|
|
|
result[newKey] = val
|
2016-09-24 15:22:42 +08:00
|
|
|
})
|
2016-03-27 19:43:30 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-22 15:21:59 +08:00
|
|
|
|
|
|
|
export default Import
|