diff --git a/frontend/src/Metamaps/Map/CheatSheet.js b/frontend/src/Metamaps/Map/CheatSheet.js new file mode 100644 index 00000000..969ee159 --- /dev/null +++ b/frontend/src/Metamaps/Map/CheatSheet.js @@ -0,0 +1,27 @@ +const CheatSheet = { + init: function () { + // tab the cheatsheet + $('#cheatSheet').tabs() + $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix') + $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left') + + // id = the id of a vimeo video + var switchVideo = function (element, id) { + $('.tutorialItem').removeClass('active') + $(element).addClass('active') + $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id) + } + + $('#gettingStarted').click(function () { + // switchVideo(this,'88334167') + }) + $('#upYourSkillz').click(function () { + // switchVideo(this,'100118167') + }) + $('#advancedMapping').click(function () { + // switchVideo(this,'88334167') + }) + } +} + +export default CheatSheet diff --git a/frontend/src/Metamaps/Map.js b/frontend/src/Metamaps/Map/InfoBox.js similarity index 51% rename from frontend/src/Metamaps/Map.js rename to frontend/src/Metamaps/Map/InfoBox.js index cd2c3d2e..eaceba29 100644 --- a/frontend/src/Metamaps/Map.js +++ b/frontend/src/Metamaps/Map/InfoBox.js @@ -1,405 +1,19 @@ /* global Metamaps, $ */ import Active from './Active' -import AutoLayout from './AutoLayout' -import Create from './Create' -import Filter from './Filter' -import GlobalUI from './GlobalUI' -import JIT from './JIT' -import Realtime from './Realtime' -import Selected from './Selected' -import SynapseCard from './SynapseCard' -import TopicCard from './TopicCard' -import Visualize from './Visualize' +import GlobalUI from '../GlobalUI' +import Router from '../Router' /* - * Metamaps.Map.js.erb - * - * Dependencies: - * - Metamaps.Backbone - * - Metamaps.Erb - * - Metamaps.Loading - * - Metamaps.Mappers - * - Metamaps.Mappings - * - Metamaps.Maps - * - Metamaps.Messages - * - Metamaps.Router - * - Metamaps.Synapses - * - Metamaps.Topics - * - * Major sub-modules: - * - Metamaps.Map.CheatSheet - * - Metamaps.Map.InfoBox + * Metamaps.Collaborators + * Metamaps.Erb + * Metamaps.Mappers + * Metamaps.Maps + * Metamaps.Synapses + * Metamaps.Topics */ -window.Metamaps = window.Metamaps || {} -Metamaps.Map = { - events: { - editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' - }, - init: function () { - var self = Metamaps.Map - - // prevent right clicks on the main canvas, so as to not get in the way of our right clicks - $('#center-container').bind('contextmenu', function (e) { - return false - }) - - $('.starMap').click(function () { - if ($(this).is('.starred')) self.unstar() - else self.star() - }) - - $('.sidebarFork').click(function () { - self.fork() - }) - - GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() - - self.updateStar() - self.InfoBox.init() - self.CheatSheet.init() - - $(document).on(Metamaps.Map.events.editedByActiveMapper, self.editedByActiveMapper) - }, - launch: function (id) { - var bb = Metamaps.Backbone - var start = function (data) { - Active.Map = new bb.Map(data.map) - Metamaps.Mappers = new bb.MapperCollection(data.mappers) - Metamaps.Collaborators = new bb.MapperCollection(data.collaborators) - Metamaps.Topics = new bb.TopicCollection(data.topics) - Metamaps.Synapses = new bb.SynapseCollection(data.synapses) - Metamaps.Mappings = new bb.MappingCollection(data.mappings) - Metamaps.Messages = data.messages - Metamaps.Stars = data.stars - Metamaps.Backbone.attachCollectionEvents() - - var map = Active.Map - var mapper = Active.Mapper - - // add class to .wrapper for specifying whether you can edit the map - if (map.authorizeToEdit(mapper)) { - $('.wrapper').addClass('canEditMap') - } - - // add class to .wrapper for specifying if the map can - // be collaborated on - if (map.get('permission') === 'commons') { - $('.wrapper').addClass('commonsMap') - } - - Metamaps.Map.updateStar() - - // set filter mapper H3 text - $('#filter_by_mapper h3').html('MAPPERS') - - // build and render the visualization - Visualize.type = 'ForceDirected' - JIT.prepareVizData() - - // update filters - Filter.reset() - - // reset selected arrays - Selected.reset() - - // set the proper mapinfobox content - Metamaps.Map.InfoBox.load() - - // these three update the actual filter box with the right list items - Filter.checkMetacodes() - Filter.checkSynapses() - Filter.checkMappers() - - Realtime.startActiveMap() - Metamaps.Loading.hide() - - // for mobile - $('#header_content').html(map.get('name')) - } - - $.ajax({ - url: '/maps/' + id + '/contains.json', - success: start - }) - }, - end: function () { - if (Active.Map) { - $('.wrapper').removeClass('canEditMap commonsMap') - AutoLayout.resetSpiral() - - $('.rightclickmenu').remove() - TopicCard.hideCard() - SynapseCard.hideCard() - Create.newTopic.hide(true) // true means force (and override pinned) - Create.newSynapse.hide() - Filter.close() - Metamaps.Map.InfoBox.close() - Realtime.endActiveMap() - } - }, - updateStar: function () { - if (!Active.Mapper || !Metamaps.Stars) return - // update the star/unstar icon - if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) { - $('.starMap').addClass('starred') - $('.starMap .tooltipsAbove').html('Unstar') - } else { - $('.starMap').removeClass('starred') - $('.starMap .tooltipsAbove').html('Star') - } - }, - star: function () { - var self = Metamaps.Map - - if (!Active.Map) return - $.post('/maps/' + Active.Map.id + '/star') - Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) - Metamaps.Maps.Starred.add(Active.Map) - GlobalUI.notifyUser('Map is now starred') - self.updateStar() - }, - unstar: function () { - var self = Metamaps.Map - - if (!Active.Map) return - $.post('/maps/' + Active.Map.id + '/unstar') - Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id }) - Metamaps.Maps.Starred.remove(Active.Map) - self.updateStar() - }, - fork: function () { - GlobalUI.openLightbox('forkmap') - - var nodes_data = '', - synapses_data = '' - var nodes_array = [] - var synapses_array = [] - // 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 - nodes_array.push(id) - var x, y - if (n.pos.x && n.pos.y) { - x = n.pos.x - y = n.pos.y - } else { - var x = Math.cos(n.pos.theta) * n.pos.rho - var y = Math.sin(n.pos.theta) * n.pos.rho - } - nodes_data += id + '/' + x + '/' + y + ',' - } - }) - // collect the unfiltered synapses - Metamaps.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 = nodes_array.indexOf(synapse.get('node1_id')) > -1 - topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1 - if (descNotFiltered && topicsNotFiltered) { - synapses_array.push(synapse.id) - } - }) - - synapses_data = synapses_array.join() - nodes_data = nodes_data.slice(0, -1) - - GlobalUI.CreateMap.topicsToMap = nodes_data - GlobalUI.CreateMap.synapsesToMap = synapses_data - }, - leavePrivateMap: function () { - var map = Active.Map - Metamaps.Maps.Active.remove(map) - Metamaps.Maps.Featured.remove(map) - Metamaps.Router.home() - 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 = confirm(confirmString) - if (c) { - Metamaps.Router.maps(Active.Map.id) - } - }, - editedByActiveMapper: function () { - if (Active.Mapper) { - Metamaps.Mappers.add(Active.Mapper) - } - }, - exportImage: function () { - 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 - return this.size = { - width: canvas.width, - height: canvas.height - } - } - canvas.scale = function (x, y) { - var px = this.scaleOffsetX * x, - py = this.scaleOffsetY * y - var dx = this.translateOffsetX * (x - 1) / px, - 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) { - var sx = this.scaleOffsetX, - 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) - - var c = canvas.canvas, - ctx = canvas.getCtx(), - scale = canvas.scaleOffsetX - - // draw a grey background - ctx.fillStyle = '#d8d9da' - var xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale), - 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 - }) - - var imageData = { - encoded_image: canvas.canvas.toDataURL() - } - - var map = Active.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([separator = '-']) - var downloadMessage = '' - downloadMessage += 'Captured map screenshot! ' - downloadMessage += "DOWNLOAD" - GlobalUI.notifyUser(downloadMessage) - - $.ajax({ - type: 'POST', - dataType: 'json', - url: '/maps/' + Active.Map.id + '/upload_screenshot', - data: imageData, - success: function (data) { - console.log('successfully uploaded map screenshot') - }, - error: function () { - console.log('failed to save map screenshot') - } - }) - } -} - -/* - * - * CHEATSHEET - * - */ -Metamaps.Map.CheatSheet = { - init: function () { - // tab the cheatsheet - $('#cheatSheet').tabs() - $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix') - $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left') - - // id = the id of a vimeo video - var switchVideo = function (element, id) { - $('.tutorialItem').removeClass('active') - $(element).addClass('active') - $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id) - } - - $('#gettingStarted').click(function () { - // switchVideo(this,'88334167') - }) - $('#upYourSkillz').click(function () { - // switchVideo(this,'100118167') - }) - $('#advancedMapping').click(function () { - // switchVideo(this,'88334167') - }) - } -}; // end Metamaps.Map.CheatSheet - -/* - * - * INFOBOX - * - */ -Metamaps.Map.InfoBox = { +const InfoBox = { isOpen: false, changing: false, selectingPermission: false, @@ -407,7 +21,7 @@ Metamaps.Map.InfoBox = { nameHTML: '{{name}}', descHTML: '{{desc}}', init: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon').click(self.toggleBox) $('.mapInfoBox').click(function (event) { @@ -426,7 +40,7 @@ Metamaps.Map.InfoBox = { } }, toggleBox: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (self.isOpen) self.close() else self.open() @@ -434,7 +48,7 @@ Metamaps.Map.InfoBox = { event.stopPropagation() }, open: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon div').addClass('hide') if (!self.isOpen && !self.changing) { self.changing = true @@ -445,7 +59,7 @@ Metamaps.Map.InfoBox = { } }, close: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon div').removeClass('hide') if (!self.changing) { @@ -459,7 +73,7 @@ Metamaps.Map.InfoBox = { } }, load: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox var map = Active.Map @@ -494,7 +108,7 @@ Metamaps.Map.InfoBox = { self.attachEventListeners() }, attachEventListeners: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoBox.canEdit .best_in_place').best_in_place() @@ -547,7 +161,7 @@ Metamaps.Map.InfoBox = { $('.mapContributors .tip').unbind().click(function (event) { event.stopPropagation() }) - $('.mapContributors .tip li a').click(Metamaps.Router.intercept) + $('.mapContributors .tip li a').click(Router.intercept) $('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function () { $('.mapContributors .tip').hide() @@ -556,7 +170,7 @@ Metamaps.Map.InfoBox = { self.addTypeahead() }, addTypeahead: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (!Active.Map) return @@ -603,14 +217,14 @@ Metamaps.Map.InfoBox = { } }, removeCollaborator: function (collaboratorId) { - var self = Metamaps.Map.InfoBox + var self = InfoBox Metamaps.Collaborators.remove(Metamaps.Collaborators.get(collaboratorId)) var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) self.updateNumbers() }, addCollaborator: function (newCollaboratorId) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (Metamaps.Collaborators.get(newCollaboratorId)) { GlobalUI.notifyUser('That user already has access') @@ -629,7 +243,7 @@ Metamaps.Map.InfoBox = { $.getJSON('/users/' + newCollaboratorId + '.json', callback) }, handleResultClick: function (event, item) { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.addCollaborator(item.id) $('.collaboratorSearchField').typeahead('val', '') @@ -641,7 +255,7 @@ Metamaps.Map.InfoBox = { $('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm) }, createContributorList: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id') var string = '' @@ -666,7 +280,7 @@ Metamaps.Map.InfoBox = { updateNumbers: function () { if (!Active.Map) return - var self = Metamaps.Map.InfoBox + var self = InfoBox var mapper = Active.Mapper var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators @@ -689,10 +303,10 @@ Metamaps.Map.InfoBox = { $('.mapTopics').text(Metamaps.Topics.length) $('.mapSynapses').text(Metamaps.Synapses.length) - $('.mapEditedAt').html('Last edited: ' + Metamaps.Util.nowDateFormatted()) + $('.mapEditedAt').html('Last edited: ' + Util.nowDateFormatted()) }, onPermissionClick: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (!self.selectingPermission) { self.selectingPermission = true @@ -709,14 +323,14 @@ Metamaps.Map.InfoBox = { } }, hidePermissionSelect: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.selectingPermission = false $('.mapPermission').removeClass('minimize') // this line flips the pull up arrow to a drop down arrow $('.mapPermission .permissionSelect').remove() }, selectPermission: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.selectingPermission = false var permission = $(this).attr('class') @@ -740,19 +354,19 @@ Metamaps.Map.InfoBox = { var authorized = map.authorizePermissionChange(mapper) if (doIt && authorized) { - Metamaps.Map.InfoBox.close() + InfoBox.close() Metamaps.Maps.Active.remove(map) Metamaps.Maps.Featured.remove(map) Metamaps.Maps.Mine.remove(map) Metamaps.Maps.Shared.remove(map) map.destroy() - Metamaps.Router.home() + Router.home() GlobalUI.notifyUser('Map eliminated!') } else if (!authorized) { alert("Hey now. We can't just go around willy nilly deleting other people's maps now can we? Run off and find something constructive to do, eh?") } } -}; // end Metamaps.Map.InfoBox +} -export default Metamaps.Map +export default InfoBox diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js new file mode 100644 index 00000000..84ee8b39 --- /dev/null +++ b/frontend/src/Metamaps/Map/index.js @@ -0,0 +1,365 @@ +/* global Metamaps, $ */ + +import Active from './Active' +import AutoLayout from './AutoLayout' +import Create from './Create' +import Filter from './Filter' +import GlobalUI from './GlobalUI' +import JIT from './JIT' +import Realtime from './Realtime' +import Router from './Router' +import Selected from './Selected' +import SynapseCard from './SynapseCard' +import TopicCard from './TopicCard' +import Visualize from './Visualize' + +import CheatSheet from './CheatSheet' +import InfoBox from './InfoBox' + +/* + * Metamaps.Map.js.erb + * + * Dependencies: + * - Metamaps.Backbone + * - Metamaps.Erb + * - Metamaps.Loading + * - Metamaps.Mappers + * - Metamaps.Mappings + * - Metamaps.Maps + * - Metamaps.Messages + * - Metamaps.Synapses + * - Metamaps.Topics + */ + +const Map = { + events: { + editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' + }, + init: function () { + var self = Map + + // prevent right clicks on the main canvas, so as to not get in the way of our right clicks + $('#center-container').bind('contextmenu', function (e) { + return false + }) + + $('.starMap').click(function () { + if ($(this).is('.starred')) self.unstar() + else self.star() + }) + + $('.sidebarFork').click(function () { + self.fork() + }) + + GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() + + self.updateStar() + self.InfoBox.init() + CheatSheet.init() + + $(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper) + }, + launch: function (id) { + var bb = Metamaps.Backbone + var start = function (data) { + Active.Map = new bb.Map(data.map) + Metamaps.Mappers = new bb.MapperCollection(data.mappers) + Metamaps.Collaborators = new bb.MapperCollection(data.collaborators) + Metamaps.Topics = new bb.TopicCollection(data.topics) + Metamaps.Synapses = new bb.SynapseCollection(data.synapses) + Metamaps.Mappings = new bb.MappingCollection(data.mappings) + Metamaps.Messages = data.messages + Metamaps.Stars = data.stars + Metamaps.Backbone.attachCollectionEvents() + + var map = Active.Map + var mapper = Active.Mapper + + // add class to .wrapper for specifying whether you can edit the map + if (map.authorizeToEdit(mapper)) { + $('.wrapper').addClass('canEditMap') + } + + // add class to .wrapper for specifying if the map can + // be collaborated on + if (map.get('permission') === 'commons') { + $('.wrapper').addClass('commonsMap') + } + + Map.updateStar() + + // set filter mapper H3 text + $('#filter_by_mapper h3').html('MAPPERS') + + // build and render the visualization + Visualize.type = 'ForceDirected' + JIT.prepareVizData() + + // update filters + Filter.reset() + + // reset selected arrays + Selected.reset() + + // set the proper mapinfobox content + Map.InfoBox.load() + + // these three update the actual filter box with the right list items + Filter.checkMetacodes() + Filter.checkSynapses() + Filter.checkMappers() + + Realtime.startActiveMap() + Metamaps.Loading.hide() + + // for mobile + $('#header_content').html(map.get('name')) + } + + $.ajax({ + url: '/maps/' + id + '/contains.json', + success: start + }) + }, + end: function () { + if (Active.Map) { + $('.wrapper').removeClass('canEditMap commonsMap') + AutoLayout.resetSpiral() + + $('.rightclickmenu').remove() + TopicCard.hideCard() + SynapseCard.hideCard() + Create.newTopic.hide(true) // true means force (and override pinned) + Create.newSynapse.hide() + Filter.close() + Map.InfoBox.close() + Realtime.endActiveMap() + } + }, + updateStar: function () { + if (!Active.Mapper || !Metamaps.Stars) return + // update the star/unstar icon + if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) { + $('.starMap').addClass('starred') + $('.starMap .tooltipsAbove').html('Unstar') + } else { + $('.starMap').removeClass('starred') + $('.starMap .tooltipsAbove').html('Star') + } + }, + star: function () { + var self = Map + + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/star') + Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) + Metamaps.Maps.Starred.add(Active.Map) + GlobalUI.notifyUser('Map is now starred') + self.updateStar() + }, + unstar: function () { + var self = Map + + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/unstar') + Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id }) + Metamaps.Maps.Starred.remove(Active.Map) + self.updateStar() + }, + fork: function () { + GlobalUI.openLightbox('forkmap') + + var nodes_data = '', + synapses_data = '' + var nodes_array = [] + var synapses_array = [] + // 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 + nodes_array.push(id) + var x, y + if (n.pos.x && n.pos.y) { + x = n.pos.x + y = n.pos.y + } else { + var x = Math.cos(n.pos.theta) * n.pos.rho + var y = Math.sin(n.pos.theta) * n.pos.rho + } + nodes_data += id + '/' + x + '/' + y + ',' + } + }) + // collect the unfiltered synapses + Metamaps.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 = nodes_array.indexOf(synapse.get('node1_id')) > -1 + topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1 + if (descNotFiltered && topicsNotFiltered) { + synapses_array.push(synapse.id) + } + }) + + synapses_data = synapses_array.join() + nodes_data = nodes_data.slice(0, -1) + + GlobalUI.CreateMap.topicsToMap = nodes_data + GlobalUI.CreateMap.synapsesToMap = synapses_data + }, + leavePrivateMap: function () { + var map = Active.Map + Metamaps.Maps.Active.remove(map) + Metamaps.Maps.Featured.remove(map) + Router.home() + 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 = confirm(confirmString) + if (c) { + Router.maps(Active.Map.id) + } + }, + editedByActiveMapper: function () { + if (Active.Mapper) { + Metamaps.Mappers.add(Active.Mapper) + } + }, + exportImage: function () { + 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 + return this.size = { + width: canvas.width, + height: canvas.height + } + } + canvas.scale = function (x, y) { + var px = this.scaleOffsetX * x, + py = this.scaleOffsetY * y + var dx = this.translateOffsetX * (x - 1) / px, + 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) { + var sx = this.scaleOffsetX, + 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) + + var c = canvas.canvas, + ctx = canvas.getCtx(), + scale = canvas.scaleOffsetX + + // draw a grey background + ctx.fillStyle = '#d8d9da' + var xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale), + 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 + }) + + var imageData = { + encoded_image: canvas.canvas.toDataURL() + } + + var map = Active.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([separator = '-']) + var downloadMessage = '' + downloadMessage += 'Captured map screenshot! ' + downloadMessage += "DOWNLOAD" + GlobalUI.notifyUser(downloadMessage) + + $.ajax({ + type: 'POST', + dataType: 'json', + url: '/maps/' + Active.Map.id + '/upload_screenshot', + data: imageData, + success: function (data) { + console.log('successfully uploaded map screenshot') + }, + error: function () { + console.log('failed to save map screenshot') + } + }) + } +} + +export CheatSheet, InfoBox +export default Map diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 9fe8925b..7b431d1f 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -13,7 +13,7 @@ import GlobalUI from './GlobalUI' import Import from './Import' import JIT from './JIT' import Listeners from './Listeners' -import Map from './Map' +import Map, { CheatSheet, InfoBox } from './Map' import Mapper from './Mapper' import Mobile from './Mobile' import Mouse from './Mouse' @@ -46,6 +46,8 @@ Metamaps.Import = Import Metamaps.JIT = JIT Metamaps.Listeners = Listeners Metamaps.Map = Map +Metamaps.Map.CheatSheet = CheatSheet +Metamaps.Map.InfoBox = InfoBox Metamaps.Maps = {} Metamaps.Mapper = Mapper Metamaps.Mobile = Mobile