diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store index 5008ddfc..94ce050f 100644 Binary files a/app/assets/images/.DS_Store and b/app/assets/images/.DS_Store differ diff --git a/app/assets/images/context_topicview_sprite.png b/app/assets/images/context_topicview_sprite.png new file mode 100644 index 00000000..c611d392 Binary files /dev/null and b/app/assets/images/context_topicview_sprite.png differ diff --git a/app/assets/images/icons/Open Data/OD_API.png b/app/assets/images/icons/Open Data/OD_API.png new file mode 100644 index 00000000..c84c0f11 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_API.png differ diff --git a/app/assets/images/icons/Open Data/OD_Business Data.png b/app/assets/images/icons/Open Data/OD_Business Data.png new file mode 100644 index 00000000..2658c658 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Business Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png b/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png new file mode 100644 index 00000000..c08ebbd6 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Creative Commons Data.png b/app/assets/images/icons/Open Data/OD_Creative Commons Data.png new file mode 100644 index 00000000..29f428fb Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Creative Commons Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Data Analyst.png b/app/assets/images/icons/Open Data/OD_Data Analyst.png new file mode 100644 index 00000000..8a9957ae Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Analyst.png differ diff --git a/app/assets/images/icons/Open Data/OD_Data Mining.png b/app/assets/images/icons/Open Data/OD_Data Mining.png new file mode 100644 index 00000000..dd192bee Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Mining.png differ diff --git a/app/assets/images/icons/Open Data/OD_Data Scientist.png b/app/assets/images/icons/Open Data/OD_Data Scientist.png new file mode 100644 index 00000000..71e71194 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Scientist.png differ diff --git a/app/assets/images/icons/Open Data/OD_Data.png b/app/assets/images/icons/Open Data/OD_Data.png new file mode 100644 index 00000000..1ae5bd38 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Database.png b/app/assets/images/icons/Open Data/OD_Database.png new file mode 100644 index 00000000..488f460e Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Database.png differ diff --git a/app/assets/images/icons/Open Data/OD_Geolocation.png b/app/assets/images/icons/Open Data/OD_Geolocation.png new file mode 100644 index 00000000..20d1474c Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Geolocation.png differ diff --git a/app/assets/images/icons/Open Data/OD_Government Data.png b/app/assets/images/icons/Open Data/OD_Government Data.png new file mode 100644 index 00000000..6981733b Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Government Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Hacker.png b/app/assets/images/icons/Open Data/OD_Hacker.png new file mode 100644 index 00000000..923bfe0c Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Hacker.png differ diff --git a/app/assets/images/icons/Open Data/OD_Map Data.png b/app/assets/images/icons/Open Data/OD_Map Data.png new file mode 100644 index 00000000..a51bbc31 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Map Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Mapper.png b/app/assets/images/icons/Open Data/OD_Mapper.png new file mode 100644 index 00000000..028d36e3 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Mapper.png differ diff --git a/app/assets/images/icons/Open Data/OD_Metadata.png b/app/assets/images/icons/Open Data/OD_Metadata.png new file mode 100644 index 00000000..5ab2065a Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Metadata.png differ diff --git a/app/assets/images/icons/Open Data/OD_Open Data.png b/app/assets/images/icons/Open Data/OD_Open Data.png new file mode 100644 index 00000000..51ad11f9 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Open Data.png differ diff --git a/app/assets/images/icons/Open Data/OD_Open Innovation.png b/app/assets/images/icons/Open Data/OD_Open Innovation.png new file mode 100644 index 00000000..d75b4aa9 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Open Innovation.png differ diff --git a/app/assets/images/icons/Open Data/OD_Startup.png b/app/assets/images/icons/Open Data/OD_Startup.png new file mode 100644 index 00000000..53845979 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Startup.png differ diff --git a/app/assets/images/icons/Open Data/OD_algorithm.png b/app/assets/images/icons/Open Data/OD_algorithm.png new file mode 100644 index 00000000..1b5cbee7 Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_algorithm.png differ diff --git a/app/assets/images/linkedmedia.png b/app/assets/images/linkedmedia.png deleted file mode 100755 index 2009b7a3..00000000 Binary files a/app/assets/images/linkedmedia.png and /dev/null differ diff --git a/app/assets/images/missing-map.png b/app/assets/images/missing-map.png index 5a51221a..54cbd843 100644 Binary files a/app/assets/images/missing-map.png and b/app/assets/images/missing-map.png differ diff --git a/app/assets/images/screenshot_sprite.png b/app/assets/images/screenshot_sprite.png new file mode 100644 index 00000000..d3c87c5a Binary files /dev/null and b/app/assets/images/screenshot_sprite.png differ diff --git a/app/assets/images/synapse32padded.png b/app/assets/images/synapse32padded.png new file mode 100644 index 00000000..09e52fc0 Binary files /dev/null and b/app/assets/images/synapse32padded.png differ diff --git a/app/assets/images/synapsestar.png b/app/assets/images/synapsestar.png deleted file mode 100755 index ba9a7dd3..00000000 Binary files a/app/assets/images/synapsestar.png and /dev/null differ diff --git a/app/assets/images/topic_description_signifier.png b/app/assets/images/topic_description_signifier.png new file mode 100644 index 00000000..956db0a3 Binary files /dev/null and b/app/assets/images/topic_description_signifier.png differ diff --git a/app/assets/images/topic_link_signifier.png b/app/assets/images/topic_link_signifier.png new file mode 100644 index 00000000..a8b8b8e5 Binary files /dev/null and b/app/assets/images/topic_link_signifier.png differ diff --git a/app/assets/javascripts/src/JIT.js b/app/assets/javascripts/src/JIT.js index 743a7eef..498183ef 100644 --- a/app/assets/javascripts/src/JIT.js +++ b/app/assets/javascripts/src/JIT.js @@ -1,6 +1,3 @@ - -var requestAnimId; - /* Copyright (c) 2011 Sencha Inc. - Author: Nicolas Garcia Belmonte (http://philogb.github.com/) diff --git a/app/assets/javascripts/src/Metamaps.JIT.js b/app/assets/javascripts/src/Metamaps.JIT.js index faf895f2..88436a80 100644 --- a/app/assets/javascripts/src/Metamaps.JIT.js +++ b/app/assets/javascripts/src/Metamaps.JIT.js @@ -20,19 +20,26 @@ Metamaps.JIT = { $(".zoomIn").click(self.zoomIn); $(".zoomOut").click(self.zoomOut); - $(".zoomExtents").click(self.zoomExtents); - self.synapseStarImage = new Image(); - self.synapseStarImage.src = '/assets/synapsestar.png'; + var zoomExtents = function (event) { + self.zoomExtents(event, Metamaps.Visualize.mGraph.canvas); + }; + $(".zoomExtents").click(zoomExtents); - self.topicMediaImage = new Image(); - self.topicMediaImage.src = '/assets/linkedmedia.png'; + $(".takeScreenshot").click(Metamaps.Map.exportImage); + + self.topicDescImage = new Image(); + self.topicDescImage.src = '/assets/topic_description_signifier.png'; + + self.topicLinkImage = new Image(); + self.topicLinkImage.src = '/assets/topic_link_signifier.png'; }, /** * convert our topic JSON into something JIT can use */ - prepareVizData: function () { - var self = Metamaps.JIT; + convertModelsToJIT: function(topics, synapses) { + var jitReady = []; + var synapsesToRemove = []; var topic; var mapping; @@ -42,18 +49,14 @@ Metamaps.JIT = { var edge; var edges = []; - // reset/empty vizData - self.vizData = []; - Metamaps.Visualize.loadLater = false; - - Metamaps.Topics.each(function (t) { + topics.each(function (t) { node = t.createNode(); nodes[node.id] = node; }); - Metamaps.Synapses.each(function (s) { + synapses.each(function (s) { edge = s.createEdge(); - if(Metamaps.Topics.get(s.get('node1_id')) === undefined || Metamaps.Topics.get(s.get('node2_id')) === undefined) { + if (topics.get(s.get('node1_id')) === undefined || topics.get(s.get('node2_id')) === undefined) { // this means it's an invalid synapse synapsesToRemove.push(s); } @@ -83,17 +86,31 @@ Metamaps.JIT = { } }); + _.each(nodes, function (node) { + jitReady.push(node); + }); + + return [jitReady, synapsesToRemove]; + }, + prepareVizData: function () { + var self = Metamaps.JIT; + var mapping; + + // reset/empty vizData + self.vizData = []; + Metamaps.Visualize.loadLater = false; + + var results = self.convertModelsToJIT(Metamaps.Topics, Metamaps.Synapses); + + self.vizData = results[0]; + // clean up the synapses array in case of any faulty data - _.each(synapsesToRemove, function (synapse) { + _.each(results[1], function (synapse) { mapping = synapse.getMapping(); Metamaps.Synapses.remove(synapse); Metamaps.Mappings.remove(mapping); }); - _.each(nodes, function (node) { - self.vizData.push(node); - }); - if (self.vizData.length == 0) { Metamaps.Visualize.loadLater = true; } @@ -123,24 +140,45 @@ Metamaps.JIT = { var directionCat = synapse.get("category"); //label placement on edges - Metamaps.JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse); + if (canvas.denySelected) { + var color = Metamaps.Settings.colors.synapses.normal; + canvas.getCtx().fillStyle = canvas.getCtx().strokeStyle = color; + } + Metamaps.JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse, canvas); //check for edge label in data var desc = synapse.get("desc"); var showDesc = adj.getData("showDesc"); - var drawStar = function (context, x, y) { - var starImage = Metamaps.JIT.synapseStarImage; - var starImageLoaded = starImage.complete || - (typeof starImage.naturalWidth !== "undefined" && - starImage.naturalWidth !== 0) - if (starImageLoaded) { - context.drawImage(starImage, x, y, 16, 16); - } + var drawSynapseCount = function (context, x, y, count) { + /* + circle size: 16x16px + positioning: overlay and center on top right corner of synapse label - 8px left and 8px down + color: #dab539 + border color: #424242 + border size: 1.5px + font: DIN medium + font-size: 14pt + font-color: #424242 + */ + context.beginPath(); + context.arc(x, y, 8, 0, 2 * Math.PI, false); + context.fillStyle = '#DAB539'; + context.strokeStyle = '#424242'; + context.lineWidth = 1.5; + context.closePath(); + context.fill(); + context.stroke(); + + // add the synapse count + context.fillStyle = '#424242'; + context.textAlign = 'center'; + context.font = '14px din-medium'; + context.fillText(count, x, y - 6); }; - if (desc != "" && showDesc) { + if (!canvas.denySelected && desc != "" && showDesc) { // '&' to '&' desc = Metamaps.Util.decodeEntities(desc); @@ -155,7 +193,7 @@ Metamaps.JIT = { for (index = 0; index < arrayOfLabelLines.length; ++index) { lineWidths.push(ctx.measureText(arrayOfLabelLines[index]).width) } - var width = Math.max.apply(null, lineWidths) + 8; + var width = Math.max.apply(null, lineWidths) + 16; var height = (16 * arrayOfLabelLines.length) + 8; var x = (pos.x + posChild.x - width) / 2; @@ -177,23 +215,29 @@ Metamaps.JIT = { ctx.closePath(); ctx.fill(); + // get number of synapses + var synapseNum = adj.getData("synapses").length; + //render text - ctx.fillStyle = '#222222'; + ctx.fillStyle = '#424242'; ctx.textAlign = 'center'; for (index = 0; index < arrayOfLabelLines.length; ++index) { - ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 5 + (16 * index)); + ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 7 + (16 * index)); } - if (adj.getData("synapses").length > 1) { - drawStar(ctx, x + width, y); + if (synapseNum > 1) { + drawSynapseCount(ctx, x + width, y, synapseNum); } } - else if (showDesc) { - if (adj.getData("synapses").length > 1) { + else if (!canvas.denySelected && showDesc) { + // get number of synapses + var synapseNum = adj.getData("synapses").length; + + if (synapseNum > 1) { var ctx = canvas.getCtx(); var x = (pos.x + posChild.x) / 2; var y = (pos.y + posChild.y) / 2; - drawStar(ctx, x, y); + drawSynapseCount(ctx, x, y, synapseNum); } } @@ -400,7 +444,7 @@ Metamaps.JIT = { ctx = canvas.getCtx(); // if the topic is selected draw a circle around it - if (node.selected) { + if (!canvas.denySelected && node.selected) { ctx.beginPath(); ctx.arc(pos.x, pos.y, dim + 3, 0, 2 * Math.PI, false); ctx.strokeStyle = Metamaps.Settings.colors.topics.selected; @@ -423,12 +467,22 @@ Metamaps.JIT = { // if the topic has a link, draw a small image to indicate that var hasLink = topic && topic.get('link') !== "" && topic.get('link') !== null; - var linkImage = Metamaps.JIT.topicMediaImage; + var linkImage = Metamaps.JIT.topicLinkImage; var linkImageLoaded = linkImage.complete || (typeof linkImage.naturalWidth !== "undefined" && linkImage.naturalWidth !== 0) if (hasLink && linkImageLoaded) { - ctx.drawImage(linkImage, pos.x + dim / 2, pos.y - dim - 8, 16, 16); + ctx.drawImage(linkImage, pos.x - dim - 8, pos.y - dim - 8, 16, 16); + } + + // if the topic has a desc, draw a small image to indicate that + var hasDesc = topic && topic.get('desc') !== "" && topic.get('desc') !== null; + var descImage = Metamaps.JIT.topicDescImage; + var descImageLoaded = descImage.complete || + (typeof descImage.naturalWidth !== "undefined" && + descImage.naturalWidth !== 0) + if (hasDesc && descImageLoaded) { + ctx.drawImage(descImage, pos.x + dim - 8, pos.y - dim - 8, 16, 16); } }, 'contains': function (node, pos) { @@ -469,7 +523,7 @@ Metamaps.JIT = { if (-1 < pos.x && pos.x < 1) pos.x = 0; if (-1 < pos.y && pos.y < 1) pos.y = 0; - return $jit.Graph.Plot.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon); + return $jit.Graph.Plot.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon + 5); } } } @@ -865,6 +919,9 @@ Metamaps.JIT = { }; } } + else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && Metamaps.Active.Topic) { + Metamaps.GlobalUI.notifyUser("Cannot create in Topic view."); + } else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && !authorized) { Metamaps.GlobalUI.notifyUser("Cannot edit Public map."); } @@ -959,6 +1016,10 @@ Metamaps.JIT = { Metamaps.GlobalUI.notifyUser("Cannot edit Public map."); return; } + else if (Metamaps.Active.Topic) { + Metamaps.GlobalUI.notifyUser("Cannot create in Topic view."); + return; + } // DOUBLE CLICK //pop up node creation :) Metamaps.Create.newTopic.addSynapse = false; @@ -1269,7 +1330,9 @@ Metamaps.JIT = { if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
  • Delete
  • '; - if (Metamaps.Active.Topic) menustring += '
  • Center this topic
  • '; + if (Metamaps.Active.Topic) { + menustring += '
  • Center this topic
  • '; + } menustring += '
  • Open in new tab
  • '; if (Metamaps.Active.Mapper) { var options = ''; rightclickmenu.innerHTML = menustring; @@ -1376,7 +1448,70 @@ Metamaps.JIT = { Metamaps.Control.updateSelectedMetacodes($(this).attr('data-id')); }); - }, //selectNodeOnRightClickHandler + + // fetch relatives + var fetched = false; + $('.rc-siblings').hover(function () { + if (!fetched) { + Metamaps.JIT.populateRightClickSiblings(node); + fetched = true; + } + }); + $('.rc-siblings .fetchAll').click(function () { + $('.rightclickmenu').remove(); + // data-id is a metacode id + Metamaps.Topic.fetchRelatives(node); + }); + }, //selectNodeOnRightClickHandler, + populateRightClickSiblings: function(node) { + var self = Metamaps.JIT; + + // depending on how many topics are selected, do different things + /*if (Metamaps.Selected.Nodes.length > 1) { + // we don't bother filling the submenu with + // specific numbers, because there are too many topics + // selected to find those numbers + $('#loadingSiblings').remove(); + return; + }*/ + + var topic = node.getData('topic'); + + // add a loading icon for now + var loader = new CanvasLoader('loadingSiblings'); + loader.setColor('#4FC059'); // default is '#000000' + loader.setDiameter(15); // default is 40 + loader.setDensity(41); // default is 40 + loader.setRange(0.9); // default is 1.3 + loader.show(); // Hidden by default + + var topics = Metamaps.Topics.map(function(t){ return t.id }); + var topics_string = topics.join(); + + var successCallback = function(data) { + $('#loadingSiblings').remove(); + + for (var key in data) { + var string = Metamaps.Metacodes.get(key).get('name') + ' (' + data[key] + ')'; + $('#fetchSiblingList').append('
  • ' + string + '
  • '); + } + + $('.rc-siblings .getSiblings').click(function () { + $('.rightclickmenu').remove(); + // data-id is a metacode id + Metamaps.Topic.fetchRelatives(node, $(this).attr('data-id')); + }); + }; + + $.ajax({ + type: "Get", + url: "/topics/" + topic.id + "/relative_numbers.json?network=" + topics_string, + success: successCallback, + error: function () { + + } + }); + }, selectEdgeOnClickHandler: function (adj, e) { if (Metamaps.Visualize.mGraph.busy) return; @@ -1595,12 +1730,10 @@ Metamaps.JIT = { ctx.lineTo(v2.x, v2.y); ctx.stroke(); }, // renderMidArrow - renderEdgeArrows: function (edgeHelper, adj, synapse) { + renderEdgeArrows: function (edgeHelper, adj, synapse, canvas) { var self = Metamaps.JIT; - var canvas = Metamaps.Visualize.mGraph.canvas; - var directionCat = synapse.get('category'); var direction = synapse.getDirection(); @@ -1657,8 +1790,7 @@ Metamaps.JIT = { Metamaps.Visualize.mGraph.canvas.scale(0.8,0.8); $(document).trigger(Metamaps.JIT.events.zoom, [event]); }, - centerMap: function () { - var canvas = Metamaps.Visualize.mGraph.canvas; + centerMap: function (canvas) { var offsetScale = canvas.scaleOffsetX; canvas.scale(1/offsetScale,1/offsetScale); @@ -1674,7 +1806,8 @@ Metamaps.JIT = { eX = Metamaps.Mouse.boxEndCoordinates.x, eY = Metamaps.Mouse.boxEndCoordinates.y; - Metamaps.JIT.centerMap(); + var canvas = Metamaps.Visualize.mGraph.canvas; + Metamaps.JIT.centerMap(canvas); var height = $(document).height(), width = $(document).width(); @@ -1686,8 +1819,6 @@ Metamaps.JIT = { var newRatio = Math.min(ratioX,ratioY); - var canvas = Metamaps.Visualize.mGraph.canvas; - if(canvas.scaleOffsetX *newRatio<= 5 && canvas.scaleOffsetX*newRatio >= 0.2){ canvas.scale(newRatio,newRatio); } @@ -1711,15 +1842,14 @@ Metamaps.JIT = { Metamaps.Visualize.mGraph.plot(); }, - zoomExtents: function (event) { - Metamaps.JIT.centerMap(); - var height = $(document).height(), - width = $(document).width(), + zoomExtents: function (event, canvas, denySelected) { + Metamaps.JIT.centerMap(canvas); + var height = canvas.getSize().height, + width = canvas.getSize().width, maxX, minX, maxY, minY, counter = 0; - var canvas = Metamaps.Visualize.mGraph.canvas; - if (Metamaps.Selected.Nodes.length > 0) { + if (!denySelected && Metamaps.Selected.Nodes.length > 0) { var nodes = Metamaps.Selected.Nodes; } else { diff --git a/app/assets/javascripts/src/Metamaps.Router.js b/app/assets/javascripts/src/Metamaps.Router.js index aa4fa338..466326d2 100644 --- a/app/assets/javascripts/src/Metamaps.Router.js +++ b/app/assets/javascripts/src/Metamaps.Router.js @@ -125,7 +125,7 @@ if (Metamaps.Visualize.mGraph) { Metamaps.Visualize.mGraph.graph.empty(); Metamaps.Visualize.mGraph.plot(); - Metamaps.JIT.centerMap(); + Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas); } Metamaps.Famous.viz.show(); Metamaps.Topic.end(); @@ -156,7 +156,7 @@ if (Metamaps.Visualize.mGraph) { Metamaps.Visualize.mGraph.graph.empty(); Metamaps.Visualize.mGraph.plot(); - Metamaps.JIT.centerMap(); + Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas); } Metamaps.Famous.viz.show(); Metamaps.Map.end(); diff --git a/app/assets/javascripts/src/Metamaps.js b/app/assets/javascripts/src/Metamaps.js index 0591b7d6..9f82b40e 100644 --- a/app/assets/javascripts/src/Metamaps.js +++ b/app/assets/javascripts/src/Metamaps.js @@ -82,6 +82,7 @@ Metamaps.Backbone.init = function () { self.Metacode = Backbone.Model.extend({ initialize: function () { var image = new Image(); + image.crossOrigin = "Anonymous"; image.src = this.get('icon'); this.set('image',image); }, @@ -218,7 +219,6 @@ Metamaps.Backbone.init = function () { var mapping; var node = this.get('node'); node.setData('topic', this); - node.id = this.isNew() ? this.cid : this.id; if (Metamaps.Active.Map) { mapping = this.getMapping(); @@ -476,6 +476,9 @@ Metamaps.Backbone.init = function () { Metamaps.Mappers = Metamaps.Mappers ? new self.MapperCollection(Metamaps.Mappers) : new self.MapperCollection(); + // this is for topic view + Metamaps.Creators = Metamaps.Creators ? new self.MapperCollection(Metamaps.Creators) : new self.MapperCollection(); + if (Metamaps.Active.Map) { Metamaps.Mappings = Metamaps.Mappings ? new self.MappingCollection(Metamaps.Mappings) : new self.MappingCollection(); @@ -1504,6 +1507,8 @@ Metamaps.Visualize = { mapping; if (self.type == "RGraph") { + var i, l, startPos, endPos, topic, synapse; + self.mGraph.graph.eachNode(function (n) { topic = Metamaps.Topics.get(n.id); topic.set({ node: n }, { silent: true }); @@ -3150,12 +3155,30 @@ Metamaps.Filter = { var removed = []; var added = []; - Metamaps[collection].each(function(model) { - var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false; - if (prop && newList.indexOf(prop) === -1) { - newList.push(prop); - } - }); + // the first option enables us to accept + // ['Topics', 'Synapses'] as 'collection' + if (typeof collection === "object") { + Metamaps[collection[0]].each(function(model) { + var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false; + if (prop && newList.indexOf(prop) === -1) { + newList.push(prop); + } + }); + Metamaps[collection[1]].each(function(model) { + var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false; + if (prop && newList.indexOf(prop) === -1) { + newList.push(prop); + } + }); + } + else if (typeof collection === "string") { + Metamaps[collection].each(function(model) { + var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false; + if (prop && newList.indexOf(prop) === -1) { + newList.push(prop); + } + }); + } removed = _.difference(self.filters[filtersToUse], newList); added = _.difference(newList, self.filters[filtersToUse]); @@ -3198,7 +3221,14 @@ Metamaps.Filter = { }, checkMappers: function () { var self = Metamaps.Filter; - self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper'); + var onMap = Metamaps.Active.Map ? true : false; + if (onMap) { + self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper'); + } + else { + // on topic view + self.updateFilters(['Topics', 'Synapses'], 'user_id', 'Creators', 'mappers', 'mapper'); + } }, checkSynapses: function () { var self = Metamaps.Filter; @@ -3279,7 +3309,11 @@ Metamaps.Filter = { if (Metamaps.Active.Map) { onMap = true; } - else passesMapper = true; // for when you're on a topic page + else if (Metamaps.Active.Topic) { + onMap = false; + } + + var opacityForFilter = onMap ? 0 : 0.4; Metamaps.Topics.each(function(topic) { var n = topic.get('node'); @@ -3289,10 +3323,21 @@ Metamaps.Filter = { else passesMetacode = true; if (onMap) { + // when on a map, + // we filter by mapper according to the person who added the + // topic or synapse to the map var user_id = topic.getMapping().get("user_id").toString(); if (visible.mappers.indexOf(user_id) == -1) passesMapper = false; else passesMapper = true; } + else { + // when on a topic view, + // we filter by mapper according to the person who created the + // topic or synapse + var user_id = topic.get("user_id").toString(); + if (visible.mappers.indexOf(user_id) == -1) passesMapper = false; + else passesMapper = true; + } if (passesMetacode && passesMapper) { if (n) { @@ -3303,7 +3348,7 @@ Metamaps.Filter = { else { if (n) { Metamaps.Control.deselectNode(n, true); - n.setData('alpha', 0, 'end'); + n.setData('alpha', opacityForFilter, 'end'); n.eachAdjacency(function(e){ Metamaps.Control.deselectEdge(e, true); }); @@ -3320,10 +3365,13 @@ Metamaps.Filter = { else passesSynapse = true; if (onMap) { - var user_id = synapse.getMapping().get("user_id").toString(); - if (visible.mappers.indexOf(user_id) == -1) passesMapper = false; - else passesMapper = true; + // when on a map, + // we filter by mapper according to the person who added the + // topic or synapse to the map + user_id = synapse.getMapping().get("user_id").toString(); } + if (visible.mappers.indexOf(user_id) == -1) passesMapper = false; + else passesMapper = true; var color = Metamaps.Settings.colors.synapses.normal; if (passesSynapse && passesMapper) { @@ -3336,10 +3384,10 @@ Metamaps.Filter = { else { if (e) { Metamaps.Control.deselectEdge(e, true); - e.setData('alpha', 0, 'end'); + e.setData('alpha', opacityForFilter, 'end'); } else console.log(synapse); - } + } }); // run the animation @@ -3389,7 +3437,7 @@ Metamaps.Listeners = { case 69: //if e or E is pressed if (e.ctrlKey){ e.preventDefault(); - Metamaps.JIT.zoomExtents(); + Metamaps.JIT.zoomExtents(null, Metamaps.Visualize.mGraph.canvas); } break; case 77: //if m or M is pressed @@ -3590,10 +3638,14 @@ Metamaps.Topic = { var bb = Metamaps.Backbone; var start = function (data) { Metamaps.Active.Topic = new bb.Topic(data.topic); + Metamaps.Creators = new bb.MapperCollection(data.creators); Metamaps.Topics = new bb.TopicCollection([data.topic].concat(data.relatives)); Metamaps.Synapses = new bb.SynapseCollection(data.synapses); Metamaps.Backbone.attachCollectionEvents(); + // set filter mapper H3 text + $('#filter_by_mapper h3').html('CREATORS'); + // build and render the visualization Metamaps.Visualize.type = "RGraph"; Metamaps.JIT.prepareVizData(); @@ -3620,12 +3672,12 @@ Metamaps.Topic = { $('.rightclickmenu').remove(); Metamaps.TopicCard.hideCard(); Metamaps.SynapseCard.hideCard(); + Metamaps.Filter.close(); } }, centerOn: function (nodeid) { if (!Metamaps.Visualize.mGraph.busy) { - var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid); - Metamaps.Visualize.mGraph.onClick(node.id, { + Metamaps.Visualize.mGraph.onClick(nodeid, { hideLabels: false, duration: 1000, onComplete: function () { @@ -3634,6 +3686,66 @@ Metamaps.Topic = { }); } }, + fetchRelatives: function(node, metacode_id) { + + var topics = Metamaps.Topics.map(function(t){ return t.id }); + var topics_string = topics.join(); + + var creators = Metamaps.Creators.map(function(t){ return t.id }); + var creators_string = creators.join(); + + var topic = node.getData('topic'); + + var successCallback = function(data) { + if (data.creators.length > 0) Metamaps.Creators.add(data.creators); + if (data.topics.length > 0) Metamaps.Topics.add(data.topics); + if (data.synapses.length > 0) Metamaps.Synapses.add(data.synapses); + + var topicColl = new Metamaps.Backbone.TopicCollection(data.topics); + topicColl.add(topic); + var synapseColl = new Metamaps.Backbone.SynapseCollection(data.synapses); + + var graph = Metamaps.JIT.convertModelsToJIT(topicColl, synapseColl)[0]; + Metamaps.Visualize.mGraph.op.sum(graph, { + type: 'fade', + duration: 500, + hideLabels: false + }); + + var i, l, t, s; + + Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + t = Metamaps.Topics.get(n.id); + t.set({ node: n }, { silent: true }); + t.updateNode(); + + n.eachAdjacency(function (edge) { + if(!edge.getData('init')) { + edge.setData('init', true); + + l = edge.getData('synapseIDs').length; + for (i = 0; i < l; i++) { + s = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]); + s.set({ edge: edge }, { silent: true }); + s.updateEdge(); + } + } + }); + }); + }; + + var paramsString = metacode_id ? "metacode=" + metacode_id + "&" : ""; + paramsString += "network=" + topics_string + "&creators=" + creators_string; + + $.ajax({ + type: "Get", + url: "/topics/" + topic.id + "/relatives.json?" + paramsString, + success: successCallback, + error: function () { + + } + }); + }, /* * * @@ -4048,6 +4160,9 @@ Metamaps.Map = { $('.wrapper').addClass('commonsMap'); } + // set filter mapper H3 text + $('#filter_by_mapper h3').html('MAPPERS'); + // build and render the visualization Metamaps.Visualize.type = "ForceDirected"; Metamaps.JIT.prepareVizData(); @@ -4086,6 +4201,7 @@ Metamaps.Map = { Metamaps.SynapseCard.hideCard(); Metamaps.Create.newTopic.hide(); Metamaps.Create.newSynapse.hide(); + Metamaps.Filter.close(); Metamaps.Realtime.endActiveMap(); } }, @@ -4094,31 +4210,37 @@ Metamaps.Map = { var nodes_data = "", synapses_data = ""; - var synapses_array = new Array(); + var nodes_array = []; + var synapses_array = []; + // collect the unfiltered topics Metamaps.Visualize.mGraph.graph.eachNode(function (n) { - //don't add to the map if it was filtered out - // TODO - //if (categoryVisible[n.getData('metacode')] == false) { - // return; - //} - - 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; + // 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 + ','; } - nodes_data += n.id + '/' + x + '/' + y + ','; - n.eachAdjacency(function (adj) { - synapses_array.push(adj.getData("synapses")[0].id); // TODO - }); }); + // collect the unfiltered synapses + Metamaps.Synapses.each(function(synapse){ + var desc = synapse.get("desc"); - //get unique values only - synapses_array = $.grep(synapses_array, function (value, key) { - return $.inArray(value, synapses_array) === key; + var descNotFiltered = Metamaps.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(); @@ -4209,6 +4331,131 @@ Metamaps.Map = { Metamaps.Map.sideLength = 1; Metamaps.Map.timeToTurn = 0; Metamaps.Map.turnCount = 0; + }, + 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 = Metamaps.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 + Metamaps.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() + }; + + console.log(imageData.encoded_image); + var map = Metamaps.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"; + Metamaps.GlobalUI.notifyUser(downloadMessage); + + $.ajax({ + type: "POST", + dataType: 'json', + url: "/maps/" + Metamaps.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'); + } + }); } }; @@ -4559,8 +4806,6 @@ Metamaps.Account = { var destWidth = 84; var destHeight = 84; - //debugger; - context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight); $('.userImageDiv').prepend($canvas); }; diff --git a/app/assets/javascripts/src/codeleft.js b/app/assets/javascripts/src/codeleft.js deleted file mode 100644 index 413fc62a..00000000 --- a/app/assets/javascripts/src/codeleft.js +++ /dev/null @@ -1,34 +0,0 @@ -function fetchRelatives(node) { - var myA = $.ajax({ - type: "Get", - url: "/topics/" + node.id + "?format=json", - success: function (data) { - if (gType == "centered") { - Mconsole.busy = true; - Mconsole.op.sum(data, { - type: 'fade', - duration: 500, - hideLabels: false - }); - Mconsole.graph.eachNode(function (n) { - n.eachAdjacency(function (a) { - if (!a.getData('showDesc')) { - a.setData('alpha', 0.4, 'start'); - a.setData('alpha', 0.4, 'current'); - a.setData('alpha', 0.4, 'end'); - } - }); - }); - Mconsole.busy = false; - } else { - Mconsole.op.sum(data, { - type: 'nothing', - }); - Mconsole.plot(); - } - }, - error: function () { - alert('failure'); - } - }); -} \ No newline at end of file diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index e925ad4c..1c72ee8e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -519,19 +519,19 @@ input[type="submit"]:active { #new_topic .twitter-typeahead { position: absolute !important; - top: 40px; - left: 35px; + top: 45px; + left: 41px; z-index: 9999; - width: 270px; + width: 256px; height: 42px; } .new_topic #topic_name, .new_topic .tt-hint { - width: 254px; + width: 244px; background: #FFFFFF; height: 14px; margin: 0; - padding: 14px 8px; + padding: 10px 6px; border: none; border-radius: 2px; outline: none; @@ -581,11 +581,11 @@ input[type="submit"]:active { } .new_synapse #synapse_desc, .new_synapse .tt-hint { - width: 254px; + width: 244px; background: #FFFFFF; height: 14px; margin: 0; - padding: 14px 8px; + padding: 10px 6px; border: none; border-radius: 2px; outline: none; @@ -1170,8 +1170,9 @@ h3.realtimeBoxTitle { .rightclickmenu { position: absolute; - width: 300px; + width: 260px; background: #FFFFFF; + padding: 6px 0px 6px 0px; z-index: 20; border-radius: 2px; color: black; @@ -1184,8 +1185,8 @@ h3.realtimeBoxTitle { list-style: none; padding: 6px 10px 6px 32px; font-family: helvetica, sans-serif; - font-size: 12px; - line-height: 12px; + font-size: 13px; + line-height: 15px; position: relative; } .rightclickmenu li:hover { @@ -1219,7 +1220,7 @@ h3.realtimeBoxTitle { } .rightclickmenu .rc-center .rc-icon { - + background-image: url(context_topicview_sprite.png); } .rightclickmenu .rc-popout .rc-icon { background-position: 0 -72px; @@ -1230,6 +1231,10 @@ h3.realtimeBoxTitle { .rightclickmenu .rc-metacode .rc-icon { background-position: 0 -120px; } +.rightclickmenu .rc-siblings .rc-icon { + background-position: 0 -24px; + background-image: url(context_topicview_sprite.png); +} .rightclickmenu .expandLi { position: absolute; top: 4px; @@ -1243,7 +1248,9 @@ h3.realtimeBoxTitle { .rc-metacode li img { float: left; } -.rightclickmenu .rc-permission ul, .rightclickmenu .rc-metacode ul { +.rightclickmenu .rc-permission ul, +.rightclickmenu .rc-metacode ul, +.rightclickmenu .rc-siblings ul { display: none; background: white; top: 0; @@ -1254,7 +1261,9 @@ float: left; border-top-right-radius: 2px; box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24); } -.rightclickmenu .rc-permission:hover > ul, .rightclickmenu .rc-metacode:hover > ul { +.rightclickmenu .rc-permission:hover > ul, +.rightclickmenu .rc-metacode:hover > ul, + .rightclickmenu .rc-siblings:hover > ul { display: block; } .rightclickmenu p { @@ -1282,20 +1291,24 @@ float: left; .rightclickmenu li.toPrivate .rc-perm-icon { background-position: -24px 0; } -.rightclickmenu .rc-metacode > ul > li { +.rightclickmenu .rc-metacode > ul > li, +.rightclickmenu .rc-siblings > ul > li { padding: 6px 10px 6px 8px; width: 100px; } -.rightclickmenu .rc-metacode ul ul { +.rightclickmenu .rc-metacode ul ul, +.rightclickmenu .rc-siblings ul ul { display: none; max-height: 270px; overflow-y: auto; overflow-x: hidden; } -.rightclickmenu .rc-metacode li:hover ul { +.rightclickmenu .rc-metacode li:hover ul, +.rightclickmenu .rc-siblings li:hover ul { display: block; } -.rightclickmenu .rc-metacode ul ul li { +.rightclickmenu .rc-metacode ul ul li, +.rightclickmenu .rc-siblings ul ul li { padding: 4px 10px 4px 8px; width: 120px; } @@ -1314,15 +1327,24 @@ float: left; display: block; } -.moveMenusUp .rc-metacode ul, .moveMenusUp .rc-permission ul { +.moveMenusUp .rc-metacode ul, +.moveMenusUp .rc-permission ul, +.moveMenusUp .rc-siblings ul { top: auto; bottom: 0; } -.moveMenusToLeft .rc-metacode ul, .moveMenusToLeft .rc-permission ul { +.moveMenusToLeft .rc-metacode ul, +.moveMenusToLeft .rc-permission ul, +.moveMenusToLeft .rc-siblings ul { left: auto; right: 100%; } +#loadingSiblings div { + width: 15px; + margin: 0 auto; +} + /* end right click menu */ @@ -1337,7 +1359,7 @@ float: left; #new_topic .tt-suggestion, #new_synapse .tt-suggestion { background: #F5F5F5; - width: 270px; + width: 256px; position: relative; } #new_topic .autocompleteSection { @@ -1606,7 +1628,7 @@ float: left; background-position: 13px center; } .mapSynapses { - background-image: url(synapse32.png); + background-image: url(synapse32padded.png); background-position: 13px center; } .mapInfoBox .mapPermission { @@ -1671,7 +1693,7 @@ float: left; .mapInfoBox .mapInfoDesc { font-family: helvetica, sans-serif; color: #E0E0E0; - margin: 8px; + margin: 16px; padding-right: 16px; height: 115px; font-size: 14px; diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/base.css index 6cfa3d69..b894b317 100644 --- a/app/assets/stylesheets/base.css +++ b/app/assets/stylesheets/base.css @@ -110,7 +110,7 @@ display:block; padding: 8px 0 8px 16px; height: 152px; - font-size: 12px; + font-size: 13px; line-height:15px; font-family: helvetica, sans-serif; overflow-y: auto; @@ -120,7 +120,7 @@ } .CardOnGraph .best_in_place_desc textarea { - font-size: 12px; + font-size: 13px; line-height:15px; font-family: helvetica, sans-serif; color: #424242; @@ -170,8 +170,8 @@ resize: none; z-index: 1; position: relative; color: #424242; - font-size: 12px; - line-height:12px; + font-size: 14px; + line-height:14px; height:12px; padding:17px 0; } @@ -187,9 +187,9 @@ resize: none; height: 48px; } .linkItem.contributor { - margin-left:32px; + margin-left:40px; z-index:1; - padding:17px 16px 17px 32px; + padding:17px 16px 17px 30px; position: relative; } .contributor .contributorIcon { @@ -202,8 +202,9 @@ resize: none; display:none; } .linkItem.mapCount { + margin-left: 12px; width: 24px; - padding:17px 0 17px 35px; + padding:17px 0 17px 36px; } .linkItem.mapCount .mapCountIcon { position: absolute; @@ -219,8 +220,9 @@ resize: none; background-position: 0 -32px; } .linkItem.synapseCount { + margin-left: 2px; width: 24px; - padding:17px 0 17px 35px; + padding:17px 0 17px 32px; } .linkItem.synapseCount .synapseCountIcon { position: absolute; @@ -241,6 +243,7 @@ resize: none; padding: 0; min-width: 32px; margin-top: 8px; + margin-left: 8px; background-image: url(permissions32_sprite.png); background-position: 0 0; } @@ -507,6 +510,8 @@ background-color: #E0E0E0; width: 268px; padding: 8px 16px 8px 16px; position: relative; + border: none; + line-height: 14px; } #addLinkInput input{ diff --git a/app/assets/stylesheets/clean.css b/app/assets/stylesheets/clean.css index 521f70c6..db90dd04 100644 --- a/app/assets/stylesheets/clean.css +++ b/app/assets/stylesheets/clean.css @@ -191,7 +191,7 @@ .explorePage .sidebarSearchField, .explorePage .sidebarSearch .tt-hint { width: 380px; - padding: 7px 10px 3px 10px; + padding: 5px 10px 5px 10px; } .sidebarSearchField { @@ -207,7 +207,7 @@ border-bottom: 1px solid #BDBDBD; border-left: none; border-right: none; - padding: 7px 0 3px 0; + padding: 5px 0 5px 0; width: 0px; margin: 0; outline: none; @@ -218,7 +218,7 @@ } .sidebarSearch .tt-dropdown-menu { top: 40px !important; - background: #FFF; + background: #F5F5F5; width: 472px; overflow-y: auto; overflow-x: hidden; @@ -577,7 +577,7 @@ top: 0; } -.topicPage .sidebarCollaborate, .topicPage .sidebarFilter { +.topicPage .sidebarCollaborate { display: none; } @@ -767,6 +767,20 @@ .mapControls:hover, .infoAndHelp:hover { z-index: 4; } + +.takeScreenshot { + margin-bottom: 5px; + border-radius: 2px; + background-image: url(screenshot_sprite.png); + display: none; +} +.takeScreenshot:hover { + background-position: -32px 0; +} +.canEditMap .takeScreenshot { + display: block; +} + .zoomExtents { margin-bottom:5px; border-radius: 2px; @@ -1026,6 +1040,10 @@ line-height:14px; } +.toast a { + color: #4fc059; +} + /* end toast */ /* feedback */ diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 0fbad24b..58f778d9 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,6 +1,6 @@ class MapsController < ApplicationController - before_filter :require_user, only: [:create, :update, :destroy] + before_filter :require_user, only: [:create, :update, :screenshot, :destroy] respond_to :html, :json @@ -83,7 +83,14 @@ class MapsController < ApplicationController @allmappers = @map.contributors @alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @allsynapses = @map.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } - @allmappings = @map.mappings + @allmappings = @map.mappings.delete_if {|m| + if m.category == "Synapse" + object = m.synapse + elsif m.category == "Topic" + object = m.topic + end + !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) + } respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map) } @@ -104,7 +111,14 @@ class MapsController < ApplicationController @allmappers = @map.contributors @alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @allsynapses = @map.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } - @allmappings = @map.mappings + @allmappings = @map.mappings.delete_if {|m| + if m.category == "Synapse" + object = m.synapse + elsif m.category == "Topic" + object = m.topic + end + !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) + } @json = Hash.new() @json['map'] = @map @@ -183,6 +197,30 @@ class MapsController < ApplicationController end end + # POST maps/:id/upload_screenshot + def screenshot + @current = current_user + @map = Map.find(params[:id]).authorize_to_edit(@current) + + if @map + png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) + StringIO.open(png) do |data| + data.class.class_eval { attr_accessor :original_filename, :content_type } + data.original_filename = "map-" + @map.id.to_s + "-screenshot.png" + data.content_type = "image/png" + @map.screenshot = data + end + + if @map.save + render :json => {:message => "Successfully uploaded the map screenshot."} + else + render :json => {:message => "Failed to upload image."} + end + else + render :json => {:message => "Unauthorized to set map screenshot."} + end + end + # DELETE maps/:id def destroy @current = current_user diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index e63bdc04..e39b67a8 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -29,7 +29,7 @@ class TopicsController < ApplicationController @topic = Topic.find(params[:id]).authorize_to_show(@current) if not @topic - redirect_to root_url and return + redirect_to root_url, notice: "Access denied. That topic is private." and return end respond_to do |format| @@ -37,7 +37,19 @@ class TopicsController < ApplicationController @alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } # should limit to topics visible to user @allsynapses = @topic.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } - respond_with(@allsynapses, @alltopics, @topic) + @allcreators = [] + @alltopics.each do |t| + if @allcreators.index(t.user) == nil + @allcreators.push(t.user) + end + end + @allsynapses.each do |s| + if @allcreators.index(s.user) == nil + @allcreators.push(s.user) + end + end + + respond_with(@allsynapses, @alltopics, @allcreators, @topic) } format.json { render json: @topic } end @@ -49,14 +61,27 @@ class TopicsController < ApplicationController @topic = Topic.find(params[:id]).authorize_to_show(@current) if not @topic - redirect_to root_url and return + redirect_to root_url, notice: "Access denied. That topic is private." and return end @alltopics = @topic.relatives.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @allsynapses = @topic.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } - + @allcreators = [] + @allcreators.push(@topic.user) + @alltopics.each do |t| + if @allcreators.index(t.user) == nil + @allcreators.push(t.user) + end + end + @allsynapses.each do |s| + if @allcreators.index(s.user) == nil + @allcreators.push(s.user) + end + end + @json = Hash.new() @json['topic'] = @topic + @json['creators'] = @allcreators @json['relatives'] = @alltopics @json['synapses'] = @allsynapses @@ -65,6 +90,85 @@ class TopicsController < ApplicationController end end + # GET topics/:id/relative_numbers + def relative_numbers + @current = current_user + @topic = Topic.find(params[:id]).authorize_to_show(@current) + + if not @topic + redirect_to root_url, notice: "Access denied. That topic is private." and return + end + + @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] + + @alltopics = @topic.relatives.delete_if {|t| + @topicsAlreadyHas.index(t.id.to_s) != nil || + (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + } + + @alltopics.uniq! + + @json = Hash.new() + @alltopics.each do |t| + if @json[t.metacode.id] + @json[t.metacode.id] += 1 + else + @json[t.metacode.id] = 1 + end + end + + respond_to do |format| + format.json { render json: @json } + end + end + + # GET topics/:id/relatives + def relatives + @current = current_user + @topic = Topic.find(params[:id]).authorize_to_show(@current) + + if not @topic + redirect_to root_url, notice: "Access denied. That topic is private." and return + end + + @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] + + @alltopics = @topic.relatives.delete_if {|t| + @topicsAlreadyHas.index(t.id.to_s) != nil || + (params[:metacode] && t.metacode_id.to_s != params[:metacode]) || + (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + } + + @alltopics.uniq! + + @allsynapses = @topic.synapses.delete_if {|s| + (s.topic1 == @topic && @alltopics.index(s.topic2) == nil) || + (s.topic2 == @topic && @alltopics.index(s.topic1) == nil) + } + + @creatorsAlreadyHas = params[:creators] ? params[:creators].split(',') : [] + @allcreators = [] + @alltopics.each do |t| + if @allcreators.index(t.user) == nil && @creatorsAlreadyHas.index(t.user_id.to_s) == nil + @allcreators.push(t.user) + end + end + @allsynapses.each do |s| + if @allcreators.index(s.user) == nil && @creatorsAlreadyHas.index(s.user_id.to_s) == nil + @allcreators.push(s.user) + end + end + + @json = Hash.new() + @json['topics'] = @alltopics + @json['synapses'] = @allsynapses + @json['creators'] = @allcreators + + respond_to do |format| + format.json { render json: @json } + end + end + # POST /topics # POST /topics.json def create diff --git a/app/models/map.rb b/app/models/map.rb index fcfefc81..91bc0a11 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -8,12 +8,12 @@ class Map < ActiveRecord::Base has_many :topics, :through => :topicmappings has_many :synapses, :through => :synapsemappings - after_touch :save_screenshot + #after_touch :save_screenshot # This method associates the attribute ":image" with a file attachment has_attached_file :screenshot, :styles => { - :thumb => ['188x126#', :png], - :full => ['940x630#', :png] + :thumb => ['188x126#', :png] + #:full => ['940x630#', :png] }, :default_url => "/assets/missing-map.png" diff --git a/app/views/layouts/_lightboxes.html.erb b/app/views/layouts/_lightboxes.html.erb index e745bcd9..47fbd3f0 100644 --- a/app/views/layouts/_lightboxes.html.erb +++ b/app/views/layouts/_lightboxes.html.erb @@ -112,19 +112,20 @@
  • Asana
  • Invision App *
  • Docracy *
  • -
  • Google Hangouts
  • Google Plus *
  • -
  • Hipchat
  • Hackpad *
  • Loomio *
  • Twitter *
  • +
  • Hipchat
  • +
  • Google Hangouts
  • Vimeo
  • Youtube

  • -

    Development

    +

    Design & Development

    +
  • Github*
  • +
  • Pixelapse*
  • +

    Documentation