trying to scope all the modules per map or topic

This commit is contained in:
Connor Turland 2017-03-22 19:20:10 -04:00
parent 663706b1f7
commit f07b97d573
29 changed files with 1366 additions and 1311 deletions

View file

@ -22,11 +22,16 @@
<div class="clearfloat"></div> <div class="clearfloat"></div>
<script> <script>
Metamaps.ServerData = Metamaps.ServerData || {}
Metamaps.ServerData.selectedMetacodes = []
Metamaps.ServerData.newSelectedMetacodes = []
Metamaps.ServerData.selectedMetacodeNames = []
Metamaps.ServerData.newSelectedMetacodeNames = []
<% @metacodes.each do |metacode| %> <% @metacodes.each do |metacode| %>
Metamaps.Create.selectedMetacodes.push("<%= metacode.id %>"); Metamaps.ServerData.selectedMetacodes.push("<%= metacode.id %>");
Metamaps.Create.newSelectedMetacodes.push("<%= metacode.id %>"); Metamaps.ServerData.newSelectedMetacodes.push("<%= metacode.id %>");
Metamaps.Create.selectedMetacodeNames.push("<%= metacode.name %>"); Metamaps.ServerData.selectedMetacodeNames.push("<%= metacode.name %>");
Metamaps.Create.newSelectedMetacodeNames.push("<%= metacode.name %>"); Metamaps.ServerData.newSelectedMetacodeNames.push("<%= metacode.name %>");
<% end %> <% end %>
</script> </script>
<% end %> <% end %>

View file

@ -116,6 +116,7 @@
<div class="clearfloat"></div> <div class="clearfloat"></div>
<script> <script>
Metamaps.Create.selectedMetacodeSet = "metacodeset-<%= selectedSet %>" Metamaps.ServerData = Metamaps.ServerData || {}
Metamaps.Create.selectedMetacodeSetIndex = <%= index %> Metamaps.ServerData.selectedMetacodeSet = "metacodeset-<%= selectedSet %>"
Metamaps.ServerData.selectedMetacodeSetIndex = <%= index %>
</script> </script>

View file

@ -1,7 +1,9 @@
const Active = { const Active = (map = null, mapper = null, topic = null) => {
Map: null, return {
Mapper: null, Map: map,
Topic: null Mapper: mapper,
Topic: topic
}
} }
export default Active export default Active

View file

@ -1,77 +1,79 @@
const AutoLayout = { const AutoLayout = () => {
nextX: 0, return {
nextY: 0, nextX: 0,
sideLength: 1, nextY: 0,
turnCount: 0, sideLength: 1,
nextXshift: 1, turnCount: 0,
nextYshift: 0, nextXshift: 1,
timeToTurn: 0, nextYshift: 0,
timeToTurn: 0,
getNextCoord: function(opts = {}) { getNextCoord: function(opts = {}) {
var self = AutoLayout var self = AutoLayout
var nextX = self.nextX var nextX = self.nextX
var nextY = self.nextY var nextY = self.nextY
var DISTANCE_BETWEEN = 120 var DISTANCE_BETWEEN = 120
self.nextX = self.nextX + DISTANCE_BETWEEN * self.nextXshift self.nextX = self.nextX + DISTANCE_BETWEEN * self.nextXshift
self.nextY = self.nextY + DISTANCE_BETWEEN * self.nextYshift self.nextY = self.nextY + DISTANCE_BETWEEN * self.nextYshift
self.timeToTurn += 1 self.timeToTurn += 1
// if true, it's time to turn // if true, it's time to turn
if (self.timeToTurn === self.sideLength) { if (self.timeToTurn === self.sideLength) {
self.turnCount += 1 self.turnCount += 1
// if true, it's time to increase side length // if true, it's time to increase side length
if (self.turnCount % 2 === 0) { if (self.turnCount % 2 === 0) {
self.sideLength += 1 self.sideLength += 1
}
self.timeToTurn = 0
// going right? turn down
if (self.nextXshift === 1 && self.nextYshift === 0) {
self.nextXshift = 0
self.nextYshift = 1
} else if (self.nextXshift === 0 && self.nextYshift === 1) {
// going down? turn left
self.nextXshift = -1
self.nextYshift = 0
} else if (self.nextXshift === -1 && self.nextYshift === 0) {
// going left? turn up
self.nextXshift = 0
self.nextYshift = -1
} else if (self.nextXshift === 0 && self.nextYshift === -1) {
// going up? turn right
self.nextXshift = 1
self.nextYshift = 0
}
} }
if (opts.mappings && self.coordsTaken(nextX, nextY, opts.mappings)) {
// 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, mappings) {
if (mappings.findWhere({ xloc: x, yloc: y })) {
return true
} else {
return false
}
},
resetSpiral: function() {
var self = AutoLayout
self.nextX = 0
self.nextY = 0
self.nextXshift = 1
self.nextYshift = 0
self.sideLength = 1
self.timeToTurn = 0 self.timeToTurn = 0
self.turnCount = 0
// going right? turn down
if (self.nextXshift === 1 && self.nextYshift === 0) {
self.nextXshift = 0
self.nextYshift = 1
} else if (self.nextXshift === 0 && self.nextYshift === 1) {
// going down? turn left
self.nextXshift = -1
self.nextYshift = 0
} else if (self.nextXshift === -1 && self.nextYshift === 0) {
// going left? turn up
self.nextXshift = 0
self.nextYshift = -1
} else if (self.nextXshift === 0 && self.nextYshift === -1) {
// going up? turn right
self.nextXshift = 1
self.nextYshift = 0
}
} }
if (opts.mappings && self.coordsTaken(nextX, nextY, opts.mappings)) {
// 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, mappings) {
if (mappings.findWhere({ xloc: x, yloc: y })) {
return true
} else {
return false
}
},
resetSpiral: function() {
var self = AutoLayout
self.nextX = 0
self.nextY = 0
self.nextXshift = 1
self.nextYshift = 0
self.sideLength = 1
self.timeToTurn = 0
self.turnCount = 0
} }
} }

View file

@ -2,24 +2,13 @@
import { indexOf } from 'lodash' import { indexOf } from 'lodash'
import Active from './Active'
import Control from './Control'
import DataModel from './DataModel'
import Map from './Map'
import Mapper from './Mapper' import Mapper from './Mapper'
import Synapse from './Synapse'
import Topic from './Topic'
import { ChatView } from './Views'
import Visualize from './Visualize'
const Cable = { const Cable = ({Active, Control, DataModel, Map, Synapse, Topic, ChatView, Visualize}) => {
init: () => { const toExport = {
let self = Cable
self.cable = ActionCable.createConsumer()
},
subscribeToMap: id => { subscribeToMap: id => {
let self = Cable let self = toExport
self.sub = self.cable.subscriptions.create({ self.sub = Cable.cable.subscriptions.create({
channel: 'MapChannel', channel: 'MapChannel',
id: id id: id
}, { }, {
@ -27,7 +16,7 @@ const Cable = {
}) })
}, },
unsubscribeFromMap: () => { unsubscribeFromMap: () => {
let self = Cable let self = toExport
self.sub.unsubscribe() self.sub.unsubscribe()
delete self.sub delete self.sub
}, },
@ -230,5 +219,10 @@ const Cable = {
}) })
} }
} }
return toExport
}
Cable.init = () => {
Cable.cable = ActionCable.createConsumer()
}
export default Cable export default Cable

View file

@ -1,452 +1,448 @@
import _ from 'lodash' import _ from 'lodash'
import outdent from 'outdent' import outdent from 'outdent'
import Active from './Active'
import DataModel from './DataModel'
import Filter from './Filter'
import GlobalUI from './GlobalUI' import GlobalUI from './GlobalUI'
import Mouse from './Mouse'
import Selected from './Selected'
import Settings from './Settings' import Settings from './Settings'
import Visualize from './Visualize'
const Control = { const Control = ({Active, DataModel, Filter, Mouse, Selected, Visualize}) => {
selectNode: function(node, e) { return {
var filtered = node.getData('alpha') === 0 selectNode: function(node, e) {
var filtered = node.getData('alpha') === 0
if (filtered || Selected.Nodes.indexOf(node) !== -1) return if (filtered || Selected.Nodes.indexOf(node) !== -1) return
node.selected = true node.selected = true
node.setData('dim', 30, 'current') node.setData('dim', 30, 'current')
Selected.Nodes.push(node) Selected.Nodes.push(node)
}, },
selectNeighbors: function() { selectNeighbors: function() {
if (Selected.Nodes.length > 0) { if (Selected.Nodes.length > 0) {
//For each selected node, select all connected node and the synapses too //For each selected node, select all connected node and the synapses too
Selected.Nodes.forEach((item) => { Selected.Nodes.forEach((item) => {
if (Visualize.mGraph.graph.getNode(item.id).adjacencies) { if (Visualize.mGraph.graph.getNode(item.id).adjacencies) {
for (const adjID in Visualize.mGraph.graph.getNode(item.id).adjacencies) { for (const adjID in Visualize.mGraph.graph.getNode(item.id).adjacencies) {
Control.selectNode(Visualize.mGraph.graph.getNode(adjID)) Control.selectNode(Visualize.mGraph.graph.getNode(adjID))
Control.selectEdge(Visualize.mGraph.graph.getNode(item.id).adjacencies[adjID]) Control.selectEdge(Visualize.mGraph.graph.getNode(item.id).adjacencies[adjID])
}
} }
} })
})
Visualize.mGraph.plot() Visualize.mGraph.plot()
}
},
deselectAllNodes: function() {
var l = Selected.Nodes.length
for (var i = l - 1; i >= 0; i -= 1) {
var node = Selected.Nodes[i]
Control.deselectNode(node)
}
Visualize.mGraph.plot()
},
deselectNode: function(node) {
delete node.selected
node.setData('dim', 25, 'current')
// remove the node
Selected.Nodes.splice(
Selected.Nodes.indexOf(node), 1)
},
deleteSelected: function() {
if (!Active.Map) return
var n = Selected.Nodes.length
var e = Selected.Edges.length
var ntext = n === 1 ? '1 topic' : n + ' topics'
var etext = e === 1 ? '1 synapse' : e + ' synapses'
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
var r = window.confirm(outdent`
You have ${ntext} and ${etext} selected. Are you sure you want
to permanently delete them all? This will remove them from all
maps they appear on.`)
if (r) {
Control.deleteSelectedEdges()
Control.deleteSelectedNodes()
}
if (DataModel.Topics.length === 0) {
Map.setHasLearnedTopicCreation(false)
}
},
deleteSelectedNodes: function() { // refers to deleting topics permanently
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
var l = Selected.Nodes.length
for (var i = l - 1; i >= 0; i -= 1) {
var node = Selected.Nodes[i]
Control.deleteNode(node.id)
}
},
deleteNode: function(nodeid) { // refers to deleting topics permanently
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
var node = Visualize.mGraph.graph.getNode(nodeid)
var topic = node.getData('topic')
var permToDelete = Active.Mapper.id === topic.get('user_id') || Active.Mapper.get('admin')
if (permToDelete) {
var mapping = node.getData('mapping')
topic.destroy()
DataModel.Mappings.remove(mapping)
Control.hideNode(nodeid)
} else {
GlobalUI.notifyUser('Only topics you created can be deleted')
}
},
removeSelectedNodes: function() { // refers to removing topics permanently from a map
if (Active.Topic) {
// hideNode will handle synapses as well
var nodeids = _.map(Selected.Nodes, function(node) {
return node.id
})
_.each(nodeids, function(nodeid) {
if (Active.Topic.id !== nodeid) {
DataModel.Topics.remove(nodeid)
Control.hideNode(nodeid)
}
})
return
}
if (!Active.Map) return
const l = Selected.Nodes.length
const authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
for (let i = l - 1; i >= 0; i -= 1) {
const node = Selected.Nodes[i]
Control.removeNode(node.id)
}
},
removeNode: function(nodeid) { // refers to removing topics permanently from a map
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
var node = Visualize.mGraph.graph.getNode(nodeid)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
var topic = node.getData('topic')
var mapping = node.getData('mapping')
mapping.destroy()
DataModel.Topics.remove(topic)
Control.hideNode(nodeid)
},
hideSelectedNodes: function() {
const l = Selected.Nodes.length
for (let i = l - 1; i >= 0; i -= 1) {
const node = Selected.Nodes[i]
Control.hideNode(node.id)
}
},
hideNode: function(nodeid) {
var node = Visualize.mGraph.graph.getNode(nodeid)
var graph = Visualize.mGraph
Control.deselectNode(node)
node.setData('alpha', 0, 'end')
node.eachAdjacency(function(adj) {
adj.setData('alpha', 0, 'end')
})
Visualize.mGraph.fx.animate({
modes: ['node-property:alpha',
'edge-property:alpha'
],
duration: 500
})
setTimeout(function() {
if (nodeid === Visualize.mGraph.root) { // && Visualize.type === "RGraph"
var newroot = _.find(graph.graph.nodes, function(n) { return n.id !== nodeid })
graph.root = newroot ? newroot.id : null
} }
Visualize.mGraph.graph.removeNode(nodeid) },
}, 500) deselectAllNodes: function() {
Filter.checkMetacodes() var l = Selected.Nodes.length
Filter.checkMappers() for (var i = l - 1; i >= 0; i -= 1) {
}, var node = Selected.Nodes[i]
selectEdge: function(edge) { Control.deselectNode(node)
var filtered = edge.getData('alpha') === 0 // don't select if the edge is filtered }
Visualize.mGraph.plot()
},
deselectNode: function(node) {
delete node.selected
node.setData('dim', 25, 'current')
if (filtered || Selected.Edges.indexOf(edge) !== -1) return // remove the node
Selected.Nodes.splice(
Selected.Nodes.indexOf(node), 1)
},
deleteSelected: function() {
if (!Active.Map) return
var width = Mouse.edgeHoveringOver === edge ? 4 : 2 var n = Selected.Nodes.length
edge.setDataset('current', { var e = Selected.Edges.length
showDesc: true, var ntext = n === 1 ? '1 topic' : n + ' topics'
lineWidth: width, var etext = e === 1 ? '1 synapse' : e + ' synapses'
color: Settings.colors.synapses.selected
})
Visualize.mGraph.plot()
Selected.Edges.push(edge) var authorized = Active.Map.authorizeToEdit(Active.Mapper)
},
deselectAllEdges: function() {
var l = Selected.Edges.length
for (var i = l - 1; i >= 0; i -= 1) {
var edge = Selected.Edges[i]
Control.deselectEdge(edge)
}
Visualize.mGraph.plot()
},
deselectEdge: function(edge) {
edge.setData('showDesc', false, 'current')
edge.setDataset('current', { if (!authorized) {
lineWidth: 2, GlobalUI.notifyUser('Cannot edit Public map.')
color: Settings.colors.synapses.normal return
}) }
if (Mouse.edgeHoveringOver === edge) { var r = window.confirm(outdent`
You have ${ntext} and ${etext} selected. Are you sure you want
to permanently delete them all? This will remove them from all
maps they appear on.`)
if (r) {
Control.deleteSelectedEdges()
Control.deleteSelectedNodes()
}
if (DataModel.Topics.length === 0) {
Map.setHasLearnedTopicCreation(false)
}
},
deleteSelectedNodes: function() { // refers to deleting topics permanently
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
var l = Selected.Nodes.length
for (var i = l - 1; i >= 0; i -= 1) {
var node = Selected.Nodes[i]
Control.deleteNode(node.id)
}
},
deleteNode: function(nodeid) { // refers to deleting topics permanently
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
var node = Visualize.mGraph.graph.getNode(nodeid)
var topic = node.getData('topic')
var permToDelete = Active.Mapper.id === topic.get('user_id') || Active.Mapper.get('admin')
if (permToDelete) {
var mapping = node.getData('mapping')
topic.destroy()
DataModel.Mappings.remove(mapping)
Control.hideNode(nodeid)
} else {
GlobalUI.notifyUser('Only topics you created can be deleted')
}
},
removeSelectedNodes: function() { // refers to removing topics permanently from a map
if (Active.Topic) {
// hideNode will handle synapses as well
var nodeids = _.map(Selected.Nodes, function(node) {
return node.id
})
_.each(nodeids, function(nodeid) {
if (Active.Topic.id !== nodeid) {
DataModel.Topics.remove(nodeid)
Control.hideNode(nodeid)
}
})
return
}
if (!Active.Map) return
const l = Selected.Nodes.length
const authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
for (let i = l - 1; i >= 0; i -= 1) {
const node = Selected.Nodes[i]
Control.removeNode(node.id)
}
},
removeNode: function(nodeid) { // refers to removing topics permanently from a map
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
var node = Visualize.mGraph.graph.getNode(nodeid)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
var topic = node.getData('topic')
var mapping = node.getData('mapping')
mapping.destroy()
DataModel.Topics.remove(topic)
Control.hideNode(nodeid)
},
hideSelectedNodes: function() {
const l = Selected.Nodes.length
for (let i = l - 1; i >= 0; i -= 1) {
const node = Selected.Nodes[i]
Control.hideNode(node.id)
}
},
hideNode: function(nodeid) {
var node = Visualize.mGraph.graph.getNode(nodeid)
var graph = Visualize.mGraph
Control.deselectNode(node)
node.setData('alpha', 0, 'end')
node.eachAdjacency(function(adj) {
adj.setData('alpha', 0, 'end')
})
Visualize.mGraph.fx.animate({
modes: ['node-property:alpha',
'edge-property:alpha'
],
duration: 500
})
setTimeout(function() {
if (nodeid === Visualize.mGraph.root) { // && Visualize.type === "RGraph"
var newroot = _.find(graph.graph.nodes, function(n) { return n.id !== nodeid })
graph.root = newroot ? newroot.id : null
}
Visualize.mGraph.graph.removeNode(nodeid)
}, 500)
Filter.checkMetacodes()
Filter.checkMappers()
},
selectEdge: function(edge) {
var filtered = edge.getData('alpha') === 0 // don't select if the edge is filtered
if (filtered || Selected.Edges.indexOf(edge) !== -1) return
var width = Mouse.edgeHoveringOver === edge ? 4 : 2
edge.setDataset('current', { edge.setDataset('current', {
showDesc: true, showDesc: true,
lineWidth: 4 lineWidth: width,
color: Settings.colors.synapses.selected
}) })
} Visualize.mGraph.plot()
Visualize.mGraph.plot() Selected.Edges.push(edge)
},
deselectAllEdges: function() {
var l = Selected.Edges.length
for (var i = l - 1; i >= 0; i -= 1) {
var edge = Selected.Edges[i]
Control.deselectEdge(edge)
}
Visualize.mGraph.plot()
},
deselectEdge: function(edge) {
edge.setData('showDesc', false, 'current')
// remove the edge edge.setDataset('current', {
Selected.Edges.splice( lineWidth: 2,
Selected.Edges.indexOf(edge), 1) color: Settings.colors.synapses.normal
}, })
deleteSelectedEdges: function() { // refers to deleting topics permanently
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (Mouse.edgeHoveringOver === edge) {
edge.setDataset('current', {
showDesc: true,
lineWidth: 4
})
}
if (!authorized) { Visualize.mGraph.plot()
GlobalUI.notifyUser('Cannot edit Public map.')
return
}
const l = Selected.Edges.length // remove the edge
for (let i = l - 1; i >= 0; i -= 1) { Selected.Edges.splice(
const edge = Selected.Edges[i] Selected.Edges.indexOf(edge), 1)
Control.deleteEdge(edge) },
} deleteSelectedEdges: function() { // refers to deleting topics permanently
}, if (!Active.Map) return
deleteEdge: function(edge) {
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper) var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) { if (!authorized) {
GlobalUI.notifyUser('Cannot edit Public map.') GlobalUI.notifyUser('Cannot edit Public map.')
return return
} }
var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0 const l = Selected.Edges.length
for (let i = l - 1; i >= 0; i -= 1) {
const edge = Selected.Edges[i]
Control.deleteEdge(edge)
}
},
deleteEdge: function(edge) {
if (!Active.Map) return
var synapse = edge.getData('synapses')[index] var authorized = Active.Map.authorizeToEdit(Active.Mapper)
var mapping = edge.getData('mappings')[index]
var permToDelete = Active.Mapper.id === synapse.get('user_id') || Active.Mapper.get('admin') if (!authorized) {
if (permToDelete) { GlobalUI.notifyUser('Cannot edit Public map.')
if (edge.getData('synapses').length - 1 === 0) { return
}
var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0
var synapse = edge.getData('synapses')[index]
var mapping = edge.getData('mappings')[index]
var permToDelete = Active.Mapper.id === synapse.get('user_id') || Active.Mapper.get('admin')
if (permToDelete) {
if (edge.getData('synapses').length - 1 === 0) {
Control.hideEdge(edge)
}
synapse.destroy()
// the server will destroy the mapping, we just need to remove it here
DataModel.Mappings.remove(mapping)
edge.getData('mappings').splice(index, 1)
edge.getData('synapses').splice(index, 1)
if (edge.getData('displayIndex')) {
delete edge.data.$displayIndex
}
} else {
GlobalUI.notifyUser('Only synapses you created can be deleted')
}
},
removeSelectedEdges: function() {
// Topic view is handled by removeSelectedNodes
if (!Active.Map) return
const l = Selected.Edges.length
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
for (let i = l - 1; i >= 0; i -= 1) {
const edge = Selected.Edges[i]
Control.removeEdge(edge)
}
Selected.Edges = [ ]
},
removeEdge: function(edge) {
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
if (edge.getData('mappings').length - 1 === 0) {
Control.hideEdge(edge) Control.hideEdge(edge)
} }
synapse.destroy()
// the server will destroy the mapping, we just need to remove it here var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0
DataModel.Mappings.remove(mapping)
var synapse = edge.getData('synapses')[index]
var mapping = edge.getData('mappings')[index]
mapping.destroy()
DataModel.Synapses.remove(synapse)
edge.getData('mappings').splice(index, 1) edge.getData('mappings').splice(index, 1)
edge.getData('synapses').splice(index, 1) edge.getData('synapses').splice(index, 1)
if (edge.getData('displayIndex')) { if (edge.getData('displayIndex')) {
delete edge.data.$displayIndex delete edge.data.$displayIndex
} }
} else { },
GlobalUI.notifyUser('Only synapses you created can be deleted') hideSelectedEdges: function() {
} const l = Selected.Edges.length
}, for (let i = l - 1; i >= 0; i -= 1) {
removeSelectedEdges: function() { const edge = Selected.Edges[i]
// Topic view is handled by removeSelectedNodes Control.hideEdge(edge)
if (!Active.Map) return
const l = Selected.Edges.length
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
for (let i = l - 1; i >= 0; i -= 1) {
const edge = Selected.Edges[i]
Control.removeEdge(edge)
}
Selected.Edges = [ ]
},
removeEdge: function(edge) {
if (!Active.Map) return
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
if (!authorized) {
GlobalUI.notifyUser('Cannot edit this map.')
return
}
if (Active.Mapper.get('follow_map_on_contributed')) {
Active.Mapper.followMap(Active.Map.id)
}
if (edge.getData('mappings').length - 1 === 0) {
Control.hideEdge(edge)
}
var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0
var synapse = edge.getData('synapses')[index]
var mapping = edge.getData('mappings')[index]
mapping.destroy()
DataModel.Synapses.remove(synapse)
edge.getData('mappings').splice(index, 1)
edge.getData('synapses').splice(index, 1)
if (edge.getData('displayIndex')) {
delete edge.data.$displayIndex
}
},
hideSelectedEdges: function() {
const l = Selected.Edges.length
for (let i = l - 1; i >= 0; i -= 1) {
const edge = Selected.Edges[i]
Control.hideEdge(edge)
}
Selected.Edges = [ ]
},
hideEdge: function(edge) {
var from = edge.nodeFrom.id
var to = edge.nodeTo.id
edge.setData('alpha', 0, 'end')
Control.deselectEdge(edge)
Visualize.mGraph.fx.animate({
modes: ['edge-property:alpha'],
duration: 500
})
setTimeout(function() {
Visualize.mGraph.graph.removeAdjacence(from, to)
}, 500)
Filter.checkSynapses()
Filter.checkMappers()
},
updateSelectedPermissions: function(permission) {
var edge, synapse, node, topic
GlobalUI.notifyUser('Working...')
// variables to keep track of how many nodes and synapses you had the ability to change the permission of
var nCount = 0
var sCount = 0
// change the permission of the selected synapses, if logged in user is the original creator
const edgesLength = Selected.Edges.length
for (let i = edgesLength - 1; i >= 0; i -= 1) {
edge = Selected.Edges[i]
synapse = edge.getData('synapses')[0]
if (synapse.authorizePermissionChange(Active.Mapper)) {
synapse.save({
permission: permission
})
sCount++
} }
} Selected.Edges = [ ]
},
hideEdge: function(edge) {
var from = edge.nodeFrom.id
var to = edge.nodeTo.id
edge.setData('alpha', 0, 'end')
Control.deselectEdge(edge)
Visualize.mGraph.fx.animate({
modes: ['edge-property:alpha'],
duration: 500
})
setTimeout(function() {
Visualize.mGraph.graph.removeAdjacence(from, to)
}, 500)
Filter.checkSynapses()
Filter.checkMappers()
},
updateSelectedPermissions: function(permission) {
var edge, synapse, node, topic
// change the permission of the selected topics, if logged in user is the original creator GlobalUI.notifyUser('Working...')
const nodesLength = Selected.Nodes.length
for (let i = nodesLength - 1; i >= 0; i -= 1) {
node = Selected.Nodes[i]
topic = node.getData('topic')
if (topic.authorizePermissionChange(Active.Mapper)) { // variables to keep track of how many nodes and synapses you had the ability to change the permission of
topic.save({ var nCount = 0
permission: permission var sCount = 0
})
nCount++ // change the permission of the selected synapses, if logged in user is the original creator
const edgesLength = Selected.Edges.length
for (let i = edgesLength - 1; i >= 0; i -= 1) {
edge = Selected.Edges[i]
synapse = edge.getData('synapses')[0]
if (synapse.authorizePermissionChange(Active.Mapper)) {
synapse.save({
permission: permission
})
sCount++
}
} }
}
var nString = nCount === 1 ? (nCount.toString() + ' topic and ') : (nCount.toString() + ' topics and ') // change the permission of the selected topics, if logged in user is the original creator
var sString = sCount === 1 ? (sCount.toString() + ' synapse') : (sCount.toString() + ' synapses') const nodesLength = Selected.Nodes.length
for (let i = nodesLength - 1; i >= 0; i -= 1) {
node = Selected.Nodes[i]
topic = node.getData('topic')
var message = nString + sString + ' you created updated to ' + permission if (topic.authorizePermissionChange(Active.Mapper)) {
GlobalUI.notifyUser(message) topic.save({
}, permission: permission
updateSelectedMetacodes: function(metacodeId) { })
var node, topic nCount++
}
GlobalUI.notifyUser('Working...')
var metacode = DataModel.Metacodes.get(metacodeId)
// variables to keep track of how many nodes and synapses you had the ability to change the permission of
var nCount = 0
// change the permission of the selected topics, if logged in user is the original creator
var l = Selected.Nodes.length
for (var i = l - 1; i >= 0; i -= 1) {
node = Selected.Nodes[i]
topic = node.getData('topic')
if (topic.authorizeToEdit(Active.Mapper)) {
topic.save({
'metacode_id': metacodeId
})
nCount++
} }
var nString = nCount === 1 ? (nCount.toString() + ' topic and ') : (nCount.toString() + ' topics and ')
var sString = sCount === 1 ? (sCount.toString() + ' synapse') : (sCount.toString() + ' synapses')
var message = nString + sString + ' you created updated to ' + permission
GlobalUI.notifyUser(message)
},
updateSelectedMetacodes: function(metacodeId) {
var node, topic
GlobalUI.notifyUser('Working...')
var metacode = DataModel.Metacodes.get(metacodeId)
// variables to keep track of how many nodes and synapses you had the ability to change the permission of
var nCount = 0
// change the permission of the selected topics, if logged in user is the original creator
var l = Selected.Nodes.length
for (var i = l - 1; i >= 0; i -= 1) {
node = Selected.Nodes[i]
topic = node.getData('topic')
if (topic.authorizeToEdit(Active.Mapper)) {
topic.save({
'metacode_id': metacodeId
})
nCount++
}
}
var nString = nCount === 1 ? (nCount.toString() + ' topic') : (nCount.toString() + ' topics')
var message = nString + ' you can edit updated to ' + metacode.get('name')
GlobalUI.notifyUser(message)
Visualize.mGraph.plot()
} }
var nString = nCount === 1 ? (nCount.toString() + ' topic') : (nCount.toString() + ' topics')
var message = nString + ' you can edit updated to ' + metacode.get('name')
GlobalUI.notifyUser(message)
Visualize.mGraph.plot()
} }
} }

