Merge branch 'master' into thevalueweb

This commit is contained in:
Connor Turland 2015-02-06 17:44:10 -05:00
commit 96cee3cf21
27 changed files with 316 additions and 276 deletions

2
.gitignore vendored
View file

@ -19,3 +19,5 @@ log/*.log
tmp tmp
.DS_Store .DS_Store
.vagrant

View file

@ -49,7 +49,7 @@ Driessen][git-branching-model]. Here's an overview:
changing all the time. It's important that any changes you make are based on changing all the time. It's important that any changes you make are based on
the most recent version of metamaps, since it's possible that something may the most recent version of metamaps, since it's possible that something may
have changed that breaks your pull request or invalidates its need. have changed that breaks your pull request or invalidates its need.
4. Make sure you have a [Contributor License Agreement][cla] on file. 4. Make sure you have a [Contributor License Agreement](http://caa.metamaps.cc) on file.
5. Read on ... 5. Read on ...
@ -59,7 +59,7 @@ Before we can accept any contributions to Metamaps, we first require that all
individuals or companies agree to our Contributor License Agreement (CLA). The e-mail individuals or companies agree to our Contributor License Agreement (CLA). The e-mail
address used in the pull request will be used to check if a CLA has already been address used in the pull request will be used to check if a CLA has already been
filed, so be sure to list all email addresses that you might use to submit your filed, so be sure to list all email addresses that you might use to submit your
pull requests when filling it out. Our CLA can be found [here][cla]. pull requests when filling it out. Our CLA can be found [here](http://caa.metamaps.cc).
### Testing and Linting ### Testing and Linting

View file

@ -1,6 +1,8 @@
Metamaps Metamaps
======= =======
[![Join the chat at https://gitter.im/metamaps/metamaps_gen002](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/metamaps/metamaps_gen002?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Welcome to the Metamaps GitHub repo. Welcome to the Metamaps GitHub repo.
## About ## About
@ -15,19 +17,41 @@ To get connected with the community interested in Metamaps, join our [Google+ co
## Installation ## Installation
Depending on which OS you are using, the instructions for getting set up with a local installation of the Metamaps software will vary. Because the software has both Node.js components, and RubyOnRails, getting set up with your local copy can take 1 to 2 hours. If you are on Mac or Ubuntu you can use the following instructions to quickly get a local copy of metamaps up and running using a Vagrant virtualbox. Don't be intimidated, it's easy!
```
git clone git@github.com:metamaps/metamaps_gen002.git
```
Now ensure you have VirtualBox and Vagrant installed on your computer
```
cd metamaps_gen002
./configure.sh
```
This will do all the setup steps to make Metamaps work with a bit of behind the scenes ninja magick.
To start servers which will run metamaps you can then run:
```
./bin/start
```
To stop them:
```
./bin/stop
```
With your webservers running, open a web browser and go to `http://localhost:3000`
You can sign in with the default account
email: `user@user.com`
password: `toolsplusconsciousness`
OR create a new account at `/join`, and use access code `qwertyui`
Start mapping and programming!
While we are still figuring out vagrant for Windows, there is an older set of instructions below
- [For Windows][windows-installation] - [For Windows][windows-installation]
- [For Ubuntu][ubuntu-installation]
- [For Mac][mac-installation]
## Contributing ## Contributing
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved. Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
## Documentation
- TODO
## Community ## Community
- If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing]. - If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing].
@ -41,7 +65,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
The license can be read [here][license]. The license can be read [here][license].
Copyright (c) 2014 Connor Turland Copyright (c) 2015 Connor Turland
[site-blog]: http://blog.metamaps.cc [site-blog]: http://blog.metamaps.cc
@ -51,5 +75,3 @@ Copyright (c) 2014 Connor Turland
[contributing]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md [contributing]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md
[contributing-issues]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md#reporting-bugs-and-other-issues [contributing-issues]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md#reporting-bugs-and-other-issues
[windows-installation]: https://github.com/metamaps/metamaps_gen002/blob/master/WindowsInstallation.md [windows-installation]: https://github.com/metamaps/metamaps_gen002/blob/master/WindowsInstallation.md
[mac-installation]: https://github.com/metamaps/metamaps_gen002/blob/master/MacInstallation.md
[ubuntu-installation]: https://github.com/metamaps/metamaps_gen002/blob/master/UbuntuInstallation.md

View file

@ -40,29 +40,7 @@ alright now we can download metamaps from the master using git
git clone https://github.com/metamaps/metamaps_gen002.git git clone https://github.com/metamaps/metamaps_gen002.git
now there is a couple other things we are going to need which is phantomjs, nodejs, postgresql, libpq-dev and redis-server now there is a couple other things we are going to need which is nodejs, postgresql, libpq-dev and redis-server
// 64 bit ubuntu
cd /usr/local/share
sudo wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2
sudo tar xjf phantomjs-1.9.7-linux-x86_64.tar.bz2
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/local/share/phantomjs
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/bin/phantomjs
// 32 bit ubuntu
cd /usr/local/share
sudo wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-i686.tar.bz2
sudo tar xjf phantomjs-1.9.7-linux-i686.tar.bz2
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-i686/bin/phantomjs /usr/local/share/phantomjs
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-i686/bin/phantomjs /usr/local/bin/phantomjs
sudo ln -s /usr/local/share/phantomjs-1.9.7-linux-i686/bin/phantomjs /usr/bin/phantomjs
// on either running
phantomjs -v
// will confirm it's installed
sudo apt-get install nodejs sudo apt-get install nodejs
@ -113,7 +91,7 @@ Execute the server:
rails s rails s
and dont forget to run the two other servers, for sidekiq, and realtime... and dont forget to run the other server for realtime...
open a new terminal open a new terminal
navigate to ./realtime and run navigate to ./realtime and run
@ -121,11 +99,6 @@ navigate to ./realtime and run
npm install npm install
nodejs realtime-server.js nodejs realtime-server.js
open a new terminal
navigate to the main directory and run
sidekiq
Now you're all set enjoy your personal server of metamaps :) Now you're all set enjoy your personal server of metamaps :)
Navigate your browser to localhost:3000 once you have the server running Navigate your browser to localhost:3000 once you have the server running

43
Vagrantfile vendored Normal file
View file

@ -0,0 +1,43 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
$script = <<SCRIPT
# install base req's
sudo apt-get update
sudo apt-get install git curl -y
# rvm and ruby
su - vagrant -c 'curl -sSL https://rvm.io/mpapis.asc | gpg --import -'
su - vagrant -c 'curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1.3'
# install some other deps
sudo apt-get install nodejs -y
sudo apt-get install npm -y
sudo apt-get install postgresql -y
sudo apt-get install libpq-dev -y
sudo apt-get install redis-server -y
# Install node
ln -fs /usr/bin/nodejs /usr/bin/node
# install forever for running the node server
sudo npm install forever -g
# set the postgres password
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '3112';"
SCRIPT
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "trusty64"
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
config.vm.network :forwarded_port, guest: 3000, host: 3000
config.vm.network :forwarded_port, guest: 5001, host: 5001
config.vm.network "private_network", ip: "10.0.1.11"
config.vm.synced_folder ".", "/vagrant", :nfs => true
config.vm.provision "shell", inline: $script
end

File diff suppressed because one or more lines are too long

View file

@ -2449,6 +2449,7 @@ Extras.Classes.Navigation = new Class({
if(!this.config.zooming) return; if(!this.config.zooming) return;
// START METAMAPS CODE // START METAMAPS CODE
e.preventDefault();
if (e.target.id != 'infovis-canvas') return; if (e.target.id != 'infovis-canvas') return;
if (Metamaps.Create.newTopic.beingCreated) return; if (Metamaps.Create.newTopic.beingCreated) return;
// END METAMAPS CODE // END METAMAPS CODE

View file

@ -1,7 +1,7 @@
Metamaps.Backbone = {}; Metamaps.Backbone = {};
Metamaps.Backbone.Map = Backbone.Model.extend({ Metamaps.Backbone.Map = Backbone.Model.extend({
urlRoot: '/maps', urlRoot: '/maps',
blacklist: ['created_at', 'updated_at', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'], blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'],
toJSON: function (options) { toJSON: function (options) {
return _.omit(this.attributes, this.blacklist); return _.omit(this.attributes, this.blacklist);
}, },
@ -169,23 +169,30 @@ Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({
temp = a; temp = a;
a = b; a = b;
b = temp; b = temp;
a = (new Date(a)).getTime();
b = (new Date(b)).getTime();
} }
return a > b ? 1 : a < b ? -1 : 0; return a > b ? 1 : a < b ? -1 : 0;
}, },
getMaps: function () { getMaps: function (cb) {
var self = this; var self = this;
Metamaps.Loading.show();
if (this.page != "loadedAll") { if (this.page != "loadedAll") {
var numBefore = this.length; var numBefore = this.length;
this.fetch({ this.fetch({
remove: false, remove: false,
silent: true,
data: { page: this.page }, data: { page: this.page },
success: function (collection, response, options) { success: function (collection, response, options) {
// you can pass additional options to the event you trigger here as well // you can pass additional options to the event you trigger here as well
if (collection.length - numBefore < 20) self.page = "loadedAll"; if (collection.length - numBefore < 20) {
self.page = "loadedAll";
}
else self.page += 1; else self.page += 1;
self.trigger('successOnFetch'); self.trigger('successOnFetch', cb);
}, },
error: function (collection, response, options) { error: function (collection, response, options) {
// you can pass additional options to the event you trigger here as well // you can pass additional options to the event you trigger here as well
@ -194,7 +201,7 @@ Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({
}); });
} }
else { else {
self.trigger('successOnFetch'); self.trigger('successOnFetch', cb);
} }
} }
}); });

View file

@ -1758,7 +1758,9 @@ Metamaps.JIT = {
var posChild = adj.nodeTo.pos.getc(true); var posChild = adj.nodeTo.pos.getc(true);
//plot arrow edge //plot arrow edge
if (directionCat == "none") { if (!direction) {
// render nothing for this arrow if the direction couldn't be retrieved
} else if (directionCat == "none") {
edgeHelper.line.render({ edgeHelper.line.render({
x: pos.x, x: pos.x,
y: pos.y y: pos.y

View file

@ -10,6 +10,7 @@
"maps/:id": "maps" // #maps/7 "maps/:id": "maps" // #maps/7
}, },
home: function () { home: function () {
clearTimeout(Metamaps.routerTimeoutId);
if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps'; if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps';
else document.title = 'Home | Metamaps'; else document.title = 'Home | Metamaps';
@ -21,6 +22,11 @@
var classes = Metamaps.Active.Mapper ? "homePage explorePage" : "homePage"; var classes = Metamaps.Active.Mapper ? "homePage explorePage" : "homePage";
$('.wrapper').addClass(classes); $('.wrapper').addClass(classes);
var navigate = function() {
Metamaps.routerTimeoutId = setTimeout(function() {
Metamaps.Router.navigate("");
}, 300);
};
// all this only for the logged in home page // all this only for the logged in home page
if (Metamaps.Active.Mapper) { if (Metamaps.Active.Mapper) {
@ -37,10 +43,10 @@
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps.Active ); Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps.Active );
if (Metamaps.Maps.Active.length === 0) { if (Metamaps.Maps.Active.length === 0) {
Metamaps.Maps.Active.getMaps(); // this will trigger an explore maps render Metamaps.Maps.Active.getMaps(navigate); // this will trigger an explore maps render
} }
else { else {
Metamaps.Views.exploreMaps.render(); Metamaps.Views.exploreMaps.render(navigate);
} }
} }
// logged out home page // logged out home page
@ -54,9 +60,7 @@
Metamaps.GlobalUI.Search.close(0, true); Metamaps.GlobalUI.Search.close(0, true);
Metamaps.Famous.maps.hide(); Metamaps.Famous.maps.hide();
setTimeout(function(){ Metamaps.routerTimeoutId = setTimeout(navigate, 500);
Metamaps.Router.navigate("");
}, 500);
} }
Metamaps.Famous.viz.hide(); Metamaps.Famous.viz.hide();
@ -66,6 +70,7 @@
Metamaps.Active.Topic = null; Metamaps.Active.Topic = null;
}, },
explore: function (section, id) { explore: function (section, id) {
clearTimeout(Metamaps.routerTimeoutId);
// just capitalize the variable section // just capitalize the variable section
// either 'featured', 'mapper', or 'active' // either 'featured', 'mapper', or 'active'
@ -107,18 +112,32 @@
} }
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ); Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] );
var navigate = function(){
var path = "/explore/" + Metamaps.currentPage;
// alter url if for mapper profile page
if (Metamaps.currentPage == "mapper") {
path += "/" + Metamaps.Maps.Mapper.mapperId;
}
Metamaps.Router.navigate(path);
};
var navigateTimeout = function() {
Metamaps.routerTimeoutId = setTimeout(navigate, 300);
};
if (Metamaps.Maps[capitalize].length === 0) { if (Metamaps.Maps[capitalize].length === 0) {
Metamaps.Loading.show(); Metamaps.Loading.show();
setTimeout(function(){ setTimeout(function(){
Metamaps.Maps[capitalize].getMaps(); // this will trigger an explore maps render Metamaps.Maps[capitalize].getMaps(navigate); // this will trigger an explore maps render
}, 300); // wait 300 milliseconds till the other animations are done to do the fetch }, 300); // wait 300 milliseconds till the other animations are done to do the fetch
} }
else { else {
if (id) { if (id) {
Metamaps.Views.exploreMaps.fetchUserThenRender(); Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout);
} }
else { else {
Metamaps.Views.exploreMaps.render(); Metamaps.Views.exploreMaps.render(navigateTimeout);
} }
} }
@ -139,6 +158,7 @@
Metamaps.Active.Topic = null; Metamaps.Active.Topic = null;
}, },
maps: function (id) { maps: function (id) {
clearTimeout(Metamaps.routerTimeoutId);
document.title = 'Map ' + id + ' | Metamaps'; document.title = 'Map ' + id + ' | Metamaps';
@ -172,6 +192,7 @@
Metamaps.Map.launch(id); Metamaps.Map.launch(id);
}, },
topics: function (id) { topics: function (id) {
clearTimeout(Metamaps.routerTimeoutId);
document.title = 'Topic ' + id + ' | Metamaps'; document.title = 'Topic ' + id + ' | Metamaps';

View file

@ -54,10 +54,15 @@ Metamaps.Views.init = function () {
this.listenTo(this.collection, 'successOnFetch', this.handleSuccess); this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
this.listenTo(this.collection, 'errorOnFetch', this.handleError); this.listenTo(this.collection, 'errorOnFetch', this.handleError);
}, },
render: function (mapperObj) { render: function (mapperObj, cb) {
var that = this; var that = this;
if (typeof mapperObj === "function") {
var cb = mapperObj;
mapperObj = null;
}
this.el.innerHTML = ""; this.el.innerHTML = "";
// in case it is a page where we have to display the mapper card // in case it is a page where we have to display the mapper card
@ -76,57 +81,47 @@ Metamaps.Views.init = function () {
this.$el.append('<div class="clearfloat"></div>'); this.$el.append('<div class="clearfloat"></div>');
var m = Metamaps.Famous.maps.surf; var m = Metamaps.Famous.maps.surf;
m.setContent(this.el); m.setContent(this.el);
setTimeout(function(){
var updateHeight = function(){
var height = $(that.el).height() + 32 + 56; var height = $(that.el).height() + 32 + 56;
m.setSize([undefined, height]); m.setSize([undefined, height]);
}, 100); Metamaps.Famous.maps.lock = false;
if (cb) cb();
};
if (!initialized) { if (!initialized) {
m.deploy(m._currTarget); m.deploy(m._currTarget);
initialized = true; initialized = true;
setTimeout(function(){ setTimeout(updateHeight, 100);
var height = $(that.el).height() + 32 + 56; } else {
m.setSize([undefined, height]); setTimeout(updateHeight, 100);
}, 100);
} }
Metamaps.Loading.hide(); Metamaps.Loading.hide();
clearTimeout(Metamaps.routerTimeoutFunctionIds);
Metamaps.routerTimeoutId = setTimeout((function(localCurrentPage){ return function(){
var path = (Metamaps.currentSection == "") ? "" : "/explore/" + localCurrentPage;
// alter url if for mapper profile page
if (that.collection && that.collection.mapperId) {
path += "/" + that.collection.mapperId;
}
Metamaps.Router.navigate(path);
}})(Metamaps.currentPage), 500);
}, },
handleSuccess: function () { handleSuccess: function (cb) {
var that = this; var that = this;
if (this.collection && this.collection.id === "mapper") { if (this.collection && this.collection.id === "mapper") {
this.fetchUserThenRender(); this.fetchUserThenRender(cb);
} }
else { else {
this.render(); this.render(cb);
} }
}, },
handleError: function () { handleError: function () {
console.log('error loading maps!'); //TODO console.log('error loading maps!'); //TODO
}, },
fetchUserThenRender: function () { fetchUserThenRender: function (cb) {
var that = this; var that = this;
// first load the mapper object and then call the render function // first load the mapper object and then call the render function
$.ajax({ $.ajax({
url: "/users/" + this.collection.mapperId + "/details.json", url: "/users/" + this.collection.mapperId + "/details.json",
success: function (response) { success: function (response) {
that.render(response); that.render(response, cb);
}, },
error: function () { error: function () {
that.render(cb);
} }
}); });
} }

View file

@ -356,10 +356,13 @@ Metamaps.Backbone.init = function () {
return Metamaps.Topics.get(this.get('node2_id')); return Metamaps.Topics.get(this.get('node2_id'));
}, },
getDirection: function () { getDirection: function () {
return [ var t1 = this.getTopic1(),
this.getTopic1().get('node').id, t2 = this.getTopic2();
this.getTopic2().get('node').id
]; return t1 && t2 ? [
t1.get('node').id,
t2.get('node').id
] : false;
}, },
getMapping: function () { getMapping: function () {
@ -893,7 +896,6 @@ Metamaps.TopicCard = {
}); });
var embedlyEl = $('<a/>', { var embedlyEl = $('<a/>', {
id: 'embedlyLink', id: 'embedlyLink',
'data-card-chrome': '0',
'data-card-description': '0', 'data-card-description': '0',
href: text href: text
}).html(text); }).html(text);
@ -1176,7 +1178,7 @@ Metamaps.TopicCard = {
nodeValues.attachmentsHidden = ''; nodeValues.attachmentsHidden = '';
if (topic.get('link') && topic.get('link')!== '') { if (topic.get('link') && topic.get('link')!== '') {
nodeValues.embeds = '<a href="' + topic.get('link') + '" id="embedlyLink" target="_blank" data-card-chrome="0" data-card-description="0">'; nodeValues.embeds = '<a href="' + topic.get('link') + '" id="embedlyLink" target="_blank" data-card-description="0">';
nodeValues.embeds += topic.get('link'); nodeValues.embeds += topic.get('link');
nodeValues.embeds += '</a><div id="embedlyLinkLoader"></div>'; nodeValues.embeds += '</a><div id="embedlyLinkLoader"></div>';
nodeValues.attachmentsHidden = 'hidden'; nodeValues.attachmentsHidden = 'hidden';
@ -1652,8 +1654,8 @@ Metamaps.Visualize = {
$jit.ForceDirected.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings); $jit.ForceDirected.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings);
$jit.ForceDirected.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings); $jit.ForceDirected.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings);
FDSettings.width = $(document).width(); FDSettings.width = $('body').width();
FDSettings.height = $(document).height(); FDSettings.height = $('body').height();
self.mGraph = new $jit.ForceDirected(FDSettings); self.mGraph = new $jit.ForceDirected(FDSettings);
@ -1666,6 +1668,7 @@ Metamaps.Visualize = {
self.mGraph.graph.empty(); self.mGraph.graph.empty();
} }
function runAnimation() {
Metamaps.Loading.hide(); Metamaps.Loading.hide();
// load JSON data, if it's not empty // load JSON data, if it's not empty
if (!self.loadLater) { if (!self.loadLater) {
@ -1689,9 +1692,32 @@ Metamaps.Visualize = {
self.mGraph.animate(Metamaps.JIT.ForceDirected.animateFDLayout); self.mGraph.animate(Metamaps.JIT.ForceDirected.animateFDLayout);
} }
} }
}
// hold until all the needed metacode images are loaded
// hold for a maximum of 80 passes, or 4 seconds of waiting time
var tries = 0;
function hold() {
var unique = _.uniq(Metamaps.Topics.models, function (metacode) { return metacode.get('metacode_id'); }),
requiredMetacodes = _.map(unique, function (metacode) { return metacode.get('metacode_id'); }),
loadedCount = 0;
_.each(requiredMetacodes, function (metacode_id) {
var metacode = Metamaps.Metacodes.get(metacode_id),
img = metacode ? metacode.get('image') : false;
if (img && (img.complete || (typeof img.naturalWidth !== "undefined" && img.naturalWidth !== 0))) {
loadedCount += 1;
}
});
if (loadedCount === requiredMetacodes.length || tries > 80) runAnimation();
else setTimeout(function(){ tries++; hold() }, 50);
}
hold();
// update the url now that the map is ready // update the url now that the map is ready
setTimeout(function(){ clearTimeout(Metamaps.routerTimeoutId);
Metamaps.routerTimeoutId = setTimeout(function(){
var m = Metamaps.Active.Map; var m = Metamaps.Active.Map;
var t = Metamaps.Active.Topic; var t = Metamaps.Active.Topic;
@ -2748,6 +2774,9 @@ Metamaps.Control = {
var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid); var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid);
var topic = node.getData('topic'); var topic = node.getData('topic');
var permToDelete = Metamaps.Active.Mapper.id === topic.get('user_id');
if (permToDelete) {
var topicid = topic.id; var topicid = topic.id;
var mapping = node.getData('mapping'); var mapping = node.getData('mapping');
topic.destroy(); topic.destroy();
@ -2756,6 +2785,9 @@ Metamaps.Control = {
topicid: topicid topicid: topicid
}]); }]);
Metamaps.Control.hideNode(nodeid); Metamaps.Control.hideNode(nodeid);
} else {
Metamaps.GlobalUI.notifyUser('Only topics you created can be deleted');
}
}, },
removeSelectedNodes: function () { // refers to removing topics permanently from a map removeSelectedNodes: function () { // refers to removing topics permanently from a map
@ -2811,10 +2843,6 @@ Metamaps.Control = {
hideNode: function (nodeid) { hideNode: function (nodeid) {
var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid); var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid);
var graph = Metamaps.Visualize.mGraph; var graph = Metamaps.Visualize.mGraph;
if (nodeid == Metamaps.Visualize.mGraph.root) { // && Metamaps.Visualize.type === "RGraph"
var newroot = _.find(graph.graph.nodes, function(n){ return n.id !== nodeid; });
graph.root = newroot ? newroot.id : null;
}
Metamaps.Control.deselectNode(node); Metamaps.Control.deselectNode(node);
@ -2829,6 +2857,10 @@ Metamaps.Control = {
duration: 500 duration: 500
}); });
setTimeout(function () { setTimeout(function () {
if (nodeid == Metamaps.Visualize.mGraph.root) { // && Metamaps.Visualize.type === "RGraph"
var newroot = _.find(graph.graph.nodes, function(n){ return n.id !== nodeid; });
graph.root = newroot ? newroot.id : null;
}
Metamaps.Visualize.mGraph.graph.removeNode(nodeid); Metamaps.Visualize.mGraph.graph.removeNode(nodeid);
}, 500); }, 500);
Metamaps.Filter.checkMetacodes(); Metamaps.Filter.checkMetacodes();
@ -2907,14 +2939,17 @@ Metamaps.Control = {
return; return;
} }
if (edge.getData("synapses").length - 1 === 0) {
Metamaps.Control.hideEdge(edge);
}
var index = edge.getData("displayIndex") ? edge.getData("displayIndex") : 0; var index = edge.getData("displayIndex") ? edge.getData("displayIndex") : 0;
var synapse = edge.getData("synapses")[index]; var synapse = edge.getData("synapses")[index];
var mapping = edge.getData("mappings")[index]; var mapping = edge.getData("mappings")[index];
var permToDelete = Metamaps.Active.Mapper.id === synapse.get('user_id');
if (permToDelete) {
if (edge.getData("synapses").length - 1 === 0) {
Metamaps.Control.hideEdge(edge);
}
var synapseid = synapse.id; var synapseid = synapse.id;
synapse.destroy(); synapse.destroy();
@ -2928,6 +2963,9 @@ Metamaps.Control = {
$(document).trigger(Metamaps.JIT.events.deleteSynapse, [{ $(document).trigger(Metamaps.JIT.events.deleteSynapse, [{
synapseid: synapseid synapseid: synapseid
}]); }]);
} else {
Metamaps.GlobalUI.notifyUser('Only synapses you created can be deleted');
}
}, },
removeSelectedEdges: function () { removeSelectedEdges: function () {
var l = Metamaps.Selected.Edges.length, var l = Metamaps.Selected.Edges.length,
@ -4705,7 +4743,7 @@ Metamaps.Map.InfoBox = {
var map = Metamaps.Active.Map; var map = Metamaps.Active.Map;
var obj = map.pick("permission","contributor_count","topic_count","synapse_count","created_at","updated_at"); var obj = map.pick("permission","contributor_count","topic_count","synapse_count");
var isCreator = map.authorizePermissionChange(Metamaps.Active.Mapper); var isCreator = map.authorizePermissionChange(Metamaps.Active.Mapper);
var canEdit = map.authorizeToEdit(Metamaps.Active.Mapper); var canEdit = map.authorizeToEdit(Metamaps.Active.Mapper);
@ -4719,6 +4757,8 @@ Metamaps.Map.InfoBox = {
obj["contributor_image"] = Metamaps.Mappers.length > 0 ? Metamaps.Mappers.models[0].get("image") : "/assets/user.png"; obj["contributor_image"] = Metamaps.Mappers.length > 0 ? Metamaps.Mappers.models[0].get("image") : "/assets/user.png";
obj["contributor_list"] = self.createContributorList(); obj["contributor_list"] = self.createContributorList();
obj["user_name"] = isCreator ? "You" : map.get("user_name"); obj["user_name"] = isCreator ? "You" : map.get("user_name");
obj["created_at"] = map.get("created_at_clean");
obj["updated_at"] = map.get("updated_at_clean");
var classes = isCreator ? "yourMap" : ""; var classes = isCreator ? "yourMap" : "";
classes += canEdit ? " canEdit" : ""; classes += canEdit ? " canEdit" : "";
@ -4794,7 +4834,6 @@ Metamaps.Map.InfoBox = {
var self = Metamaps.Map.InfoBox; var self = Metamaps.Map.InfoBox;
var string = ""; var string = "";
console.log("hello!!")
string += "<ul>"; string += "<ul>";
Metamaps.Mappers.each(function(m){ Metamaps.Mappers.each(function(m){
@ -4802,7 +4841,6 @@ Metamaps.Map.InfoBox = {
}); });
string += "</ul>"; string += "</ul>";
console.log(string);
return string; return string;
}, },
updateNumbers: function () { updateNumbers: function () {

View file

@ -2724,7 +2724,7 @@ and it won't be important on password protected instances */
color: #999; color: #999;
} }
#upYourSkillz { #upYourSkillz {
margin: 0 68px; margin: 0 67px;
} }
#moreResources { #moreResources {
padding: 16px 0 0 0; padding: 16px 0 0 0;

