From 1562d8fcfe63a8076ca0755bfda8c06018ed0678 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 12:14:38 +0800 Subject: [PATCH 1/7] topics imported with a link get Reference metacode --- frontend/src/Metamaps/Import.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index 1307aa45..26a72952 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -40,9 +40,9 @@ const Import = { const topicsRegex = /("?Topics"?)([\s\S]*)/mi const synapsesRegex = /("?Synapses"?)([\s\S]*)/mi - let topicsText = text.match(topicsRegex) + let topicsText = text.match(topicsRegex) || "" if (topicsText) topicsText = topicsText[2].replace(synapsesRegex, '') - let synapsesText = text.match(synapsesRegex) + let synapsesText = text.match(synapsesRegex) || "" if (synapsesText) synapsesText = synapsesText[2].replace(topicsRegex, '') // merge default options and extra options passed in parserOpts argument @@ -54,13 +54,19 @@ const Import = { const topicsPromise = $.Deferred() parse(topicsText, csv_parser_options, (err, data) => { - if (err) return topicsPromise.reject(err) + if (err) { + console.warn(err) + return topicsPromise.resolve([]) + } topicsPromise.resolve(data.map(row => self.lowercaseKeys(row))) }) const synapsesPromise = $.Deferred() parse(synapsesText, csv_parser_options, (err, data) => { - if (err) return synapsesPromise.reject(err) + if (err) { + console.warn(err) + return synapsesPromise.resolve([]) + } synapsesPromise.resolve(data.map(row => self.lowercaseKeys(row))) }) @@ -240,6 +246,10 @@ const Import = { } } + if (topic.name && topic.link && !topic.metacode) { + topic.metacode = "Reference" + } + self.createTopicWithParameters( topic.name, topic.metacode, topic.permission, topic.desc, topic.link, x, y, topic.id From fdf03ac83af1d4128f59ef5ae40fc51f70969780 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 12:32:40 +0800 Subject: [PATCH 2/7] source maps! (I think) --- webpack.config.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index f94f904a..31adaaa1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,7 +26,7 @@ const config = module.exports = { test: /\.(js|jsx)?$/, exclude: /node_modules/, loaders: [ - "babel-loader?cacheDirectory" + "babel-loader?cacheDirectory&retainLines=true" ] } ] @@ -36,6 +36,7 @@ const config = module.exports = { }, output: { path: './app/assets/javascripts/webpacked', - filename: '[name].js' + filename: '[name].js', + devtoolModuleFilenameTemplate: '[absolute-resource-path]' } } From 4949f0dbd63c977b5cb88ac92dbeadce88287f6e Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 12:43:02 +0800 Subject: [PATCH 3/7] eslint and use AutoLayout --- frontend/src/Metamaps/Import.js | 25 +++++++------------------ webpack.config.js | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index 26a72952..e5e3e774 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -4,6 +4,7 @@ import parse from 'csv-parse' import _ from 'lodash' import Active from './Active' +import AutoLayout from './AutoLayout' import GlobalUI from './GlobalUI' import Map from './Map' import Synapse from './Synapse' @@ -40,9 +41,9 @@ const Import = { const topicsRegex = /("?Topics"?)([\s\S]*)/mi const synapsesRegex = /("?Synapses"?)([\s\S]*)/mi - let topicsText = text.match(topicsRegex) || "" + let topicsText = text.match(topicsRegex) || '' if (topicsText) topicsText = topicsText[2].replace(synapsesRegex, '') - let synapsesText = text.match(synapsesRegex) || "" + let synapsesText = text.match(synapsesRegex) || '' if (synapsesText) synapsesText = synapsesText[2].replace(topicsRegex, '') // merge default options and extra options passed in parserOpts argument @@ -223,31 +224,19 @@ const Import = { importTopics: function (parsedTopics) { var self = 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 - } + const coords = AutoLayout.getNextCoord() + x = coords.x + y = coords.y } if (topic.name && topic.link && !topic.metacode) { - topic.metacode = "Reference" + topic.metacode = 'Reference' } self.createTopicWithParameters( diff --git a/webpack.config.js b/webpack.config.js index 31adaaa1..91498abd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,7 +26,7 @@ const config = module.exports = { test: /\.(js|jsx)?$/, exclude: /node_modules/, loaders: [ - "babel-loader?cacheDirectory&retainLines=true" + 'babel-loader?cacheDirectory&retainLines=true' ] } ] From c5564e02fcceebdfad60c80995d50057aaaedaf6 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 12:47:30 +0800 Subject: [PATCH 4/7] don't needt o open topic card --- frontend/src/Metamaps/PasteInput.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index e7029d66..8166f7c0 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -2,7 +2,6 @@ import AutoLayout from './AutoLayout' import Import from './Import' -import TopicCard from './TopicCard' import Util from './Util' const PasteInput = { @@ -101,10 +100,6 @@ const PasteInput = { topic.set('name', data.title) topic.save() }) - TopicCard.showCard(topic.get('node'), function() { - $('#showcard #titleActivator').click() - .find('textarea, input').focus() - }) } } ) From 20a32afe3b260fa9246c4cf555b2498763443793 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 12:57:19 +0800 Subject: [PATCH 5/7] integrate handleURL into Import --- frontend/src/Metamaps/Import.js | 78 +++++++++++++++++++++++------ frontend/src/Metamaps/PasteInput.js | 39 +-------------- 2 files changed, 64 insertions(+), 53 deletions(-) diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index e5e3e774..2de7ca02 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -59,7 +59,7 @@ const Import = { console.warn(err) return topicsPromise.resolve([]) } - topicsPromise.resolve(data.map(row => self.lowercaseKeys(row))) + topicsPromise.resolve(data.map(row => self.normalizeKeys(row))) }) const synapsesPromise = $.Deferred() @@ -68,7 +68,7 @@ const Import = { console.warn(err) return synapsesPromise.resolve([]) } - synapsesPromise.resolve(data.map(row => self.lowercaseKeys(row))) + synapsesPromise.resolve(data.map(row => self.normalizeKeys(row))) }) $.when(topicsPromise, synapsesPromise).done((topics, synapses) => { @@ -225,23 +225,25 @@ const Import = { var self = Import parsedTopics.forEach(function (topic) { - var x, y - if (topic.x && topic.y) { - x = topic.x - y = topic.y - } else { - const coords = AutoLayout.getNextCoord() - x = coords.x - y = coords.y + let coords = { x: topic.x, y: topic.y } + if (!coords.x || !coords.y) { + coords = AutoLayout.getNextCoord() } - if (topic.name && topic.link && !topic.metacode) { - topic.metacode = 'Reference' + if (!topic.name && topic.link || + topic.name && topic.link && !topic.metacode) { + self.handleURL(topic.link, { + coords, + name: topic.name, + permission: topic.permission, + import_id: topic.id + }) + return // "continue" } self.createTopicWithParameters( topic.name, topic.metacode, topic.permission, - topic.desc, topic.link, x, y, topic.id + topic.desc, topic.link, coords.x, coords.y, topic.id ) }) }, @@ -344,6 +346,47 @@ const Import = { Synapse.renderSynapse(mapping, synapse, node1, node2, true) }, + handleURL: function (url, opts = {}) { + let coords = opts.coords + if (!coords || coords.x === undefined || coords.y === undefined) { + coords = AutoLayout.getNextCoord() + } + + const name = opts.name || 'Link' + const metacode = opts.metacode || 'Reference' + const import_id = opts.import_id || null // don't store a cidMapping + const permission = opts.permission || null // use default + const desc = opts.desc || url + + Import.createTopicWithParameters( + name, + metacode, + permission, + desc, + url, + coords.x, + coords.y, + import_id, + { + success: function(topic) { + if (topic.get('name') !== 'Link') return + $.get('/hacks/load_url_title', { + url + }, function success(data, textStatus) { + var selector = '#showcard #topic_' + topic.get('id') + ' .best_in_place' + 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() + }) + } + } + ) + }, + /* * helper functions */ @@ -352,6 +395,7 @@ const Import = { console.error(message) }, + // TODO investigate replacing with es6 (?) trim() simplify: function (string) { return string .replace(/(^\s*|\s*$)/g, '') @@ -360,9 +404,13 @@ const Import = { // thanks to http://stackoverflow.com/a/25290114/5332286 - lowercaseKeys: function(obj) { + normalizeKeys: function(obj) { return _.transform(obj, (result, val, key) => { - result[key.toLowerCase()] = val + let newKey = key.toLowerCase() + if (newKey === 'url') key = 'link' + if (newKey === 'title') key = 'name' + if (newKey === 'description') key = 'desc' + result[newKey] = val }) } } diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index 8166f7c0..272ac030 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -1,6 +1,5 @@ /* global $ */ -import AutoLayout from './AutoLayout' import Import from './Import' import Util from './Util' @@ -57,7 +56,7 @@ const PasteInput = { var self = PasteInput if (text.match(self.URL_REGEX)) { - self.handleURL(text, coords) + Import.handleURL(text, coords) } else if (text[0] === '{') { Import.handleJSON(text) } else if (text.match(/\t/)) { @@ -68,42 +67,6 @@ const PasteInput = { } }, - handleURL: function (text, coords) { - var title = 'Link' - if (!coords || !coords.x || !coords.y) { - coords = AutoLayout.getNextCoord() - } - - var import_id = null // don't store a cidMapping - var permission = null // use default - - Import.createTopicWithParameters( - title, - 'Reference', // metacode - todo fix - permission, - text, // desc - todo load from url? - text, // link - todo fix because this isn't being POSTed - coords.x, - coords.y, - import_id, - { - success: function(topic) { - $.get('/hacks/load_url_title', { - url: text - }, function success(data, textStatus) { - var selector = '#showcard #topic_' + topic.get('id') + ' .best_in_place' - 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() - }) - } - } - ) - } } export default PasteInput From bb013787b6eb65298bc466674f0c9dd6df07442e Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 13:34:52 +0800 Subject: [PATCH 6/7] make AutoLayout skip over coordinates if there is a mapping at that exact position --- frontend/src/Metamaps/AutoLayout.js | 23 +++++++++++++++++++---- frontend/src/Metamaps/Import.js | 4 ++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/frontend/src/Metamaps/AutoLayout.js b/frontend/src/Metamaps/AutoLayout.js index ee9dc33c..e0835473 100644 --- a/frontend/src/Metamaps/AutoLayout.js +++ b/frontend/src/Metamaps/AutoLayout.js @@ -1,3 +1,5 @@ +import Active from './Active' + const AutoLayout = { nextX: 0, nextY: 0, @@ -7,7 +9,7 @@ const AutoLayout = { nextYshift: 0, timeToTurn: 0, - getNextCoord: function () { + getNextCoord: function (opts = {}) { var self = AutoLayout var nextX = self.nextX var nextY = self.nextY @@ -49,9 +51,22 @@ const AutoLayout = { } } - return { - x: nextX, - y: nextY + if (opts.map && self.coordsTaken(nextX, nextY, opts.map)) { + // check if the coordinate is already taken on the current map + return self.getNextCoord(opts) + } else { + return { + x: nextX, + y: nextY + } + } + }, + coordsTaken: function(x, y, map) { + const mappings = map.getMappings() + if (mappings.findWhere({ xloc: x, yloc: y })) { + return true + } else { + return false } }, resetSpiral: function () { diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index 2de7ca02..5d5f91a7 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -227,7 +227,7 @@ const Import = { parsedTopics.forEach(function (topic) { let coords = { x: topic.x, y: topic.y } if (!coords.x || !coords.y) { - coords = AutoLayout.getNextCoord() + coords = AutoLayout.getNextCoord({ map: Active.Map }) } if (!topic.name && topic.link || @@ -349,7 +349,7 @@ const Import = { handleURL: function (url, opts = {}) { let coords = opts.coords if (!coords || coords.x === undefined || coords.y === undefined) { - coords = AutoLayout.getNextCoord() + coords = AutoLayout.getNextCoord({ map: Active.Map }) } const name = opts.name || 'Link' From 8f230736dc11c4ea4158af993fc87216762112d5 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 1 Oct 2016 13:47:16 +0800 Subject: [PATCH 7/7] code climate --- frontend/src/Metamaps/AutoLayout.js | 4 +--- frontend/src/Metamaps/PasteInput.js | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/Metamaps/AutoLayout.js b/frontend/src/Metamaps/AutoLayout.js index e0835473..f3e91440 100644 --- a/frontend/src/Metamaps/AutoLayout.js +++ b/frontend/src/Metamaps/AutoLayout.js @@ -1,5 +1,3 @@ -import Active from './Active' - const AutoLayout = { nextX: 0, nextY: 0, @@ -61,7 +59,7 @@ const AutoLayout = { } } }, - coordsTaken: function(x, y, map) { + coordsTaken: function (x, y, map) { const mappings = map.getMappings() if (mappings.findWhere({ xloc: x, yloc: y })) { return true diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index 272ac030..bc20ec43 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -65,8 +65,7 @@ const PasteInput = { // just try to see if CSV works Import.handleCSV(text) } - }, - + } } export default PasteInput