View file

@ -1,15 +1,9 @@
/* global $, Hogan, Bloodhound */ /* global $, Hogan, Bloodhound */
import DataModel from './DataModel'
import Map from './Map'
import Mouse from './Mouse'
import Selected from './Selected'
import Synapse from './Synapse'
import Topic from './Topic'
import Visualize from './Visualize'
import GlobalUI from './GlobalUI' import GlobalUI from './GlobalUI'
const Create = { const toExport = ({DataModel, Map, Mouse, Selected, Synapse, Topic, Visualize}) => {
const toExport = {
isSwitchingSet: false, // indicates whether the metacode set switch lightbox is open isSwitchingSet: false, // indicates whether the metacode set switch lightbox is open
selectedMetacodeSet: null, selectedMetacodeSet: null,
selectedMetacodeSetIndex: null, selectedMetacodeSetIndex: null,
@ -17,52 +11,54 @@ const Create = {
newSelectedMetacodeNames: [], newSelectedMetacodeNames: [],
selectedMetacodes: [], selectedMetacodes: [],
newSelectedMetacodes: [], newSelectedMetacodes: [],
init: function() { init: function(serverData) {
var self = Create toExport.newTopic.init()
self.newTopic.init() toExport.newSynapse.init()
self.newSynapse.init() toExport.selectedMetacodeSet = serverData.selectedMetacodeSet
toExport.selectedMetacodeSetIndex = serverData.selectedMetacodeSetIndex
toExport.selectedMetacodes = serverData.selectedMetacodes
toExport.newSelectedMetacodes = serverData.newSelectedMetacodes
toExport.selectedMetacodeNames = serverData.newSelectedMetacodeNames
toExport.newSelectedMetacodeNames = serverData.newSelectedMetacodeNames
// // SWITCHING METACODE SETS // // SWITCHING METACODE SETS
$('#metacodeSwitchTabs').tabs({ $('#metacodeSwitchTabs').tabs({
active: self.selectedMetacodeSetIndex active: toExport.selectedMetacodeSetIndex
}).addClass('ui-tabs-vertical ui-helper-clearfix') }).addClass('ui-tabs-vertical ui-helper-clearfix')
$('#metacodeSwitchTabs .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left') $('#metacodeSwitchTabs .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left')
$('.customMetacodeList li').click(self.toggleMetacodeSelected) // within the custom metacode set tab $('.customMetacodeList li').click(toExport.toggleMetacodeSelected) // within the custom metacode set tab
$('.selectAll').click(self.metacodeSelectorSelectAll) $('.selectAll').click(toExport.metacodeSelectorSelectAll)
$('.selectNone').click(self.metacodeSelectorSelectNone) $('.selectNone').click(toExport.metacodeSelectorSelectNone)
}, },
toggleMetacodeSelected: function() { toggleMetacodeSelected: function() {
var self = Create
if ($(this).attr('class') !== 'toggledOff') { if ($(this).attr('class') !== 'toggledOff') {
$(this).addClass('toggledOff') $(this).addClass('toggledOff')
var valueToRemove = $(this).attr('id') var valueToRemove = $(this).attr('id')
var nameToRemove = $(this).attr('data-name') var nameToRemove = $(this).attr('data-name')
self.newSelectedMetacodes.splice(self.newSelectedMetacodes.indexOf(valueToRemove), 1) toExport.newSelectedMetacodes.splice(self.newSelectedMetacodes.indexOf(valueToRemove), 1)
self.newSelectedMetacodeNames.splice(self.newSelectedMetacodeNames.indexOf(nameToRemove), 1) toExport.newSelectedMetacodeNames.splice(self.newSelectedMetacodeNames.indexOf(nameToRemove), 1)
} else if ($(this).attr('class') === 'toggledOff') { } else if ($(this).attr('class') === 'toggledOff') {
$(this).removeClass('toggledOff') $(this).removeClass('toggledOff')
self.newSelectedMetacodes.push($(this).attr('id')) toExport.newSelectedMetacodes.push($(this).attr('id'))
self.newSelectedMetacodeNames.push($(this).attr('data-name')) toExport.newSelectedMetacodeNames.push($(this).attr('data-name'))
} }
self.updateSelectAllColors() toExport.updateSelectAllColors()
}, },
updateSelectAllColors: function() { updateSelectAllColors: function() {
$('.selectAll, .selectNone').removeClass('selected') $('.selectAll, .selectNone').removeClass('selected')
if (Create.metacodeSelectorAreAllSelected()) { if (toExport.metacodeSelectorAreAllSelected()) {
$('.selectAll').addClass('selected') $('.selectAll').addClass('selected')
} else if (Create.metacodeSelectorAreNoneSelected()) { } else if (toExport.metacodeSelectorAreNoneSelected()) {
$('.selectNone').addClass('selected') $('.selectNone').addClass('selected')
} }
}, },
metacodeSelectorSelectAll: function() { metacodeSelectorSelectAll: function() {
$('.customMetacodeList li.toggledOff').each(Create.toggleMetacodeSelected) $('.customMetacodeList li.toggledOff').each(toExport.toggleMetacodeSelected)
Create.updateSelectAllColors() toExport.updateSelectAllColors()
}, },
metacodeSelectorSelectNone: function() { metacodeSelectorSelectNone: function() {
$('.customMetacodeList li').not('.toggledOff').each(Create.toggleMetacodeSelected) $('.customMetacodeList li').not('.toggledOff').each(toExport.toggleMetacodeSelected)
Create.updateSelectAllColors() toExport.updateSelectAllColors()
}, },
metacodeSelectorAreAllSelected: function() { metacodeSelectorAreAllSelected: function() {
return $('.customMetacodeList li').toArray() return $('.customMetacodeList li').toArray()
@ -75,41 +71,41 @@ const Create = {
.reduce((curr, prev) => curr && prev) .reduce((curr, prev) => curr && prev)
}, },
metacodeSelectorToggleSelectAll: function() { metacodeSelectorToggleSelectAll: function() {
// should be called when Create.isSwitchingSet is true and .customMetacodeList is visible // should be called when toExport.isSwitchingSet is true and .customMetacodeList is visible
if (!Create.isSwitchingSet) return if (!toExport.isSwitchingSet) return
if (!$('.customMetacodeList').is(':visible')) return if (!$('.customMetacodeList').is(':visible')) return
// If all are selected, then select none. Otherwise, select all. // If all are selected, then select none. Otherwise, select all.
if (Create.metacodeSelectorAreAllSelected()) { if (toExport.metacodeSelectorAreAllSelected()) {
Create.metacodeSelectorSelectNone() toExport.metacodeSelectorSelectNone()
} else { } else {
// if some, but not all, are selected, it still runs this function // if some, but not all, are selected, it still runs this function
Create.metacodeSelectorSelectAll() toExport.metacodeSelectorSelectAll()
} }
}, },
updateMetacodeSet: function(set, index, custom) { updateMetacodeSet: function(set, index, custom) {
if (custom && Create.newSelectedMetacodes.length === 0) { if (custom && toExport.newSelectedMetacodes.length === 0) {
window.alert('Please select at least one metacode to use!') window.alert('Please select at least one metacode to use!')
return false return false
} }
var codesToSwitchToIds var codesToSwitchToIds
var metacodeModels = new DataModel.MetacodeCollection() var metacodeModels = new DataModel.MetacodeCollection()
Create.selectedMetacodeSetIndex = index toExport.selectedMetacodeSetIndex = index
Create.selectedMetacodeSet = 'metacodeset-' + set toExport.selectedMetacodeSet = 'metacodeset-' + set
if (!custom) { if (!custom) {
codesToSwitchToIds = $('#metacodeSwitchTabs' + set).attr('data-metacodes').split(',') codesToSwitchToIds = $('#metacodeSwitchTabs' + set).attr('data-metacodes').split(',')
$('.customMetacodeList li').addClass('toggledOff') $('.customMetacodeList li').addClass('toggledOff')
Create.selectedMetacodes = [] toExport.selectedMetacodes = []
Create.selectedMetacodeNames = [] toExport.selectedMetacodeNames = []
Create.newSelectedMetacodes = [] toExport.newSelectedMetacodes = []
Create.newSelectedMetacodeNames = [] toExport.newSelectedMetacodeNames = []
} else if (custom) { } else if (custom) {
// uses .slice to avoid setting the two arrays to the same actual array // uses .slice to avoid setting the two arrays to the same actual array
Create.selectedMetacodes = Create.newSelectedMetacodes.slice(0) toExport.selectedMetacodes = Create.newSelectedMetacodes.slice(0)
Create.selectedMetacodeNames = Create.newSelectedMetacodeNames.slice(0) toExport.selectedMetacodeNames = Create.newSelectedMetacodeNames.slice(0)
codesToSwitchToIds = Create.selectedMetacodes.slice(0) codesToSwitchToIds = toExport.selectedMetacodes.slice(0)
} }
// sort by name // sort by name
@ -141,7 +137,7 @@ const Create = {
var mdata = { var mdata = {
'metacodes': { 'metacodes': {
'value': custom ? Create.selectedMetacodes.toString() : Create.selectedMetacodeSet 'value': custom ? toExport.selectedMetacodes.toString() : Create.selectedMetacodeSet
} }
} }
$.ajax({ $.ajax({
@ -158,26 +154,25 @@ const Create = {
}) })
}, },
cancelMetacodeSetSwitch: function() { cancelMetacodeSetSwitch: function() {
var self = Create toExport.isSwitchingSet = false
self.isSwitchingSet = false
if (self.selectedMetacodeSet !== 'metacodeset-custom') { if (toExport.selectedMetacodeSet !== 'metacodeset-custom') {
$('.customMetacodeList li').addClass('toggledOff') $('.customMetacodeList li').addClass('toggledOff')
self.selectedMetacodes = [] toExport.selectedMetacodes = []
self.selectedMetacodeNames = [] toExport.selectedMetacodeNames = []
self.newSelectedMetacodes = [] toExport.newSelectedMetacodes = []
self.newSelectedMetacodeNames = [] toExport.newSelectedMetacodeNames = []
} else { // custom set is selected } else { // custom set is selected
// reset it to the current actual selection // reset it to the current actual selection
$('.customMetacodeList li').addClass('toggledOff') $('.customMetacodeList li').addClass('toggledOff')
for (var i = 0; i < self.selectedMetacodes.length; i++) { for (var i = 0; i < toExport.selectedMetacodes.length; i++) {
$('#' + self.selectedMetacodes[i]).removeClass('toggledOff') $('#' + toExport.selectedMetacodes[i]).removeClass('toggledOff')
} }
// uses .slice to avoid setting the two arrays to the same actual array // uses .slice to avoid setting the two arrays to the same actual array
self.newSelectedMetacodeNames = self.selectedMetacodeNames.slice(0) toExport.newSelectedMetacodeNames = self.selectedMetacodeNames.slice(0)
self.newSelectedMetacodes = self.selectedMetacodes.slice(0) toExport.newSelectedMetacodes = self.selectedMetacodes.slice(0)
} }
$('#metacodeSwitchTabs').tabs('option', 'active', self.selectedMetacodeSetIndex) $('#metacodeSwitchTabs').tabs('option', 'active', toExport.selectedMetacodeSetIndex)
$('#topic_name').focus() $('#topic_name').focus()
}, },
newTopic: { newTopic: {
@ -186,19 +181,19 @@ const Create = {
const ESC = 27 const ESC = 27
if (e.keyCode === ESC) { if (e.keyCode === ESC) {
Create.newTopic.hide() toExport.newTopic.hide()
} // if } // if
Create.newTopic.name = $(this).val() toExport.newTopic.name = $(this).val()
}) })
$('.pinCarousel').click(function() { $('.pinCarousel').click(function() {
if (Create.newTopic.pinned) { if (toExport.newTopic.pinned) {
$('.pinCarousel').removeClass('isPinned') $('.pinCarousel').removeClass('isPinned')
Create.newTopic.pinned = false toExport.newTopic.pinned = false
} else { } else {
$('.pinCarousel').addClass('isPinned') $('.pinCarousel').addClass('isPinned')
Create.newTopic.pinned = true toExport.newTopic.pinned = true
} }
}) })
@ -232,7 +227,7 @@ const Create = {
// tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete // tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete
$('#topic_name').bind('typeahead:select', function(event, datum, dataset) { $('#topic_name').bind('typeahead:select', function(event, datum, dataset) {
Create.newTopic.beingCreated = false toExport.newTopic.beingCreated = false
if (datum.rtype === 'topic') { if (datum.rtype === 'topic') {
Topic.getTopicFromAutocomplete(datum.id) Topic.getTopicFromAutocomplete(datum.id)
} else if (datum.rtype === 'map') { } else if (datum.rtype === 'map') {
@ -259,7 +254,7 @@ const Create = {
}, },
name: null, name: null,
newId: 1, newId: 1,
beingCreated: false, beingtoExportd: false,
metacode: null, metacode: null,
x: null, x: null,
y: null, y: null,
@ -269,22 +264,22 @@ const Create = {
$('#new_topic').fadeIn('fast', function() { $('#new_topic').fadeIn('fast', function() {
$('#topic_name').focus() $('#topic_name').focus()
}) })
Create.newTopic.beingCreated = true toExport.newTopic.beingCreated = true
Create.newTopic.name = '' toExport.newTopic.name = ''
Map.setHasLearnedTopicCreation(true) //Map.setHasLearnedTopicCreation(true)
}, },
hide: function(force) { hide: function(force) {
if (force || !Create.newTopic.pinned) { if (force || !toExport.newTopic.pinned) {
$('#new_topic').fadeOut('fast') $('#new_topic').fadeOut('fast')
} }
if (force) { if (force) {
$('.pinCarousel').removeClass('isPinned') $('.pinCarousel').removeClass('isPinned')
Create.newTopic.pinned = false toExport.newTopic.pinned = false
} }
if (DataModel.Topics.length === 0) { if (DataModel.Topics.length === 0) {
Map.setHasLearnedTopicCreation(false) Map.setHasLearnedTopicCreation(false)
} }
Create.newTopic.beingCreated = false toExport.newTopic.beingCreated = false
}, },
reset: function() { reset: function() {
$('#topic_name').typeahead('val', '') $('#topic_name').typeahead('val', '')
@ -306,9 +301,8 @@ const Create = {
remote: { remote: {
url: '/search/synapses?topic1id=%TOPIC1&topic2id=%TOPIC2', url: '/search/synapses?topic1id=%TOPIC1&topic2id=%TOPIC2',
prepare: function(query, settings) { prepare: function(query, settings) {
var self = Create.newSynapse if (Selected.Nodes.length < 2 && toExport.newSynapse.topic1id && self.newSynapse.topic2id) {
if (Selected.Nodes.length < 2 && self.topic1id && self.topic2id) { settings.url = settings.url.replace('%TOPIC1', toExport.newSynapse.topic1id).replace('%TOPIC2', toExport.newSynapse.topic2id)
settings.url = settings.url.replace('%TOPIC1', self.topic1id).replace('%TOPIC2', self.topic2id)
return settings return settings
} else { } else {
return null return null
@ -351,21 +345,21 @@ const Create = {
const ESC = 27 const ESC = 27
if (e.keyCode === ESC) { if (e.keyCode === ESC) {
Create.newSynapse.hide() toExport.newSynapse.hide()
} // if } // if
Create.newSynapse.description = $(this).val() toExport.newSynapse.description = $(this).val()
}) })
$('#synapse_desc').focusout(function() { $('#synapse_desc').focusout(function() {
if (Create.newSynapse.beingCreated) { if (toExport.newSynapse.beingCreated) {
Synapse.createSynapseLocally() Synapse.createSynapseLocally()
} }
}) })
$('#synapse_desc').keydown(function(e) { $('#synapse_desc').keydown(function(e) {
const TAB = 9 const TAB = 9
if (Create.newSynapse.beingCreated && e.keyCode === TAB) { if (toExport.newSynapse.beingCreated && e.keyCode === TAB) {
e.preventDefault() e.preventDefault()
Synapse.createSynapseLocally() Synapse.createSynapseLocally()
} }
@ -375,12 +369,12 @@ const Create = {
if (datum.id) { // if they clicked on an existing synapse get it if (datum.id) { // if they clicked on an existing synapse get it
Synapse.getSynapseFromAutocomplete(datum.id) Synapse.getSynapseFromAutocomplete(datum.id)
} else { } else {
Create.newSynapse.description = datum.value toExport.newSynapse.description = datum.value
Synapse.createSynapseLocally() Synapse.createSynapseLocally()
} }
}) })
}, },
beingCreated: false, beingtoExportd: false,
description: null, description: null,
topic1id: null, topic1id: null,
topic2id: null, topic2id: null,
@ -389,19 +383,21 @@ const Create = {
$('#new_synapse').fadeIn(100, function() { $('#new_synapse').fadeIn(100, function() {
$('#synapse_desc').focus() $('#synapse_desc').focus()
}) })
Create.newSynapse.beingCreated = true toExport.newSynapse.beingCreated = true
}, },
hide: function() { hide: function() {
$('#new_synapse').fadeOut('fast') $('#new_synapse').fadeOut('fast')
$('#synapse_desc').typeahead('val', '') $('#synapse_desc').typeahead('val', '')
Create.newSynapse.beingCreated = false toExport.newSynapse.beingCreated = false
Create.newTopic.addSynapse = false toExport.newTopic.addSynapse = false
Create.newSynapse.topic1id = 0 toExport.newSynapse.topic1id = 0
Create.newSynapse.topic2id = 0 toExport.newSynapse.topic2id = 0
Mouse.synapseStartCoordinates = [] Mouse.synapseStartCoordinates = []
if (Visualize.mGraph) Visualize.mGraph.plot() if (Visualize.mGraph) Visualize.mGraph.plot()
} }
} }
} }
return toExport
}
export default Create export default toExport

View file

@ -1,7 +1,3 @@
import Active from '../Active'
import Filter from '../Filter'
import { InfoBox } from '../Map'
import Map from './Map' import Map from './Map'
import MapCollection from './MapCollection' import MapCollection from './MapCollection'
import Message from './Message' import Message from './Message'
@ -17,57 +13,20 @@ import SynapseCollection from './SynapseCollection'
import Mapping from './Mapping' import Mapping from './Mapping'
import MappingCollection from './MappingCollection' import MappingCollection from './MappingCollection'
const DataModel = { const DataModel = ({Filter, InfoBox}) => {
Map: Map, const toExport = {
MapCollection: MapCollection,
Message: Message,
MessageCollection: MessageCollection,
Mapper: Mapper,
MapperCollection: MapperCollection,
Metacode: Metacode,
MetacodeCollection: MetacodeCollection,
Topic: Topic,
TopicCollection: TopicCollection,
Synapse: Synapse,
SynapseCollection: SynapseCollection,
Mapping: Mapping,
MappingCollection: MappingCollection,
Collaborators: new MapperCollection(), Collaborators: new MapperCollection(),
Creators: new MapperCollection(), Creators: new MapperCollection(),
Mappers: new MapperCollection(), Mappers: new MapperCollection(),
Mappings: new MappingCollection(), Mappings: new MappingCollection(),
Maps: {
Mine: [],
Shared: [],
Starred: [],
Mapper: {
models: [],
mapperId: null
},
Featured: [],
Active: []
},
Messages: [], Messages: [],
Metacodes: new MetacodeCollection(), Metacodes: new MetacodeCollection(),
Stars: [], Stars: [],
Synapses: new SynapseCollection(), Synapses: new SynapseCollection(),
Topics: new TopicCollection(), Topics: new TopicCollection(),
setMap: function(serverData) {
init: function(serverData) { var self = toExport
var self = DataModel
// workaround circular import problem
if (!self.MapCollection.model) self.MapCollection.model = Map
self.synapseIconUrl = serverData['synapse16.png']
if (serverData.ActiveMap) Active.Map = new Map(serverData.ActiveMap)
if (serverData.ActiveMapper) Active.Mapper = new Mapper(serverData.ActiveMapper)
if (serverData.ActiveTopic) Active.Topic = new Topic(serverData.ActiveTopic)
if (serverData.Collaborators) self.Collaborators = new MapperCollection(serverData.Collaborators) if (serverData.Collaborators) self.Collaborators = new MapperCollection(serverData.Collaborators)
if (serverData.Creators) self.Creators = new MapperCollection(serverData.Creators)
if (serverData.Mappers) self.Mappers = new MapperCollection(serverData.Mappers) if (serverData.Mappers) self.Mappers = new MapperCollection(serverData.Mappers)
if (serverData.Mappings) self.Mappings = new MappingCollection(serverData.Mappings) if (serverData.Mappings) self.Mappings = new MappingCollection(serverData.Mappings)
if (serverData.Messages) self.Messages = serverData.Messages if (serverData.Messages) self.Messages = serverData.Messages
@ -75,42 +34,28 @@ const DataModel = {
if (serverData.Stars) self.Stars = serverData.Stars if (serverData.Stars) self.Stars = serverData.Stars
if (serverData.Synapses) self.Synapses = new SynapseCollection(serverData.Synapses) if (serverData.Synapses) self.Synapses = new SynapseCollection(serverData.Synapses)
if (serverData.Topics) self.Topics = new TopicCollection(serverData.Topics) if (serverData.Topics) self.Topics = new TopicCollection(serverData.Topics)
self.attachCollectionEvents()
// initialize global backbone models and collections },
var myCollection = serverData.Mine ? serverData.Mine : [] setTopic: function(serverData) {
var sharedCollection = serverData.Shared ? serverData.Shared : [] var self = toExport
var starredCollection = serverData.Starred ? serverData.Starred : [] if (serverData.Creators) self.Creators = new MapperCollection(serverData.Creators)
var mapperCollection = serverData.Mapper ? serverData.Mapper : [] if (serverData.Metacodes) self.Metacodes = new MetacodeCollection(serverData.Metacodes)
var mapperOptionsObj = { id: 'mapper', sortBy: 'updated_at' } if (serverData.Synapses) self.Synapses = new SynapseCollection(serverData.Synapses)
if (serverData.Mapper && serverData.Mapper.mapperId) { if (serverData.Topics) self.Topics = new TopicCollection(serverData.Topics)
mapperCollection = serverData.Mapper.models
mapperOptionsObj.mapperId = serverData.Mapper.mapperId
}
var featuredCollection = serverData.Featured ? serverData.Featured : []
var activeCollection = serverData.Active ? serverData.Active : []
self.Maps.Mine = new MapCollection(myCollection, { id: 'mine', sortBy: 'updated_at' })
self.Maps.Shared = new MapCollection(sharedCollection, { id: 'shared', sortBy: 'updated_at' })
self.Maps.Starred = new MapCollection(starredCollection, { id: 'starred', sortBy: 'updated_at' })
// 'Mapper' refers to another mapper
self.Maps.Mapper = new MapCollection(mapperCollection, mapperOptionsObj)
self.Maps.Featured = new MapCollection(featuredCollection, { id: 'featured', sortBy: 'updated_at' })
self.Maps.Active = new MapCollection(activeCollection, { id: 'active', sortBy: 'updated_at' })
self.attachCollectionEvents() self.attachCollectionEvents()
}, },
attachCollectionEvents: function() { attachCollectionEvents: function() {
DataModel.Topics.on('add remove', function(topic) { toExport.Topics.on('add remove', function(topic) {
InfoBox.updateNumbers() InfoBox.updateNumbers()
Filter.checkMetacodes() Filter.checkMetacodes()
Filter.checkMappers() Filter.checkMappers()
}) })
DataModel.Synapses.on('add remove', function(synapse) { toExport.Synapses.on('add remove', function(synapse) {
InfoBox.updateNumbers() InfoBox.updateNumbers()
Filter.checkSynapses() Filter.checkSynapses()
Filter.checkMappers() Filter.checkMappers()
}) })
DataModel.Mappings.on('add remove', function(mapping) { toExport.Mappings.on('add remove', function(mapping) {
InfoBox.updateNumbers() InfoBox.updateNumbers()
Filter.checkSynapses() Filter.checkSynapses()
Filter.checkMetacodes() Filter.checkMetacodes()
@ -118,7 +63,43 @@ const DataModel = {
}) })
} }
} }
return toExport
}
DataModel.Maps = {
Mine: [],
Shared: [],
Starred: [],
Mapper: {
models: [],
mapperId: null
},
Featured: [],
Active: []
}
DataModel.init = function(serverData) {
var self = DataModel
self.synapseIconUrl = serverData['synapse16.png']
// initialize global backbone models and collections
var myCollection = serverData.Mine ? serverData.Mine : []
var sharedCollection = serverData.Shared ? serverData.Shared : []
var starredCollection = serverData.Starred ? serverData.Starred : []
var mapperCollection = serverData.Mapper ? serverData.Mapper : []
var mapperOptionsObj = { id: 'mapper', sortBy: 'updated_at' }
if (serverData.Mapper && serverData.Mapper.mapperId) {
mapperCollection = serverData.Mapper.models
mapperOptionsObj.mapperId = serverData.Mapper.mapperId
}
var featuredCollection = serverData.Featured ? serverData.Featured : []
var activeCollection = serverData.Active ? serverData.Active : []
self.Maps.Mine = new MapCollection(myCollection, { id: 'mine', sortBy: 'updated_at' })
self.Maps.Shared = new MapCollection(sharedCollection, { id: 'shared', sortBy: 'updated_at' })
self.Maps.Starred = new MapCollection(starredCollection, { id: 'starred', sortBy: 'updated_at' })
// 'Mapper' refers to another mapper
self.Maps.Mapper = new MapCollection(mapperCollection, mapperOptionsObj)
self.Maps.Featured = new MapCollection(featuredCollection, { id: 'featured', sortBy: 'updated_at' })
self.Maps.Active = new MapCollection(activeCollection, { id: 'active', sortBy: 'updated_at' })
}
// Note: Topics, Metacodes, Synapses, Mappers, Mappings, Collaborators, Creators are not exported // Note: Topics, Metacodes, Synapses, Mappers, Mappings, Collaborators, Creators are not exported
// You can access them by importing DataModel // You can access them by importing DataModel

View file

@ -2,14 +2,11 @@
import _ from 'lodash' import _ from 'lodash'
import Active from './Active'
import Control from './Control'
import DataModel from './DataModel'
import GlobalUI, { ReactApp } from './GlobalUI' import GlobalUI, { ReactApp } from './GlobalUI'
import Settings from './Settings' import Settings from './Settings'
import Visualize from './Visualize'
const Filter = { const Filter = ({Active, Control, DataModel, Visualize}) => {
const toExport = {
dataForPresentation: { dataForPresentation: {
metacodes: {}, metacodes: {},
mappers: {}, mappers: {},
@ -26,7 +23,7 @@ const Filter = {
synapses: [] synapses: []
}, },
reset: function() { reset: function() {
var self = Filter var self = toExport
self.filters.metacodes = [] self.filters.metacodes = []
self.filters.mappers = [] self.filters.mappers = []
self.filters.synapses = [] self.filters.synapses = []
@ -41,7 +38,7 @@ const Filter = {
// an abstraction function for checkMetacodes, checkMappers, checkSynapses to reduce // an abstraction function for checkMetacodes, checkMappers, checkSynapses to reduce
// code redundancy // code redundancy
updateFilters: function(collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) { updateFilters: function(collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) {
var self = Filter var self = toExport
var newList = [] var newList = []
var removed = [] var removed = []
var added = [] var added = []
@ -97,11 +94,11 @@ const Filter = {
ReactApp.render() ReactApp.render()
}, },
checkMetacodes: function() { checkMetacodes: function() {
var self = Filter var self = toExport
self.updateFilters('Topics', 'metacode_id', 'Metacodes', 'metacodes', 'metacode') self.updateFilters('Topics', 'metacode_id', 'Metacodes', 'metacodes', 'metacode')
}, },
checkMappers: function() { checkMappers: function() {
var self = Filter var self = toExport
if (Active.Map) { if (Active.Map) {
self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper') self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper')
} else { } else {
@ -110,23 +107,23 @@ const Filter = {
} }
}, },
checkSynapses: function() { checkSynapses: function() {
var self = Filter var self = toExport
self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse') self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse')
}, },
filterAllMetacodes: function(toVisible) { filterAllMetacodes: function(toVisible) {
var self = Filter var self = toExport
self.visible.metacodes = toVisible ? self.filters.metacodes.slice() : [] self.visible.metacodes = toVisible ? self.filters.metacodes.slice() : []
ReactApp.render() ReactApp.render()
self.passFilters() self.passFilters()
}, },
filterAllMappers: function(toVisible) { filterAllMappers: function(toVisible) {
var self = Filter var self = toExport
self.visible.mappers = toVisible ? self.filters.mappers.slice() : [] self.visible.mappers = toVisible ? self.filters.mappers.slice() : []
ReactApp.render() ReactApp.render()
self.passFilters() self.passFilters()
}, },
filterAllSynapses: function(toVisible) { filterAllSynapses: function(toVisible) {
var self = Filter var self = toExport
self.visible.synapses = toVisible ? self.filters.synapses.slice() : [] self.visible.synapses = toVisible ? self.filters.synapses.slice() : []
ReactApp.render() ReactApp.render()
self.passFilters() self.passFilters()
@ -135,7 +132,7 @@ const Filter = {
// to reduce code redundancy // to reduce code redundancy
// gets called in the context of a list item in a filter box // gets called in the context of a list item in a filter box
toggleLi: function(whichToFilter, id) { toggleLi: function(whichToFilter, id) {
var self = Filter var self = toExport
if (self.visible[whichToFilter].indexOf(id) === -1) { if (self.visible[whichToFilter].indexOf(id) === -1) {
self.visible[whichToFilter].push(id) self.visible[whichToFilter].push(id)
} else { } else {
@ -146,19 +143,19 @@ const Filter = {
self.passFilters() self.passFilters()
}, },
toggleMetacode: function(id) { toggleMetacode: function(id) {
var self = Filter var self = toExport
self.toggleLi('metacodes', id) self.toggleLi('metacodes', id)
}, },
toggleMapper: function(id) { toggleMapper: function(id) {
var self = Filter var self = toExport
self.toggleLi('mappers', id) self.toggleLi('mappers', id)
}, },
toggleSynapse: function(id) { toggleSynapse: function(id) {
var self = Filter var self = toExport
self.toggleLi('synapses', id) self.toggleLi('synapses', id)
}, },
passFilters: function() { passFilters: function() {
var self = Filter var self = toExport
var visible = self.visible var visible = self.visible
var passesMetacode, passesMapper, passesSynapse var passesMetacode, passesMapper, passesSynapse
@ -276,5 +273,7 @@ const Filter = {
}) })
} }
} }
return toExport
}
export default Filter export default Filter

View file

@ -7,13 +7,12 @@ import { merge } from 'lodash'
import { notifyUser } from './index.js' import { notifyUser } from './index.js'
import ImportDialog from './ImportDialog' import ImportDialog from './ImportDialog'
import Active from '../Active' import Mapper from '../DataModel/Mapper'
import DataModel from '../DataModel'
import { ExploreMaps, ChatView, TopicCard } from '../Views' import { ExploreMaps, ChatView, TopicCard } from '../Views'
import Filter from '../Filter' import Filter from '../Filter'
import JIT from '../JIT' import JIT from '../JIT'
import Realtime from '../Realtime' import Realtime from '../Realtime'
import Map, { InfoBox } from '../Map' import Map, { mapControl } from '../Map'
import Topic from '../Topic' import Topic from '../Topic'
import Visualize from '../Visualize' import Visualize from '../Visualize'
import makeRoutes from '../../components/makeRoutes' import makeRoutes from '../../components/makeRoutes'
@ -27,8 +26,11 @@ const MAX_COLUMNS = 4
const ReactApp = { const ReactApp = {
serverData: {}, serverData: {},
currentUser: null,
mapId: null, mapId: null,
openMap: null,
topicId: null, topicId: null,
openTopic: null,
unreadNotificationsCount: 0, unreadNotificationsCount: 0,
mapsWidth: 0, mapsWidth: 0,
toast: '', toast: '',
@ -36,9 +38,11 @@ const ReactApp = {
mobileTitle: '', mobileTitle: '',
mobileTitleWidth: 0, mobileTitleWidth: 0,
metacodeSets: [], metacodeSets: [],
juntoState: { connectedPeople: {}, liveMaps: {} },
init: function(serverData, openLightbox) { init: function(serverData, openLightbox) {
const self = ReactApp const self = ReactApp
self.serverData = serverData self.serverData = serverData
self.currentUser = new Mapper(serverData.ActiveMapper)
self.unreadNotificationsCount = serverData.unreadNotificationsCount self.unreadNotificationsCount = serverData.unreadNotificationsCount
self.mobileTitle = serverData.mobileTitle self.mobileTitle = serverData.mobileTitle
self.openLightbox = openLightbox self.openLightbox = openLightbox
@ -52,12 +56,13 @@ const ReactApp = {
const pathname = this.state.location.pathname const pathname = this.state.location.pathname
switch (pathname.split('/')[1]) { switch (pathname.split('/')[1]) {
case '': case '':
if (Active.Mapper && Active.Mapper.id) { if (self.currentUser && self.currentUser.id) {
$('#yield').hide() $('#yield').hide()
ExploreMaps.updateFromPath(pathname) ExploreMaps.updateFromPath(pathname)
self.mapId = null self.mapId = null
Active.Map = null self.topicId = null
Active.Topic = null self.openMap = null
self.openTopic = null
} }
break break
case 'explore': case 'explore':
@ -65,19 +70,19 @@ const ReactApp = {
ExploreMaps.updateFromPath(pathname) ExploreMaps.updateFromPath(pathname)
self.mapId = null self.mapId = null
self.topicId = null self.topicId = null
Active.Map = null self.openMap = null
Active.Topic = null self.openTopic = null
break break
case 'topics': case 'topics':
$('#yield').hide() $('#yield').hide()
Active.Map = null self.openMap = null
self.mapId = null self.mapId = null
self.topicId = pathname.split('/')[2] self.topicId = pathname.split('/')[2]
break break
case 'maps': case 'maps':
if (!pathname.includes('request_access')) { if (!pathname.includes('request_access')) {
$('#yield').hide() $('#yield').hide()
Active.Topic = null self.openTopic = null
self.topicId = null self.topicId = null
self.mapId = pathname.split('/')[2] self.mapId = pathname.split('/')[2]
} }
@ -99,14 +104,18 @@ const ReactApp = {
const self = ReactApp const self = ReactApp
return merge({ return merge({
unreadNotificationsCount: self.unreadNotificationsCount, unreadNotificationsCount: self.unreadNotificationsCount,
currentUser: Active.Mapper, currentUser: self.currentUser,
toast: self.toast, toast: self.toast,
mobile: self.mobile, mobile: self.mobile,
mobileTitle: self.mobileTitle, mobileTitle: self.mobileTitle,
mobileTitleWidth: self.mobileTitleWidth, mobileTitleWidth: self.mobileTitleWidth,
mobileTitleClick: (e) => Active.Map && InfoBox.toggleBox(e), mobileTitleClick: (e) => self.openMap && self.openMap.InfoBox.toggleBox(e),
openInviteLightbox: () => self.openLightbox('invite'), openInviteLightbox: () => self.openLightbox('invite'),
serverData: self.serverData serverData: self.serverData,
endActiveMap: mapControl.end,
launchNewMap: mapControl.launch,
mapId: self.mapId,
topicId: self.topicId
}, },
self.getMapProps(), self.getMapProps(),
self.getTopicProps(), self.getTopicProps(),
@ -118,27 +127,27 @@ const ReactApp = {
}, },
getMapProps: function() { getMapProps: function() {
const self = ReactApp const self = ReactApp
if (!self.openMap) return {}
return { return {
mapId: self.mapId, map: self.openMap.Active.Map,
map: Active.Map, hasLearnedTopicCreation: self.openMap.Map.hasLearnedTopicCreation,
hasLearnedTopicCreation: Map.hasLearnedTopicCreation, userRequested: self.openMap.Map.userRequested,
userRequested: Map.userRequested, requestAnswered: self.openMap.Map.requestAnswered,
requestAnswered: Map.requestAnswered, requestApproved: self.openMap.Map.requestApproved,
requestApproved: Map.requestApproved, onRequestAccess: self.openMap.Map.requestAccess,
onRequestAccess: Map.requestAccess, mapIsStarred: self.openMap.Map.mapIsStarred,
mapIsStarred: Map.mapIsStarred, toggleMapInfoBox: self.openMap.InfoBox.toggleBox,
endActiveMap: Map.end, infoBoxHtml: self.openMap.InfoBox.html,
launchNewMap: Map.launch,
toggleMapInfoBox: InfoBox.toggleBox,
infoBoxHtml: InfoBox.html,
openImportLightbox: () => ImportDialog.show(), openImportLightbox: () => ImportDialog.show(),
forkMap: Map.fork, forkMap: self.openMap.Map.fork,
onMapStar: Map.star, onMapStar: self.openMap.Map.star,
onMapUnstar: Map.unstar onMapUnstar: self.openMap.Map.unstar
} }
}, },
getCommonProps: function() { getCommonProps: function() {
const self = ReactApp const self = ReactApp
if (!(self.openMap || self.openTopic)) return {}
const { JIT, Visualize } = self.openMap || self.openTopic
return { return {
openHelpLightbox: () => self.openLightbox('cheatsheet'), openHelpLightbox: () => self.openLightbox('cheatsheet'),
onZoomExtents: event => JIT.zoomExtents(event, Visualize.mGraph.canvas), onZoomExtents: event => JIT.zoomExtents(event, Visualize.mGraph.canvas),
@ -148,20 +157,22 @@ const ReactApp = {
}, },
getTopicCardProps: function() { getTopicCardProps: function() {
const self = ReactApp const self = ReactApp
if (!(self.openMap || self.openTopic)) return {}
const { TopicCard } = self.openMap || self.openTopic
return { return {
openTopic: TopicCard.openTopic, openTopic: TopicCard.openTopic,
metacodeSets: self.metacodeSets, metacodeSets: self.metacodeSets,
updateTopic: (topic, obj) => topic.save(obj), updateTopic: (topic, obj) => topic.save(obj),
onTopicFollow: Topic.onTopicFollow onTopicFollow: Topic.onTopicFollow // todo
} }
}, },
getTopicProps: function() { getTopicProps: function() {
const self = ReactApp const self = ReactApp
if (!self.openTopic) return {}
return { return {
topicId: self.topicId, topic: self.openTopic.Active.Topic,
topic: Active.Topic, endActiveTopic: Topic.end, // todo
endActiveTopic: Topic.end, launchNewTopic: Topic.launch // todo
launchNewTopic: Topic.launch
} }
}, },
getMapsProps: function() { getMapsProps: function() {
@ -169,7 +180,7 @@ const ReactApp = {
return { return {
section: ExploreMaps.collection && ExploreMaps.collection.id, section: ExploreMaps.collection && ExploreMaps.collection.id,
maps: ExploreMaps.collection, maps: ExploreMaps.collection,
juntoState: Realtime.juntoState, juntoState: self.juntoState,
moreToLoad: ExploreMaps.collection && ExploreMaps.collection.page !== 'loadedAll', moreToLoad: ExploreMaps.collection && ExploreMaps.collection.page !== 'loadedAll',
user: ExploreMaps.collection && ExploreMaps.collection.id === 'mapper' ? ExploreMaps.mapper : null, user: ExploreMaps.collection && ExploreMaps.collection.id === 'mapper' ? ExploreMaps.mapper : null,
loadMore: ExploreMaps.loadMore, loadMore: ExploreMaps.loadMore,
@ -182,6 +193,11 @@ const ReactApp = {
}, },
getChatProps: function() { getChatProps: function() {
const self = ReactApp const self = ReactApp
if (!self.openMap) return {
participants: [],
messages: []
}
const { ChatView, Realtime } = self.openMap
return { return {
unreadMessages: ChatView.unreadMessages, unreadMessages: ChatView.unreadMessages,
conversationLive: ChatView.conversationLive, conversationLive: ChatView.conversationLive,
@ -204,6 +220,8 @@ const ReactApp = {
}, },
getFilterProps: function() { getFilterProps: function() {
const self = ReactApp const self = ReactApp
if (!self.openMap) return {}
const { Filter } = self.openMap
return { return {
filterData: Filter.dataForPresentation, filterData: Filter.dataForPresentation,
allForFiltering: Filter.filters, allForFiltering: Filter.filters,
@ -219,7 +237,7 @@ const ReactApp = {
resize: function() { resize: function() {
const self = ReactApp const self = ReactApp
const maps = ExploreMaps.collection const maps = ExploreMaps.collection
const currentUser = Active.Mapper const currentUser = self.currentUser
const user = maps && maps.id === 'mapper' ? ExploreMaps.mapper : null const user = maps && maps.id === 'mapper' ? ExploreMaps.mapper : null
const numCards = (maps ? maps.length : 0) + (user || currentUser ? 1 : 0) const numCards = (maps ? maps.length : 0) + (user || currentUser ? 1 : 0)
const mapSpaces = Math.floor(document.body.clientWidth / MAP_WIDTH) const mapSpaces = Math.floor(document.body.clientWidth / MAP_WIDTH)

View file

@ -3,15 +3,10 @@
import parse from 'csv-parse' import parse from 'csv-parse'
import _ from 'lodash' import _ from 'lodash'
import Active from './Active'
import AutoLayout from './AutoLayout'
import DataModel from './DataModel'
import GlobalUI from './GlobalUI' import GlobalUI from './GlobalUI'
import Map from './Map'
import Synapse from './Synapse'
import Topic from './Topic'
const Import = { const Import = ({Active, AutoLayout, DataModel, Map, Synapse, Topic}) => {
const toExport = {
// note that user is not imported // note that user is not imported
topicWhitelist: [ topicWhitelist: [
'id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission' 'id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission'
@ -22,12 +17,12 @@ const Import = {
cidMappings: {}, // to be filled by importId => cid mappings cidMappings: {}, // to be filled by importId => cid mappings
handleTSV: function(text) { handleTSV: function(text) {
const results = Import.parseTabbedString(text) const results = toExport.parseTabbedString(text)
Import.handle(results) toExport.handle(results)
}, },
handleCSV: function(text, parserOpts = {}) { handleCSV: function(text, parserOpts = {}) {
const self = Import const self = toExport
const topicsRegex = /("?Topics"?[, \t"]*)([\s\S]*)/mi const topicsRegex = /("?Topics"?[, \t"]*)([\s\S]*)/mi
const synapsesRegex = /("?Synapses"?[, \t"]*)([\s\S]*)/mi const synapsesRegex = /("?Synapses"?[, \t"]*)([\s\S]*)/mi
@ -68,11 +63,11 @@ const Import = {
handleJSON: function(text) { handleJSON: function(text) {
const results = JSON.parse(text) const results = JSON.parse(text)
Import.handle(results) toExport.handle(results)
}, },
handle: function(results) { handle: function(results) {
var self = Import var self = toExport
var topics = results.topics.map(topic => self.normalizeKeys(topic)) var topics = results.topics.map(topic => self.normalizeKeys(topic))
var synapses = results.synapses.map(synapse => self.normalizeKeys(synapse)) var synapses = results.synapses.map(synapse => self.normalizeKeys(synapse))
@ -87,7 +82,7 @@ const Import = {
}, },
parseTabbedString: function(text) { parseTabbedString: function(text) {
var self = Import var self = toExport
// determine line ending and split lines // determine line ending and split lines
var delim = '\n' var delim = '\n'
@ -213,7 +208,7 @@ const Import = {
}, },
importTopics: function(parsedTopics) { importTopics: function(parsedTopics) {
var self = Import var self = toExport
parsedTopics.forEach(topic => { parsedTopics.forEach(topic => {
let coords = { x: topic.x, y: topic.y } let coords = { x: topic.x, y: topic.y }
@ -240,7 +235,7 @@ const Import = {
}, },
importSynapses: function(parsedSynapses) { importSynapses: function(parsedSynapses) {
var self = Import var self = toExport
parsedSynapses.forEach(function(synapse) { parsedSynapses.forEach(function(synapse) {
// only createSynapseWithParameters once both topics are persisted // only createSynapseWithParameters once both topics are persisted
@ -279,7 +274,7 @@ const Import = {
createTopicWithParameters: function(name, metacodeName, permission, desc, createTopicWithParameters: function(name, metacodeName, permission, desc,
link, xloc, yloc, importId, opts = {}) { link, xloc, yloc, importId, opts = {}) {
var self = Import var self = toExport
$(document).trigger(Map.events.editedByActiveMapper) $(document).trigger(Map.events.editedByActiveMapper)
var metacode = DataModel.Metacodes.where({name: metacodeName})[0] || null var metacode = DataModel.Metacodes.where({name: metacodeName})[0] || null
if (metacode === null) { if (metacode === null) {
@ -359,7 +354,7 @@ const Import = {
const permission = opts.permission || null // use default const permission = opts.permission || null // use default
const desc = opts.desc || url const desc = opts.desc || url
Import.createTopicWithParameters( toExport.createTopicWithParameters(
name, name,
metacode, metacode,
permission, permission,
@ -423,5 +418,7 @@ const Import = {
}) })
} }
} }
return toExport
}
export default Import export default Import

View file

@ -35,17 +35,6 @@ return {
animationDone: 'Metamaps:JIT:events:animationDone' animationDone: 'Metamaps:JIT:events:animationDone'
}, },
vizData: [], // contains the visualization-compatible graph vizData: [], // contains the visualization-compatible graph
/**
* This method will bind the event handlers it is interested and initialize the class.
*/
init: function(serverData) {
const self = JIT
self.topicDescImage = new Image()
self.topicDescImage.src = serverData['topic_description_signifier.png']
self.topicLinkImage = new Image()
self.topicLinkImage.src = serverData['topic_link_signifier.png']
},
/** /**
* convert our topic JSON into something JIT can use * convert our topic JSON into something JIT can use
*/ */
@ -1968,5 +1957,12 @@ return {
} }
} }
} }
JIT.init = function(serverData) {
JIT.topicDescImage = new Image()
JIT.topicDescImage.src = serverData['topic_description_signifier.png']
JIT.topicLinkImage = new Image()
JIT.topicLinkImage.src = serverData['topic_link_signifier.png']
}
export default JIT export default JIT

View file

@ -5,9 +5,9 @@ import { Search } from './GlobalUI'
const Listeners = ({ Active, Create, Control, DataModel, JIT, Realtime, Selected, Topic, Visualize }) => { const Listeners = ({ Active, Create, Control, DataModel, JIT, Realtime, Selected, Topic, Visualize }) => {
return { return {
init: function() { activate: function() {
var self = this var self = this
$(document).on('keydown', function(e) { $(document).on('keydown.map', function(e) {
if (!(Active.Map || Active.Topic)) return if (!(Active.Map || Active.Topic)) return
const onCanvas = e.target.tagName === 'BODY' const onCanvas = e.target.tagName === 'BODY'
@ -131,7 +131,7 @@ return {
break break
} }
}) })
$(window).resize(function() { $(window).on('resize.map', function() {
if (Visualize && Visualize.mGraph) { if (Visualize && Visualize.mGraph) {
Util.resizeCanvas(Visualize.mGraph.canvas) Util.resizeCanvas(Visualize.mGraph.canvas)
} }

View file

@ -3,12 +3,11 @@
import outdent from 'outdent' import outdent from 'outdent'
import { browserHistory } from 'react-router' import { browserHistory } from 'react-router'
import Active from '../Active'
import DataModel from '../DataModel'
import GlobalUI, { ReactApp } from '../GlobalUI' import GlobalUI, { ReactApp } from '../GlobalUI'
import Util from '../Util' import Util from '../Util'
const InfoBox = { const InfoBox = ({Active, DataModel}) => {
const toExport = {
isOpen: false, isOpen: false,
selectingPermission: false, selectingPermission: false,
changePermissionText: "<div class='tooltips'>As the creator, you can change the permission of this map, and the permission of all the topics and synapses you have authority to change will change as well.</div>", changePermissionText: "<div class='tooltips'>As the creator, you can change the permission of this map, and the permission of all the topics and synapses you have authority to change will change as well.</div>",
@ -36,32 +35,32 @@ const InfoBox = {
userImageUrl: '', userImageUrl: '',
html: '', html: '',
init: function(serverData, updateThumbnail) { init: function(serverData, updateThumbnail) {
var self = InfoBox var self = toExport
self.updateThumbnail = updateThumbnail self.updateThumbnail = updateThumbnail
$('.mapInfoBox').click(function(event) { $('.maptoExport').click(function(event) {
event.stopPropagation() event.stopPropagation()
}) })
$('body').click(self.close) $('body').click(self.close)
self.attachEventListeners() self.attachEventListeners()
self.generateBoxHTML = Hogan.compile($('#mapInfoBoxTemplate').html()) self.generateBoxHTML = Hogan.compile($('#maptoExportTemplate').html())
self.userImageUrl = serverData['user.png'] self.userImageUrl = serverData['user.png']
var querystring = window.location.search.replace(/^\?/, '') var querystring = window.location.search.replace(/^\?/, '')
if (querystring === 'new') { if (querystring === 'new') {
self.open() self.open()
$('.mapInfoBox').addClass('mapRequestTitle') $('.maptoExport').addClass('mapRequestTitle')
$('#mapInfoName').trigger('click') $('#mapInfoName').trigger('click')
$('#mapInfoName textarea').focus() $('#mapInfoName textarea').focus()
$('#mapInfoName textarea').select() $('#mapInfoName textarea').select()
} }
}, },
toggleBox: function(event) { toggleBox: function(event) {
var self = InfoBox var self = toExport
if (self.isOpen) self.close() if (self.isOpen) self.close()
else self.open() else self.open()
@ -69,23 +68,23 @@ const InfoBox = {
event.stopPropagation() event.stopPropagation()
}, },
open: function() { open: function() {
var self = InfoBox var self = toExport
$('.mapInfoIcon div').addClass('hide') $('.mapInfoIcon div').addClass('hide')
$('.mapInfoBox').fadeIn(200, function() { $('.maptoExport').fadeIn(200, function() {
self.isOpen = true self.isOpen = true
}) })
}, },
close: function() { close: function() {
var self = InfoBox var self = toExport
$('.mapInfoIcon div').removeClass('hide') $('.mapInfoIcon div').removeClass('hide')
$('.mapInfoBox').fadeOut(200, function() { $('.maptoExport').fadeOut(200, function() {
self.isOpen = false self.isOpen = false
self.hidePermissionSelect() self.hidePermissionSelect()
$('.mapContributors .tip').hide() $('.mapContributors .tip').hide()
}) })
}, },
load: function() { load: function() {
var self = InfoBox var self = toExport
var map = Active.Map var map = Active.Map
@ -115,12 +114,12 @@ const InfoBox = {
self.attachEventListeners() self.attachEventListeners()
}, },
attachEventListeners: function() { attachEventListeners: function() {
var self = InfoBox var self = toExport
$('.mapInfoBox.canEdit .best_in_place').best_in_place() $('.maptoExport.canEdit .best_in_place').best_in_place()
// because anyone who can edit the map can change the map title // because anyone who can edit the map can change the map title
var bipName = $('.mapInfoBox .best_in_place_name') var bipName = $('.maptoExport .best_in_place_name')
bipName.unbind('best_in_place:activate').bind('best_in_place:activate', function() { bipName.unbind('best_in_place:activate').bind('best_in_place:activate', function() {
var $el = bipName.find('textarea') var $el = bipName.find('textarea')
var el = $el[0] var el = $el[0]
@ -144,7 +143,7 @@ const InfoBox = {
Active.Map.trigger('saved') Active.Map.trigger('saved')
// mobile menu // mobile menu
$('#header_content').html(name) $('#header_content').html(name)
$('.mapInfoBox').removeClass('mapRequestTitle') $('.maptoExport').removeClass('mapRequestTitle')
document.title = `${name} | Metamaps` document.title = `${name} | Metamaps`
window.history.replaceState('', `${name} | Metamaps`, window.location.pathname) window.history.replaceState('', `${name} | Metamaps`, window.location.pathname)
}) })
@ -164,8 +163,8 @@ const InfoBox = {
$('.yourMap .mapPermission').unbind().click(self.onPermissionClick) $('.yourMap .mapPermission').unbind().click(self.onPermissionClick)
// .yourMap in the unbind/bind is just a namespace for the events // .yourMap in the unbind/bind is just a namespace for the events
// not a reference to the class .yourMap on the .mapInfoBox // not a reference to the class .yourMap on the .maptoExport
$('.mapInfoBox.yourMap').unbind('.yourMap').bind('click.yourMap', self.hidePermissionSelect) $('.maptoExport.yourMap').unbind('.yourMap').bind('click.yourMap', self.hidePermissionSelect)
$('.yourMap .mapInfoDelete').unbind().click(self.deleteActiveMap) $('.yourMap .mapInfoDelete').unbind().click(self.deleteActiveMap)
$('.mapInfoThumbnail').unbind().click(self.updateThumbnail) $('.mapInfoThumbnail').unbind().click(self.updateThumbnail)
@ -178,14 +177,14 @@ const InfoBox = {
event.stopPropagation() event.stopPropagation()
}) })
$('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function() { $('.maptoExport').unbind('.hideTip').bind('click.hideTip', function() {
$('.mapContributors .tip').hide() $('.mapContributors .tip').hide()
}) })
self.addTypeahead() self.addTypeahead()
}, },
addTypeahead: function() { addTypeahead: function() {
var self = InfoBox var self = toExport
if (!Active.Map) return if (!Active.Map) return
@ -232,14 +231,14 @@ const InfoBox = {
} }
}, },
removeCollaborator: function(collaboratorId) { removeCollaborator: function(collaboratorId) {
var self = InfoBox var self = toExport
DataModel.Collaborators.remove(DataModel.Collaborators.get(collaboratorId)) DataModel.Collaborators.remove(DataModel.Collaborators.get(collaboratorId))
var mapperIds = DataModel.Collaborators.models.map(function(mapper) { return mapper.id }) var mapperIds = DataModel.Collaborators.models.map(function(mapper) { return mapper.id })
$.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds })
self.updateNumbers() self.updateNumbers()
}, },
addCollaborator: function(newCollaboratorId) { addCollaborator: function(newCollaboratorId) {
var self = InfoBox var self = toExport
if (DataModel.Collaborators.get(newCollaboratorId)) { if (DataModel.Collaborators.get(newCollaboratorId)) {
GlobalUI.notifyUser('That user already has access') GlobalUI.notifyUser('That user already has access')
@ -258,16 +257,16 @@ const InfoBox = {
$.getJSON('/users/' + newCollaboratorId + '.json', callback) $.getJSON('/users/' + newCollaboratorId + '.json', callback)
}, },
handleResultClick: function(event, item) { handleResultClick: function(event, item) {
var self = InfoBox var self = toExport
self.addCollaborator(item.id) self.addCollaborator(item.id)
$('.collaboratorSearchField').typeahead('val', '') $('.collaboratorSearchField').typeahead('val', '')
}, },
updateNameDescPerm: function(name, desc, perm) { updateNameDescPerm: function(name, desc, perm) {
$('.mapInfoBox').removeClass('mapRequestTitle') $('.maptoExport').removeClass('mapRequestTitle')
$('.mapInfoName .best_in_place_name').html(name) $('.mapInfoName .best_in_place_name').html(name)
$('.mapInfoDesc .best_in_place_desc').html(desc) $('.mapInfoDesc .best_in_place_desc').html(desc)
$('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm) $('.maptoExport .mapPermission').removeClass('commons public private').addClass(perm)
}, },
createContributorList: function() { createContributorList: function() {
var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
@ -294,7 +293,7 @@ const InfoBox = {
updateNumbers: function() { updateNumbers: function() {
if (!Active.Map) return if (!Active.Map) return
const self = InfoBox const self = toExport
var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
@ -323,7 +322,7 @@ const InfoBox = {
$('.mapEditedAt').html('<span>Last edited: </span>' + Util.nowDateFormatted()) $('.mapEditedAt').html('<span>Last edited: </span>' + Util.nowDateFormatted())
}, },
onPermissionClick: function(event) { onPermissionClick: function(event) {
var self = InfoBox var self = toExport
if (!self.selectingPermission) { if (!self.selectingPermission) {
self.selectingPermission = true self.selectingPermission = true
@ -340,14 +339,14 @@ const InfoBox = {
} }
}, },
hidePermissionSelect: function() { hidePermissionSelect: function() {
var self = InfoBox var self = toExport
self.selectingPermission = false self.selectingPermission = false
$('.mapPermission').removeClass('minimize') // this line flips the pull up arrow to a drop down arrow $('.mapPermission').removeClass('minimize') // this line flips the pull up arrow to a drop down arrow
$('.mapPermission .permissionSelect').remove() $('.mapPermission .permissionSelect').remove()
}, },
selectPermission: function(event) { selectPermission: function(event) {
var self = InfoBox var self = toExport
self.selectingPermission = false self.selectingPermission = false
var permission = $(this).attr('class') var permission = $(this).attr('class')
@ -358,7 +357,7 @@ const InfoBox = {
const shareable = permission === 'private' ? '' : 'shareable' const shareable = permission === 'private' ? '' : 'shareable'
$('.mapPermission').removeClass('commons public private minimize').addClass(permission) $('.mapPermission').removeClass('commons public private minimize').addClass(permission)
$('.mapPermission .permissionSelect').remove() $('.mapPermission .permissionSelect').remove()
$('.mapInfoBox').removeClass('shareable').addClass(shareable) $('.maptoExport').removeClass('shareable').addClass(shareable)
event.stopPropagation() event.stopPropagation()
}, },
deleteActiveMap: function() { deleteActiveMap: function() {
@ -371,7 +370,7 @@ const InfoBox = {
var authorized = map.authorizePermissionChange(mapper) var authorized = map.authorizePermissionChange(mapper)
if (doIt && authorized) { if (doIt && authorized) {
InfoBox.close() toExport.close()
DataModel.Maps.Active.remove(map) DataModel.Maps.Active.remove(map)
DataModel.Maps.Featured.remove(map) DataModel.Maps.Featured.remove(map)
DataModel.Maps.Mine.remove(map) DataModel.Maps.Mine.remove(map)
@ -384,5 +383,7 @@ const InfoBox = {
} }
} }
} }
return toExport
}
export default InfoBox export default InfoBox

View file

@ -6,414 +6,442 @@ import { browserHistory } from 'react-router'
import Active from '../Active' import Active from '../Active'
import AutoLayout from '../AutoLayout' import AutoLayout from '../AutoLayout'
import Cable from '../Cable'
import Control from '../Control'
import Create from '../Create' import Create from '../Create'
import DataModel from '../DataModel' import DataModel from '../DataModel'
import DataModelMap from '../DataModel/Map' import DataModelMap from '../DataModel/Map'
import MapperCollection from '../DataModel/MapperCollection'
import TopicCollection from '../DataModel/TopicCollection'
import SynapseCollection from '../DataModel/SynapseCollection'
import MappingCollection from '../DataModel/MappingCollection'
import Filter from '../Filter' import Filter from '../Filter'
import GlobalUI, { ReactApp } from '../GlobalUI' import GlobalUI, { ReactApp } from '../GlobalUI'
import Import from '../Import'
import InfoBox from './InfoBox'
import JIT from '../JIT' import JIT from '../JIT'
import Listeners from '../Listeners' import Listeners from '../Listeners'
import Loading from '../Loading' import Loading from '../Loading'
import Mouse from '../Mouse'
import Organize from '../Organize' import Organize from '../Organize'
import PasteInput from '../PasteInput'
import Realtime from '../Realtime' import Realtime from '../Realtime'
import Selected from '../Selected' import Selected from '../Selected'
import Synapse from '../Synapse'
import SynapseCard from '../SynapseCard' import SynapseCard from '../SynapseCard'
import Topic from '../Topic' import Topic from '../Topic'
import TopicCard from '../Views/TopicCard' import TopicCard from '../Views/TopicCard'
import ChatView from '../Views/ChatView'
import Visualize from '../Visualize' import Visualize from '../Visualize'
import CheatSheet from './CheatSheet' import CheatSheet from './CheatSheet'
import InfoBox from './InfoBox'
const Map = { const mapControl = {
events: { launch: function(id, serverData) {
editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' var dataIsReadySetupMap = function(data) {
}, const newMap = {
mapIsStarred: false, Active: null,
requests: [], AutoLayout: null,
userRequested: false, Cable: null,
requestAnswered: false, ChatView: null,
requestApproved: false, Control: null,
hasLearnedTopicCreation: true, Create: null,
init: function(serverData) { DataModel: null,
var self = Map Filter: null,
self.mapIsStarred = serverData.mapIsStarred Import: null,
self.requests = serverData.requests JIT: null,
self.setAccessRequest() Listeners: null,
$('#wrapper').mousedown(function(e) { Mouse: null,
if (e.button === 1) return false Organize: null,
}) PasteInput: null,
GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() Realtime: null,
InfoBox.init(serverData, function updateThumbnail() { Selected: null,
self.uploadMapScreenshot() Synapse: null,
}) SynapseCard: null,
CheatSheet.init(serverData) Topic: null,
$(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper) TopicCard: null,
}, Visualize: null
setHasLearnedTopicCreation: function(value) {
const self = Map
self.hasLearnedTopicCreation = value
ReactApp.render()
},
requestAccess: function() {
const self = Map
self.requests.push({
user_id: Active.Mapper.id,
answered: false,
approved: false
})
self.setAccessRequest()
const mapId = Active.Map.id
$.post({
url: `/maps/${mapId}/access_request`
})
GlobalUI.notifyUser('Map creator will be notified of your request')
},
setAccessRequest: function() {
const self = Map
if (Active.Mapper) {
const request = _find(self.requests, r => r.user_id === Active.Mapper.id)
if (!request) {
self.userRequested = false
self.requestAnswered = false
self.requestApproved = false
} }
else if (request && !request.answered) { newMap.Active = Active()
self.userRequested = true newMap.AutoLayout = AutoLayout(newMap)
self.requestAnswered = false newMap.Cable = Cable(newMap)
self.requestApproved = false newMap.ChatView = ChatView(newMap)
} newMap.Control = Control(newMap)
else if (request && request.answered && !request.approved) { newMap.Create = Create(newMap)
self.userRequested = true newMap.DataModel = DataModel(newMap)
self.requestAnswered = true newMap.Filter = Filter(newMap)
self.requestApproved = false newMap.Import = Import(newMap)
} newMap.InfoBox = InfoBox(newMap)
} newMap.JIT = JIT(newMap)
ReactApp.render() newMap.Listeners = Listeners(newMap)
}, newMap.Map = Map(newMap)
launch: function(id) { newMap.Mouse = Mouse(newMap)
const self = Map newMap.Organize = Organize(newMap)
newMap.PasteInput = PasteInput(newMap)
newMap.Realtime = Realtime(newMap)
newMap.Selected = Selected(newMap)
newMap.Synapse = Synapse(newMap)
newMap.SynapseCard = SynapseCard(newMap)
newMap.Topic = Topic(newMap)
newMap.TopicCard = TopicCard(newMap)
newMap.Visualize = Visualize(newMap)
const newMap = { console.log(newMap)
Active: null,
AutoLayout: null,
Cable: null,
Control: null,
Create: null,
DataModel: null,
Filter: null,
Import: null,
JIT: null,
Listeners: null,
Loading: null,
Map: null,
Mouse: null,
Organize: null,
PasteInput: null,
Realtime: null,
Selected: null,
Settings: null,
Synapse: null,
SynapseCard: null,
Topic: null,
Views: null,
Visualize: null
}
newMap.JIT = JIT(newMap)
newMap.Listeners = Listeners(newMap)
console.log(newMap)
var dataIsReadySetupMap = function() { newMap.Active.Map = new DataModelMap(data.map)
Map.setAccessRequest() newMap.DataModel.Mappers = new MapperCollection(data.mappers)
Visualize.type = 'ForceDirected' newMap.DataModel.Collaborators = new MapperCollection(data.collaborators)
newMap.DataModel.Topics = new TopicCollection(data.topics)
newMap.DataModel.Synapses = new SynapseCollection(data.synapses)
newMap.DataModel.Mappings = new MappingCollection(data.mappings)
newMap.DataModel.Messages = data.messages
newMap.DataModel.Stars = data.stars
newMap.DataModel.attachCollectionEvents()
newMap.Map.requests = data.requests
newMap.Map.setAccessRequest()
newMap.Visualize.type = 'ForceDirected'
newMap.JIT.prepareVizData() newMap.JIT.prepareVizData()
Selected.reset() newMap.InfoBox.load()
InfoBox.load() newMap.Filter.checkMetacodes()
Filter.reset() newMap.Filter.checkSynapses()
Filter.checkMetacodes() newMap.Filter.checkMappers()
Filter.checkSynapses() newMap.Realtime.startActiveMap()
Filter.checkMappers()
Realtime.startActiveMap()
Loading.hide() Loading.hide()
document.title = Active.Map.get('name') + ' | Metamaps' document.title = newMap.Active.Map.get('name') + ' | Metamaps'
ReactApp.mobileTitle = Active.Map.get('name') ReactApp.openMap = newMap
ReactApp.mobileTitle = newMap.Active.Map.get('name')
ReactApp.render() ReactApp.render()
} }
function isLoaded() { if (false) {
if (InfoBox.generateBoxHTML) dataIsReadySetupMap() // do something with serverData here
else setTimeout(() => isLoaded(), 50) dataIsReadySetupMap()
}
if (Active.Map && Active.Map.id === id) {
isLoaded()
} }
else { else {
Loading.show() Loading.show()
$.ajax({ $.ajax({
url: '/maps/' + id + '/contains.json', url: '/maps/' + id + '/contains.json',
success: function(data) { success: dataIsReadySetupMap
Active.Map = new DataModelMap(data.map)
DataModel.Mappers = new DataModel.MapperCollection(data.mappers)
DataModel.Collaborators = new DataModel.MapperCollection(data.collaborators)
DataModel.Topics = new DataModel.TopicCollection(data.topics)
DataModel.Synapses = new DataModel.SynapseCollection(data.synapses)
DataModel.Mappings = new DataModel.MappingCollection(data.mappings)
DataModel.Messages = data.messages
DataModel.Stars = data.stars
DataModel.attachCollectionEvents()
self.requests = data.requests
isLoaded()
}
}) })
} }
}, },
end: function() { end: function(map) {
if (Active.Map) { $('.main').removeClass('compressed')
$('.main').removeClass('compressed') $('.rightclickmenu').remove()
AutoLayout.resetSpiral() map.AutoLayout.resetSpiral()
$('.rightclickmenu').remove() map.TopicCard.hideCard()
TopicCard.hideCard() map.SynapseCard.hideCard()
SynapseCard.hideCard() map.Create.newTopic.hide(true) // true means force (and override pinned)
Create.newTopic.hide(true) // true means force (and override pinned) map.Create.newSynapse.hide()
Create.newSynapse.hide() map.InfoBox.close()
InfoBox.close() map.Realtime.endActiveMap()
Realtime.endActiveMap() map.Map.requests = []
self.requests = [] map.Map.hasLearnedTopicCreation = true
self.hasLearnedTopicCreation = true
}
},
star: function() {
var self = Map
if (!Active.Map) return
$.post('/maps/' + Active.Map.id + '/star')
DataModel.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
DataModel.Maps.Starred.add(Active.Map)
GlobalUI.notifyUser('Map is now starred')
self.mapIsStarred = true
ReactApp.render()
},
unstar: function() {
var self = Map
if (!Active.Map) return
$.post('/maps/' + Active.Map.id + '/unstar')
DataModel.Stars = DataModel.Stars.filter(function(s) { return s.user_id !== Active.Mapper.id })
DataModel.Maps.Starred.remove(Active.Map)
self.mapIsStarred = false
ReactApp.render()
},
fork: function() {
GlobalUI.openLightbox('forkmap')
let nodesData = ''
let synapsesData = ''
let nodesArray = []
let synapsesArray = []
// collect the unfiltered topics
Visualize.mGraph.graph.eachNode(function(n) {
// if the opacity is less than 1 then it's filtered
if (n.getData('alpha') === 1) {
var id = n.getData('topic').id
nodesArray.push(id)
let x, y
if (n.pos.x && n.pos.y) {
x = n.pos.x
y = n.pos.y
} else {
x = Math.cos(n.pos.theta) * n.pos.rho
y = Math.sin(n.pos.theta) * n.pos.rho
}
nodesData += id + '/' + x + '/' + y + ','
}
})
// collect the unfiltered synapses
DataModel.Synapses.each(function(synapse) {
var desc = synapse.get('desc')
var descNotFiltered = Filter.visible.synapses.indexOf(desc) > -1
// make sure that both topics are being added, otherwise, it
// doesn't make sense to add the synapse
var topicsNotFiltered = nodesArray.indexOf(synapse.get('topic1_id')) > -1
topicsNotFiltered = topicsNotFiltered && nodesArray.indexOf(synapse.get('topic2_id')) > -1
if (descNotFiltered && topicsNotFiltered) {
synapsesArray.push(synapse.id)
}
})
synapsesData = synapsesArray.join()
nodesData = nodesData.slice(0, -1)
GlobalUI.CreateMap.topicsToMap = nodesData
GlobalUI.CreateMap.synapsesToMap = synapsesData
},
leavePrivateMap: function() {
var map = Active.Map
DataModel.Maps.Active.remove(map)
DataModel.Maps.Featured.remove(map)
browserHistory.push('/')
GlobalUI.notifyUser('Sorry! That map has been changed to Private.')
},
cantEditNow: function() {
Realtime.turnOff(true) // true is for 'silence'
GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.')
Active.Map.trigger('changeByOther')
},
canEditNow: function() {
var confirmString = "You've been granted permission to edit this map. "
confirmString += 'Do you want to reload and enable realtime collaboration?'
var c = window.confirm(confirmString)
if (c) {
window.location.reload()
}
},
editedByActiveMapper: function() {
if (Active.Mapper) {
DataModel.Mappers.add(Active.Mapper)
}
},
offerScreenshotDownload: () => {
const canvas = Map.getMapCanvasForScreenshots()
const filename = Map.getMapScreenshotFilename(Active.Map)
var downloadMessage = outdent`
Captured map screenshot!
<a id="map-screenshot-download-link"
href="${canvas.canvas.toDataURL()}"
download="${filename}"
>
DOWNLOAD
</a>`
GlobalUI.notifyUser(downloadMessage)
},
uploadMapScreenshot: () => {
const canvas = Map.getMapCanvasForScreenshots()
const filename = Map.getMapScreenshotFilename(Active.Map)
canvas.canvas.toBlob(imageBlob => {
const formData = new window.FormData()
formData.append('map[screenshot]', imageBlob, filename)
$.ajax({
type: 'PATCH',
dataType: 'json',
url: `/maps/${Active.Map.id}`,
data: formData,
processData: false,
contentType: false,
success: function(data) {
GlobalUI.notifyUser('Successfully updated map screenshot.')
},
error: function() {
GlobalUI.notifyUser('Failed to update map screenshot.')
}
})
})
},
getMapCanvasForScreenshots: () => {
var canvas = {}
canvas.canvas = document.createElement('canvas')
canvas.canvas.width = 1880 // 960
canvas.canvas.height = 1260 // 630
canvas.scaleOffsetX = 1
canvas.scaleOffsetY = 1
canvas.translateOffsetY = 0
canvas.translateOffsetX = 0
canvas.denySelected = true
canvas.getSize = function() {
if (this.size) return this.size
var canvas = this.canvas
this.size = {
width: canvas.width,
height: canvas.height
}
return this.size
}
canvas.scale = function(x, y) {
const px = this.scaleOffsetX * x
const py = this.scaleOffsetY * y
const dx = this.translateOffsetX * (x - 1) / px
const dy = this.translateOffsetY * (y - 1) / py
this.scaleOffsetX = px
this.scaleOffsetY = py
this.getCtx().scale(x, y)
this.translate(dx, dy)
}
canvas.translate = function(x, y) {
const sx = this.scaleOffsetX
const sy = this.scaleOffsetY
this.translateOffsetX += x * sx
this.translateOffsetY += y * sy
this.getCtx().translate(x, y)
}
canvas.getCtx = function() {
return this.canvas.getContext('2d')
}
// center it
canvas.getCtx().translate(1880 / 2, 1260 / 2)
var mGraph = Visualize.mGraph
var id = mGraph.root
var root = mGraph.graph.getNode(id)
var T = !!root.visited
// pass true to avoid basing it on a selection
JIT.zoomExtents(null, canvas, true)
const c = canvas.canvas
const ctx = canvas.getCtx()
const scale = canvas.scaleOffsetX
// draw a grey background
ctx.fillStyle = '#d8d9da'
const xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale)
const yPoint = (-(c.height / scale) / 2) - (canvas.translateOffsetY / scale)
ctx.fillRect(xPoint, yPoint, c.width / scale, c.height / scale)
// draw the graph
mGraph.graph.eachNode(function(node) {
var nodeAlpha = node.getData('alpha')
node.eachAdjacency(function(adj) {
var nodeTo = adj.nodeTo
if (!!nodeTo.visited === T && node.drawn && nodeTo.drawn) {
mGraph.fx.plotLine(adj, canvas)
}
})
if (node.drawn) {
mGraph.fx.plotNode(node, canvas)
}
if (!mGraph.labelsHidden) {
if (node.drawn && nodeAlpha >= 0.95) {
mGraph.labels.plotLabel(canvas, node)
} else {
mGraph.labels.hideLabel(node, false)
}
}
node.visited = !T
})
return canvas
},
getMapScreenshotFilename: map => {
var today = new Date()
var dd = today.getDate()
var mm = today.getMonth() + 1 // January is 0!
var yyyy = today.getFullYear()
if (dd < 10) {
dd = '0' + dd
}
if (mm < 10) {
mm = '0' + mm
}
today = mm + '/' + dd + '/' + yyyy
var mapName = map.get('name').split(' ').join(['-'])
const filename = `metamap-${map.id}-${mapName}-${today}.png`
return filename
} }
} }
export { mapControl }
export { CheatSheet, InfoBox } const Map = ({Active, DataModel, JIT, Visualize, Realtime}) => {
const toExport = {
mapIsStarred: false,
requests: [],
userRequested: false,
requestAnswered: false,
requestApproved: false,
hasLearnedTopicCreation: true,
init: function(serverData) {
var self = toExport
self.mapIsStarred = serverData.mapIsStarred
self.requests = serverData.requests
self.setAccessRequest()
$('#wrapper').mousedown(function(e) {
if (e.button === 1) return false
})
GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
//InfoBox.init(serverData, function updateThumbnail() {
// self.uploadMapScreenshot()
//})
CheatSheet.init(serverData)
$(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper)
},
setHasLearnedTopicCreation: function(value) {
const self = toExport
self.hasLearnedTopicCreation = value
ReactApp.render()
},
requestAccess: function() {
const self = toExport
self.requests.push({
user_id: Active.Mapper.id,
answered: false,
approved: false
})
self.setAccessRequest()
const mapId = Active.Map.id
$.post({
url: `/maps/${mapId}/access_request`
})
GlobalUI.notifyUser('Map creator will be notified of your request')
},
setAccessRequest: function() {
const self = toExport
if (Active.Mapper) {
const request = _find(self.requests, r => r.user_id === Active.Mapper.id)
if (!request) {
self.userRequested = false
self.requestAnswered = false
self.requestApproved = false
}
else if (request && !request.answered) {
self.userRequested = true
self.requestAnswered = false
self.requestApproved = false
}
else if (request && request.answered && !request.approved) {
self.userRequested = true
self.requestAnswered = true
self.requestApproved = false
}
}
ReactApp.render()
},
star: function() {
var self = toExport
if (!Active.Map) return
$.post('/maps/' + Active.Map.id + '/star')
DataModel.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
DataModel.Maps.Starred.add(Active.Map)
GlobalUI.notifyUser('Map is now starred')
self.mapIsStarred = true
ReactApp.render()
},
unstar: function() {
var self = toExport
if (!Active.Map) return
$.post('/maps/' + Active.Map.id + '/unstar')
DataModel.Stars = DataModel.Stars.filter(function(s) { return s.user_id !== Active.Mapper.id })
DataModel.Maps.Starred.remove(Active.Map)
self.mapIsStarred = false
ReactApp.render()
},
fork: function() {
GlobalUI.openLightbox('forkmap')
let nodesData = ''
let synapsesData = ''
let nodesArray = []
let synapsesArray = []
// collect the unfiltered topics
Visualize.mGraph.graph.eachNode(function(n) {
// if the opacity is less than 1 then it's filtered
if (n.getData('alpha') === 1) {
var id = n.getData('topic').id
nodesArray.push(id)
let x, y
if (n.pos.x && n.pos.y) {
x = n.pos.x
y = n.pos.y
} else {
x = Math.cos(n.pos.theta) * n.pos.rho
y = Math.sin(n.pos.theta) * n.pos.rho
}
nodesData += id + '/' + x + '/' + y + ','
}
})
// collect the unfiltered synapses
DataModel.Synapses.each(function(synapse) {
var desc = synapse.get('desc')
var descNotFiltered = Filter.visible.synapses.indexOf(desc) > -1
// make sure that both topics are being added, otherwise, it
// doesn't make sense to add the synapse
var topicsNotFiltered = nodesArray.indexOf(synapse.get('topic1_id')) > -1
topicsNotFiltered = topicsNotFiltered && nodesArray.indexOf(synapse.get('topic2_id')) > -1
if (descNotFiltered && topicsNotFiltered) {
synapsesArray.push(synapse.id)
}
})
synapsesData = synapsesArray.join()
nodesData = nodesData.slice(0, -1)
GlobalUI.CreateMap.topicsToMap = nodesData
GlobalUI.CreateMap.synapsesToMap = synapsesData
},
leavePrivateMap: function() {
var map = Active.Map
DataModel.Maps.Active.remove(map)
DataModel.Maps.Featured.remove(map)
browserHistory.push('/')
GlobalUI.notifyUser('Sorry! That map has been changed to Private.')
},
cantEditNow: function() {
Realtime.turnOff(true) // true is for 'silence'
GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.')
Active.Map.trigger('changeByOther')
},
canEditNow: function() {
var confirmString = "You've been granted permission to edit this map. "
confirmString += 'Do you want to reload and enable realtime collaboration?'
var c = window.confirm(confirmString)
if (c) {
window.location.reload()
}
},
editedByActiveMapper: function() {
if (Active.Mapper) {
DataModel.Mappers.add(Active.Mapper)
}
},
offerScreenshotDownload: () => {
const canvas = toExport.getMapCanvasForScreenshots()
const filename = toExport.getMapScreenshotFilename(Active.Map)
var downloadMessage = outdent`
Captured map screenshot!
<a id="map-screenshot-download-link"
href="${canvas.canvas.toDataURL()}"
download="${filename}"
>
DOWNLOAD
</a>`
GlobalUI.notifyUser(downloadMessage)
},
uploadMapScreenshot: () => {
const canvas = toExport.getMapCanvasForScreenshots()
const filename = toExport.getMapScreenshotFilename(Active.Map)
canvas.canvas.toBlob(imageBlob => {
const formData = new window.FormData()
formData.append('map[screenshot]', imageBlob, filename)
$.ajax({
type: 'PATCH',
dataType: 'json',
url: `/maps/${Active.Map.id}`,
data: formData,
processData: false,
contentType: false,
success: function(data) {
GlobalUI.notifyUser('Successfully updated map screenshot.')
},
error: function() {
GlobalUI.notifyUser('Failed to update map screenshot.')
}
})
})
},
getMapCanvasForScreenshots: () => {
var canvas = {}
canvas.canvas = document.createElement('canvas')
canvas.canvas.width = 1880 // 960
canvas.canvas.height = 1260 // 630
canvas.scaleOffsetX = 1
canvas.scaleOffsetY = 1
canvas.translateOffsetY = 0
canvas.translateOffsetX = 0
canvas.denySelected = true
canvas.getSize = function() {
if (this.size) return this.size
var canvas = this.canvas
this.size = {
width: canvas.width,
height: canvas.height
}
return this.size
}
canvas.scale = function(x, y) {
const px = this.scaleOffsetX * x
const py = this.scaleOffsetY * y
const dx = this.translateOffsetX * (x - 1) / px
const dy = this.translateOffsetY * (y - 1) / py
this.scaleOffsetX = px
this.scaleOffsetY = py
this.getCtx().scale(x, y)
this.translate(dx, dy)
}
canvas.translate = function(x, y) {
const sx = this.scaleOffsetX
const sy = this.scaleOffsetY
this.translateOffsetX += x * sx
this.translateOffsetY += y * sy
this.getCtx().translate(x, y)
}
canvas.getCtx = function() {
return this.canvas.getContext('2d')
}
// center it
canvas.getCtx().translate(1880 / 2, 1260 / 2)
var mGraph = Visualize.mGraph
var id = mGraph.root
var root = mGraph.graph.getNode(id)
var T = !!root.visited
// pass true to avoid basing it on a selection
JIT.zoomExtents(null, canvas, true)
const c = canvas.canvas
const ctx = canvas.getCtx()
const scale = canvas.scaleOffsetX
// draw a grey background
ctx.fillStyle = '#d8d9da'
const xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale)
const yPoint = (-(c.height / scale) / 2) - (canvas.translateOffsetY / scale)
ctx.fillRect(xPoint, yPoint, c.width / scale, c.height / scale)
// draw the graph
mGraph.graph.eachNode(function(node) {
var nodeAlpha = node.getData('alpha')
node.eachAdjacency(function(adj) {
var nodeTo = adj.nodeTo
if (!!nodeTo.visited === T && node.drawn && nodeTo.drawn) {
mGraph.fx.plotLine(adj, canvas)
}
})
if (node.drawn) {
mGraph.fx.plotNode(node, canvas)
}
if (!mGraph.labelsHidden) {
if (node.drawn && nodeAlpha >= 0.95) {
mGraph.labels.plotLabel(canvas, node)
} else {
mGraph.labels.hideLabel(node, false)
}
}
node.visited = !T
})
return canvas
},
getMapScreenshotFilename: map => {
var today = new Date()
var dd = today.getDate()
var mm = today.getMonth() + 1 // January is 0!
var yyyy = today.getFullYear()
if (dd < 10) {
dd = '0' + dd
}
if (mm < 10) {
mm = '0' + mm
}
today = mm + '/' + dd + '/' + yyyy
var mapName = map.get('name').split(' ').join(['-'])
const filename = `metamap-${map.id}-${mapName}-${today}.png`
return filename
}
}
return toExport
}
Map.events = {
editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
}
export { CheatSheet }
export default Map export default Map

View file

@ -1,16 +1,18 @@
const Mouse = { const Mouse = () => {
didPan: false, return {
didBoxZoom: false, didPan: false,
changeInX: 0, didBoxZoom: false,
changeInY: 0, changeInX: 0,
edgeHoveringOver: false, changeInY: 0,
boxStartCoordinates: false, edgeHoveringOver: false,
boxEndCoordinates: false, boxStartCoordinates: false,
synapseStartCoordinates: [], boxEndCoordinates: false,
synapseEndCoordinates: null, synapseStartCoordinates: [],
lastNodeClick: 0, synapseEndCoordinates: null,
lastCanvasClick: 0, lastNodeClick: 0,
DOUBLE_CLICK_TOLERANCE: 300 lastCanvasClick: 0,
DOUBLE_CLICK_TOLERANCE: 300
}
} }
export default Mouse export default Mouse

View file

@ -2,10 +2,8 @@ import _ from 'lodash'
import $jit from '../patched/JIT' import $jit from '../patched/JIT'
import Visualize from './Visualize' const Organize = ({Visualize, JIT}) => {
import JIT from './JIT' const toExport = {
const Organize = {
arrange: function(layout, centerNode) { arrange: function(layout, centerNode) {
// first option for layout to implement is 'grid', will do an evenly spaced grid with its center at the 0,0 origin // first option for layout to implement is 'grid', will do an evenly spaced grid with its center at the 0,0 origin
if (layout === 'grid') { if (layout === 'grid') {
@ -112,5 +110,7 @@ const Organize = {
} }
} }
} }
return toExport
}
export default Organize export default Organize

View file

@ -1,16 +1,15 @@
/* global $ */ /* global $ */
import Import from './Import'
import Util from './Util' import Util from './Util'
import Visualize from './Visualize'
const PasteInput = { const PasteInput = ({Import, Visualize}) => {
const toReturn = {
// thanks to https://github.com/kevva/url-regex // thanks to https://github.com/kevva/url-regex
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
URL_REGEX: new RegExp('^(?:(?:(?:[a-z]+:)?//)|www\.)(?:\S+(?::\S*)?@)?(?:localhost|(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#][^\s"]*)?$'), URL_REGEX: new RegExp('^(?:(?:(?:[a-z]+:)?//)|www\.)(?:\S+(?::\S*)?@)?(?:localhost|(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#][^\s"]*)?$'),
init: function() { init: function() {
var self = PasteInput var self = toReturn
// intercept dragged files // intercept dragged files
// see http://stackoverflow.com/questions/6756583 // see http://stackoverflow.com/questions/6756583
@ -50,7 +49,7 @@ const PasteInput = {
}, },
handleFile: (file, coords = null) => { handleFile: (file, coords = null) => {
var self = PasteInput var self = toReturn
var fileReader = new window.FileReader() var fileReader = new window.FileReader()
fileReader.readAsText(file) fileReader.readAsText(file)
fileReader.onload = function(e) { fileReader.onload = function(e) {
@ -64,7 +63,7 @@ const PasteInput = {
}, },
handle: function(text, coords = {}) { handle: function(text, coords = {}) {
var self = PasteInput var self = toReturn
if (text.match(self.URL_REGEX)) { if (text.match(self.URL_REGEX)) {
Import.handleURL(text, coords) Import.handleURL(text, coords)
@ -78,5 +77,7 @@ const PasteInput = {
} }
} }
} }
return toReturn
}
export default PasteInput export default PasteInput

View file

@ -3,13 +3,8 @@
import SimpleWebRTC from 'simplewebrtc' import SimpleWebRTC from 'simplewebrtc'
import SocketIoConnection from 'simplewebrtc/socketioconnection' import SocketIoConnection from 'simplewebrtc/socketioconnection'
import Active from '../Active'
import Cable from '../Cable'
import DataModel from '../DataModel'
import JIT from '../JIT'
import Util from '../Util' import Util from '../Util'
import Views, { ChatView } from '../Views' import Views from '../Views'
import Visualize from '../Visualize'
import { import {
JUNTO_UPDATED, JUNTO_UPDATED,
@ -63,8 +58,8 @@ import {
dragTopic dragTopic
} from './sendable' } from './sendable'
let Realtime = { const Realtime = ({Active, Cable, DataModel, JIT, Visualize}) => {
juntoState: { connectedPeople: {}, liveMaps: {} }, const toExport = {
videoId: 'video-wrapper', videoId: 'video-wrapper',
socket: null, socket: null,
webrtc: null, webrtc: null,
@ -78,7 +73,7 @@ let Realtime = {
localVideo: null, localVideo: null,
'junto_spinner_darkgrey.gif': '', 'junto_spinner_darkgrey.gif': '',
init: function(serverData) { init: function(serverData) {
var self = Realtime var self = toExport
self.addJuntoListeners() self.addJuntoListeners()
@ -154,7 +149,7 @@ let Realtime = {
} // if Active.Mapper } // if Active.Mapper
}, },
addJuntoListeners: function() { addJuntoListeners: function() {
var self = Realtime var self = toExport
$(document).on(ChatView.events.openTray, function() { $(document).on(ChatView.events.openTray, function() {
$('.main').addClass('compressed') $('.main').addClass('compressed')
@ -180,7 +175,7 @@ let Realtime = {
}) })
}, },
startActiveMap: function() { startActiveMap: function() {
var self = Realtime var self = toExport
if (Active.Map && Active.Mapper) { if (Active.Map && Active.Mapper) {
if (Active.Map.authorizeToEdit(Active.Mapper)) { if (Active.Map.authorizeToEdit(Active.Mapper)) {
self.turnOn() self.turnOn()
@ -192,7 +187,7 @@ let Realtime = {
} }
}, },
endActiveMap: function() { endActiveMap: function() {
var self = Realtime var self = toExport
$(document).off('.map') $(document).off('.map')
// leave the appropriate rooms to leave // leave the appropriate rooms to leave
if (self.inConversation) self.leaveCall() if (self.inConversation) self.leaveCall()
@ -202,7 +197,7 @@ let Realtime = {
Cable.unsubscribeFromMap() Cable.unsubscribeFromMap()
}, },
turnOn: function(notify) { turnOn: function(notify) {
var self = Realtime var self = toExport
$('.collabCompass').show() $('.collabCompass').show()
self.room.room = 'map-' + Active.Map.id self.room.room = 'map-' + Active.Map.id
self.activeMapper = { self.activeMapper = {
@ -219,13 +214,13 @@ let Realtime = {
self.setupLocalEvents() self.setupLocalEvents()
}, },
setupChat: function() { setupChat: function() {
const self = Realtime const self = toExport
ChatView.setNewMap() ChatView.setNewMap()
ChatView.addParticipant(self.activeMapper) ChatView.addParticipant(self.activeMapper)
ChatView.addMessages(new DataModel.MessageCollection(DataModel.Messages), true) ChatView.addMessages(new DataModel.MessageCollection(DataModel.Messages), true)
}, },
setupLocalEvents: function() { setupLocalEvents: function() {
var self = Realtime var self = toExport
// local event listeners that trigger events // local event listeners that trigger events
$(document).on(JIT.events.zoom + '.map', self.positionPeerIcons) $(document).on(JIT.events.zoom + '.map', self.positionPeerIcons)
$(document).on(JIT.events.pan + '.map', self.positionPeerIcons) $(document).on(JIT.events.pan + '.map', self.positionPeerIcons)
@ -242,7 +237,7 @@ let Realtime = {
}) })
}, },
countOthersInConversation: function() { countOthersInConversation: function() {
var self = Realtime var self = toExport
var count = 0 var count = 0
for (var key in self.mappersOnMap) { for (var key in self.mappersOnMap) {
if (self.mappersOnMap[key].inConversation) count++ if (self.mappersOnMap[key].inConversation) count++
@ -250,7 +245,7 @@ let Realtime = {
return count return count
}, },
handleVideoAdded: function(v, id) { handleVideoAdded: function(v, id) {
var self = Realtime var self = toExport
self.positionVideos() self.positionVideos()
v.setParent($('#wrapper')) v.setParent($('#wrapper'))
v.$container.find('.video-cutoff').css({ v.$container.find('.video-cutoff').css({
@ -259,7 +254,7 @@ let Realtime = {
$('#wrapper').append(v.$container) $('#wrapper').append(v.$container)
}, },
positionVideos: function() { positionVideos: function() {
var self = Realtime var self = toExport
var videoIds = Object.keys(self.room.videos) var videoIds = Object.keys(self.room.videos)
// var numOfVideos = videoIds.length // var numOfVideos = videoIds.length
// var numOfVideosToPosition = _.filter(videoIds, function(id) { // var numOfVideosToPosition = _.filter(videoIds, function(id) {
@ -290,7 +285,7 @@ let Realtime = {
} }
// do self first // do self first
var myVideo = Realtime.localVideo.view var myVideo = toExport.localVideo.view
if (!myVideo.manuallyPositioned) { if (!myVideo.manuallyPositioned) {
myVideo.$container.css({ myVideo.$container.css({
top: yFormula() + 'px', top: yFormula() + 'px',
@ -308,7 +303,7 @@ let Realtime = {
}) })
}, },
callEnded: function() { callEnded: function() {
var self = Realtime var self = toExport
ChatView.conversationEnded() ChatView.conversationEnded()
self.room.leaveVideoOnly() self.room.leaveVideoOnly()
@ -336,13 +331,13 @@ let Realtime = {
}) })
}, },
positionPeerIcons: function() { positionPeerIcons: function() {
var self = Realtime var self = toExport
for (var key in self.mappersOnMap) { for (var key in self.mappersOnMap) {
self.positionPeerIcon(key) self.positionPeerIcon(key)
} }
}, },
positionPeerIcon: function(id) { positionPeerIcon: function(id) {
var self = Realtime var self = toExport
var mapper = self.mappersOnMap[id] var mapper = self.mappersOnMap[id]
var origPixels = Util.coordsToPixels(Visualize.mGraph, mapper.coords) var origPixels = Util.coordsToPixels(Visualize.mGraph, mapper.coords)
@ -371,7 +366,7 @@ let Realtime = {
} }
}, },
limitPixelsToScreen: function(pixels) { limitPixelsToScreen: function(pixels) {
var self = Realtime var self = toExport
var boundary = self.chatOpen ? '#wrapper' : document var boundary = self.chatOpen ? '#wrapper' : document
var xLimit, yLimit var xLimit, yLimit
@ -405,25 +400,28 @@ const sendables = [
['dragTopic', dragTopic] ['dragTopic', dragTopic]
] ]
sendables.forEach(sendable => { sendables.forEach(sendable => {
Realtime[sendable[0]] = sendable[1](Realtime) toExport[sendable[0]] = sendable[1](toExport)
}) })
const subscribeToEvents = (Realtime, socket) => { const subscribeToEvents = (toExport, socket) => {
socket.on(JUNTO_UPDATED, juntoUpdated(Realtime)) socket.on(JUNTO_UPDATED, juntoUpdated(toExport))
socket.on(INVITED_TO_CALL, invitedToCall(Realtime)) socket.on(INVITED_TO_CALL, invitedToCall(toExport))
socket.on(INVITED_TO_JOIN, invitedToJoin(Realtime)) socket.on(INVITED_TO_JOIN, invitedToJoin(toExport))
socket.on(CALL_ACCEPTED, callAccepted(Realtime)) socket.on(CALL_ACCEPTED, callAccepted(toExport))
socket.on(CALL_DENIED, callDenied(Realtime)) socket.on(CALL_DENIED, callDenied(toExport))
socket.on(INVITE_DENIED, inviteDenied(Realtime)) socket.on(INVITE_DENIED, inviteDenied(toExport))
socket.on(CALL_IN_PROGRESS, callInProgress(Realtime)) socket.on(CALL_IN_PROGRESS, callInProgress(toExport))
socket.on(CALL_STARTED, callStarted(Realtime)) socket.on(CALL_STARTED, callStarted(toExport))
socket.on(MAPPER_LIST_UPDATED, mapperListUpdated(Realtime)) socket.on(MAPPER_LIST_UPDATED, mapperListUpdated(toExport))
socket.on(MAPPER_JOINED_CALL, mapperJoinedCall(Realtime)) socket.on(MAPPER_JOINED_CALL, mapperJoinedCall(toExport))
socket.on(MAPPER_LEFT_CALL, mapperLeftCall(Realtime)) socket.on(MAPPER_LEFT_CALL, mapperLeftCall(toExport))
socket.on(PEER_COORDS_UPDATED, peerCoordsUpdated(Realtime)) socket.on(PEER_COORDS_UPDATED, peerCoordsUpdated(toExport))
socket.on(NEW_MAPPER, newMapper(Realtime)) socket.on(NEW_MAPPER, newMapper(toExport))
socket.on(LOST_MAPPER, lostMapper(Realtime)) socket.on(LOST_MAPPER, lostMapper(toExport))
socket.on(TOPIC_DRAGGED, topicDragged(Realtime)) socket.on(TOPIC_DRAGGED, topicDragged(toExport))
}
return toExport
} }
export default Realtime export default Realtime

View file

@ -9,12 +9,12 @@ import { JUNTO_UPDATED } from './events'
import Active from '../Active' import Active from '../Active'
import { ChatView } from '../Views' import { ChatView } from '../Views'
import DataModel from '../DataModel' import DataModel from '../DataModel'
import GlobalUI from '../GlobalUI' import GlobalUI, { ReactApp } from '../GlobalUI'
import Util from '../Util' import Util from '../Util'
import Visualize from '../Visualize' import Visualize from '../Visualize'
export const juntoUpdated = self => state => { export const juntoUpdated = self => state => {
self.juntoState = state ReactApp.juntoState = state
$(document).trigger(JUNTO_UPDATED) $(document).trigger(JUNTO_UPDATED)
} }

View file

@ -1,11 +1,14 @@
const Selected = { const Selected = () => {
reset: function() { const toExport = {
var self = Selected reset: function() {
self.Nodes = [] var self = toExport
self.Edges = [] self.Nodes = []
}, self.Edges = []
Nodes: [], },
Edges: [] Nodes: [],
Edges: []
}
return toExport
} }
export default Selected export default Selected

View file

@ -1,17 +1,11 @@
/* global $ */ /* global $ */
import Active from './Active'
import Control from './Control'
import Create from './Create'
import DataModel from './DataModel'
import Map from './Map'
import Selected from './Selected'
import Settings from './Settings' import Settings from './Settings'
import Visualize from './Visualize'
const noOp = () => {} const noOp = () => {}
const Synapse = { const Synapse = ({Active, Control, Create, DataModel, Map, Selected, Visualize}) => {
const toExport = {
// this function is to retrieve a synapse JSON object from the database // this function is to retrieve a synapse JSON object from the database
// @param id = the id of the synapse to retrieve // @param id = the id of the synapse to retrieve
get: function(id, callback = noOp) { get: function(id, callback = noOp) {
@ -77,7 +71,7 @@ const Synapse = {
} }
}, },
createSynapseLocally: function() { createSynapseLocally: function() {
var self = Synapse var self = toExport
let topic1 let topic1
let topic2 let topic2
let node1 let node1
@ -124,7 +118,7 @@ const Synapse = {
Create.newSynapse.hide() Create.newSynapse.hide()
}, },
getSynapseFromAutocomplete: function(id) { getSynapseFromAutocomplete: function(id) {
var self = Synapse var self = toExport
self.get(id, synapse => { self.get(id, synapse => {
const mapping = new DataModel.Mapping({ const mapping = new DataModel.Mapping({
@ -141,5 +135,7 @@ const Synapse = {
}) })
} }
} }
return toExport
}
export default Synapse export default Synapse

View file

@ -1,13 +1,11 @@
/* global $ */ /* global $ */
import Active from './Active'
import Control from './Control'
import Mapper from './Mapper' import Mapper from './Mapper'
import Visualize from './Visualize'
const SynapseCard = { const SynapseCard = ({Active, Control, Visualize}) => {
const toExport = {
openSynapseCard: null, openSynapseCard: null,
showCard: function(edge, e) { showCard: function(edge, e) {
var self = SynapseCard var self = toExport
// reset so we don't interfere with other edges, but first, save its x and y // reset so we don't interfere with other edges, but first, save its x and y
var myX = $('#edit_synapse').css('left') var myX = $('#edit_synapse').css('left')
@ -53,11 +51,11 @@ const SynapseCard = {
hideCard: function() { hideCard: function() {
$('#edit_synapse').remove() $('#edit_synapse').remove()
SynapseCard.openSynapseCard = null toExport.openSynapseCard = null
}, },
populateShowCard: function(edge, synapse) { populateShowCard: function(edge, synapse) {
var self = SynapseCard var self = toExport
self.add_synapse_count(edge) self.add_synapse_count(edge)
self.add_desc_form(synapse) self.add_desc_form(synapse)
@ -156,7 +154,7 @@ const SynapseCard = {
var index = parseInt($(this).attr('data-synapse-index')) var index = parseInt($(this).attr('data-synapse-index'))
edge.setData('displayIndex', index) edge.setData('displayIndex', index)
Visualize.mGraph.plot() Visualize.mGraph.plot()
SynapseCard.showCard(edge, false) toExport.showCard(edge, false)
}) })
} }
}, },
@ -291,5 +289,7 @@ const SynapseCard = {
} // if } // if
} // add_direction_form } // add_direction_form
} }
return toExport
}
export default SynapseCard export default SynapseCard

View file

@ -2,27 +2,15 @@
import $jit from '../patched/JIT' import $jit from '../patched/JIT'
import Active from './Active'
import AutoLayout from './AutoLayout'
import Create from './Create'
import DataModel from './DataModel'
import Filter from './Filter'
import GlobalUI, { ReactApp } from './GlobalUI' import GlobalUI, { ReactApp } from './GlobalUI'
import JIT from './JIT'
import Loading from './Loading' import Loading from './Loading'
import Map from './Map'
import Selected from './Selected'
import Settings from './Settings' import Settings from './Settings'
import SynapseCard from './SynapseCard'
import TopicCard from './Views/TopicCard'
import Util from './Util' import Util from './Util'
import Visualize from './Visualize'
const noOp = () => {} const noOp = () => {}
const Topic = { const Topic = ({Active, AutoLayout, Create, DataModel, Filter, JIT, MAP, Selected, SynapseCard, TopicCard, Visualize}) => {
// this function is to retrieve a topic JSON object from the database const toExport = {
// @param id = the id of the topic to retrieve
get: function(id, callback = noOp) { get: function(id, callback = noOp) {
// if the desired topic is not yet in the local topic repository, fetch it // if the desired topic is not yet in the local topic repository, fetch it
if (DataModel.Topics.get(id) === undefined) { if (DataModel.Topics.get(id) === undefined) {
@ -101,7 +89,7 @@ const Topic = {
ReactApp.render() ReactApp.render()
}, },
fetchRelatives: function(nodes, metacodeId) { fetchRelatives: function(nodes, metacodeId) {
var self = this var self = toExport
var node = $.isArray(nodes) ? nodes[0] : nodes var node = $.isArray(nodes) ? nodes[0] : nodes
@ -292,7 +280,7 @@ const Topic = {
} }
}, },
createTopicLocally: function() { createTopicLocally: function() {
var self = Topic var self = toExport
if (Create.newTopic.name === '') { if (Create.newTopic.name === '') {
GlobalUI.notifyUser('Please enter a topic title...') GlobalUI.notifyUser('Please enter a topic title...')
@ -330,7 +318,7 @@ const Topic = {
self.renderTopic(mapping, topic, true, true) // this function also includes the creation of the topic in the database self.renderTopic(mapping, topic, true, true) // this function also includes the creation of the topic in the database
}, },
getTopicFromAutocomplete: function(id) { getTopicFromAutocomplete: function(id) {
var self = Topic var self = toExport
Map.setHasLearnedTopicCreation(true) Map.setHasLearnedTopicCreation(true)
@ -357,7 +345,7 @@ const Topic = {
}) })
}, },
getMapFromAutocomplete: function(data) { getMapFromAutocomplete: function(data) {
var self = Topic var self = toExport
$(document).trigger(Map.events.editedByActiveMapper) $(document).trigger(Map.events.editedByActiveMapper)
@ -387,7 +375,7 @@ const Topic = {
if (Create.newTopic.pinned) Create.newTopic.beingCreated = true if (Create.newTopic.pinned) Create.newTopic.beingCreated = true
}, },
getTopicFromSearch: function(event, id) { getTopicFromSearch: function(event, id) {
var self = Topic var self = toExport
$(document).trigger(Map.events.editedByActiveMapper) $(document).trigger(Map.events.editedByActiveMapper)
@ -409,5 +397,7 @@ const Topic = {
return false return false
} }
} }
return toExport
}
export default Topic export default Topic

View file

@ -3,18 +3,17 @@
import Backbone from 'backbone' import Backbone from 'backbone'
import { Howl } from 'howler' import { Howl } from 'howler'
import Active from '../Active'
import DataModel from '../DataModel'
import ReactApp from '../GlobalUI/ReactApp' import ReactApp from '../GlobalUI/ReactApp'
const ChatView = { const ChatView = ({Active, DataModel}) => {
const toExport = {
isOpen: false, isOpen: false,
unreadMessages: 0, unreadMessages: 0,
messages: new Backbone.Collection(), messages: new Backbone.Collection(),
conversationLive: false, conversationLive: false,
isParticipating: false, isParticipating: false,
init: function(urls) { init: function(urls) {
const self = ChatView const self = toExport
self.sound = new Howl({ self.sound = new Howl({
src: urls, src: urls,
sprite: { sprite: {
@ -27,7 +26,7 @@ const ChatView = {
}) })
}, },
setNewMap: function() { setNewMap: function() {
const self = ChatView const self = toExport
self.unreadMessages = 0 self.unreadMessages = 0
self.isOpen = false self.isOpen = false
self.conversationLive = false self.conversationLive = false
@ -41,74 +40,74 @@ const ChatView = {
}, },
render: () => { render: () => {
if (!Active.Map) return if (!Active.Map) return
const self = ChatView const self = toExport
ReactApp.render() ReactApp.render()
}, },
onOpen: () => { onOpen: () => {
const self = ChatView const self = toExport
self.isOpen = true self.isOpen = true
self.unreadMessages = 0 self.unreadMessages = 0
self.render() self.render()
$(document).trigger(ChatView.events.openTray) $(document).trigger(ChatView.events.openTray)
}, },
onClose: () => { onClose: () => {
const self = ChatView const self = toExport
self.isOpen = false self.isOpen = false
$(document).trigger(ChatView.events.closeTray) $(document).trigger(ChatView.events.closeTray)
}, },
addParticipant: participant => { addParticipant: participant => {
ChatView.participants.add(participant) toExport.participants.add(participant)
ChatView.render() toExport.render()
}, },
removeParticipant: participant => { removeParticipant: participant => {
ChatView.participants.remove(participant) toExport.participants.remove(participant)
ChatView.render() toExport.render()
}, },
leaveConversation: () => { leaveConversation: () => {
ChatView.isParticipating = false toExport.isParticipating = false
ChatView.render() toExport.render()
}, },
mapperJoinedCall: id => { mapperJoinedCall: id => {
const mapper = ChatView.participants.findWhere({id}) const mapper = toExport.participants.findWhere({id})
mapper && mapper.set('isParticipating', true) mapper && mapper.set('isParticipating', true)
ChatView.render() toExport.render()
}, },
mapperLeftCall: id => { mapperLeftCall: id => {
const mapper = ChatView.participants.findWhere({id}) const mapper = toExport.participants.findWhere({id})
mapper && mapper.set('isParticipating', false) mapper && mapper.set('isParticipating', false)
ChatView.render() toExport.render()
}, },
invitationPending: id => { invitationPending: id => {
const mapper = ChatView.participants.findWhere({id}) const mapper = toExport.participants.findWhere({id})
mapper && mapper.set('isPending', true) mapper && mapper.set('isPending', true)
ChatView.render() toExport.render()
}, },
invitationAnswered: id => { invitationAnswered: id => {
const mapper = ChatView.participants.findWhere({id}) const mapper = toExport.participants.findWhere({id})
mapper && mapper.set('isPending', false) mapper && mapper.set('isPending', false)
ChatView.render() toExport.render()
}, },
conversationInProgress: participating => { conversationInProgress: participating => {
ChatView.conversationLive = true toExport.conversationLive = true
ChatView.isParticipating = participating toExport.isParticipating = participating
ChatView.render() toExport.render()
}, },
conversationEnded: () => { conversationEnded: () => {
ChatView.conversationLive = false toExport.conversationLive = false
ChatView.isParticipating = false toExport.isParticipating = false
ChatView.participants.forEach(p => p.set({isParticipating: false, isPending: false})) toExport.participants.forEach(p => p.set({isParticipating: false, isPending: false}))
ChatView.render() toExport.render()
}, },
videoToggleClick: function() { videoToggleClick: function() {
ChatView.videosShowing = !ChatView.videosShowing toExport.videosShowing = !toExport.videosShowing
$(document).trigger(ChatView.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff) $(document).trigger(toExport.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff)
}, },
cursorToggleClick: function() { cursorToggleClick: function() {
ChatView.cursorsShowing = !ChatView.cursorsShowing toExport.cursorsShowing = !toExport.cursorsShowing
$(document).trigger(ChatView.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff) $(document).trigger(toExport.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff)
}, },
soundToggleClick: function() { soundToggleClick: function() {
ChatView.alertSound = !ChatView.alertSound toExport.alertSound = !toExport.alertSound
}, },
inputFocus: () => { inputFocus: () => {
$(document).trigger(ChatView.events.inputFocus) $(document).trigger(ChatView.events.inputFocus)
@ -117,15 +116,15 @@ const ChatView = {
$(document).trigger(ChatView.events.inputBlur) $(document).trigger(ChatView.events.inputBlur)
}, },
addMessage: (message, isInitial, wasMe) => { addMessage: (message, isInitial, wasMe) => {
const self = ChatView const self = toExport
if (!isInitial && !self.isOpen) self.unreadMessages += 1 if (!isInitial && !self.isOpen) self.unreadMessages += 1
if (!wasMe && !isInitial && self.alertSound) self.sound.play('receivechat') if (!wasMe && !isInitial && self.alertSound) self.sound.play('receivechat')
self.messages.add(message) self.messages.add(message)
if (!isInitial && self.isOpen) self.render() if (!isInitial && self.isOpen) self.render()
}, },
sendChatMessage: message => { sendChatMessage: message => {
var self = ChatView var self = toExport
if (ChatView.alertSound) ChatView.sound.play('sendchat') if (toExport.alertSound) toExport.sound.play('sendchat')
var m = new DataModel.Message({ var m = new DataModel.Message({
message: message.message, message: message.message,
resource_id: Active.Map.id, resource_id: Active.Map.id,
@ -141,14 +140,16 @@ const ChatView = {
}) })
}, },
handleInputMessage: text => { handleInputMessage: text => {
ChatView.sendChatMessage({message: text}) toExport.sendChatMessage({message: text})
}, },
// they should be instantiated as backbone models before they get // they should be instantiated as backbone models before they get
// passed to this function // passed to this function
addMessages: (messages, isInitial, wasMe) => { addMessages: (messages, isInitial, wasMe) => {
messages.models.forEach(m => ChatView.addMessage(m, isInitial, wasMe)) messages.models.forEach(m => toExport.addMessage(m, isInitial, wasMe))
} }
} }
return toExport
}
/** /**
* @class * @class

View file

@ -1,15 +1,18 @@
import { ReactApp } from '../GlobalUI' import { ReactApp } from '../GlobalUI'
const TopicCard = { const TopicCard = () => {
const toExport = {
openTopic: null, openTopic: null,
showCard: function(node) { showCard: function(node) {
TopicCard.openTopic = node.getData('topic') toExport.openTopic = node.getData('topic')
ReactApp.render() ReactApp.render()
}, },
hideCard: function() { hideCard: function() {
TopicCard.openTopic = null toExport.openTopic = null
ReactApp.render() ReactApp.render()
} }
} }
return toExport
}
export default TopicCard export default TopicCard

View file

@ -10,7 +10,7 @@ import { JUNTO_UPDATED } from '../Realtime/events'
const Views = { const Views = {
init: (serverData) => { init: (serverData) => {
$(document).on(JUNTO_UPDATED, () => ExploreMaps.render()) $(document).on(JUNTO_UPDATED, () => ExploreMaps.render())
ChatView.init([serverData['sounds/MM_sounds.mp3'], serverData['sounds/MM_sounds.ogg']]) //ChatView.init([serverData['sounds/MM_sounds.mp3'], serverData['sounds/MM_sounds.ogg']])
}, },
ExploreMaps, ExploreMaps,
ChatView, ChatView,

View file

@ -10,14 +10,15 @@ import JIT from './JIT'
import Loading from './Loading' import Loading from './Loading'
import TopicCard from './Views/TopicCard' import TopicCard from './Views/TopicCard'
const Visualize = { const Visualize = ({Active, DataModel, JIT, TopicCard}) => {
const toExport = {
mGraph: null, // a reference to the graph object. mGraph: null, // a reference to the graph object.
cameraPosition: null, // stores the camera position when using a 3D visualization cameraPosition: null, // stores the camera position when using a 3D visualization
type: 'ForceDirected', // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D" type: 'ForceDirected', // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D"
loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created
touchDragNode: null, touchDragNode: null,
init: function(serverData) { init: function(serverData) {
var self = Visualize var self = toExport
if (serverData.VisualizeType) self.type = serverData.VisualizeType if (serverData.VisualizeType) self.type = serverData.VisualizeType
@ -45,7 +46,7 @@ const Visualize = {
}) })
}, },
computePositions: function() { computePositions: function() {
const self = Visualize const self = toExport
if (self.type === 'RGraph') { if (self.type === 'RGraph') {
let i let i
@ -107,7 +108,7 @@ const Visualize = {
* *
*/ */
render: function() { render: function() {
const self = Visualize const self = toExport
if (self.type === 'RGraph') { if (self.type === 'RGraph') {
// clear the previous canvas from #infovis // clear the previous canvas from #infovis
@ -199,11 +200,14 @@ const Visualize = {
hold() hold()
}, },
clearVisualization: function() { clearVisualization: function() {
Visualize.mGraph.graph.empty() const self = toExport
Visualize.mGraph.plot() self.mGraph.graph.empty()
self.mGraph.plot()
JIT.centerMap(Visualize.mGraph.canvas) JIT.centerMap(Visualize.mGraph.canvas)
$('#infovis').empty() $('#infovis').empty()
} }
} }
return toExport
}
export default Visualize export default Visualize

View file

@ -1,32 +1,72 @@
import Account from './Account' import Account from './Account'
import Active from './Active' import Active from './Active'
import Admin from './Admin' import Admin from './Admin'
import AutoLayout from './AutoLayout'
import Cable from './Cable'
import Control from './Control'
import Create from './Create'
import DataModel from './DataModel'
import Debug from './Debug' import Debug from './Debug'
import Filter from './Filter'
import GlobalUI, { import GlobalUI, {
ReactApp, Search, CreateMap, ImportDialog ReactApp, Search, CreateMap, ImportDialog
} from './GlobalUI' } from './GlobalUI'
import Import from './Import' import Import from './Import'
import JIT from './JIT'
import Listeners from './Listeners'
import Loading from './Loading' import Loading from './Loading'
import Map, { CheatSheet } from './Map'
import Mapper from './Mapper' import Mapper from './Mapper'
import Mouse from './Mouse'
import Organize from './Organize'
import PasteInput from './PasteInput'
import Realtime from './Realtime'
import Selected from './Selected'
import Settings from './Settings'
import Synapse from './Synapse'
import SynapseCard from './SynapseCard'
import Topic from './Topic' import Topic from './Topic'
import Util from './Util' import Util from './Util'
import Views from './Views'
import Visualize from './Visualize'
const Metamaps = window.Metamaps || {} const Metamaps = window.Metamaps || {}
Metamaps.Account = Account Metamaps.Account = Account
Metamaps.Active = Active Metamaps.Active = Active
Metamaps.Admin = Admin Metamaps.Admin = Admin
Metamaps.AutoLayout = AutoLayout
Metamaps.Cable = Cable
Metamaps.Control = Control
Metamaps.Create = Create
Metamaps.DataModel = DataModel
Metamaps.Debug = Debug Metamaps.Debug = Debug
Metamaps.Filter = Filter
Metamaps.Import = Import
Metamaps.JIT = JIT
Metamaps.Listeners = Listeners
Metamaps.Loading = Loading
Metamaps.Map = Map
Metamaps.Map.CheatSheet = CheatSheet
Metamaps.Maps = {}
Metamaps.Mapper = Mapper
Metamaps.Mouse = Mouse
Metamaps.Organize = Organize
Metamaps.PasteInput = PasteInput
Metamaps.Realtime = Realtime
Metamaps.Selected = Selected
Metamaps.Settings = Settings
Metamaps.Synapse = Synapse
Metamaps.SynapseCard = SynapseCard
Metamaps.Topic = Topic
Metamaps.Util = Util
Metamaps.Views = Views
Metamaps.Visualize = Visualize
Metamaps.GlobalUI = GlobalUI Metamaps.GlobalUI = GlobalUI
Metamaps.GlobalUI.ReactApp = ReactApp Metamaps.GlobalUI.ReactApp = ReactApp
Metamaps.GlobalUI.Search = Search Metamaps.GlobalUI.Search = Search
Metamaps.GlobalUI.CreateMap = CreateMap Metamaps.GlobalUI.CreateMap = CreateMap
Metamaps.GlobalUI.ImportDialog = ImportDialog Metamaps.GlobalUI.ImportDialog = ImportDialog
Metamaps.Import = Import
Metamaps.Loading = Loading
Metamaps.Maps = {}
Metamaps.Mapper = Mapper
Metamaps.Topic = Topic
Metamaps.Util = Util
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// initialize all the modules // initialize all the modules
@ -37,6 +77,7 @@ document.addEventListener('DOMContentLoaded', function() {
Metamaps[prop].hasOwnProperty('init') && Metamaps[prop].hasOwnProperty('init') &&
typeof (Metamaps[prop].init) === 'function' typeof (Metamaps[prop].init) === 'function'
) { ) {
console.log(prop)
Metamaps[prop].init(Metamaps.ServerData) Metamaps[prop].init(Metamaps.ServerData)
} }
} }