View file

@ -84,7 +84,7 @@
/* logo */ /* logo */
.footer { .footer {
z-index: 3; z-index: 3 !important; /* important necessary for firefox */
} }
.logo { .logo {
@ -1041,7 +1041,7 @@
.sidebarCollaborateIcon div:after, .sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after { .sidebarCollaborateIcon div:after, .sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after {
content: ''; content: '';
position: absolute; position: absolute;
top: 128%; top: 129%;
margin-top: -30px; margin-top: -30px;
width: 0; width: 0;
height: 0; height: 0;
@ -1053,7 +1053,7 @@
.mapInfoIcon div:after, .openCheatsheet div:after { .mapInfoIcon div:after, .openCheatsheet div:after {
content: ''; content: '';
position: absolute; position: absolute;
top: 77%; top: 76%;
left: 41%; left: 41%;
margin-top: 5px; margin-top: 5px;
width: 0; width: 0;
@ -1187,7 +1187,7 @@
color: #F5F5F5; color: #F5F5F5;
padding: 16px; padding: 16px;
border-radius: 2px; border-radius: 2px;
z-index: 1; z-index: 1 !important; /* important necessary for firefox */
font-size: 14px; font-size: 14px;
line-height:14px; line-height:14px;
} }

View file

@ -47,16 +47,16 @@ class SynapsesController < ApplicationController
# DELETE synapses/:id # DELETE synapses/:id
def destroy def destroy
@current = current_user @current = current_user
@synapse = Synapse.find(params[:id]).authorize_to_edit(@current) @synapse = Synapse.find(params[:id]).authorize_to_delete(@current)
if @synapse
@synapse.mappings.each do |m| @synapse.mappings.each do |m|
m.map.touch(:updated_at) m.map.touch(:updated_at)
m.delete m.delete
end end
@synapse.delete if @synapse @synapse.delete
end
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }

View file

@ -198,7 +198,7 @@ class TopicsController < ApplicationController
# DELETE topics/:id # DELETE topics/:id
def destroy def destroy
@current = current_user @current = current_user
@topic = Topic.find(params[:id]).authorize_to_edit(@current) @topic = Topic.find(params[:id]).authorize_to_delete(@current)
if @topic if @topic
@synapses = @topic.synapses @synapses = @topic.synapses
@ -228,7 +228,7 @@ class TopicsController < ApplicationController
end end
respond_to do |format| respond_to do |format|
format.js { render :json => "success" } format.json { head :no_content }
end end
end end
end end

View file

@ -76,9 +76,9 @@ class Map < ActiveRecord::Base
end end
def as_json(options={}) def as_json(options={})
json = super(:methods =>[:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :screenshot_url], :except => [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at, :created_at, :updated_at]) json = super(:methods =>[:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :screenshot_url], :except => [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at])
json[:created_at] = self.created_at_str json[:created_at_clean] = self.created_at_str
json[:updated_at] = self.updated_at_str json[:updated_at_clean] = self.updated_at_str
json json
end end

View file

@ -40,6 +40,13 @@ class Synapse < ActiveRecord::Base
return self return self
end end
def authorize_to_delete(user)
if (self.user != user)
return false
end
return self
end
# returns Boolean if user allowed to view Topic, Synapse, or Map # returns Boolean if user allowed to view Topic, Synapse, or Map
def authorize_to_view(user) def authorize_to_view(user)
if (self.permission == "private" && self.user != user) if (self.permission == "private" && self.user != user)

View file

@ -111,6 +111,13 @@ class Topic < ActiveRecord::Base
return self return self
end end
def authorize_to_delete(user)
if (self.user != user)
return false
end
return self
end
# returns Boolean if user allowed to view Topic, Synapse, or Map # returns Boolean if user allowed to view Topic, Synapse, or Map
def authorize_to_view(user) def authorize_to_view(user)
if (self.permission == "private" && self.user != user) if (self.permission == "private" && self.user != user)

2
bin/start Executable file
View file

@ -0,0 +1,2 @@
#start rails server and realtime node server
vagrant ssh --command "cd /vagrant; rails s -d; forever start ./realtime/realtime-server.js"

2
bin/stop Executable file
View file

@ -0,0 +1,2 @@
# stop rails server and node server
vagrant ssh --command "cd /vagrant; kill -9 $(cat tmp/pids/server.pid); forever stopall"

View file

@ -1,71 +0,0 @@
FILE /app/views/layouts/application.html.erb
<head>
...
<%= javascript_include_tag "application" %>
<% if (controller_name == "maps" || controller_name == "topics") && action_name == "show" %>
<%= javascript_include_tag "compileMapPages" %>
<% end %>
...
</head>
WHAT DOES IT MEAN?
____________________________________________________________________
FILE /app/assets/javascripts/application.js
...
//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require ./orderedLibraries/underscore
//= require ./orderedLibraries/backbone
//= require_directory ./librariesForAllPages
//= require ./metamaps/Metamaps.GlobalUI
//= require ./metamaps/Metamaps.Backbone
WHAT DOES IT MEAN?
____________________________________________________________________
FILE /app/assets/javascripts/compileMapPages.js
...
//= require ./librariesForMapPages/cloudcarousel
//= require ./librariesForMapPages/socket.io
//= require ./metamaps/JIT
//= require ./metamaps/Metamaps
//= require ./metamaps/Metamaps.JIT
WHAT DOES IT MEAN?
____________________________________________________________________
FILE /app/assets/javascripts/metamaps/Metamaps.GlobalUI.js
var Metamaps = {};
...
$(document).ready(function () {
for (var prop in Metamaps) {
// this runs the init function within each sub-object on the Metamaps one
if (Metamaps.hasOwnProperty(prop) &&
Metamaps[prop].hasOwnProperty('init') &&
typeof (Metamaps[prop].init) == 'function'
) {
Metamaps[prop].init();
}
}
});
Metamaps.GlobalUI = {
...
};
WHAT DOES IT MEAN?
____________________________________________________________________

16
configure.sh Executable file
View file

@ -0,0 +1,16 @@
# Make sure we've got NFS handy.
if [ $(uname) == 'Linux' ] && [ ! -e /etc/init.d/nfs-kernel-server ]; then
sudo apt-get install -y nfs-common nfs-kernel-server rpcbind
fi
# Vagrant up
vagrant up
# Bundle!
vagrant ssh --command "cd /vagrant; bundle install";
# copy the db config
vagrant ssh --command "cd /vagrant; cp config/database.yml.default config/database.yml";
# Rake all the things
vagrant ssh --command "cd /vagrant; rake db:create; rake db:schema:load; rake db:fixtures:load"

View file

@ -206,15 +206,24 @@ Metamaps.Famous.build = function () {
f.maps.mod.setTransform(Transform.translate(window.innerWidth, 94, 0)); f.maps.mod.setTransform(Transform.translate(window.innerWidth, 94, 0));
}; };
var mapsScroll = new Scrollview(); var mapsScroll = new Scrollview();
mapsScroll._scroller.on('edgeHit', function(data){ f.maps.lock = false;
if (data.position > 0 && mapsScroll._eventInput.on('update', _.throttle(function(data) {
var bottom = f.maps.surf.getSize()[1], // how far down it goes
pos = mapsScroll.getPosition(), // how far down you are
containerSize = f.maps.mod.getSize()[1], // height of the viewable area
distanceToBottom = bottom - (pos + containerSize),
triggerDistance = 700;
if (!f.maps.lock &&
distanceToBottom < triggerDistance &&
Metamaps.Views && Metamaps.Views &&
Metamaps.Views.exploreMaps && Metamaps.Views.exploreMaps &&
Metamaps.Views.exploreMaps.collection && Metamaps.Views.exploreMaps.collection &&
Metamaps.Views.exploreMaps.collection.page != "loadedAll") { Metamaps.Views.exploreMaps.collection.page != "loadedAll") {
f.maps.lock = true;
Metamaps.Views.exploreMaps.collection.getMaps(); Metamaps.Views.exploreMaps.collection.getMaps();
} }
}); }, 500));
f.maps.resetScroll = function() { f.maps.resetScroll = function() {
// set the scrollView back to the top // set the scrollView back to the top
mapsScroll._physicsEngine.detachAll(); mapsScroll._physicsEngine.detachAll();

View file

@ -1,45 +1,9 @@
/*var http = require('http'),
express = require('express'),
port = process.env.PORT || 5001,
app = express(),
server = http.createServer(app).listen(port),
io = require('socket.io').listen(server);
console.log(port);
app.configure(function() {
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
return next();
});
}); */
//var rtg = require("url").parse("redis://redistogo:0ca046a3d56533cc162e2447db383192@pearlfish.redistogo.com:9060/"),
//redis = require('redis').createClient(rtg.port, rtg.hostname, {no_ready_check: true});
var io = require('socket.io').listen(5001); var io = require('socket.io').listen(5001);
//var redis = require('redis').createClient();
//redis.auth(rtg.auth.split(":")[1], function() {
// start();
//});
function start() { function start() {
//redis.subscribe('maps');
io.on('connection', function (socket) { io.on('connection', function (socket) {
// this will ping everyone on a map with updates to the map
/*redis.on('message', function (channel, message) {
console.log(message);
var m = JSON.parse(message);
var room = 'maps-' + m.mapid;
socket.emit(room, m);
});*/
// this will ping a new person with awareness of who's already on the map // this will ping a new person with awareness of who's already on the map
socket.on('updateNewMapperList', function (data) { socket.on('updateNewMapperList', function (data) {
var existingUser = { var existingUser = {