This commit is contained in:
Connor Turland 2015-10-28 18:55:00 +00:00
commit 0b6d388b52
94 changed files with 18521 additions and 1874 deletions

9
.gitignore vendored
View file

@ -4,10 +4,14 @@
# or operating system, you probably want to add a global ignore instead: # or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global # git config --global core.excludesfile ~/.gitignore_global
#assety stuff
realtime/node_modules realtime/node_modules
public/assets
#secrets
config/database.yml config/database.yml
config/secrets.yml
.env .env
#public/assets
# Ignore bundler config # Ignore bundler config
.bundle .bundle
@ -20,5 +24,6 @@ log/*.log
tmp tmp
.DS_Store .DS_Store
*/.DS_Store
.DS_Store?
.vagrant .vagrant

40
Gemfile
View file

@ -1,15 +1,12 @@
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '2.1.3' ruby '2.1.3'
gem 'rails', '3.2.17' gem 'rails', '4.2.4'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'devise' gem 'devise'
gem 'redis' gem 'redis'
gem 'pg' gem 'pg'
gem 'cancan' gem 'cancancan'
gem 'formula' gem 'formula'
gem 'formtastic' gem 'formtastic'
gem 'json' gem 'json'
@ -22,6 +19,10 @@ gem 'dotenv'
gem 'paperclip' gem 'paperclip'
gem 'aws-sdk' gem 'aws-sdk'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'jbuilder'
#gem 'therubyracer' #optional #gem 'therubyracer' #optional
#gem 'rb-readline' #gem 'rb-readline'
@ -29,32 +30,23 @@ gem 'aws-sdk'
# in production environments by default. # in production environments by default.
group :assets do group :assets do
gem 'sass-rails' gem 'sass-rails'
gem 'coffee-rails', '~> 3.2.1' gem 'coffee-rails'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes # See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer' # gem 'therubyracer'
gem 'uglifier', '>= 1.0.3' gem 'uglifier'
end end
group :production do #this is used on heroku group :production do #this is used on heroku
#gem 'rmagick' #gem 'rmagick'
gem 'rails_12factor'
end end
gem 'jquery-rails', '2.1.2' group :development, :test do
gem 'pry-rails'
# To use ActiveModel has_secure_password gem 'pry-byebug'
# gem 'bcrypt-ruby', '~> 3.0.0' gem 'better_errors'
gem 'binding_of_caller'
# To use Jbuilder templates for JSON gem 'quiet_assets'
gem 'jbuilder', '0.8.2' end
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'

View file

@ -1,58 +1,77 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actionmailer (3.2.17) actionmailer (4.2.4)
actionpack (= 3.2.17) actionpack (= 4.2.4)
mail (~> 2.5.4) actionview (= 4.2.4)
actionpack (3.2.17) activejob (= 4.2.4)
activemodel (= 3.2.17) mail (~> 2.5, >= 2.5.4)
activesupport (= 3.2.17) rails-dom-testing (~> 1.0, >= 1.0.5)
builder (~> 3.0.0) actionpack (4.2.4)
actionview (= 4.2.4)
activesupport (= 4.2.4)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.4)
activesupport (= 4.2.4)
builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
journey (~> 1.0.4) rails-dom-testing (~> 1.0, >= 1.0.5)
rack (~> 1.4.5) rails-html-sanitizer (~> 1.0, >= 1.0.2)
rack-cache (~> 1.2) activejob (4.2.4)
rack-test (~> 0.6.1) activesupport (= 4.2.4)
sprockets (~> 2.2.1) globalid (>= 0.3.0)
activemodel (3.2.17) activemodel (4.2.4)
activesupport (= 3.2.17) activesupport (= 4.2.4)
builder (~> 3.0.0) builder (~> 3.1)
activerecord (3.2.17) activerecord (4.2.4)
activemodel (= 3.2.17) activemodel (= 4.2.4)
activesupport (= 3.2.17) activesupport (= 4.2.4)
arel (~> 3.0.2) arel (~> 6.0)
tzinfo (~> 0.3.29) activesupport (4.2.4)
activeresource (3.2.17) i18n (~> 0.7)
activemodel (= 3.2.17) json (~> 1.7, >= 1.7.7)
activesupport (= 3.2.17) minitest (~> 5.1)
activesupport (3.2.17) thread_safe (~> 0.3, >= 0.3.4)
i18n (~> 0.6, >= 0.6.4) tzinfo (~> 1.1)
multi_json (~> 1.0) arel (6.0.3)
arel (3.0.3) aws-sdk (2.1.19)
aws-sdk (1.54.0) aws-sdk-resources (= 2.1.19)
aws-sdk-v1 (= 1.54.0) aws-sdk-core (2.1.19)
aws-sdk-v1 (1.54.0) jmespath (~> 1.0)
json (~> 1.4) aws-sdk-resources (2.1.19)
nokogiri (>= 1.4.4) aws-sdk-core (= 2.1.19)
bcrypt (3.1.7) bcrypt (3.1.10)
bcrypt (3.1.7-x86-mingw32) best_in_place (3.0.3)
best_in_place (2.1.0) actionpack (>= 3.2)
jquery-rails railties (>= 3.2)
rails (~> 3.1) better_errors (2.1.1)
builder (3.0.4) coderay (>= 1.0.0)
cancan (1.6.10) erubis (>= 2.6.6)
rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (4.0.5)
columnize (= 0.9.0)
cancancan (1.12.0)
climate_control (0.0.3) climate_control (0.0.3)
activesupport (>= 3.0) activesupport (>= 3.0)
cocaine (0.5.4) cocaine (0.5.7)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
coffee-rails (3.2.2) coderay (1.1.0)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (~> 3.2.0) railties (>= 4.0.0, < 5.0)
coffee-script (2.3.0) coffee-script (2.4.1)
coffee-script-source coffee-script-source
execjs execjs
coffee-script-source (1.8.0) coffee-script-source (1.9.1.1)
devise (3.4.0) columnize (0.9.0)
debug_inspector (0.0.2)
devise (3.5.2)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5) railties (>= 3.2.6, < 5)
@ -61,92 +80,120 @@ GEM
warden (~> 1.2.3) warden (~> 1.2.3)
dotenv (2.0.0) dotenv (2.0.0)
erubis (2.7.0) erubis (2.7.0)
execjs (2.2.1) execjs (2.6.0)
ezcrypto (0.7.2) ezcrypto (0.7.2)
formtastic (3.0.0) formtastic (3.1.3)
actionpack (>= 3.2.13) actionpack (>= 3.2.13)
formula (1.0.1) formula (1.1.1)
rails (> 3.0.0) rails (> 3.0.0)
hike (1.2.3) globalid (0.3.6)
i18n (0.6.11) activesupport (>= 4.1.0)
jbuilder (0.8.2) i18n (0.7.0)
activesupport (>= 3.0.0) jbuilder (2.3.1)
journey (1.0.4) activesupport (>= 3.0.0, < 5)
jquery-rails (2.1.2) multi_json (~> 1.2)
railties (>= 3.1.0, < 5.0) jmespath (1.0.2)
thor (~> 0.14) multi_json (~> 1.0)
json (1.8.1) jquery-rails (4.0.5)
kaminari (0.16.1) rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (5.0.5)
railties (>= 3.2.16)
json (1.8.3)
kaminari (0.16.3)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
mail (2.5.4) loofah (2.0.3)
mime-types (~> 1.16) nokogiri (>= 1.5.9)
treetop (~> 1.4.8) mail (2.6.3)
mime-types (1.25.1) mime-types (>= 1.16, < 3)
mini_portile (0.6.0) method_source (0.8.2)
multi_json (1.10.1) mime-types (2.6.1)
nokogiri (1.6.3.1) mimemagic (0.3.0)
mini_portile (= 0.6.0) mini_portile (0.6.2)
nokogiri (1.6.3.1-x86-mingw32) minitest (5.8.0)
mini_portile (= 0.6.0) multi_json (1.11.2)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
oauth (0.4.7) oauth (0.4.7)
orm_adapter (0.5.0) orm_adapter (0.5.0)
paperclip (4.2.0) paperclip (4.3.0)
activemodel (>= 3.0.0) activemodel (>= 3.2.0)
activesupport (>= 3.0.0) activesupport (>= 3.2.0)
cocaine (~> 0.5.3) cocaine (~> 0.5.5)
mime-types mime-types
pg (0.17.1) mimemagic (= 0.3.0)
pg (0.17.1-x86-mingw32) pg (0.18.3)
polyglot (0.3.5) pry (0.10.1)
rack (1.4.5) coderay (~> 1.1.0)
rack-cache (1.2) method_source (~> 0.8.1)
rack (>= 0.4) slop (~> 3.4)
rack-ssl (1.3.4) pry-byebug (3.1.0)
rack byebug (~> 4.0)
rack-test (0.6.2) pry (~> 0.10)
pry-rails (0.3.4)
pry (>= 0.9.10)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
rack (1.6.4)
rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (3.2.17) rails (4.2.4)
actionmailer (= 3.2.17) actionmailer (= 4.2.4)
actionpack (= 3.2.17) actionpack (= 4.2.4)
activerecord (= 3.2.17) actionview (= 4.2.4)
activeresource (= 3.2.17) activejob (= 4.2.4)
activesupport (= 3.2.17) activemodel (= 4.2.4)
bundler (~> 1.0) activerecord (= 4.2.4)
railties (= 3.2.17) activesupport (= 4.2.4)
rails3-jquery-autocomplete (1.0.14) bundler (>= 1.3.0, < 2.0)
rails (>= 3.0) railties (= 4.2.4)
railties (3.2.17) sprockets-rails
actionpack (= 3.2.17) rails-deprecated_sanitizer (1.0.3)
activesupport (= 3.2.17) activesupport (>= 4.2.0.alpha)
rack-ssl (~> 1.3.2) rails-dom-testing (1.0.7)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
rails3-jquery-autocomplete (1.0.15)
rails (>= 3.2)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.4)
rails_stdout_logging (0.0.4)
railties (4.2.4)
actionpack (= 4.2.4)
activesupport (= 4.2.4)
rake (>= 0.8.7) rake (>= 0.8.7)
rdoc (~> 3.4) thor (>= 0.18.1, < 2.0)
thor (>= 0.14.6, < 2.0) rake (10.4.2)
rake (10.3.2) redis (3.2.1)
rdoc (3.12.2) responders (2.1.0)
json (~> 1.4) railties (>= 4.2.0, < 5)
redis (3.1.0) sass (3.4.18)
responders (1.1.1) sass-rails (5.0.4)
railties (>= 3.2, < 4.2) railties (>= 4.0.0, < 5.0)
sass (3.4.5) sass (~> 3.1)
sass-rails (3.2.6) sprockets (>= 2.8, < 4.0)
railties (~> 3.2.0) sprockets-rails (>= 2.0, < 4.0)
sass (>= 3.1.10) tilt (>= 1.1, < 3)
tilt (~> 1.3) slop (3.6.0)
sprockets (2.2.2) sprockets (3.3.4)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0) rack (~> 1.0)
tilt (~> 1.1, != 1.3.0) sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
thor (0.19.1) thor (0.19.1)
thread_safe (0.3.4) thread_safe (0.3.5)
tilt (1.4.1) tilt (2.0.1)
treetop (1.4.15) tzinfo (1.2.2)
polyglot thread_safe (~> 0.1)
polyglot (>= 0.3.1) uglifier (2.7.2)
tzinfo (0.3.41)
uglifier (2.5.3)
execjs (>= 0.3.0) execjs (>= 0.3.0)
json (>= 1.8.0) json (>= 1.8.0)
uservoice-ruby (0.0.11) uservoice-ruby (0.0.11)
@ -158,26 +205,35 @@ GEM
PLATFORMS PLATFORMS
ruby ruby
x86-mingw32
DEPENDENCIES DEPENDENCIES
aws-sdk aws-sdk
best_in_place best_in_place
cancan better_errors
coffee-rails (~> 3.2.1) binding_of_caller
cancancan
coffee-rails
devise devise
dotenv dotenv
formtastic formtastic
formula formula
jbuilder (= 0.8.2) jbuilder
jquery-rails (= 2.1.2) jquery-rails
jquery-ui-rails
json json
kaminari kaminari
paperclip paperclip
pg pg
rails (= 3.2.17) pry-byebug
pry-rails
quiet_assets
rails (= 4.2.4)
rails3-jquery-autocomplete rails3-jquery-autocomplete
rails_12factor
redis redis
sass-rails sass-rails
uglifier (>= 1.0.3) uglifier
uservoice-ruby uservoice-ruby
BUNDLED WITH
1.10.6

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
app/assets/images/junto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -20,6 +20,9 @@
//= require ./src/Metamaps.Router //= require ./src/Metamaps.Router
//= require ./src/Metamaps.Backbone //= require ./src/Metamaps.Backbone
//= require ./src/Metamaps.Views //= require ./src/Metamaps.Views
//= require ./src/views/chatView
//= require ./src/views/videoView
//= require ./src/views/room
//= require ./src/JIT //= require ./src/JIT
//= require ./src/Metamaps //= require ./src/Metamaps
//= require ./src/Metamaps.JIT //= require ./src/Metamaps.JIT

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
var attachMediaStream = function (stream, el, options) {
var URL = window.URL;
var opts = {
autoplay: true,
mirror: false,
muted: false
};
var element = el || document.createElement('video');
var item;
if (options) {
for (item in options) {
opts[item] = options[item];
}
}
if (opts.autoplay) element.autoplay = 'autoplay';
if (opts.muted) element.muted = true;
if (opts.mirror) {
['', 'moz', 'webkit', 'o', 'ms'].forEach(function (prefix) {
var styleName = prefix ? prefix + 'Transform' : 'transform';
element.style[styleName] = 'scaleX(-1)';
});
}
// this first one should work most everywhere now
// but we have a few fallbacks just in case.
if (URL && URL.createObjectURL) {
element.src = URL.createObjectURL(stream);
} else if (element.srcObject) {
element.srcObject = stream;
} else if (element.mozSrcObject) {
element.mozSrcObject = stream;
} else {
return false;
}
return element;
};

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,23 @@
function SocketIoConnection(config) {
this.connection = io.connect(config.url, config.socketio);
}
SocketIoConnection.prototype.on = function (ev, fn) {
this.connection.on(ev, fn);
};
SocketIoConnection.prototype.emit = function () {
this.connection.emit.apply(this.connection, arguments);
};
SocketIoConnection.prototype.removeAllListeners = function () {
this.connection.removeAllListeners();
};
SocketIoConnection.prototype.getSessionid = function () {
return this.connection.socket.sessionid;
};
SocketIoConnection.prototype.disconnect = function () {
return this.connection.disconnect();
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3127,7 +3127,7 @@ var Canvas;
ctx = base.getCtx(), ctx = base.getCtx(),
scale = base.scaleOffsetX; scale = base.scaleOffsetX;
//var pattern = new Image(); //var pattern = new Image();
//pattern.src = "/assets/cubes.png"; //pattern.src = "<%= asset_path('cubes.png') %>";
//var ptrn = ctx.createPattern(pattern, 'repeat'); //var ptrn = ctx.createPattern(pattern, 'repeat');
//ctx.fillStyle = ptrn; //ctx.fillStyle = ptrn;
ctx.fillStyle = Metamaps.Settings.colors.background; ctx.fillStyle = Metamaps.Settings.colors.background;

View file

@ -495,7 +495,7 @@ Metamaps.GlobalUI.Search = {
dataset.push({ dataset.push({
value: "No results", value: "No results",
label: "No results", label: "No results",
typeImageURL: "/assets/icons/wildcard.png", typeImageURL: "<%= asset_path('icons/wildcard.png') %>",
rtype: "noresult" rtype: "noresult"
}); });
} }
@ -549,7 +549,7 @@ Metamaps.GlobalUI.Search = {
filter: function (dataset) { filter: function (dataset) {
if (dataset.length == 0) { if (dataset.length == 0) {
dataset.push({ dataset.push({
profile: "/assets/user.png", profile: "<%= asset_path('user.png') %>",
value: "No results", value: "No results",
label: "No results", label: "No results",
@ -616,7 +616,7 @@ Metamaps.GlobalUI.Search = {
var self = Metamaps.GlobalUI.Search; var self = Metamaps.GlobalUI.Search;
function toggleResultSet(set) { function toggleResultSet(set) {
var s = $('.tt-dataset-' + set + ' .tt-suggestions'); var s = $('.tt-dataset-' + set + ' .tt-dataset');
if (s.css('height') == '0px') { if (s.css('height') == '0px') {
s.css({ s.css({
'height': 'auto', 'height': 'auto',
@ -658,4 +658,4 @@ Metamaps.GlobalUI.Search = {
showLoader: function () { showLoader: function () {
$('#searchLoading').show(); $('#searchLoading').show();
} }
}; };

View file

@ -29,10 +29,10 @@ Metamaps.JIT = {
$(".takeScreenshot").click(Metamaps.Map.exportImage); $(".takeScreenshot").click(Metamaps.Map.exportImage);
self.topicDescImage = new Image(); self.topicDescImage = new Image();
self.topicDescImage.src = '/assets/topic_description_signifier.png'; self.topicDescImage.src = '<%= asset_path('topic_description_signifier.png') %>';
self.topicLinkImage = new Image(); self.topicLinkImage = new Image();
self.topicLinkImage.src = '/assets/topic_link_signifier.png'; self.topicLinkImage.src = '<%= asset_path('topic_link_signifier.png') %>';
}, },
/** /**
* convert our topic JSON into something JIT can use * convert our topic JSON into something JIT can use

View file

@ -37,7 +37,7 @@ Metamaps.Settings = {
background: '#18202E', background: '#18202E',
text: '#DDD' text: '#DDD'
} }
} },
}; };
Metamaps.Touch = { Metamaps.Touch = {
@ -157,7 +157,7 @@ Metamaps.Backbone.init = function () {
this.on('saved', this.savedEvent); this.on('saved', this.savedEvent);
this.on('nowPrivate', function(){ this.on('nowPrivate', function(){
var removeTopicData = { var removeTopicData = {
topicid: this.id mappableid: this.id
}; };
$(document).trigger(Metamaps.JIT.events.removeTopic, [removeTopicData]); $(document).trigger(Metamaps.JIT.events.removeTopic, [removeTopicData]);
@ -165,7 +165,7 @@ Metamaps.Backbone.init = function () {
this.on('noLongerPrivate', function(){ this.on('noLongerPrivate', function(){
var newTopicData = { var newTopicData = {
mappingid: this.getMapping().id, mappingid: this.getMapping().id,
topicid: this.id mappableid: this.id
}; };
$(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]); $(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]);
@ -194,7 +194,8 @@ Metamaps.Backbone.init = function () {
return Metamaps.Mappings.findWhere({ return Metamaps.Mappings.findWhere({
map_id: Metamaps.Active.Map.id, map_id: Metamaps.Active.Map.id,
topic_id: this.isNew() ? this.cid : this.id mappable_type: "Topic",
mappable_id: this.isNew() ? this.cid : this.id
}); });
}, },
createNode: function () { createNode: function () {
@ -320,14 +321,14 @@ Metamaps.Backbone.init = function () {
this.on('noLongerPrivate', function(){ this.on('noLongerPrivate', function(){
var newSynapseData = { var newSynapseData = {
mappingid: this.getMapping().id, mappingid: this.getMapping().id,
synapseid: this.id mappableid: this.id
}; };
$(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]); $(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]);
}); });
this.on('nowPrivate', function(){ this.on('nowPrivate', function(){
$(document).trigger(Metamaps.JIT.events.removeSynapse, [{ $(document).trigger(Metamaps.JIT.events.removeSynapse, [{
synapseid: this.id mappableid: this.id
}]); }]);
}); });
@ -336,7 +337,7 @@ Metamaps.Backbone.init = function () {
prepareLiForFilter: function () { prepareLiForFilter: function () {
var li = ''; var li = '';
li += '<li data-id="' + this.get('desc') + '">'; li += '<li data-id="' + this.get('desc') + '">';
li += '<img src="/assets/synapse16.png"'; li += '<img src="<%= asset_path('synapse16.png') %>"';
li += ' alt="synapse icon" />'; li += ' alt="synapse icon" />';
li += '<p>' + this.get('desc') + '</p></li>'; li += '<p>' + this.get('desc') + '</p></li>';
return li; return li;
@ -370,7 +371,8 @@ Metamaps.Backbone.init = function () {
return Metamaps.Mappings.findWhere({ return Metamaps.Mappings.findWhere({
map_id: Metamaps.Active.Map.id, map_id: Metamaps.Active.Map.id,
synapse_id: this.isNew() ? this.cid : this.id mappable_type: "Synapse",
mappable_id: this.isNew() ? this.cid : this.id
}); });
}, },
createEdge: function () { createEdge: function () {
@ -457,11 +459,11 @@ Metamaps.Backbone.init = function () {
return Metamaps.Map.get(this.get('map_id')); return Metamaps.Map.get(this.get('map_id'));
}, },
getTopic: function () { getTopic: function () {
if (this.get('category') === 'Topic') return Metamaps.Topic.get(this.get('topic_id')); if (this.get('mappable_type') === 'Topic') return Metamaps.Topic.get(this.get('mappable_id'));
else return false; else return false;
}, },
getSynapse: function () { getSynapse: function () {
if (this.get('category') === 'Synapse') return Metamaps.Synapse.get(this.get('synapse_id')); if (this.get('mappable_type') === 'Synapse') return Metamaps.Synapse.get(this.get('mappable_id'));
else return false; else return false;
} }
}); });
@ -664,24 +666,36 @@ Metamaps.Create = {
Metamaps.Create.newTopic.name = $(this).val(); Metamaps.Create.newTopic.name = $(this).val();
}); });
var topicBloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/topics/autocomplete_topic?term=%QUERY',
wildcard: '%QUERY',
},
});
// initialize the autocomplete results for the metacode spinner // initialize the autocomplete results for the metacode spinner
$('#topic_name').typeahead( $('#topic_name').typeahead(
{ {
highlight: true,
minLength: 2, minLength: 2,
}, },
[{ [{
name: 'topic_autocomplete', name: 'topic_autocomplete',
limit: 8, limit: 8,
template: $('#topicAutocompleteTemplate').html(), display: function (s) { return s.label; },
remote: { templates: {
url: '/topics/autocomplete_topic?term=%QUERY' suggestion: function(s) {
return Hogan.compile($('#topicAutocompleteTemplate').html()).render(s);
},
}, },
engine: Hogan source: topicBloodhound,
}] }]
); );
// tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete // tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete
$('#topic_name').bind('typeahead:selected', function (event, datum, dataset) { $('#topic_name').bind('typeahead:select', function (event, datum, dataset) {
Metamaps.Topic.getTopicFromAutocomplete(datum.id); Metamaps.Topic.getTopicFromAutocomplete(datum.id);
}); });
@ -714,7 +728,7 @@ Metamaps.Create = {
}, },
hide: function () { hide: function () {
$('#new_topic').fadeOut('fast'); $('#new_topic').fadeOut('fast');
$("#topic_name").typeahead('setQuery', ''); $("#topic_name").typeahead('val', '');
Metamaps.Create.newTopic.beingCreated = false; Metamaps.Create.newTopic.beingCreated = false;
} }
}, },
@ -726,35 +740,62 @@ Metamaps.Create = {
Metamaps.Create.newSynapse.description = $(this).val(); Metamaps.Create.newSynapse.description = $(this).val();
}); });
var synapseBloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/search/synapses?term=%QUERY',
wildcard: '%QUERY',
},
});
var existingSynapseBloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/search/synapses?topic1id=%TOPIC1&topic2id=%TOPIC2',
prepare: function(query, settings) {
var self = Metamaps.Create.newSynapse;
if (Metamaps.Selected.Nodes.length < 2) {
settings.url = settings.url.replace("%TOPIC1", self.topic1id).replace("%TOPIC2", self.topic2id);
return settings;
} else {
return null;
}
},
},
});
// initialize the autocomplete results for synapse creation // initialize the autocomplete results for synapse creation
$('#synapse_desc').typeahead( $('#synapse_desc').typeahead(
{ {
highlight: true,
minLength: 2, minLength: 2,
}, },
[{ [{
name: 'synapse_autocomplete', name: 'synapse_autocomplete',
template: "<div class='genericSynapseDesc'>{{label}}</div>", display: function(s) { return s.label; },
remote: { templates: {
url: '/search/synapses?term=%QUERY' suggestion: function(s) {
return Hogan.compile("<div class='genericSynapseDesc'>{{label}}</div>").render(s);
},
}, },
engine: Hogan source: synapseBloodhound,
}, },
{ {
name: 'existing_synapses', name: 'existing_synapses',
limit: 50, limit: 50,
template: $('#synapseAutocompleteTemplate').html(), display: function(s) { return s.label; },
remote: { templates: {
url: '/search/synapses', suggestion: function(s) {
replace: function () { return Hogan.compile($('#synapseAutocompleteTemplate').html()).render(s);
return self.getSearchQuery(); },
} header: "<h3>Existing synapses</h3>"
}, },
engine: Hogan, source: existingSynapseBloodhound,
header: "<h3>Existing synapses</h3>"
}] }]
); );
$('#synapse_desc').bind('typeahead:selected', function (event, datum, dataset) { $('#synapse_desc').bind('typeahead:select', function (event, datum, dataset) {
if (datum.id) { // if they clicked on an existing synapse get it if (datum.id) { // if they clicked on an existing synapse get it
Metamaps.Synapse.getSynapseFromAutocomplete(datum.id); Metamaps.Synapse.getSynapseFromAutocomplete(datum.id);
} }
@ -777,7 +818,7 @@ Metamaps.Create = {
}, },
hide: function () { hide: function () {
$('#new_synapse').fadeOut('fast'); $('#new_synapse').fadeOut('fast');
$("#synapse_desc").typeahead('setQuery', ''); $("#synapse_desc").typeahead('val', '');
Metamaps.Create.newSynapse.beingCreated = false; Metamaps.Create.newSynapse.beingCreated = false;
Metamaps.Create.newTopic.addSynapse = false; Metamaps.Create.newTopic.addSynapse = false;
Metamaps.Create.newSynapse.topic1id = 0; Metamaps.Create.newSynapse.topic1id = 0;
@ -785,13 +826,6 @@ Metamaps.Create = {
Metamaps.Mouse.synapseStartCoordinates = []; Metamaps.Mouse.synapseStartCoordinates = [];
Metamaps.Visualize.mGraph.plot(); Metamaps.Visualize.mGraph.plot();
}, },
getSearchQuery: function () {
var self = Metamaps.Create.newSynapse;
if (Metamaps.Selected.Nodes.length < 2) {
return '/search/synapses?topic1id=' + self.topic1id + '&topic2id=' + self.topic2id;
} else return '';
}
} }
}; // end Metamaps.Create }; // end Metamaps.Create
@ -1534,8 +1568,6 @@ Metamaps.SynapseCard = {
////////////////////// END TOPIC AND SYNAPSE CARDS ////////////////////////////////// ////////////////////// END TOPIC AND SYNAPSE CARDS //////////////////////////////////
/* /*
* *
* VISUALIZE * VISUALIZE
@ -1878,11 +1910,15 @@ Metamaps.Realtime = {
stringForLocalhost: 'http://localhost:5001', stringForLocalhost: 'http://localhost:5001',
stringForMetamaps: 'http://metamaps.cc:5001', stringForMetamaps: 'http://metamaps.cc:5001',
stringForHeroku: 'http://gentle-savannah-1303.herokuapp.com', stringForHeroku: 'http://gentle-savannah-1303.herokuapp.com',
videoId: 'video-wrapper',
socket: null, socket: null,
webrtc: null,
readyToCall: false,
isOpen: false, isOpen: false,
changing: false, changing: false,
mappersOnMap: {}, mappersOnMap: {},
status: true, // stores whether realtime is True/On or False/Off status: true, // stores whether realtime is True/On or False/Off,
localVideo: null,
init: function () { init: function () {
var self = Metamaps.Realtime; var self = Metamaps.Realtime;
@ -1903,10 +1939,54 @@ Metamaps.Realtime = {
var railsEnv = $('body').data('env'); var railsEnv = $('body').data('env');
var whichToConnect = railsEnv === 'development' ? self.stringForLocalhost : self.stringForHeroku; var whichToConnect = railsEnv === 'development' ? self.stringForLocalhost : self.stringForHeroku;
self.socket = io.connect(whichToConnect); self.socket = new SocketIoConnection({ url: whichToConnect });
self.socket.on('connect', function () { self.socket.on('connect', function () {
self.startActiveMap(); self.startActiveMap();
}); });
self.webrtc = new SimpleWebRTC({
connection: self.socket,
localVideoEl: self.videoId,
remoteVideosEl: '',
detectSpeakingEvents: true,
autoAdjustMic: true,
autoRequestMedia: false,
localVideo: {
autoplay: true,
mirror: true,
muted: true
},
media: {
video: true,
audio: true
}
});
self.webrtc.on('readyToCall', function () {
self.readyToCall = true;
if (self.localVideo && self.status) {
$('#wrapper').append(self.localVideo.view.$container);
}
});
var
$video = $('<video></video>').attr('id', self.videoId);
self.localVideo = {
$video: $video,
view: new Metamaps.Views.videoView($video[0], $('body'), 'me', true, { DOUBLE_CLICK_TOLERANCE: 200 }),
};
self.room = new Metamaps.Views.room({
webrtc: self.webrtc,
socket: self.socket,
username: 'dude',//getUsername(opts.user, provider),
image: 'https://pbs.twimg.com/profile_images/436050101539065856/QMGlzCUn_400x400.jpeg', //getImage(opts.user, provider),
room: 'global',
$video: self.localVideo.$video,
myVideoView: self.localVideo.view,
config: { DOUBLE_CLICK_TOLERANCE: 200 }
});
self.createChat();
self.webrtc.startLocalVideo();
}, },
toggleBox: function (event) { toggleBox: function (event) {
var self = Metamaps.Realtime; var self = Metamaps.Realtime;
@ -1987,6 +2067,31 @@ Metamaps.Realtime = {
self.status = true; self.status = true;
$(".sidebarCollaborateIcon").addClass("blue"); $(".sidebarCollaborateIcon").addClass("blue");
$(".collabCompass").show(); $(".collabCompass").show();
if (self.localVideo) $('#wrapper').append(self.localVideo.view.$container);
self.room.room = 'map-' + Metamaps.Active.Map.id;
self.room.join(function (err, roomDesc) {
console.log('joining');
attachMediaStream(self.webrtc.webrtc.localStream, self.localVideo.$video[0]);
function addVideo(v) {
// random position for now
var top = Math.floor((Math.random() * ($('#wrapper').height() - 100)) + 1);
var left = Math.floor((Math.random() * ($('#wrapper').width() - 100)) + 1);
//var right = Math.floor((Math.random() * (468 - 100)) + 1);
v.setParent($('#wrapper'));
$('#wrapper').append(v.$container);
v.$container.css({
top: top + 'px',
left: left + 'px'
});
}
self.room.videoAdded(addVideo);
for (peer in self.room.videos) {
addVideo(self.room.videos[peer]);
}
});
}, },
turnOff: function (silent) { turnOff: function (silent) {
var self = Metamaps.Realtime; var self = Metamaps.Realtime;
@ -1999,6 +2104,7 @@ Metamaps.Realtime = {
self.status = false; self.status = false;
$(".sidebarCollaborateIcon").removeClass("blue"); $(".sidebarCollaborateIcon").removeClass("blue");
$(".collabCompass").hide(); $(".collabCompass").hide();
$('#' + self.videoId).remove();
} }
}, },
setupSocket: function () { setupSocket: function () {
@ -2122,6 +2228,12 @@ Metamaps.Realtime = {
socket.on('mapChangeFromServer', self.mapChange); socket.on('mapChangeFromServer', self.mapChange);
}, },
createChat: function() {
var self = Metamaps.Realtime;
$('#wrapper').append(self.room.chat.$container);
//self.room.chat.open();
},
sendRealtimeOn: function () { sendRealtimeOn: function () {
var self = Metamaps.Realtime; var self = Metamaps.Realtime;
var socket = Metamaps.Realtime.socket; var socket = Metamaps.Realtime.socket;
@ -2511,7 +2623,7 @@ Metamaps.Realtime = {
if (!self.status) return; if (!self.status) return;
function test() { function waitThenRenderTopic() {
if (topic && mapping && mapper) { if (topic && mapping && mapper) {
Metamaps.Topic.renderTopic(mapping, topic, false, false); Metamaps.Topic.renderTopic(mapping, topic, false, false);
} }
@ -2529,7 +2641,7 @@ Metamaps.Realtime = {
Metamaps.Mapper.get(data.mapperid, mapperCallback); Metamaps.Mapper.get(data.mapperid, mapperCallback);
} }
$.ajax({ $.ajax({
url: "/topics/" + data.topicid + ".json", url: "/topics/" + data.mappableid + ".json",
success: function (response) { success: function (response) {
Metamaps.Topics.add(response); Metamaps.Topics.add(response);
topic = Metamaps.Topics.get(response.id); topic = Metamaps.Topics.get(response.id);
@ -2549,7 +2661,7 @@ Metamaps.Realtime = {
} }
}); });
test(); waitThenRenderTopic();
}, },
// removeTopic // removeTopic
sendDeleteTopic: function (data) { sendDeleteTopic: function (data) {
@ -2576,7 +2688,7 @@ Metamaps.Realtime = {
if (!self.status) return; if (!self.status) return;
var topic = Metamaps.Topics.get(data.topicid); var topic = Metamaps.Topics.get(data.mappableid);
if (topic) { if (topic) {
var node = topic.get('node'); var node = topic.get('node');
var mapping = topic.getMapping(); var mapping = topic.getMapping();
@ -2604,7 +2716,7 @@ Metamaps.Realtime = {
if (!self.status) return; if (!self.status) return;
function test() { function waitThenRenderSynapse() {
if (synapse && mapping && mapper) { if (synapse && mapping && mapper) {
topic1 = synapse.getTopic1(); topic1 = synapse.getTopic1();
node1 = topic1.get('node'); node1 = topic1.get('node');
@ -2627,7 +2739,7 @@ Metamaps.Realtime = {
Metamaps.Mapper.get(data.mapperid, mapperCallback); Metamaps.Mapper.get(data.mapperid, mapperCallback);
} }
$.ajax({ $.ajax({
url: "/synapses/" + data.synapseid + ".json", url: "/synapses/" + data.mappableid + ".json",
success: function (response) { success: function (response) {
Metamaps.Synapses.add(response); Metamaps.Synapses.add(response);
synapse = Metamaps.Synapses.get(response.id); synapse = Metamaps.Synapses.get(response.id);
@ -2646,7 +2758,7 @@ Metamaps.Realtime = {
cancel = true; cancel = true;
} }
}); });
test(); waitThenRenderSynapse();
}, },
// deleteSynapse // deleteSynapse
sendDeleteSynapse: function (data) { sendDeleteSynapse: function (data) {
@ -2674,7 +2786,7 @@ Metamaps.Realtime = {
if (!self.status) return; if (!self.status) return;
var synapse = Metamaps.Synapses.get(data.synapseid); var synapse = Metamaps.Synapses.get(data.mappableid);
if (synapse) { if (synapse) {
var edge = synapse.get('edge'); var edge = synapse.get('edge');
var mapping = synapse.getMapping(); var mapping = synapse.getMapping();
@ -2784,12 +2896,12 @@ Metamaps.Control = {
var permToDelete = Metamaps.Active.Mapper.id === topic.get('user_id') || Metamaps.Active.Mapper.get('admin'); var permToDelete = Metamaps.Active.Mapper.id === topic.get('user_id') || Metamaps.Active.Mapper.get('admin');
if (permToDelete) { if (permToDelete) {
var topicid = topic.id; var mappableid = topic.id;
var mapping = node.getData('mapping'); var mapping = node.getData('mapping');
topic.destroy(); topic.destroy();
Metamaps.Mappings.remove(mapping); Metamaps.Mappings.remove(mapping);
$(document).trigger(Metamaps.JIT.events.deleteTopic, [{ $(document).trigger(Metamaps.JIT.events.deleteTopic, [{
topicid: topicid mappableid: mappableid
}]); }]);
Metamaps.Control.hideNode(nodeid); Metamaps.Control.hideNode(nodeid);
} else { } else {
@ -2828,12 +2940,12 @@ Metamaps.Control = {
} }
var topic = node.getData('topic'); var topic = node.getData('topic');
var topicid = topic.id; var mappableid = topic.id;
var mapping = node.getData('mapping'); var mapping = node.getData('mapping');
mapping.destroy(); mapping.destroy();
Metamaps.Topics.remove(topic); Metamaps.Topics.remove(topic);
$(document).trigger(Metamaps.JIT.events.removeTopic, [{ $(document).trigger(Metamaps.JIT.events.removeTopic, [{
topicid: topicid mappableid: mappableid
}]); }]);
Metamaps.Control.hideNode(nodeid); Metamaps.Control.hideNode(nodeid);
}, },
@ -2957,7 +3069,7 @@ Metamaps.Control = {
Metamaps.Control.hideEdge(edge); Metamaps.Control.hideEdge(edge);
} }
var synapseid = synapse.id; var mappableid = synapse.id;
synapse.destroy(); synapse.destroy();
// the server will destroy the mapping, we just need to remove it here // the server will destroy the mapping, we just need to remove it here
@ -2968,7 +3080,7 @@ Metamaps.Control = {
delete edge.data.$displayIndex; delete edge.data.$displayIndex;
} }
$(document).trigger(Metamaps.JIT.events.deleteSynapse, [{ $(document).trigger(Metamaps.JIT.events.deleteSynapse, [{
synapseid: synapseid mappableid: mappableid
}]); }]);
} else { } else {
Metamaps.GlobalUI.notifyUser('Only synapses you created can be deleted'); Metamaps.GlobalUI.notifyUser('Only synapses you created can be deleted');
@ -3013,7 +3125,7 @@ Metamaps.Control = {
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 synapseid = synapse.id; var mappableid = synapse.id;
mapping.destroy(); mapping.destroy();
Metamaps.Synapses.remove(synapse); Metamaps.Synapses.remove(synapse);
@ -3024,7 +3136,7 @@ Metamaps.Control = {
delete edge.data.$displayIndex; delete edge.data.$displayIndex;
} }
$(document).trigger(Metamaps.JIT.events.removeSynapse, [{ $(document).trigger(Metamaps.JIT.events.removeSynapse, [{
synapseid: synapseid mappableid: mappableid
}]); }]);
}, },
hideSelectedEdges: function () { hideSelectedEdges: function () {
@ -4024,14 +4136,14 @@ Metamaps.Topic = {
var mappingSuccessCallback = function (mappingModel, response) { var mappingSuccessCallback = function (mappingModel, response) {
var newTopicData = { var newTopicData = {
mappingid: mappingModel.id, mappingid: mappingModel.id,
topicid: mappingModel.get('topic_id') mappableid: mappingModel.get('mappable_id')
}; };
$(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]); $(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]);
}; };
var topicSuccessCallback = function (topicModel, response) { var topicSuccessCallback = function (topicModel, response) {
if (Metamaps.Active.Map) { if (Metamaps.Active.Map) {
mapping.save({ topic_id: topicModel.id }, { mapping.save({ mappable_id: topicModel.id }, {
success: mappingSuccessCallback, success: mappingSuccessCallback,
error: function (model, response) { error: function (model, response) {
console.log('error saving mapping to database'); console.log('error saving mapping to database');
@ -4081,10 +4193,10 @@ Metamaps.Topic = {
Metamaps.Topics.add(topic); Metamaps.Topics.add(topic);
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
category: "Topic",
xloc: Metamaps.Create.newTopic.x, xloc: Metamaps.Create.newTopic.x,
yloc: Metamaps.Create.newTopic.y, yloc: Metamaps.Create.newTopic.y,
topic_id: topic.cid mappable_id: topic.cid,
mappable_type: "Topic",
}); });
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping);
@ -4103,10 +4215,10 @@ Metamaps.Topic = {
var topic = self.get(id); var topic = self.get(id);
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
category: "Topic",
xloc: Metamaps.Create.newTopic.x, xloc: Metamaps.Create.newTopic.x,
yloc: Metamaps.Create.newTopic.y, yloc: Metamaps.Create.newTopic.y,
topic_id: topic.id mappable_type: "Topic",
mappable_id: topic.id,
}); });
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping);
@ -4121,10 +4233,10 @@ Metamaps.Topic = {
var nextCoords = Metamaps.Map.getNextCoord(); var nextCoords = Metamaps.Map.getNextCoord();
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
category: "Topic",
xloc: nextCoords.x, xloc: nextCoords.x,
yloc: nextCoords.y, yloc: nextCoords.y,
topic_id: topic.id mappable_type: "Topic",
mappable_id: topic.id,
}); });
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping);
@ -4195,14 +4307,14 @@ Metamaps.Synapse = {
var mappingSuccessCallback = function (mappingModel, response) { var mappingSuccessCallback = function (mappingModel, response) {
var newSynapseData = { var newSynapseData = {
mappingid: mappingModel.id, mappingid: mappingModel.id,
synapseid: mappingModel.get('synapse_id') mappableid: mappingModel.get('mappable_id')
}; };
$(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]); $(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]);
}; };
var synapseSuccessCallback = function (synapseModel, response) { var synapseSuccessCallback = function (synapseModel, response) {
if (Metamaps.Active.Map) { if (Metamaps.Active.Map) {
mapping.save({ synapse_id: synapseModel.id }, { mapping.save({ mappable_id: synapseModel.id }, {
success: mappingSuccessCallback success: mappingSuccessCallback
}); });
} }
@ -4252,15 +4364,15 @@ Metamaps.Synapse = {
node1 = synapsesToCreate[i]; node1 = synapsesToCreate[i];
topic1 = node1.getData('topic'); topic1 = node1.getData('topic');
synapse = new Metamaps.Backbone.Synapse({ synapse = new Metamaps.Backbone.Synapse({
desc: Metamaps.Create.newSynapse.description, desc: Metamaps.Create.newSynapse.description,// || "",
node1_id: topic1.isNew() ? topic1.cid : topic1.id, node1_id: topic1.isNew() ? topic1.cid : topic1.id,
node2_id: topic2.isNew() ? topic2.cid : topic2.id, node2_id: topic2.isNew() ? topic2.cid : topic2.id,
}); });
Metamaps.Synapses.add(synapse); Metamaps.Synapses.add(synapse);
mapping = new Metamaps.Backbone.Mapping({ mapping = new Metamaps.Backbone.Mapping({
category: "Synapse", mappable_type: "Synapse",
synapse_id: synapse.cid mappable_id: synapse.cid,
}); });
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping);
@ -4280,8 +4392,8 @@ Metamaps.Synapse = {
var synapse = self.get(id); var synapse = self.get(id);
var mapping = new Metamaps.Backbone.Mapping({ var mapping = new Metamaps.Backbone.Mapping({
category: "Synapse", mappable_type: "Synapse",
synapse_id: synapse.id mappable_id: synapse.id,
}); });
Metamaps.Mappings.add(mapping); Metamaps.Mappings.add(mapping);
@ -4761,7 +4873,7 @@ Metamaps.Map.InfoBox = {
obj["map_creator_tip"] = isCreator ? self.changePermissionText : ""; obj["map_creator_tip"] = isCreator ? self.changePermissionText : "";
obj["contributors_class"] = Metamaps.Mappers.length > 1 ? "multiple" : ""; obj["contributors_class"] = Metamaps.Mappers.length > 1 ? "multiple" : "";
obj["contributors_class"] += Metamaps.Mappers.length === 2 ? " mTwo" : ""; obj["contributors_class"] += Metamaps.Mappers.length === 2 ? " mTwo" : "";
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") : "<%= asset_path('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["created_at"] = map.get("created_at_clean");
@ -4858,7 +4970,7 @@ Metamaps.Map.InfoBox = {
if (Metamaps.Mappers.length === 2) contributors_class = "multiple mTwo"; if (Metamaps.Mappers.length === 2) contributors_class = "multiple mTwo";
else if (Metamaps.Mappers.length > 2) contributors_class = "multiple"; else if (Metamaps.Mappers.length > 2) contributors_class = "multiple";
var contributors_image = "/assets/user.png"; var contributors_image = "<%= asset_path('user.png') %>";
if (Metamaps.Mappers.length > 0) { if (Metamaps.Mappers.length > 0) {
// get the first contributor and use their image // get the first contributor and use their image
contributors_image = Metamaps.Mappers.models[0].get("image"); contributors_image = Metamaps.Mappers.models[0].get("image");
@ -5039,7 +5151,7 @@ Metamaps.Account = {
var self = Metamaps.Account; var self = Metamaps.Account;
$('.userImageDiv canvas').remove(); $('.userImageDiv canvas').remove();
$('.userImageDiv img').attr('src', '/assets/user.png').show(); $('.userImageDiv img').attr('src', '<%= asset_path('user.png') %>').show();
$('.userImageMenu').hide(); $('.userImageMenu').hide();
var input = $('#user_image'); var input = $('#user_image');

View file

@ -0,0 +1,272 @@
Metamaps.Views = Metamaps.Views || {};
Metamaps.Views.chatView = (function () {
var
chatView,
linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false });
var Private = {
messageHTML: "<div class='chat-message'>" +
"<div class='chat-message-user'><img src='<%= image %>' title='<%= user %>'/></div>" +
"<div class='chat-message-text'><%= message %></div>" +
"<div class='chat-message-time'><%= timestamp %></div>" +
"<div class='clearfloat'></div>" +
"</div>",
participantHTML: "<div class='participant participant-<%= username %>'>" +
"<div class='chat-participant-image'><img src='<%= image %>' /></div>" +
"<div class='chat-participant-name'><%= username %></div>" +
"<div class='clearfloat'></div>" +
"</div>",
templates: function() {
this.messageTemplate = _.template(Private.messageHTML);
this.participantTemplate = _.template(Private.participantHTML);
},
createElements: function() {
this.$unread = $('<div class="chat-unread"></div>');
this.$button = $('<div class="chat-button"></div>');
this.$messageInput = $('<textarea placeholder="Send a message..." class="chat-input"></textarea>');
this.$juntoHeader = $('<div class="junto-header">PARTICIPANTS</div>');
this.$videoToggle = $('<div class="video-toggle"></div>');
this.$cursorToggle = $('<div class="cursor-toggle"></div>');
this.$participants = $('<div class="participants"></div>');
this.$chatHeader = $('<div class="chat-header">CHAT</div>');
this.$soundToggle = $('<div class="sound-toggle active"></div>');
this.$messages = $('<div class="chat-messages"></div>');
this.$container = $('<div class="chat-box"></div>');
},
attachElements: function() {
this.$button.append(this.$unread);
this.$juntoHeader.append(this.$videoToggle);
this.$juntoHeader.append(this.$cursorToggle);
this.$chatHeader.append(this.$soundToggle);
this.$container.append(this.$juntoHeader);
this.$container.append(this.$participants);
this.$container.append(this.$chatHeader);
this.$container.append(this.$messageInput);
this.$container.append(this.$button);
this.$container.append(this.$messages);
},
addEventListeners: function() {
var self = this;
this.participants.on('add', function (participant) {
Private.addParticipant.call(self, participant);
});
this.participants.on('remove', function (participant) {
Private.removeParticipant.call(self, participant);
});
// add the event listener so that when
// the realtime module adds messages to the collection
// from other mappers, it will update the UI
this.messages.on('add', function (message) {
Private.addMessage.call(self, message);
});
this.$button.on('click', function () {
Handlers.buttonClick.call(self);
});
this.$videoToggle.on('click', function () {
Handlers.videoToggleClick.call(self);
});
this.$cursorToggle.on('click', function () {
Handlers.cursorToggleClick.call(self);
});
this.$soundToggle.on('click', function () {
Handlers.soundToggleClick.call(self);
});
this.$messageInput.on('keyup', function (event) {
Handlers.keyUp.call(self, event);
});
this.$messageInput.on('focus', function () {
Handlers.inputFocus.call(self);
});
this.$messageInput.on('blur', function () {
Handlers.inputBlur.call(self);
});
},
initializeSounds: function() {
this.sound = new Howl({
urls: ['/assets/sounds/sounds.mp3', '/assets/sounds/sounds.ogg'],
sprite: {
laser: [3000, 700]
}
});
},
incrementUnread: function() {
this.unreadMessages++;
this.$unread.html(this.unreadMessages);
this.$unread.show();
},
addMessage: function(message) {
if (!this.isOpen) Private.incrementUnread.call(this);
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
var m = _.clone(message.attributes);
var today = new Date();
m.timestamp = new Date(m.timestamp);
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate();
date += " " + addZero(m.timestamp.getHours()) + ":" + addZero(m.timestamp.getMinutes());
m.timestamp = date;
m.image = m.image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png';
m.message = linker.link(m.message);
var $html = $(this.messageTemplate(m));
this.$messages.append($html);
this.scrollMessages(200);
if (this.alertSound) this.sound.play('laser');
},
initialMessages: function() {
var messages = this.messages.models;
for (var i = 0; i < messages.length; i++) {
Private.addMessage.call(this, messages[i]);
}
},
handleInputMessage: function() {
var message = {
message: this.$messageInput.val(),
timestamp: Date.now(),
user: this.mapper.get('name'),
image: this.mapper.get('image')
};
this.$messageInput.val('');
$(document).trigger(chatView.events.message + '-' + this.room, [message]);
},
addParticipant: function(participant) {
var p = _.clone(participant.attributes);
var html = this.participantTemplate(p);
this.$participants.append(html);
},
removeParticipant: function(participant) {
this.$container.find('.participant-' + participant.get('username')).remove();
}
};
var Handlers = {
buttonClick: function() {
if (this.isOpen) this.close();
else if (!this.isOpen) this.open();
},
videoToggleClick: function() {
this.$videoToggle.toggleClass('active');
},
cursorToggleClick: function() {
this.$cursorToggle.toggleClass('active');
},
soundToggleClick: function() {
this.alertSound = !this.alertSound;
this.$soundToggle.toggleClass('active');
},
keyUp: function(event) {
switch(event.which) {
case 13: // enter
Private.handleInputMessage.call(this);
break;
}
},
inputFocus: function() {
$(document).trigger(chatView.events.inputFocus);
},
inputBlur: function() {
$(document).trigger(chatView.events.inputBlur);
}
};
chatView = function(messages, mapper, room) {
var self = this;
this.room = room;
this.mapper = mapper;
this.messages = messages; // backbone collection
this.isOpen = false;
this.alertSound = false; // whether to play sounds on arrival of new messages or not
this.unreadMessages = 0;
this.participants = new Backbone.Collection();
Private.templates.call(this);
Private.createElements.call(this);
Private.attachElements.call(this);
Private.addEventListeners.call(this);
Private.initialMessages.call(this);
Private.initializeSounds.call(this);
};
chatView.prototype.addParticipant = function (participant) {
this.participants.add(participant);
}
chatView.prototype.removeParticipant = function (username) {
var p = this.participants.find(function (p) { return p.get('username') === username; });
if (p) {
this.participants.remove(p);
}
}
chatView.prototype.removeParticipants = function () {
this.participants.remove(this.participants.models);
}
chatView.prototype.open = function () {
this.$container.css({
right: '0'
});
this.$messageInput.focus();
this.isOpen = true;
this.unreadMessages = 0;
this.$unread.hide();
this.scrollMessages(0);
}
chatView.prototype.scrollMessages = function(duration) {
duration = duration || 0;
var
numMessages = this.$messages.find('.chat-message').length,
messageHeight = 52;
this.$messages.animate({
scrollTop: numMessages * messageHeight
}, duration);
}
chatView.prototype.close = function () {
this.$container.css({
right: '-300px'
});
this.$messageInput.blur();
this.isOpen = false;
}
chatView.prototype.remove = function () {
this.$button.off();
this.$container.remove();
}
/**
* @class
* @static
*/
chatView.events = {
message: 'ChatView:message',
inputFocus: 'ChatView:inputFocus',
inputBlur: 'ChatView:inputBlur'
};
return chatView;
})();

View file

@ -0,0 +1,111 @@
Metamaps.Views = Metamaps.Views || {};
Metamaps.Views.room = (function () {
var ChatView = Metamaps.Views.chatView;
var VideoView = Metamaps.Views.videoView;
var room = function(opts) {
var self = this;
this.isActiveRoom = false;
this.socket = opts.socket;
this.webrtc = opts.webrtc;
//this.roomRef = opts.firebase;
this.room = opts.room;
this.config = opts.config;
this.peopleCount = 0;
this.$myVideo = opts.$video;
this.myVideo = opts.myVideoView;
this.messages = new Backbone.Collection();
this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image });
this.chat = new ChatView(this.messages, this.currentMapper, this.room);
this.videos = {};
this.init();
};
room.prototype.join = function(cb) {
this.isActiveRoom = true;
this.webrtc.joinRoom(this.room, cb);
}
room.prototype.leave = function() {
for (var id in this.videos) {
this.removeVideo(id);
}
this.isActiveRoom = false;
this.webrtc.leaveRoom();
this.chat.removeParticipants();
}
room.prototype.setPeopleCount = function(count) {
this.peopleCount = count;
}
room.prototype.init = function () {
var self = this;
/*this.roomRef.child('messages').on('child_added', function (snap) {
self.messages.add(snap.val());
});*/
$(document).on(VideoView.events.audioControlClick, function (event, videoView) {
if (!videoView.audioStatus) self.webrtc.mute();
else if (videoView.audioStatus) self.webrtc.unmute();
});
$(document).on(VideoView.events.videoControlClick, function (event, videoView) {
if (!videoView.videoStatus) self.webrtc.pauseVideo();
else if (videoView.videoStatus) self.webrtc.resumeVideo();
});
this.webrtc.webrtc.off('peerStreamAdded');
this.webrtc.webrtc.off('peerStreamRemoved');
this.webrtc.on('peerStreamAdded', function (peer) {
if (self.isActiveRoom) {
self.addVideo(peer);
}
});
this.webrtc.on('peerStreamRemoved', function (peer) {
if (self.isActiveRoom) {
self.removeVideo(peer);
}
});
var sendChatMessage = function (event, data) {
self.sendChatMessage(data);
};
$(document).on(ChatView.events.message + '-' + this.room, sendChatMessage);
}
room.prototype.videoAdded = function (callback) {
this._videoAdded = callback;
}
room.prototype.addVideo = function (peer) {
var
id = this.webrtc.getDomId(peer),
video = attachMediaStream(peer.stream);
v = new VideoView(video, null, id, false, { DOUBLE_CLICK_TOLERANCE: 200 });
if (this._videoAdded) this._videoAdded(v);
this.videos[peer.id] = v;
}
room.prototype.removeVideo = function (peer) {
console.log(peer);
var id = typeof peer == 'string' ? peer : peer.id;
this.videos[id].remove();
delete this.videos[id];
}
room.prototype.sendChatMessage = function (data) {
//this.roomRef.child('messages').push(data);
}
return room;
})();

View file

@ -0,0 +1,182 @@
Metamaps.Views = Metamaps.Views || {};
Metamaps.Views.videoView = (function () {
var videoView;
var Private = {
addControls: function() {
var self = this;
this.$audioControl = $('<div class="video-audio"></div>');
this.$videoControl = $('<div class="video-video"></div>');
this.$audioControl.on('click', function () {
Handlers.audioControlClick.call(self);
});
this.$videoControl.on('click', function () {
Handlers.videoControlClick.call(self);
});
this.$container.append(this.$audioControl);
this.$container.append(this.$videoControl);
},
cancelClick: function() {
this.mouseIsDown = false;
if (this.hasMoved) {
}
$(document).trigger(videoView.events.dragEnd);
}
};
var Handlers = {
mousedown: function(event) {
this.mouseIsDown = true;
this.hasMoved = false;
this.mouseMoveStart = {
x: event.pageX,
y: event.pageY
};
this.posStart = {
x: parseInt(this.$container.css('left'), '10'),
y: parseInt(this.$container.css('top'), '10')
}
$(document).trigger(videoView.events.mousedown);
},
mouseup: function(event) {
$(document).trigger(videoView.events.mouseup, [this]);
var storedTime = this.lastClick;
var now = Date.now();
this.lastClick = now;
if (now - storedTime < this.config.DOUBLE_CLICK_TOLERANCE) {
$(document).trigger(videoView.events.doubleClick, [this]);
}
},
mousemove: function(event) {
var
diffX,
diffY,
newX,
newY;
if (this.$parent && this.mouseIsDown) {
this.hasMoved = true;
diffX = event.pageX - this.mouseMoveStart.x;
diffY = this.mouseMoveStart.y - event.pageY;
newX = this.posStart.x + diffX;
newY = this.posStart.y - diffY;
this.$container.css({
top: newY,
left: newX
});
}
},
audioControlClick: function() {
if (this.audioStatus) {
this.$audioControl.addClass('active');
} else {
this.$audioControl.removeClass('active');
}
this.audioStatus = !this.audioStatus;
$(document).trigger(videoView.events.audioControlClick, [this]);
},
videoControlClick: function() {
if (this.videoStatus) {
this.$videoControl.addClass('active');
this.$avatar.show();
} else {
this.$videoControl.removeClass('active');
this.$avatar.hide();
}
this.videoStatus = !this.videoStatus;
$(document).trigger(videoView.events.videoControlClick, [this]);
}
};
var videoView = function(video, $parent, id, isMyself, config) {
var self = this;
this.$parent = $parent; // mapView
this.video = video;
this.id = id;
this.config = config;
this.mouseIsDown = false;
this.mouseDownOffset = { x: 0, y: 0 };
this.lastClick = null;
this.hasMoved = false;
this.audioStatus = true;
this.videoStatus = true;
this.$container = $('<div></div>');
this.$container.addClass('collaborator-video' + (isMyself ? ' my-video' : ''));
this.$container.attr('id', 'container_' + id);
var $vidContainer = $('<div></div>');
$vidContainer.addClass('video-cutoff');
$vidContainer.append(this.video);
this.$avatar = $('<img draggable="false" class="collaborator-video-avatar" src="/assets/default_profile.png" width="150" height="150" />');
$vidContainer.append(this.$avatar);
this.$container.append($vidContainer);
this.$container.on('mousedown', function (event) {
Handlers.mousedown.call(self, event);
});
if (isMyself) Private.addControls.call(this);
// suppress contextmenu
this.video.oncontextmenu = function () { return false; };
if (this.$parent) this.setParent(this.$parent);
};
videoView.prototype.setParent = function($parent) {
var self = this;
this.$parent = $parent;
this.$parent.off('.video' + this.id);
this.$parent.on('mouseup.video' + this.id, function (event) {
Handlers.mouseup.call(self, event);
Private.cancelClick.call(self);
});
this.$parent.on('mousemove.video' + this.id, function (event) {
Handlers.mousemove.call(self, event);
});
}
videoView.prototype.remove = function () {
this.$container.off();
if (this.$parent) this.$parent.off('.video' + this.id);
this.$container.remove();
}
/**
* @class
* @static
*/
videoView.events = {
mousedown: "VideoView:mousedown",
mouseup: "VideoView:mouseup",
doubleClick: "VideoView:doubleClick",
dragEnd: "VideoView:dragEnd",
audioControlClick: "VideoView:audioControlClick",
videoControlClick: "VideoView:videoControlClick",
};
return videoView;
})();

View file

@ -78,7 +78,7 @@ html {
} }
body { body {
background: #d8d9da url(shattered_@2X.png); background: #d8d9da url(<%= asset_data_uri('shattered_@2X.png') %>);
font-family: 'din-medium', helvetica, sans-serif; font-family: 'din-medium', helvetica, sans-serif;
color: #424242; color: #424242;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
@ -300,7 +300,7 @@ input[type="submit"]:active {
display: none; display: none;
width: 40px; width: 40px;
height: 40px; height: 40px;
background-image: url(photo.png); background-image: url(<%= asset_data_uri('photo.png') %>);
position: absolute; position: absolute;
top: 22px; top: 22px;
left: 22px; left: 22px;
@ -413,7 +413,7 @@ input[type="submit"]:active {
} }
.accountName:hover .nameEdit:after { .accountName:hover .nameEdit:after {
background:url(edit.png)no-repeat; background: url(<%= asset_data_uri('edit.png') %>) no-repeat;
content:" "; content:" ";
position:absolute; position:absolute;
width:25px; width:25px;
@ -547,7 +547,7 @@ input[type="submit"]:active {
display: block; display: block;
height: 16px; height: 16px;
width: 16px; width: 16px;
background-image: url(metacodesettings_sprite.png); background-image: url(<%= asset_data_uri('metacodesettings_sprite.png') %>);
position: absolute; position: absolute;
z-index: 2; z-index: 2;
top: 20px; top: 20px;
@ -652,7 +652,7 @@ label {
box-shadow: 6px 6px 8px rgba(0, 0, 0, 0.4); box-shadow: 6px 6px 8px rgba(0, 0, 0, 0.4);
} }
.headertop .tab { .headertop .tab {
background: url(tab.png) no-repeat 0 0; background: url('tab.png') no-repeat 0 0;
position: absolute; position: absolute;
top: -11px; top: -11px;
right: -2px; right: -2px;
@ -719,7 +719,7 @@ label {
.accountInnerArrow { .accountInnerArrow {
width:16px; width:16px;
height:16px; height:16px;
background-image: url(arrowdown_sprite.png); background-image: url(<%= asset_data_uri('arrowdown_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
position:absolute; position:absolute;
top: 8px; top: 8px;
@ -783,7 +783,7 @@ label {
position:absolute; position:absolute;
pointer-events:none; pointer-events:none;
background-repeat:no-repeat; background-repeat:no-repeat;
background-image: url(user_sprite.png); background-image: url(<%= asset_data_uri('user_sprite.png') %>);
} }
.accountSettings .accountIcon { .accountSettings .accountIcon {
background-position: 0 0; background-position: 0 0;
@ -813,7 +813,7 @@ li.accountInvite span {
padding: 9px 0 9px 62px; padding: 9px 0 9px 62px;
} }
.accountImage { .accountImage {
background-image: url(user.png); background-image: url(<%= asset_data_uri 'user.png' %>);
background-size: 84px 84px; background-size: 84px 84px;
background-repeat: no-repeat; background-repeat: no-repeat;
height:84px; height:84px;
@ -1145,7 +1145,7 @@ h3.realtimeBoxTitle {
position: absolute; position: absolute;
top: 4px; top: 4px;
right: 0; right: 0;
background-image: url('junto24_sprite.png'); background-image: url(<%= asset_data_uri('junto24_sprite.png') %>);
} }
.realtimeMapperList .littleRtOff .littleJuntoIcon { .realtimeMapperList .littleRtOff .littleJuntoIcon {
background-position: 0 0; background-position: 0 0;
@ -1222,7 +1222,7 @@ h3.realtimeBoxTitle {
position: absolute; position: absolute;
top: 0; top: 0;
left: 4px; left: 4px;
background-image: url(context_sprite.png); background-image: url(<%= asset_data_uri('context_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -1238,7 +1238,7 @@ h3.realtimeBoxTitle {
} }
.rightclickmenu .rc-center .rc-icon { .rightclickmenu .rc-center .rc-icon {
background-image: url(context_topicview_sprite.png); background-image: url(<%= asset_data_uri('context_topicview_sprite.png') %>);
} }
.rightclickmenu .rc-popout .rc-icon { .rightclickmenu .rc-popout .rc-icon {
background-position: 0 -72px; background-position: 0 -72px;
@ -1251,7 +1251,7 @@ h3.realtimeBoxTitle {
} }
.rightclickmenu .rc-siblings .rc-icon { .rightclickmenu .rc-siblings .rc-icon {
background-position: 0 -24px; background-position: 0 -24px;
background-image: url(context_topicview_sprite.png); background-image: url(<%= asset_data_uri('context_topicview_sprite.png') %>);
} }
.rightclickmenu .expandLi { .rightclickmenu .expandLi {
position: absolute; position: absolute;
@ -1259,7 +1259,7 @@ h3.realtimeBoxTitle {
right: 8px; right: 8px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(arrowright_sprite.png); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 -32px; background-position: 0 -32px;
} }
@ -1294,7 +1294,7 @@ h3.realtimeBoxTitle {
position: absolute; position: absolute;
top: 0; top: 0;
left: 4px; left: 4px;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
background-size: 72px 48px; background-size: 72px 48px;
background-repeat: no-repeat; background-repeat: no-repeat;
width: 24px; width: 24px;
@ -1339,7 +1339,7 @@ h3.realtimeBoxTitle {
right: 4px; right: 4px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(arrowright_sprite.png); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 -32px; background-position: 0 -32px;
} }
@ -1373,13 +1373,14 @@ h3.realtimeBoxTitle {
/* topic and synapse autocomplete */ /* topic and synapse autocomplete */
#new_topic .tt-suggestion.tt-is-under-cursor, #new_topic .tt-suggestion:hover,
#new_topic .tt-suggestion.tt-is-under-mouse-cursor, #new_topic .tt-suggestion.tt-cursor,
#new_synapse .tt-suggestion.tt-is-under-cursor, #new_synapse .tt-suggestion:hover,
#new_synapse .tt-suggestion.tt-is-under-mouse-cursor { #new_synapse .tt-suggestion.tt-cursor {
background: #E0E0E0; background: #E0E0E0;
} }
#new_topic .tt-suggestion, #new_topic .tt-suggestion,
#new_synapse .tt-dataset h3,
#new_synapse .tt-suggestion { #new_synapse .tt-suggestion {
background: #F5F5F5; background: #F5F5F5;
position: relative; position: relative;
@ -1418,15 +1419,15 @@ h3.realtimeBoxTitle {
top: 8px; top: 8px;
right: 8px; right: 8px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url(arrowright_sprite.png); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-position: 0 -32px; background-position: 0 -32px;
} }
#new_topic .tt-suggestion.tt-is-under-cursor .expandTopicMetadata, #new_topic .tt-suggestion:hover .expandTopicMetadata,
#new_topic .tt-suggestion.tt-is-under-mouse-cursor .expandTopicMetadata { #new_topic .tt-suggestion.tt-cursor .expandTopicMetadata {
display: block; display: block;
} }
#new_topic .tt-suggestion.tt-is-under-cursor .topicMetadata, #new_topic .tt-suggestion:hover .topicMetadata,
#new_topic .tt-suggestion.tt-is-under-mouse-cursor .topicMetadata { #new_topic .tt-suggestion.tt-cursor .topicMetadata {
display: block; display: block;
} }
#new_topic .topicMetadata { #new_topic .topicMetadata {
@ -1444,7 +1445,7 @@ h3.realtimeBoxTitle {
width: 32px; width: 32px;
height: 32px; height: 32px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
position: absolute; position: absolute;
bottom: 4px; bottom: 4px;
right: 4px; right: 4px;
@ -1464,7 +1465,7 @@ h3.realtimeBoxTitle {
#new_topic .topicNumMaps { #new_topic .topicNumMaps {
height: 14px; height: 14px;
padding: 1px 0 1px 32px; padding: 1px 0 1px 32px;
background-image: url(metamap16.png); background-image: url(<%= asset_data_uri('metamap16.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 8px 0; background-position: 8px 0;
position: absolute; position: absolute;
@ -1473,7 +1474,7 @@ h3.realtimeBoxTitle {
#new_topic .topicNumSynapses { #new_topic .topicNumSynapses {
height: 14px; height: 14px;
padding: 1px 0 1px 32px; padding: 1px 0 1px 32px;
background-image: url(synapse16.png); background-image: url(<%= asset_data_uri('synapse16.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 8px 0; background-position: 8px 0;
position: absolute; position: absolute;
@ -1563,7 +1564,7 @@ h3.realtimeBoxTitle {
width: 32px; width: 32px;
height: 32px; height: 32px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
} }
/* map info box */ /* map info box */
/* map info box */ /* map info box */
@ -1603,7 +1604,7 @@ h3.realtimeBoxTitle {
resize: none; resize: none;
} }
.mapInfoBox.canEdit #mapInfoName:hover { .mapInfoBox.canEdit #mapInfoName:hover {
background-image: url(edit.png); background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: bottom right; background-position: bottom right;
cursor: text; cursor: text;
@ -1757,11 +1758,11 @@ h3.realtimeBoxTitle {
} }
.mapTopics { .mapTopics {
background-image: url(topic32.png); background-image: url(<%= asset_data_uri('topic32.png') %>);
background-position: 13px center; background-position: 13px center;
} }
.mapSynapses { .mapSynapses {
background-image: url(synapse32padded.png); background-image: url(<%= asset_data_uri('synapse32padded.png') %>);
background-position: 13px center; background-position: 13px center;
} }
.mapInfoBox .mapPermission { .mapInfoBox .mapPermission {
@ -1771,7 +1772,7 @@ h3.realtimeBoxTitle {
padding: 0; padding: 0;
margin: 8px 30px 8px 10px; margin: 8px 30px 8px 10px;
position: relative; position: relative;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
} }
.mapInfoBox .mapPermission.commons { .mapInfoBox .mapPermission.commons {
background-position: 0 0; background-position: 0 0;
@ -1783,12 +1784,12 @@ h3.realtimeBoxTitle {
background-position: -32px 0; background-position: -32px 0;
} }
.yourMap .mapPermission:hover { .yourMap .mapPermission:hover {
background-image: url(arrowperms_sprite.png); background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
cursor: pointer; cursor: pointer;
background-position: -32px 0; background-position: -32px 0;
} }
.yourMap .mapPermission.minimize { .yourMap .mapPermission.minimize {
background-image: url(arrowperms_sprite.png) !important; background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
cursor: pointer; cursor: pointer;
background-position: 0 0; background-position: 0 0;
} }
@ -1803,7 +1804,7 @@ h3.realtimeBoxTitle {
width: 32px; width: 32px;
height: 32px; height: 32px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
} }
.mapInfoBox .mapPermission .permissionSelect .commons { .mapInfoBox .mapPermission .permissionSelect .commons {
background-position: 0 0; background-position: 0 0;
@ -1850,7 +1851,7 @@ h3.realtimeBoxTitle {
width: 340px; width: 340px;
} }
.mapInfoBox.canEdit .mapInfoDesc:hover { .mapInfoBox.canEdit .mapInfoDesc:hover {
background-image: url(edit.png); background-image: url(<%= asset_data_uri('edit.png') %>);
background-position: top right; background-position: top right;
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: text; cursor: text;
@ -1895,7 +1896,7 @@ h3.realtimeBoxTitle {
.mapInfoShareIcon { .mapInfoShareIcon {
width: 24px; width: 24px;
height: 24px; height: 24px;
background-image: url(share_sprite_mapinfo.png); background-image: url(<%= asset_data_uri('share_sprite_mapinfo.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
margin: 4px auto 0; margin: 4px auto 0;
background-position: 0 -24px; background-position: 0 -24px;
@ -1916,7 +1917,7 @@ and it won't be important on password protected instances */
width: 16px; width: 16px;
height: 16px; height: 16px;
margin: 8px auto 0; margin: 8px auto 0;
background-image: url(remove_mapinfo_sprite.png); background-image: url(<%= asset_data_uri('remove_mapinfo_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: -16px 0; background-position: -16px 0;
} }
@ -1977,7 +1978,7 @@ and it won't be important on password protected instances */
border: solid 2px #000; border: solid 2px #000;
} }
#lightbox_overlay #lightbox_main a#lightbox_close { #lightbox_overlay #lightbox_main a#lightbox_close {
background-image: url(xlightbox.png); background-image: url(<%= asset_data_uri('xlightbox.png') %>);
cursor: pointer; cursor: pointer;
height: 32px; height: 32px;
outline-style: none; outline-style: none;
@ -2076,7 +2077,7 @@ and it won't be important on password protected instances */
color: #00bcd4; color: #00bcd4;
} }
.lightbox_links .lightboxAboutIcon { .lightbox_links .lightboxAboutIcon {
background-image: url(about_sprite.png); background-image: url(<%= asset_data_uri('about_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
@ -2351,15 +2352,15 @@ and it won't be important on password protected instances */
opacity: 0.7; opacity: 0.7;
} }
#chromeIcon { #chromeIcon {
background: url(/assets/browser_icons.png) no-repeat; background: url(<%= asset_data_uri 'browser_icons.png' %>) no-repeat;
} }
#fireFoxIcon { #fireFoxIcon {
background: url(/assets/browser_icons.png) no-repeat -105px 0; background: url(<%= asset_data_uri 'browser_icons.png' %>) no-repeat -105px 0;
} }
#safariIcon { #safariIcon {
background: url(/assets/browser_icons.png) no-repeat -220px 0; background: url(<%= asset_data_uri 'browser_icons.png' %>) no-repeat -220px 0;
} }
#chromeIcon:hover{ #chromeIcon:hover{
@ -2496,7 +2497,7 @@ and it won't be important on password protected instances */
position: relative; position: relative;
} }
.new_map .mapPermIcon { .new_map .mapPermIcon {
background-image: url(permissions64sprite.png); background-image: url(<%= asset_data_uri('permissions64sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
width:64px; width:64px;
height:64px; height:64px;
@ -2611,7 +2612,7 @@ and it won't be important on password protected instances */
} }
#zoomIn { #zoomIn {
background: #424242 url(zoom_sprite.png) no-repeat; background: #424242 url(<%= asset_data_uri('zoom_sprite.png') %>) no-repeat;
width: 22px; width: 22px;
height: 22px; height: 22px;
display: inline-block; display: inline-block;
@ -2623,7 +2624,7 @@ and it won't be important on password protected instances */
} }
#zoomOut { #zoomOut {
background: #424242 url(zoom_sprite.png) no-repeat; background: #424242 url(<%= asset_data_uri('zoom_sprite.png') %>) no-repeat;
width: 22px; width: 22px;
height: 22px; height: 22px;
display: inline-block; display: inline-block;
@ -2635,7 +2636,7 @@ and it won't be important on password protected instances */
} }
#centerMap { #centerMap {
background: #424242 url(extents_sprite.png) no-repeat; background: #424242 url(<%= asset_data_uri('extents_sprite.png') %>) no-repeat;
width: 22px; width: 22px;
height: 22px; height: 22px;
display: inline-block; display: inline-block;
@ -2940,7 +2941,7 @@ and it won't be important on password protected instances */
.compassArrow { .compassArrow {
display: none; display: none;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url(compass_arrow.png); background-image: url(<%= asset_data_uri('compass_arrow.png') %>);
width: 48px; width: 48px;
height: 32px; height: 32px;
position: absolute; position: absolute;

View file

@ -85,7 +85,7 @@
padding: 0 16px; padding: 0 16px;
} }
.canEdit #titleActivator:hover { .canEdit #titleActivator:hover {
background-image: url(edit.png); background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: bottom right; background-position: bottom right;
cursor: text; cursor: text;
@ -148,7 +148,7 @@
margin-right: 8px; margin-right: 8px;
} }
.canEdit .CardOnGraph .best_in_place_desc:hover { .canEdit .CardOnGraph .best_in_place_desc:hover {
background-image: url(edit.png); background-image: url(<%= asset_data_uri('edit.png') %>);
background-position: top right; background-position: top right;
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: text; cursor: text;
@ -244,7 +244,7 @@
left: 0; left: 0;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url(map32_sprite.png); background-image: url(<%= asset_data_uri('map32_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
cursor: pointer; cursor: pointer;
@ -335,7 +335,7 @@
left: 0; left: 0;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url(synapse32_sprite.png); background-image: url(<%= asset_data_uri('synapse32_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
} }
@ -382,7 +382,7 @@
min-width: 32px; min-width: 32px;
margin-top: 8px; margin-top: 8px;
margin-left: 8px; margin-left: 8px;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
background-position: 0 0; background-position: 0 0;
} }
.mapPerm.co { .mapPerm.co {
@ -396,12 +396,12 @@
} }
.yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover { .yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover {
background-image: url(arrowperms_sprite.png); background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
background-position: -32px 0; background-position: -32px 0;
cursor:pointer; cursor:pointer;
} }
.yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize { .yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize {
background-image: url(arrowperms_sprite.png) !important; background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
background-position: 0 0; background-position: 0 0;
cursor: pointer; cursor: pointer;
} }
@ -417,7 +417,7 @@ cursor: pointer;
height: 32px; height: 32px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
} }
.mapPerm .permissionSelect .commons { .mapPerm .permissionSelect .commons {
background-position: 0 0; background-position: 0 0;
@ -462,7 +462,7 @@ cursor: pointer;
right: 16px; right: 16px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(arrowright_sprite.png); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 -32px; background-position: 0 -32px;
} }
@ -542,7 +542,7 @@ background-color: #E0E0E0;
right: 8px; right: 8px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(arrowright_sprite.png); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 -32px; background-position: 0 -32px;
} }
@ -648,10 +648,10 @@ background-color: #E0E0E0;
left: 12px; left: 12px;
} }
#linkIcon { #linkIcon {
background-image: url(link_sprite.png); background-image: url(<%= asset_data_uri('link_sprite.png') %>);
} }
#uploadIcon { #uploadIcon {
background-image: url(upload_sprite.png); background-image: url(<%= asset_data_uri('upload_sprite.png') %>);
} }
#addlink:hover #linkIcon, #addupload:hover #uploadIcon { #addlink:hover #linkIcon, #addupload:hover #uploadIcon {
background-position: 0 -24px; background-position: 0 -24px;
@ -690,7 +690,7 @@ font-family: 'din-regular', helvetica, sans-serif;
height: 24px; height: 24px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
background-image: url(link_sprite.png); background-image: url(<%= asset_data_uri('link_sprite.png') %>);
pointer-events: none; pointer-events: none;
z-index: 1; z-index: 1;
} }
@ -703,7 +703,7 @@ font-family: 'din-regular', helvetica, sans-serif;
height: 32px; height: 32px;
cursor: pointer; cursor: pointer;
float:none; float:none;
background-image: url(remove.png); background-image: url(<%= asset_data_uri('remove.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
} }
@ -740,7 +740,7 @@ font-family: 'din-regular', helvetica, sans-serif;
} }
#linkremove { #linkremove {
background-image: url(/assets/remove.png); background-image: url(<%= asset_data_uri 'remove.png' %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
width: 24px; width: 24px;
@ -781,7 +781,7 @@ font-family: 'din-regular', helvetica, sans-serif;
} }
#editSynUpperBar { #editSynUpperBar {
background: #FFFFFF url(synapse32.png) no-repeat 8px center; background: #FFFFFF url(<%= asset_data_uri('synapse32.png') %>) no-repeat 8px center;
min-height: 48px; min-height: 48px;
height: 48px; height: 48px;
border-bottom: 1px solid #222222; border-bottom: 1px solid #222222;
@ -814,7 +814,7 @@ font-family: 'din-regular', helvetica, sans-serif;
} }
.canEdit #edit_synapse_desc:hover { .canEdit #edit_synapse_desc:hover {
background-image: url(edit.png); background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 164px center; background-position: 164px center;
cursor: text; cursor: text;
@ -841,7 +841,7 @@ font-family: 'din-regular', helvetica, sans-serif;
height: 24px; height: 24px;
top: 12px; top: 12px;
right: 8px; right: 8px;
background-image: url(arrowdown_sprite.png); background-image: url(<%= asset_data_uri('arrowdown_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 4px -12px; background-position: 4px -12px;
} }
@ -923,11 +923,11 @@ font-family: 'din-regular', helvetica, sans-serif;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
#edit_synapse_right { #edit_synapse_right {
background-image: url(synapsedirectionright_sprite.png); background-image: url(<%= asset_data_uri('synapsedirectionright_sprite.png') %>);
right: 16px; right: 16px;
} }
#edit_synapse_left { #edit_synapse_left {
background-image: url(synapsedirectionleft_sprite.png); background-image: url(<%= asset_data_uri('synapsedirectionleft_sprite.png') %>);
right: 56px; right: 56px;
} }
#edit_synapse_left.checked, #edit_synapse_right.checked { #edit_synapse_left.checked, #edit_synapse_right.checked {
@ -1103,7 +1103,7 @@ font-family: 'din-regular', helvetica, sans-serif;
} }
.mapperMetadata { .mapperMetadata {
background: url(profile_card_sprite.png) no-repeat center 0; background: url(<%= asset_data_uri('profile_card_sprite.png') %>) no-repeat center 0;
height: 64px; height: 64px;
width: 160px; width: 160px;
margin: 16px auto 0; margin: 16px auto 0;
@ -1126,4 +1126,4 @@ font-family: 'din-regular', helvetica, sans-serif;
} }
.mapperMetadata .metadataSynapses { .mapperMetadata .metadataSynapses {
color: #DAB539; color: #DAB539;
} }

View file

@ -1,20 +1,20 @@
@font-face { @font-face {
font-family: 'din-medium'; font-family: 'din-medium';
src: url('/assets/Fonts/din.eot'); src: url(<%= asset_path 'Fonts/din.eot' %>);
src: url('/assets/Fonts/din.eot?#iefix') format('embedded-opentype'), src: url(<%= asset_path 'Fonts/din.eot?#iefix' %>) format('embedded-opentype'),
url('/assets/Fonts/din.woff') format('woff'), url(<%= asset_path 'Fonts/din.woff' %>) format('woff'),
url('/assets/Fonts/din.ttf') format('truetype'), url(<%= asset_path 'Fonts/din.ttf' %>) format('truetype'),
url('/assets/Fonts/din.svg#din-medium') format('svg'); url(<%= asset_path 'Fonts/din.svg#din-medium' %>) format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'din-regular'; font-family: 'din-regular';
src: url('/assets/Fonts/din-reg.eot'); src: url(<%= asset_path 'Fonts/din-reg.eot' %>);
src: url('/assets/Fonts/din-reg.eot?#iefix') format('embedded-opentype'), src: url(<%= asset_path 'Fonts/din-reg.eot?#iefix' %>) format('embedded-opentype'),
url('/assets/Fonts/din-reg.woff') format('woff'), url(<%= asset_path 'Fonts/din-reg.woff' %>) format('woff'),
url('/assets/Fonts/din-reg.ttf') format('truetype'), url(<%= asset_path 'Fonts/din-reg.ttf' %>) format('truetype'),
url('/assets/Fonts/din-reg.svg#din-reg') format('svg'); url(<%= asset_path 'Fonts/din-reg.svg#din-reg' %>) format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -134,7 +134,7 @@
width: 40px; width: 40px;
height: 32px; height: 32px;
background-color: #757575; background-color: #757575;
background-image: url(home_light.png); background-image: url(<%= asset_data_uri('home_light.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
border-top-left-radius: 2px; border-top-left-radius: 2px;
@ -142,7 +142,7 @@
float:left; float:left;
} }
.homeButton:hover { .homeButton:hover {
background-image: url(home_light.png); background-image: url(<%= asset_data_uri('home_light.png') %>);
} }
.homeButton a { .homeButton a {
display:block; display:block;
@ -176,7 +176,7 @@
border-top-right-radius: 2px; border-top-right-radius: 2px;
border-bottom-right-radius: 2px; border-bottom-right-radius: 2px;
height: 32px; height: 32px;
background: #4fb5c0 url('search.png') no-repeat center center; background: #4fb5c0 url(<%= asset_data_uri('search.png') %>) no-repeat center center;
background-size: 32px 32px; background-size: 32px 32px;
cursor: pointer; cursor: pointer;
} }
@ -288,7 +288,7 @@
.sidebarSearch .tt-dropdown-menu .minimizeResults, .sidebarSearch .tt-dropdown-menu .maximizeResults { .sidebarSearch .tt-dropdown-menu .minimizeResults, .sidebarSearch .tt-dropdown-menu .maximizeResults {
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url(arrowpermswhite_sprite.png); background-image: url(<%= asset_data_uri('arrowpermswhite_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
@ -301,7 +301,7 @@
.sidebarSearch .tt-dropdown-menu .maximizeResults { .sidebarSearch .tt-dropdown-menu .maximizeResults {
background-position: -32px 0; background-position: -32px 0;
} }
.sidebarSearch .tt-suggestions { .sidebarSearch .tt-dataset {
overflow: visible; overflow: visible;
} }
.sidebarSearch .tt-suggestion { .sidebarSearch .tt-suggestion {
@ -310,7 +310,7 @@
padding: 8px 0; padding: 8px 0;
} }
.sidebarSearch .tt-is-under-cursor, .sidebarSearch .tt-is-under-cursor,
.sidebarSearch .tt-is-under-mouse-cursor { .sidebarSearch .tt-suggestion:hover {
background: #E0E0E0; background: #E0E0E0;
} }
@ -425,7 +425,7 @@
display:none; display:none;
width: 24px; width: 24px;
height: 24px; height: 24px;
background: url(addtopic_sprite.png); background: url(<%= asset_data_uri('addtopic_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 48px 24px; background-size: 48px 24px;
top: 12px; top: 12px;
@ -442,7 +442,7 @@
.sidebarSearch div.topicCount { .sidebarSearch div.topicCount {
width: 24px; width: 24px;
height: 24px; height: 24px;
background: url(topic16.png); background: url(<%= asset_data_uri('topic16.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 center; background-position: 0 center;
top: 0; top: 0;
@ -455,7 +455,7 @@
.sidebarSearch div.mapCount { .sidebarSearch div.mapCount {
width: 24px; width: 24px;
height: 24px; height: 24px;
background: url(metamap16.png); background: url(<%= asset_data_uri('metamap16.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 center; background-position: 0 center;
left: 0; left: 0;
@ -466,7 +466,7 @@
.sidebarSearch div.synapseCount { .sidebarSearch div.synapseCount {
width: 24px; width: 24px;
height: 24px; height: 24px;
background: url(synapse16.png); background: url(<%= asset_data_uri('synapse16.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 center; background-position: 0 center;
top: 24px; top: 24px;
@ -573,7 +573,7 @@
.sidebarSearch div.mapPermission { .sidebarSearch div.mapPermission {
width: 24px; width: 24px;
height: 24px; height: 24px;
background-image: url(permissions32_sprite.png); background-image: url(<%= asset_data_uri('permissions32_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 72px 48px !important; background-size: 72px 48px !important;
top: 24px; top: 24px;
@ -665,7 +665,7 @@
.upperRightIcon { .upperRightIcon {
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url('topright_sprite.png'); background-image: url(<%= asset_data_uri('topright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
} }
@ -816,12 +816,12 @@
} }
.fullWidthWrapper.withPartners { .fullWidthWrapper.withPartners {
background: url(homepage_bg_fade.png) no-repeat center -300px; background: url(<%= asset_data_uri('homepage_bg_fade.png') %>) no-repeat center -300px;
} }
.homeWrapper.homePartners { .homeWrapper.homePartners {
padding: 64px 0 280px; padding: 64px 0 280px;
height: 96px; height: 96px;
background: url(partner_logos.png) no-repeat 0 64px; background: url(<%= asset_data_uri('partner_logos.png') %>) no-repeat 0 64px;
} }
.github-fork-ribbon-wrapper { .github-fork-ribbon-wrapper {
@ -863,7 +863,7 @@
cursor: pointer; cursor: pointer;
} }
.openCheatsheet { .openCheatsheet {
background-image: url('help_sprite.png'); background-image: url(<%= asset_data_uri('help_sprite.png') %>);
background-repeat:no-repeat; background-repeat:no-repeat;
} }
.openCheatsheet:hover { .openCheatsheet:hover {
@ -872,7 +872,7 @@
.mapInfoIcon { .mapInfoIcon {
position: relative; position: relative;
top: 56px; /* puts it just offscreen */ top: 56px; /* puts it just offscreen */
background-image: url('mapinfo_sprite.png'); background-image: url(<%= asset_data_uri('mapinfo_sprite.png') %>);
background-repeat:no-repeat; background-repeat:no-repeat;
} }
.mapInfoIcon:hover { .mapInfoIcon:hover {
@ -918,7 +918,7 @@
.takeScreenshot { .takeScreenshot {
margin-bottom: 5px; margin-bottom: 5px;
border-radius: 2px; border-radius: 2px;
background-image: url(screenshot_sprite.png); background-image: url(<%= asset_data_uri 'screenshot_sprite.png' %>);
display: none; display: none;
} }
.takeScreenshot:hover { .takeScreenshot:hover {
@ -931,7 +931,7 @@
.zoomExtents { .zoomExtents {
margin-bottom:5px; margin-bottom:5px;
border-radius: 2px; border-radius: 2px;
background-image: url(extents_sprite.png); background-image: url(<%= asset_data_uri('extents_sprite.png') %>);
} }
.zoomExtents:hover { .zoomExtents:hover {
@ -1076,7 +1076,7 @@
} }
.zoomIn { .zoomIn {
background-image: url(zoom_sprite.png); background-image: url(<%= asset_data_uri('zoom_sprite.png') %>);
background-position: 0 /…0; background-position: 0 /…0;
border-top-left-radius: 2px; border-top-left-radius: 2px;
border-top-right-radius: 2px; border-top-right-radius: 2px;
@ -1085,7 +1085,7 @@
background-position: -32px 0; background-position: -32px 0;
} }
.zoomOut { .zoomOut {
background-image: url(zoom_sprite.png); background-image: url(<%= asset_data_uri('zoom_sprite.png') %>);
background-position:0 -32px; background-position:0 -32px;
border-bottom-left-radius: 2px; border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px; border-bottom-right-radius: 2px;
@ -1163,15 +1163,15 @@
left:5px; left:5px;
} }
.exploreMapsCenter .myMaps .exploreMapsIcon { .exploreMapsCenter .myMaps .exploreMapsIcon {
background-image: url(exploremaps_sprite.png); background-image: url(<%= asset_data_uri 'exploremaps_sprite.png' %>);
background-position: 0 0; background-position: 0 0;
} }
.exploreMapsCenter .activeMaps .exploreMapsIcon { .exploreMapsCenter .activeMaps .exploreMapsIcon {
background-image: url(exploremaps_sprite.png); background-image: url(<%= asset_data_uri 'exploremaps_sprite.png' %>);
background-position: -32px 0; background-position: -32px 0;
} }
.exploreMapsCenter .featuredMaps .exploreMapsIcon { .exploreMapsCenter .featuredMaps .exploreMapsIcon {
background-image: url(exploremaps_sprite.png); background-image: url(<%= asset_data_uri 'exploremaps_sprite.png' %>);
background-position: -64px 0; background-position: -64px 0;
} }
.myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon { .myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon {
@ -1212,7 +1212,7 @@
/* feedback */ /* feedback */
body a#barometer_tab { body a#barometer_tab {
background-image: url(feedback_sprite.png); background-image: url(<%= asset_path 'feedback_sprite.png' %>);
background-position: 0 0; background-position: 0 0;
background-color: transparent; background-color: transparent;
height: 110px; height: 110px;
@ -1227,4 +1227,4 @@ box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
body a#barometer_tab:hover { body a#barometer_tab:hover {
background-position: 0 -110px; background-position: 0 -110px;
} }

View file

@ -243,25 +243,25 @@ body .ui-tooltip { border-width: 2px; }
.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; } .ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
.ui-widget .ui-widget { font-size: 1em; } .ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; } .ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(<%= asset_data_uri('ui-bg_flat_75_ffffff_40x100.png') %>)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
.ui-widget-content a { color: #222222/*{fcContent}*/; } .ui-widget-content a { color: #222222/*{fcContent}*/; }
.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; } .ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(<%= asset_data_uri('images/ui-bg_highlight-soft_75_cccccc_1x100.png') %>)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
.ui-widget-header a { color: #222222/*{fcHeader}*/; } .ui-widget-header a { color: #222222/*{fcHeader}*/; }
/* Interaction states /* Interaction states
----------------------------------*/ ----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; } .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_e6e6e6_1x400.png') %>)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 0px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; } .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 0px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_dadada_1x400.png') %>)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121/*{fcHover}*/; text-decoration: none; } .ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121/*{fcHover}*/; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; } .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(<%= asset_data_uri('images/ui-bg_glass_65_ffffff_1x400.png') %>)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
/* Interaction Cues /* Interaction Cues
----------------------------------*/ ----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; } .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(<%= asset_data_uri('images/ui-bg_glass_55_fbf9ee_1x400.png') %>)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; } .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(<%= asset_data_uri('images/ui-bg_glass_95_fef1ec_1x400.png') %>)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
@ -273,14 +273,14 @@ body .ui-tooltip { border-width: 2px; }
----------------------------------*/ ----------------------------------*/
/* states and images */ /* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } .ui-icon { width: 16px; height: 16px; background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } .ui-widget-content .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } .ui-widget-header .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsHeader}*/; }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } .ui-state-default .ui-icon { background-image: url(<%= asset_data_uri('images/ui-icons_888888_256x240.png') %>)/*{iconsDefault}*/; }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; } .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsHover}*/; }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } .ui-state-active .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsActive}*/; }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; } .ui-state-highlight .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_2e83ff_256x240.png') %>)/*{iconsHighlight}*/; }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; } .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_cd0a0a_256x240.png') %>)/*{iconsError}*/; }
/* positioning */ /* positioning */
.ui-icon-carat-1-n { background-position: 0 0; } .ui-icon-carat-1-n { background-position: 0 0; }
@ -470,5 +470,5 @@ body .ui-tooltip { border-width: 2px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
/* Overlays */ /* Overlays */
.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(<%= asset_data_uri('images/ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } .ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/<%= asset_data_uri('ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }

View file

@ -162,7 +162,7 @@
.mCSB_scrollTools .mCSB_buttonDown, .mCSB_scrollTools .mCSB_buttonDown,
.mCSB_scrollTools .mCSB_buttonLeft, .mCSB_scrollTools .mCSB_buttonLeft,
.mCSB_scrollTools .mCSB_buttonRight{ .mCSB_scrollTools .mCSB_buttonRight{
background-image:url(mCSB_buttons.png); background-image:url(<%= asset_data_uri('mCSB_buttons.png') %>);
background-repeat:no-repeat; background-repeat:no-repeat;
opacity:0.4; opacity:0.4;
filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */ filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */
@ -471,4 +471,4 @@
} }
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonRight{ .mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonRight{
background-position:-80px -56px; background-position:-80px -56px;
} }

View file

@ -0,0 +1,265 @@
.collaborator-video {
z-index: 2;
position: absolute;
width: 150px;
height: 150px;
cursor: default;
color: #FFF;
}
.collaborator-video .video-cutoff {
width: 150px;
height: 150px;
overflow: hidden;
border-radius: 75px;
z-index: 0;
position: relative;
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
}
.collaborator-video .video-cutoff video {
height: 150px;
margin-left: -25px;
}
.collaborator-video .video-cutoff .collaborator-video-avatar {
position: absolute;
top: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
-webkit-user-drag: none;
display: none;
}
.collaborator-video .video-audio {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
right: 0px;
cursor: pointer;
background: url(audio_sprite.png) no-repeat;
}
.collaborator-video .video-audio:hover {
background-position-x: -24px;
}
.collaborator-video .video-audio.active {
background-position-y: -24px;
}
.collaborator-video .video-video {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
left: 0px;
cursor: pointer;
background: url(camera_sprite.png) no-repeat;
}
.collaborator-video .video-video:hover {
background-position-x: -24px;
}
.collaborator-video .video-video.active {
background-position-y: -24px;
}
.collaborator-video.my-video {
left: 50px;
top: 50px;
}
.chat-box {
position: absolute;
z-index: 1;
right: -300px;
width: 300px;
height: 100%;
background: #424242;
box-shadow: 0px 0px 16px 8px rgba(0, 0, 0, 0.23), -2px 10px 10px rgba(0, 0, 0, 0.19);
}
.chat-box .chat-button {
position: absolute;
top: 50%;
left: -36px;
width: 36px;
height: 49px;
background: url(junto.png) no-repeat 2px 9px, url(tray_tab.png) no-repeat;
}
.chat-box .chat-button .chat-unread {
display: none;
background: #DAB539;
position: absolute;
top: -3px;
left: -11px;
width: 20px;
height: 20px;
border-radius: 11px;
border: 2px solid #424242;
color: #424242;
text-align: center;
font-size: 12px;
font-weight: bold;
line-height: 20px;
}
.chat-box .junto-header {
width: 100%;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
}
.chat-box .junto-header .cursor-toggle {
width: 32px;
height: 32px;
margin-right: 8px;
margin-top: -8px;
float: right;
background: url(cursor_sprite.png) no-repeat;
}
.chat-box .junto-header .cursor-toggle:hover {
background-position-x: -32px;
}
.chat-box .junto-header .cursor-toggle.active {
background-position-y: -32px;
}
.chat-box .junto-header .video-toggle {
width: 32px;
height: 32px;
margin-right: 32px;
margin-top: -8px;
float: right;
background: url(video_sprite.png) no-repeat;
}
.chat-box .junto-header .video-toggle:hover {
background-position-x: -32px;
}
.chat-box .junto-header .video-toggle.active {
background-position-y: -32px;
}
.chat-box .participants {
width: 100%;
height: 150px;
padding: 16px 0px 0px 0px;
text-align: left;
color: #f5f5f5;
overflow-y: auto;
}
.chat-box .participants .participant {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
}
.chat-box .participants .participant .chat-participant-image {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-box .participants .participant .chat-participant-image img {
border: 2px solid #424242;
width: 32px;
height: 32px;
border-radius: 18px;
cursor: pointer;
}
.chat-box .participants .participant .chat-participant-name {
width: 73%;
float: left;
font-size: 13px;
font-weight: bold;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-box .chat-header {
width: 100%;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
}
.chat-box .chat-header .sound-toggle {
width: 24px;
height: 24px;
margin-right: 32px;
margin-top: -2px;
float: right;
background: url(sound_sprite.png) no-repeat;
}
.chat-box .chat-header .sound-toggle:hover {
background-position-x: -24px;
}
.chat-box .chat-header .sound-toggle.active {
background-position-y: -24px;
}
.chat-box .chat-input {
position: absolute;
bottom: 0;
left: 0;
height: 80px;
width: 100%;
padding: 8px 8px 8px 8px;
font-size: 13px;
outline: none;
}
.chat-box .chat-messages {
width: 100%;
height: 196px;
padding: 16px 0px 0px 0px;
overflow-y: auto;
}
.chat-box .chat-messages .chat-message {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
}
.chat-box .chat-messages .chat-message a:link {
color: #4fb5c0;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message a:visited {
color: #aea9fd;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message a:hover {
color: #dab539;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message .chat-message-user {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-box .chat-messages .chat-message .chat-message-user img {
border: 2px solid #424242;
width: 32px;
height: 32px;
border-radius: 18px;
cursor: pointer;
}
.chat-box .chat-messages .chat-message .chat-message-text {
width: 73%;
float: left;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-box .chat-messages .chat-message .chat-message-time {
float: right;
font-size: 10px;
color: #757575;
}

View file

@ -6,7 +6,7 @@
} }
div.uv-icon.uv-bottom-left { div.uv-icon.uv-bottom-left {
background-image:url(feedback_sprite.png); background-image:url(<%= asset_data_uri 'feedback_sprite.png' %>);
background-repeat: no-repeat; background-repeat: no-repeat;
color:#FFFFFF; color:#FFFFFF;
cursor:pointer; cursor:pointer;
@ -22,4 +22,4 @@ div.uv-icon.uv-bottom-left {
div.uv-icon.uv-bottom-left:hover { div.uv-icon.uv-bottom-left:hover {
background-position: 0 -110px; background-position: 0 -110px;
} }

View file

@ -37,7 +37,7 @@ private
end end
def require_admin def require_admin
unless authenticated? && user.admin unless authenticated? && admin?
redirect_to root_url, notice: "You need to be an admin for that." redirect_to root_url, notice: "You need to be an admin for that."
return false return false
end end

View file

@ -68,25 +68,20 @@ class MainController < ApplicationController
else else
search = term.downcase + '%' search = term.downcase + '%'
if !user if user
@topics = Topic.where('LOWER("name") like ?', search).where('metacode_id = ?', filterByMetacode.id).order('"name"') @topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
@topics2 = Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"') @topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
@topics3 = Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"') @topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
@topics4 = Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"') @topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
@topics = @topics + (@topics2 - @topics) else
@topics = @topics + (@topics3 - @topics) @topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
@topics = @topics + (@topics4 - @topics) @topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
@topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
elsif user @topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
@topics = Topic.where('LOWER("name") like ?', search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')
@topics2 = Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')
@topics3 = Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')
@topics4 = Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')
@topics = @topics + (@topics2 - @topics)
@topics = @topics + (@topics3 - @topics)
@topics = @topics + (@topics4 - @topics)
end end
#get unique elements only through the magic of Sets
@topics = (@topics + @topics2 + @topics3 + @topics4).to_a
end end
elsif desc elsif desc
search = '%' + term.downcase + '%' search = '%' + term.downcase + '%'
@ -127,7 +122,7 @@ class MainController < ApplicationController
end end
#read this next line as 'delete a topic if its private and you're either 1. logged out or 2. logged in but not the topic creator #read this next line as 'delete a topic if its private and you're either 1. logged out or 2. logged in but not the topic creator
@topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
render json: autocomplete_array_json(@topics) render json: autocomplete_array_json(@topics)
end end
@ -163,7 +158,7 @@ class MainController < ApplicationController
end end
#read this next line as 'delete a map if its private and you're either 1. logged out or 2. logged in but not the map creator #read this next line as 'delete a map if its private and you're either 1. logged out or 2. logged in but not the map creator
@maps.delete_if {|m| m.permission == "private" && (!authenticated? || (authenticated? && @current.id != m.user_id)) } @maps.to_a.delete_if {|m| m.permission == "private" && (!authenticated? || (authenticated? && @current.id != m.user_id)) }
render json: autocomplete_map_array_json(@maps) render json: autocomplete_map_array_json(@maps)
end end
@ -192,14 +187,14 @@ class MainController < ApplicationController
term = params[:term] term = params[:term]
topic1id = params[:topic1id] topic1id = params[:topic1id]
topic2id = params[:topic2id] topic2id = params[:topic2id]
if term && !term.empty? if term && !term.empty?
@synapses = Synapse.select('DISTINCT "desc"').where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"') @synapses = Synapse.where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"')
# remove any duplicate synapse types that just differ by # remove any duplicate synapse types that just differ by
# leading or trailing whitespaces # leading or trailing whitespaces
collectedDesc = [] collectedDesc = []
@synapses.delete_if {|s| @synapses.to_a.uniq(&:desc).delete_if {|s|
desc = s.desc == nil || s.desc == "" ? "" : s.desc.strip desc = s.desc == nil || s.desc == "" ? "" : s.desc.strip
if collectedDesc.index(desc) == nil if collectedDesc.index(desc) == nil
collectedDesc.push(desc) collectedDesc.push(desc)
@ -211,23 +206,20 @@ class MainController < ApplicationController
#limit to 5 results #limit to 5 results
@synapses = @synapses.slice(0,5) @synapses = @synapses.slice(0,5)
render json: autocomplete_synapse_generic_json(@synapses)
elsif topic1id && !topic1id.empty? elsif topic1id && !topic1id.empty?
@one = Synapse.where('node1_id = ? AND node2_id = ?', topic1id, topic2id) @one = Synapse.where('node1_id = ? AND node2_id = ?', topic1id, topic2id)
@two = Synapse.where('node2_id = ? AND node1_id = ?', topic1id, topic2id) @two = Synapse.where('node2_id = ? AND node1_id = ?', topic1id, topic2id)
@synapses = @one + @two @synapses = @one + @two
@synapses.sort! {|s1,s2| s1.desc <=> s2.desc } @synapses.sort! {|s1,s2| s1.desc <=> s2.desc }.to_a
#read this next line as 'delete a synapse if its private and you're either 1. logged out or 2. logged in but not the synapse creator #permissions
@synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } @synapses.delete_if {|s| s.permission == "private" && !authenticated? }
@synapses.delete_if {|s| s.permission == "private" && authenticated? && @current.id != s.user_id }
render json: autocomplete_synapse_array_json(@synapses)
else else
@synapses = [] @synapses = []
render json: autocomplete_synapse_array_json(@synapses)
end end
render json: autocomplete_synapse_array_json(@synapses)
end end
end end

View file

@ -13,7 +13,7 @@ class MappingsController < ApplicationController
# POST /mappings.json # POST /mappings.json
def create def create
@mapping = Mapping.new(params[:mapping]) @mapping = Mapping.new(mapping_params)
@mapping.map.touch(:updated_at) @mapping.map.touch(:updated_at)
@ -30,7 +30,7 @@ class MappingsController < ApplicationController
@mapping.map.touch(:updated_at) @mapping.map.touch(:updated_at)
if @mapping.update_attributes(params[:mapping]) if @mapping.update_attributes(mapping_params)
head :no_content head :no_content
else else
render json: @mapping.errors, status: :unprocessable_entity render json: @mapping.errors, status: :unprocessable_entity
@ -48,4 +48,10 @@ class MappingsController < ApplicationController
head :no_content head :no_content
end end
private
# Never trust parameters from the scary internet, only allow the white list through.
def mapping_params
params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id, :user_id)
end
end end

View file

@ -72,14 +72,10 @@ class MapsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
@allmappers = @map.contributors @allmappers = @map.contributors
@alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @alltopics = @map.topics.to_a.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)) } @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
@allmappings = @map.mappings.delete_if {|m| @allmappings = @map.mappings.to_a.delete_if {|m|
if m.category == "Synapse" object = m.mappable
object = m.synapse
elsif m.category == "Topic"
object = m.topic
end
!object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
} }
@ -100,14 +96,10 @@ class MapsController < ApplicationController
end end
@allmappers = @map.contributors @allmappers = @map.contributors
@alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @alltopics = @map.topics.to_a.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)) } @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
@allmappings = @map.mappings.delete_if {|m| @allmappings = @map.mappings.to_a.delete_if {|m|
if m.category == "Synapse" object = m.mappable
object = m.synapse
elsif m.category == "Topic"
object = m.topic
end
!object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
} }
@ -141,10 +133,9 @@ class MapsController < ApplicationController
@all.each do |topic| @all.each do |topic|
topic = topic.split('/') topic = topic.split('/')
@mapping = Mapping.new() @mapping = Mapping.new()
@mapping.category = "Topic"
@mapping.user = @user @mapping.user = @user
@mapping.map = @map @mapping.map = @map
@mapping.topic = Topic.find(topic[0]) @mapping.mappable = Topic.find(topic[0])
@mapping.xloc = topic[1] @mapping.xloc = topic[1]
@mapping.yloc = topic[2] @mapping.yloc = topic[2]
@mapping.save @mapping.save
@ -155,10 +146,9 @@ class MapsController < ApplicationController
@synAll = @synAll.split(',') @synAll = @synAll.split(',')
@synAll.each do |synapse_id| @synAll.each do |synapse_id|
@mapping = Mapping.new() @mapping = Mapping.new()
@mapping.category = "Synapse"
@mapping.user = @user @mapping.user = @user
@mapping.map = @map @mapping.map = @map
@mapping.synapse = Synapse.find(synapse_id) @mapping.mappable = Synapse.find(synapse_id)
@mapping.save @mapping.save
end end
end end
@ -180,7 +170,7 @@ class MapsController < ApplicationController
respond_to do |format| respond_to do |format|
if !@map if !@map
format.json { render json: "unauthorized" } format.json { render json: "unauthorized" }
elsif @map.update_attributes(params[:map]) elsif @map.update_attributes(map_params)
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @map.errors, status: :unprocessable_entity } format.json { render json: @map.errors, status: :unprocessable_entity }
@ -218,15 +208,7 @@ class MapsController < ApplicationController
@map = Map.find(params[:id]).authorize_to_delete(@current) @map = Map.find(params[:id]).authorize_to_delete(@current)
if @map @map.delete if @map
@mappings = @map.mappings
@mappings.each do |mapping|
mapping.delete
end
@map.delete
end
respond_to do |format| respond_to do |format|
format.json { format.json {
@ -238,4 +220,11 @@ class MapsController < ApplicationController
} }
end end
end end
private
# Never trust parameters from the scary internet, only allow the white list through.
def map_params
params.require(:map).permit(:id, :name, :arranged, :desc, :permission, :user_id)
end
end end

View file

@ -1,7 +1,7 @@
class MetacodeSetsController < ApplicationController class MetacodeSetsController < ApplicationController
before_filter :require_admin before_filter :require_admin
# GET /metacode_sets # GET /metacode_sets
# GET /metacode_sets.json # GET /metacode_sets.json
def index def index
@ -45,7 +45,7 @@ class MetacodeSetsController < ApplicationController
# POST /metacode_sets.json # POST /metacode_sets.json
def create def create
@user = current_user @user = current_user
@metacode_set = MetacodeSet.new(params[:metacode_set]) @metacode_set = MetacodeSet.new(metacode_set_params)
@metacode_set.user_id = @user.id @metacode_set.user_id = @user.id
respond_to do |format| respond_to do |format|
@ -70,7 +70,7 @@ class MetacodeSetsController < ApplicationController
@metacode_set = MetacodeSet.find(params[:id]) @metacode_set = MetacodeSet.find(params[:id])
respond_to do |format| respond_to do |format|
if @metacode_set.update_attributes(params[:metacode_set]) if @metacode_set.update_attributes(metacode_set_params)
# build an array of the IDs of the metacodes currently in the set # build an array of the IDs of the metacodes currently in the set
@currentMetacodes = @metacode_set.metacodes.map{ |m| m.id.to_s } @currentMetacodes = @metacode_set.metacodes.map{ |m| m.id.to_s }
@ -116,4 +116,11 @@ class MetacodeSetsController < ApplicationController
format.json { head :no_content } format.json { head :no_content }
end end
end end
private
def metacode_set_params
params.require(:metacode_set).permit(:desc, :mapperContributed, :name)
end
end end

View file

@ -5,8 +5,10 @@ class MetacodesController < ApplicationController
# GET /metacodes # GET /metacodes
# GET /metacodes.json # GET /metacodes.json
def index def index
@metacodes = Metacode.order("name").all @metacodes = Metacode.order("name").all
@metacodes.map do |metacode|
metacode.icon = ActionController::Base.helpers.asset_path(metacode.icon)
end
respond_to do |format| respond_to do |format|
format.html { format.html {
@ -51,7 +53,7 @@ class MetacodesController < ApplicationController
# POST /metacodes # POST /metacodes
# POST /metacodes.json # POST /metacodes.json
def create def create
@metacode = Metacode.new(params[:metacode]) @metacode = Metacode.new(metacode_params)
respond_to do |format| respond_to do |format|
if @metacode.save if @metacode.save
@ -70,7 +72,7 @@ class MetacodesController < ApplicationController
@metacode = Metacode.find(params[:id]) @metacode = Metacode.find(params[:id])
respond_to do |format| respond_to do |format|
if @metacode.update_attributes(params[:metacode]) if @metacode.update_attributes(metacode_params)
format.html { redirect_to metacodes_url, notice: 'Metacode was successfully updated.' } format.html { redirect_to metacodes_url, notice: 'Metacode was successfully updated.' }
format.json { head :no_content } format.json { head :no_content }
else else
@ -93,4 +95,11 @@ class MetacodesController < ApplicationController
# format.json { head :no_content } # format.json { head :no_content }
# end # end
# end # end
private
# Never trust parameters from the scary internet, only allow the white list through.
def metacode_params
params.require(:metacode).permit(:id, :name, :icon, :color)
end
end end

View file

@ -7,4 +7,4 @@ class Users::RegistrationsController < Devise::RegistrationsController
def after_update_path_for(resource) def after_update_path_for(resource)
signed_in_root_path(resource) signed_in_root_path(resource)
end end
end end

View file

@ -21,7 +21,8 @@ class SynapsesController < ApplicationController
# POST /synapses # POST /synapses
# POST /synapses.json # POST /synapses.json
def create def create
@synapse = Synapse.new(params[:synapse]) @synapse = Synapse.new(synapse_params)
@synapse.update_attribute :desc, "" if @synapse.desc.nil?
respond_to do |format| respond_to do |format|
if @synapse.save if @synapse.save
@ -36,9 +37,10 @@ class SynapsesController < ApplicationController
# PUT /synapses/1.json # PUT /synapses/1.json
def update def update
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
@synapse.update_attribute :desc, "" if @synapse.desc.nil?
respond_to do |format| respond_to do |format|
if @synapse.update_attributes(params[:synapse]) if @synapse.update_attributes(synapse_params)
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @synapse.errors, status: :unprocessable_entity } format.json { render json: @synapse.errors, status: :unprocessable_entity }
@ -50,18 +52,16 @@ class SynapsesController < ApplicationController
def destroy def destroy
@current = current_user @current = current_user
@synapse = Synapse.find(params[:id]).authorize_to_delete(@current) @synapse = Synapse.find(params[:id]).authorize_to_delete(@current)
@synapse.delete if @synapse
if @synapse
@synapse.mappings.each do |m|
m.map.touch(:updated_at)
m.delete
end
@synapse.delete
end
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }
end end
end end
private
def synapse_params
params.require(:synapse).permit(:id, :desc, :category, :weight, :permission, :node1_id, :node2_id, :user_id)
end
end end

View file

@ -10,12 +10,11 @@ class TopicsController < ApplicationController
@current = current_user @current = current_user
term = params[:term] term = params[:term]
if term && !term.empty? if term && !term.empty?
# !connor term here needs to have .downcase
@topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"') @topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"')
#read this next line as 'delete a topic if its private and you're either #read this next line as 'delete a topic if its private and you're either
#1. logged out or 2. logged in but not the topic creator #1. logged out or 2. logged in but not the topic creator
@topics.delete_if {|t| t.permission == "private" && @topics.to_a.delete_if {|t| t.permission == "private" &&
(!authenticated? || (authenticated? && @current.id != t.user_id)) } (!authenticated? || (authenticated? && @current.id != t.user_id)) }
else else
@topics = [] @topics = []
@ -35,7 +34,7 @@ class TopicsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
@alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } # should limit to topics visible to user @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)) } @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
@allcreators = [] @allcreators = []
@alltopics.each do |t| @alltopics.each do |t|
@ -64,8 +63,8 @@ class TopicsController < ApplicationController
redirect_to root_url, notice: "Access denied. That topic is private." and return redirect_to root_url, notice: "Access denied. That topic is private." and return
end end
@alltopics = @topic.relatives.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @alltopics = @topic.relatives.to_a.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)) } @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
@allcreators = [] @allcreators = []
@allcreators.push(@topic.user) @allcreators.push(@topic.user)
@alltopics.each do |t| @alltopics.each do |t|
@ -101,7 +100,7 @@ class TopicsController < ApplicationController
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] @topicsAlreadyHas = params[:network] ? params[:network].split(',') : []
@alltopics = @topic.relatives.delete_if {|t| @alltopics = @topic.relatives.to_a.delete_if {|t|
@topicsAlreadyHas.index(t.id.to_s) != nil || @topicsAlreadyHas.index(t.id.to_s) != nil ||
(t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)))
} }
@ -133,7 +132,7 @@ class TopicsController < ApplicationController
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] @topicsAlreadyHas = params[:network] ? params[:network].split(',') : []
@alltopics = @topic.relatives.delete_if {|t| @alltopics = @topic.relatives.to_a.delete_if {|t|
@topicsAlreadyHas.index(t.id.to_s) != nil || @topicsAlreadyHas.index(t.id.to_s) != nil ||
(params[:metacode] && t.metacode_id.to_s != params[:metacode]) || (params[:metacode] && t.metacode_id.to_s != params[:metacode]) ||
(t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)))
@ -141,7 +140,7 @@ class TopicsController < ApplicationController
@alltopics.uniq! @alltopics.uniq!
@allsynapses = @topic.synapses.delete_if {|s| @allsynapses = @topic.synapses.to_a.delete_if {|s|
(s.topic1 == @topic && @alltopics.index(s.topic2) == nil) || (s.topic1 == @topic && @alltopics.index(s.topic2) == nil) ||
(s.topic2 == @topic && @alltopics.index(s.topic1) == nil) (s.topic2 == @topic && @alltopics.index(s.topic1) == nil)
} }
@ -172,7 +171,7 @@ class TopicsController < ApplicationController
# POST /topics # POST /topics
# POST /topics.json # POST /topics.json
def create def create
@topic = Topic.new(params[:topic]) @topic = Topic.new(topic_params)
respond_to do |format| respond_to do |format|
if @topic.save if @topic.save
@ -189,7 +188,7 @@ class TopicsController < ApplicationController
@topic = Topic.find(params[:id]) @topic = Topic.find(params[:id])
respond_to do |format| respond_to do |format|
if @topic.update_attributes(params[:topic]) if @topic.update_attributes(topic_params)
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @topic.errors, status: :unprocessable_entity } format.json { render json: @topic.errors, status: :unprocessable_entity }
@ -201,36 +200,16 @@ class TopicsController < ApplicationController
def destroy def destroy
@current = current_user @current = current_user
@topic = Topic.find(params[:id]).authorize_to_delete(@current) @topic = Topic.find(params[:id]).authorize_to_delete(@current)
@topic.delete if @topic
if @topic
@synapses = @topic.synapses
@mappings = @topic.mappings
@synapses.each do |synapse|
synapse.mappings.each do |m|
@map = m.map
@map.touch(:updated_at)
m.delete
end
synapse.delete
end
@mappings.each do |mapping|
@map = mapping.map
@map.touch(:updated_at)
mapping.delete
end
@topic.delete
end
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }
end end
end end
private
def topic_params
params.require(:topic).permit(:id, :name, :desc, :link, :permission, :user_id, :metacode_id)
end
end end

View file

@ -3,4 +3,4 @@ class Users::PasswordsController < Devise::PasswordsController
def after_resetting_password_path_for(resource) def after_resetting_password_path_for(resource)
signed_in_root_path(resource) signed_in_root_path(resource)
end end
end end

View file

@ -3,7 +3,7 @@ class UsersController < ApplicationController
before_filter :require_user, only: [:edit, :update, :updatemetacodes] before_filter :require_user, only: [:edit, :update, :updatemetacodes]
respond_to :html, :json respond_to :html, :json
# GET /users/1.json # GET /users/1.json
def show def show
@user = User.find(params[:id]) @user = User.find(params[:id])
@ -98,4 +98,11 @@ class UsersController < ApplicationController
end end
end end
private
def user_params
params.require(:user).permit(:name, :email, :image, :password,
:password_confirmation, :code, :joinedwithcode, :remember_me)
end
end end

View file

@ -1,2 +1,18 @@
module ApplicationHelper module ApplicationHelper
def get_metacodeset
@m = user.settings.metacodes
set = @m[0].include?("metacodeset") ? MetacodeSet.find(@m[0].sub("metacodeset-","").to_i) : false
return set
end
def user_metacodes
@m = user.settings.metacodes
set = get_metacodeset
if set
@metacodes = set.metacodes
else
@metacodes = Metacode.where(id: @m).to_a
end
@metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
end
end end

View file

@ -16,7 +16,7 @@ module MapsHelper
map['rtype'] = "map" map['rtype'] = "map"
contributorTip = '' contributorTip = ''
firstContributorImage = '/assets/user.png' firstContributorImage = asset_path('user.png')
if m.contributors.count > 0 if m.contributors.count > 0
firstContributorImage = m.contributors[0].image.url(:thirtytwo) firstContributorImage = m.contributors[0].image.url(:thirtytwo)
m.contributors.each_with_index do |c, index| m.contributors.each_with_index do |c, index|

View file

@ -10,7 +10,7 @@ module TopicsHelper
topic['value'] = t.name topic['value'] = t.name
topic['description'] = t.desc.truncate(70) # make this return matched results topic['description'] = t.desc.truncate(70) # make this return matched results
topic['type'] = t.metacode.name topic['type'] = t.metacode.name
topic['typeImageURL'] = t.metacode.icon topic['typeImageURL'] = t.metacode.asset_path_icon
topic['permission'] = t.permission topic['permission'] = t.permission
topic['mapCount'] = t.maps.count topic['mapCount'] = t.maps.count
topic['synapseCount'] = t.synapses.count topic['synapseCount'] = t.synapses.count

View file

@ -1,5 +1,4 @@
class InMetacodeSet < ActiveRecord::Base class InMetacodeSet < ActiveRecord::Base
belongs_to :metacode, :class_name => "Metacode", :foreign_key => "metacode_id" belongs_to :metacode, :class_name => "Metacode", :foreign_key => "metacode_id"
belongs_to :metacode_set, :class_name => "MetacodeSet", :foreign_key => "metacode_set_id" belongs_to :metacode_set, :class_name => "MetacodeSet", :foreign_key => "metacode_set_id"
# attr_accessible :title, :body
end end

View file

@ -2,18 +2,17 @@ class Map < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :topicmappings, :class_name => 'Mapping', :conditions => {:category => 'Topic'} has_many :topicmappings, -> { Mapping.topicmapping }, class_name: :Mapping, dependent: :destroy
has_many :synapsemappings, :class_name => 'Mapping', :conditions => {:category => 'Synapse'} has_many :synapsemappings, -> { Mapping.synapsemapping }, class_name: :Mapping, dependent: :destroy
has_many :topics, through: :topicmappings, source: :mappable, source_type: "Topic"
has_many :topics, :through => :topicmappings has_many :synapses, through: :synapsemappings, source: :mappable, source_type: "Synapse"
has_many :synapses, :through => :synapsemappings
# This method associates the attribute ":image" with a file attachment # This method associates the attribute ":image" with a file attachment
has_attached_file :screenshot, :styles => { has_attached_file :screenshot, :styles => {
:thumb => ['188x126#', :png] :thumb => ['188x126#', :png]
#:full => ['940x630#', :png] #:full => ['940x630#', :png]
}, },
:default_url => "/assets/missing-map.png" :default_url => 'https://s3.amazonaws.com/metamaps-assets/site/missing-map.png'
# Validate the attached image is image/jpg, image/png, etc # Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :screenshot, :content_type => /\Aimage\/.*\Z/ validates_attachment_content_type :screenshot, :content_type => /\Aimage\/.*\Z/

View file

@ -1,7 +1,10 @@
class Mapping < ActiveRecord::Base class Mapping < ActiveRecord::Base
belongs_to :topic, :class_name => "Topic", :foreign_key => "topic_id" scope :topicmapping, -> { where(mappable_type: :Topic) }
belongs_to :synapse, :class_name => "Synapse", :foreign_key => "synapse_id" scope :synapsemapping, -> { where(mappable_type: :Synapse) }
belongs_to :mappable, polymorphic: true
belongs_to :map, :class_name => "Map", :foreign_key => "map_id" belongs_to :map, :class_name => "Map", :foreign_key => "map_id"
belongs_to :user belongs_to :user

View file

@ -14,4 +14,18 @@ class Metacode < ActiveRecord::Base
return false return false
end end
end def asset_path_icon
if icon.start_with?('http')
icon
else
ActionController::Base.helpers.asset_path icon
end
end
#output json with asset_paths merged in
def as_json(options)
json = super(options.merge!(methods: :asset_path_icon))
json["icon"] = json["asset_path_icon"]
json.except("asset_path_icon")
end
end

View file

@ -1,6 +1,5 @@
class MetacodeSet < ActiveRecord::Base class MetacodeSet < ActiveRecord::Base
belongs_to :user belongs_to :user
attr_accessible :desc, :mapperContributed, :name
has_many :in_metacode_sets has_many :in_metacode_sets
has_many :metacodes, :through => :in_metacode_sets has_many :metacodes, :through => :in_metacode_sets
end end

View file

@ -5,9 +5,11 @@ class Synapse < ActiveRecord::Base
belongs_to :topic1, :class_name => "Topic", :foreign_key => "node1_id" belongs_to :topic1, :class_name => "Topic", :foreign_key => "node1_id"
belongs_to :topic2, :class_name => "Topic", :foreign_key => "node2_id" belongs_to :topic2, :class_name => "Topic", :foreign_key => "node2_id"
has_many :mappings has_many :mappings, as: :mappable, dependent: :destroy
has_many :maps, :through => :mappings has_many :maps, :through => :mappings
validates :desc, length: { minimum: 0, allow_nil: false }
def user_name def user_name
self.user.name self.user.name
end end

View file

@ -3,12 +3,12 @@ class Topic < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :synapses1, :class_name => 'Synapse', :foreign_key => 'node1_id' has_many :synapses1, :class_name => 'Synapse', :foreign_key => 'node1_id', dependent: :destroy
has_many :synapses2, :class_name => 'Synapse', :foreign_key => 'node2_id' has_many :synapses2, :class_name => 'Synapse', :foreign_key => 'node2_id', dependent: :destroy
has_many :topics1, :through => :synapses2, :source => :topic1 has_many :topics1, :through => :synapses2, :source => :topic1
has_many :topics2, :through => :synapses1, :source => :topic2 has_many :topics2, :through => :synapses1, :source => :topic2
has_many :mappings has_many :mappings, as: :mappable, dependent: :destroy
has_many :maps, :through => :mappings has_many :maps, :through => :mappings
# This method associates the attribute ":image" with a file attachment # This method associates the attribute ":image" with a file attachment

View file

@ -11,8 +11,6 @@ class User < ActiveRecord::Base
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable
attr_accessible :name, :email, :image, :password, :password_confirmation, :code, :joinedwithcode, :remember_me
serialize :settings, UserPreference serialize :settings, UserPreference
validates :password, :presence => true, validates :password, :presence => true,
@ -37,7 +35,7 @@ class User < ActiveRecord::Base
:ninetysix => ['96x96#', :png], :ninetysix => ['96x96#', :png],
:onetwentyeight => ['128x128#', :png] :onetwentyeight => ['128x128#', :png]
}, },
:default_url => "/assets/user.png" :default_url => 'https://s3.amazonaws.com/metamaps-assets/site/user.png'
# Validate the attached image is image/jpg, image/png, etc # Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/ validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/

View file

@ -129,7 +129,7 @@
<script type="text/template" id="mapSearchTemplate"> <script type="text/template" id="mapSearchTemplate">
<div class="result{{rtype}}"> <div class="result{{rtype}}">
<div class="searchResIconWrapper"> <div class="searchResIconWrapper">
<img class="icon" src="/assets/metamap36c.png"> <img class="icon" src="<%= asset_path('metamap36c.png') %>">
</div> </div>
<div class="resultText"> <div class="resultText">
<p class="resultTitle">{{label}}</p> <p class="resultTitle">{{label}}</p>
@ -196,6 +196,7 @@
</script> </script>
<script type="text/template" id="topicAutocompleteTemplate"> <script type="text/template" id="topicAutocompleteTemplate">
<div>
<img class="autocompleteSection topicType" width="24" height="24" src="{{typeImageURL}}" alt="{{type}}" title="{{type}}" /> <img class="autocompleteSection topicType" width="24" height="24" src="{{typeImageURL}}" alt="{{type}}" title="{{type}}" />
<p class="autocompleteSection topicTitle">{{label}}</p> <p class="autocompleteSection topicTitle">{{label}}</p>
<div class="expandTopicMetadata"></div> <div class="expandTopicMetadata"></div>
@ -209,6 +210,7 @@
<div class="topicPermission {{permission}}"></div> <div class="topicPermission {{permission}}"></div>
</div> </div>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</div>
</script> </script>
@ -234,7 +236,7 @@
<div class="metacodeSelect">{{{metacode_select}}}</div> <div class="metacodeSelect">{{{metacode_select}}}</div>
</div> </div>
<div class="linkItem contributor"> <div class="linkItem contributor">
<a href="/explore/mapper/{{userid}}"><img src="/assets/user.png" class="contributorIcon" width="32" height="32" /></a> <a href="/explore/mapper/{{userid}}"><img src="<%= asset_path('user.png') %>" class="contributorIcon" width="32" height="32" /></a>
<div class="contributorName">{{username}}</div> <div class="contributorName">{{username}}</div>
</div> </div>
<div class="linkItem mapCount"> <div class="linkItem mapCount">
@ -267,4 +269,4 @@
<div class="clearfloat"></div> <div class="clearfloat"></div>
</div> </div>
</script> </script>
</div> </div>

View file

@ -50,4 +50,4 @@
Metamaps.GlobalUI.Search.isOpen = true; Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock(); Metamaps.GlobalUI.Search.lock();
</script> </script>
<% end %> <% end %>

View file

@ -8,12 +8,12 @@
<%= @map && @map.permission != 'private' ? " shareable" : "" %>"> <%= @map && @map.permission != 'private' ? " shareable" : "" %>">
<% if @map %> <% if @map %>
<div class="mapInfoName" id="mapInfoName"><%= best_in_place @map, :name, :type => :textarea, :activator => "#mapInfoName", :classes => 'best_in_place_name' %></div> <div class="mapInfoName" id="mapInfoName"><%= best_in_place @map, :name, :as => :textarea, :activator => "#mapInfoName", :class => 'best_in_place_name' %></div>
<div class="mapInfoStat"> <div class="mapInfoStat">
<div class="infoStatIcon mapContributors hoverForTip"> <div class="infoStatIcon mapContributors hoverForTip">
<% if @map.contributors.count == 0 %> <% if @map.contributors.count == 0 %>
<img id="mapContribs" width="25" height="25" src="/assets/user.png" /> <img id="mapContribs" width="25" height="25" src="<%= asset_path('user.png'); %>" />
<% elsif @map.contributors.count == 1 %> <% elsif @map.contributors.count == 1 %>
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url(:thirtytwo) %>" /> <img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url(:thirtytwo) %>" />
<% elsif @map.contributors.count == 2 %> <% elsif @map.contributors.count == 2 %>
@ -23,7 +23,7 @@
<% end %> <% end %>
<span><%= @map.contributors.count %></span> <span><%= @map.contributors.count %></span>
<div class="tip"> <ul><% @map.contributors.each_with_index do |c, index| %> <div class="tip"> <ul><% @map.contributors.each_with_index do |c, index| %>
<li ><a href="/explore/mapper/<%= c.id %>" > <img class="rtUserImage" width="25" height="25" src="<%= c.image.url(:thirtytwo) %>" /> <li ><a href="/explore/mapper/<%= c.id %>" > <img class="rtUserImage" width="25" height="25" src="<%= asset_path c.image.url(:thirtytwo) %>" />
<%= c.name %></a> <%= c.name %></a>
</li> </li>
<% end %></ul></div> <% end %></ul></div>
@ -42,7 +42,7 @@
<div class="mapInfoDesc" id="mapInfoDesc"> <div class="mapInfoDesc" id="mapInfoDesc">
<% if (authenticated? && @map.authorize_to_edit(user)) || (!authenticated? && @map.desc != "" && @map.desc != nil )%> <% if (authenticated? && @map.authorize_to_edit(user)) || (!authenticated? && @map.desc != "" && @map.desc != nil )%>
<%= best_in_place @map, :desc, :activator => "#mapInfoDesc", :type => :textarea, :nil => "Click to add description...", :classes => 'best_in_place_desc' %> <%= best_in_place @map, :desc, :activator => "#mapInfoDesc", :as => :textarea, :placeholder => "Click to add description...", :class => 'best_in_place_desc' %>
<% end %> <% end %>
</div> </div>
@ -61,4 +61,4 @@
</div> </div>
</div> </div>
<% end %> <% end %>
</div> </div>

View file

@ -1,19 +1,10 @@
<%= form_for Topic.new, url: topics_url, remote: true do |form| %> <%= form_for Topic.new, url: topics_url, remote: true do |form| %>
<div class="openMetacodeSwitcher openLightbox" data-open="switchMetacodes"></div> <div class="openMetacodeSwitcher openLightbox" data-open="switchMetacodes"></div>
<div id="metacodeImg"> <div id="metacodeImg">
<% @m = user.settings.metacodes %> <% @metacodes = user_metacodes() %>
<% set = @m[0].include?("metacodeset") ? MetacodeSet.find(@m[0].sub("metacodeset-","").to_i) : false %> <% set = get_metacodeset() %>
<% if set %>
<% @metacodes = set.metacodes %>
<% else %>
<% @metacodes = [] %>
<% @m.each do |m| %>
<% @metacodes.push(Metacode.find(m.to_i)) %>
<% end %>
<% end %>
<% @metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1) %>
<% @metacodes.each do |metacode| %> <% @metacodes.each do |metacode| %>
<img class="cloudcarousel" width="40" height="40" src="<%= metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>" data-id="<%= metacode.id %>" /> <img class="cloudcarousel" width="40" height="40" src="<%= asset_path metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>" data-id="<%= metacode.id %>" />
<% end %> <% end %>
</div> </div>
<%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %> <%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %>

View file

@ -37,7 +37,7 @@
<% while $i < (Metacode.all.length / 4) do %> <% while $i < (Metacode.all.length / 4) do %>
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %> <li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
onclick="Metamaps.Admin.liClickHandler.call(this);"> onclick="Metamaps.Admin.liClickHandler.call(this);">
<img src="<%= @m[$i].icon %>" alt="<%= @m[$i].name %>" /> <img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
<p><%= @m[$i].name.downcase %></p> <p><%= @m[$i].name.downcase %></p>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -48,7 +48,7 @@
<% while $i < (Metacode.all.length / 4 * 2) do %> <% while $i < (Metacode.all.length / 4 * 2) do %>
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %> <li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
onclick="Metamaps.Admin.liClickHandler.call(this);"> onclick="Metamaps.Admin.liClickHandler.call(this);">
<img src="<%= @m[$i].icon %>" alt="<%= @m[$i].name %>" /> <img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
<p><%= @m[$i].name.downcase %></p> <p><%= @m[$i].name.downcase %></p>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -59,7 +59,7 @@
<% while $i < (Metacode.all.length / 4 * 3) do %> <% while $i < (Metacode.all.length / 4 * 3) do %>
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %> <li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
onclick="Metamaps.Admin.liClickHandler.call(this);"> onclick="Metamaps.Admin.liClickHandler.call(this);">
<img src="<%= @m[$i].icon %>" alt="<%= @m[$i].name %>" /> <img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
<p><%= @m[$i].name.downcase %></p> <p><%= @m[$i].name.downcase %></p>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -70,7 +70,7 @@
<% while $i < Metacode.all.length do %> <% while $i < Metacode.all.length do %>
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %> <li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
onclick="Metamaps.Admin.liClickHandler.call(this);"> onclick="Metamaps.Admin.liClickHandler.call(this);">
<img src="<%= @m[$i].icon %>" alt="<%= @m[$i].name %>" /> <img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
<p><%= @m[$i].name.downcase %></p> <p><%= @m[$i].name.downcase %></p>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -86,4 +86,4 @@
{ :class => 'button', 'data-bypass' => 'true' } %> { :class => 'button', 'data-bypass' => 'true' } %>
<%= f.submit :class => 'add', :onclick => "return Metamaps.Admin.validate();" %> <%= f.submit :class => 'add', :onclick => "return Metamaps.Admin.validate();" %>
</div> </div>
<% end %> <% end %>

View file

@ -23,7 +23,7 @@
<td class='metacodeSetDesc'><%= metacode_set.desc %></td> <td class='metacodeSetDesc'><%= metacode_set.desc %></td>
<td> <td>
<% metacode_set.metacodes.each_with_index do |metacode, index| %> <% metacode_set.metacodes.each_with_index do |metacode, index| %>
<img class='metacodeSetImage' src='<%= metacode.icon %>' /> <img class='metacodeSetImage' src='<%= asset_path metacode.icon %>' />
<% if (index+1)%4 == 0 %> <% if (index+1)%4 == 0 %>
<div class='clearfloat'></div> <div class='clearfloat'></div>
<% end %> <% end %>
@ -34,4 +34,4 @@
<% end %> <% end %>
</table> </table>
</div> </div>
</div> </div>

View file

@ -14,7 +14,7 @@
<% @metacodes.each do |metacode| %> <% @metacodes.each do |metacode| %>
<tr> <tr>
<td><%= metacode.name %></td> <td><%= metacode.name %></td>
<td class="iconURL"><%= metacode.icon %></td> <td class="iconURL"><%= asset_path metacode.icon %></td>
<% if metacode.color %> <% if metacode.color %>
<td class="iconColor" style="background-color: <%= metacode.color %>"> <td class="iconColor" style="background-color: <%= metacode.color %>">
<%= metacode.color %> <%= metacode.color %>
@ -22,10 +22,10 @@
<% else %> <% else %>
<td></td> <td></td>
<% end %> <% end %>
<td><img width='40' src='<%= metacode.icon %>' /></td> <td><img width='40' src='<%= asset_path metacode.icon %>' /></td>
<td><%= link_to 'Edit', edit_metacode_path(metacode), :data => { :bypass => 'true'} %></td> <td><%= link_to 'Edit', edit_metacode_path(metacode), :data => { :bypass => 'true'} %></td>
</tr> </tr>
<% end %> <% end %>
</table> </table>
</div> </div>
</div> </div>

View file

@ -2,4 +2,4 @@
<div class='blackBox'> <div class='blackBox'>
<%= render 'form' %> <%= render 'form' %>
</div> </div>
</div> </div>

View file

@ -61,7 +61,7 @@
<span class="csTitle">Change Topic permission:</span> Click on 'Permission' icon (only for topic creator) <span class="csTitle">Change Topic permission:</span> Click on 'Permission' icon (only for topic creator)
</div> </div>
<div class="csItem indented"> <div class="csItem indented">
<span class="csTitle">Open Topic view:</span> Click on <img src="/assets/synapse16.png" width="16" align="middle" /> icon within topic card bar <span class="csTitle">Open Topic view:</span> Click on <img src="<%= asset_path 'synapse16.png' %>" width="16" align="middle" /> icon within topic card bar
</div> </div>
<div class="csItem indented"> <div class="csItem indented">
<span class="csTitle">Close 'Topic' card:</span> Click on canvas <span class="csTitle">Close 'Topic' card:</span> Click on canvas

View file

@ -70,13 +70,13 @@
@metacodes.each_with_index do |metacode, index| @metacodes.each_with_index do |metacode, index|
@metacodelist += '<li data-id="' + metacode.id.to_s + '">' @metacodelist += '<li data-id="' + metacode.id.to_s + '">'
@metacodelist += '<img src="' + metacode.icon + '" data-id="' + metacode.id.to_s + '" alt="' + metacode.name + '" />' @metacodelist += '<img src="' + asset_path(metacode.icon) + '" data-id="' + metacode.id.to_s + '" alt="' + metacode.name + '" />'
@metacodelist += '<p>' + metacode.name.downcase + '</p></li>' @metacodelist += '<p>' + metacode.name.downcase + '</p></li>'
end end
@synapses.each_with_index do |synapse, index| @synapses.each_with_index do |synapse, index|
d = synapse.desc || "" d = synapse.desc || ""
@synapselist += '<li data-id="' + d + '">' @synapselist += '<li data-id="' + d + '">'
@synapselist += '<img src="/assets/synapse16.png" alt="synapse icon" /><p>' + d @synapselist += '<img src="' + asset_path('synapse16.png') + '" alt="synapse icon" /><p>' + d
@synapselist += '</p></li>' @synapselist += '</p></li>'
end end
@mappers.each_with_index do |mapper, index| @mappers.each_with_index do |mapper, index|

View file

@ -12,7 +12,7 @@
<ul> <ul>
<% set.metacodes.sort { |a, b| a.name <=> b.name }.each do |m| %> <% set.metacodes.sort { |a, b| a.name <=> b.name }.each do |m| %>
<li data-id="<%= m.id.to_s %>"> <li data-id="<%= m.id.to_s %>">
<img width="24" height="24" src="<%= m.icon %>" alt="<%= m.name %>" /> <img width="24" height="24" src="<%= asset_path m.icon %>" alt="<%= m.name %>" />
<div class="mSelectName"><%= m.name %></div> <div class="mSelectName"><%= m.name %></div>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -26,7 +26,7 @@
<ul> <ul>
<% Metacode.order("name").all.each do |m| %> <% Metacode.order("name").all.each do |m| %>
<li data-id="<%= m.id.to_s %>"> <li data-id="<%= m.id.to_s %>">
<img width="24" height="24" src="<%= m.icon %>" alt="<%= m.name %>" /> <img width="24" height="24" src="<%= asset_path m.icon %>" alt="<%= m.name %>" />
<div class="mSelectName"><%= m.name %></div> <div class="mSelectName"><%= m.name %></div>
<div class="clearfloat"></div> <div class="clearfloat"></div>
</li> </li>
@ -34,4 +34,4 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>

View file

@ -28,7 +28,7 @@
data-metacodes="<%= m.metacodes.map(&:id).join(',') %>"> data-metacodes="<%= m.metacodes.map(&:id).join(',') %>">
<% @list = '' %> <% @list = '' %>
<% m.metacodes.sort{|x,y| x.name <=> y.name }.each_with_index do |m, index| %> <% m.metacodes.sort{|x,y| x.name <=> y.name }.each_with_index do |m, index| %>
<% @list += '<li><img src="' + m.icon + '" alt="' + m.name + '" /><p>' + m.name.downcase + '</p><div class="clearfloat"></div></li>' %> <% @list += '<li><img src="' + asset_path(m.icon) + '" alt="' + m.name + '" /><p>' + m.name.downcase + '</p><div class="clearfloat"></div></li>' %>
<% end %> <% end %>
<div class="metacodeSwitchTab"> <div class="metacodeSwitchTab">
<p class="setDesc"><%= m.desc %></p> <p class="setDesc"><%= m.desc %></p>
@ -53,7 +53,7 @@
<% else %> <% else %>
<% mClass = "toggledOff" %> <% mClass = "toggledOff" %>
<% end %> <% end %>
<% @list += '<li id="' + m.id.to_s + '" data-name="' + m.name + '" class="' + mClass + '"><img src="' + m.icon + '" alt="' + m.name + '" /><p>' + m.name.downcase + '</p><div class="clearfloat"></div></li>' %> <% @list += '<li id="' + m.id.to_s + '" data-name="' + m.name + '" class="' + mClass + '"><img src="' + asset_path(m.icon) + '" alt="' + m.name + '" /><p>' + m.name.downcase + '</p><div class="clearfloat"></div></li>' %>
<% end %> <% end %>
<div class="customMetacodeList"> <div class="customMetacodeList">
@ -73,4 +73,4 @@
<script> <script>
Metamaps.Create.selectedMetacodeSet = "metacodeset-<%= selectedSet %>"; Metamaps.Create.selectedMetacodeSet = "metacodeset-<%= selectedSet %>";
Metamaps.Create.selectedMetacodeSetIndex = <%= index %>; Metamaps.Create.selectedMetacodeSetIndex = <%= index %>;
</script> </script>

View file

@ -20,7 +20,7 @@
<% end %> <% end %>
<% @metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1) %> <% @metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1) %>
<% @metacodes.each do |metacode| %> <% @metacodes.each do |metacode| %>
<img class="cloudcarousel" width="40" height="40" src="<%= metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>"/> <img class="cloudcarousel" width="40" height="40" src="<%= asset_path metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>"/>
<% end %> <% end %>
</div> </div>
<%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %> <%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %>

View file

@ -2,12 +2,7 @@ require File.expand_path('../boot', __FILE__)
require 'rails/all' require 'rails/all'
if defined?(Bundler) Bundler.require(:default, Rails.env)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module Metamaps module Metamaps
class Application < Rails::Application class Application < Rails::Application
@ -44,17 +39,12 @@ module Metamaps
# like if you have constraints or database-specific column types # like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql # config.active_record.schema_format = :sql
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
# config.active_record.whitelist_attributes = true
# Enable the asset pipeline # Enable the asset pipeline
config.assets.enabled = true
config.assets.initialize_on_precompile = false config.assets.initialize_on_precompile = false
# Version of your assets, change this if you want to expire all your assets # Version of your assets, change this if you want to expire all your assets
config.assets.version = '2.0' config.assets.version = '2.0'
config.active_record.raise_in_transactional_callbacks = true
end end
end end

View file

@ -1,4 +1,12 @@
require 'rubygems' require 'rubygems'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
# Set up gems listed in the Gemfile. # Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)

View file

@ -1,14 +1,14 @@
Metamaps::Application.configure do Metamaps::Application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
config.log_level = :info
config.eager_load = false
# In the development environment your application's code is reloaded on # In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development # every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes. # since you don't have to restart the web server when you make code changes.
config.cache_classes = false config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching # Show full error reports and disable caching
config.consider_all_requests_local = true config.consider_all_requests_local = true
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
@ -40,19 +40,6 @@ Metamaps::Application.configure do
# Print deprecation notices to the Rails logger # Print deprecation notices to the Rails logger
config.active_support.deprecation = :log config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets # Expands the lines which load the assets
config.assets.debug = true config.assets.debug = true
end end

View file

@ -1,6 +1,10 @@
Metamaps::Application.configure do Metamaps::Application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
config.log_level = :warn
config.eager_load = true
config.assets.js_compressor = :uglifier
# Code is not reloaded between requests # Code is not reloaded between requests
config.cache_classes = true config.cache_classes = true
@ -9,7 +13,9 @@ Metamaps::Application.configure do
config.action_controller.perform_caching = true config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this) # Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false config.serve_static_files = true
config.assets.compile = false
# Compress JavaScripts and CSS # Compress JavaScripts and CSS
config.assets.compress = true config.assets.compress = true

View file

@ -1,6 +1,8 @@
Metamaps::Application.configure do Metamaps::Application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
config.eager_load = false
# The test environment is used exclusively to run your application's # The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that # test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped # your test database is "scratch space" for the test suite and is wiped
@ -11,9 +13,6 @@ Metamaps::Application.configure do
config.serve_static_assets = true config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600" config.static_cache_control = "public, max-age=3600"
# Log error messages when you accidentally call methods on nil
config.whiny_nils = true
# Show full error reports and disable caching # Show full error reports and disable caching
config.consider_all_requests_local = true config.consider_all_requests_local = true
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
@ -29,9 +28,12 @@ Metamaps::Application.configure do
# ActionMailer::Base.deliveries array. # ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test config.action_mailer.delivery_method = :test
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Print deprecation notices to the stderr # Print deprecation notices to the stderr
config.active_support.deprecation = :stderr config.active_support.deprecation = :stderr
#assets config
config.assets.compile = true
config.assets.compress = false
config.assets.debug = false
config.assets.digest = false
end end

View file

@ -4,4 +4,4 @@
# If you change this key, all old signed cookies will become invalid! # If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random, # Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks. # no regular words or you'll be exposed to dictionary attacks.
Metamaps::Application.config.secret_token = '267c8a84f63963282f45bc3010eaddf027abfab58fc759d6e239c8005f85ee99d6d01b1ab6394cdee9ca7f8c9213a0cf91d3d8d3350f096123e2caccbcc0924f' Metamaps::Application.config.secret_key_base = '267c8a84f63963282f45bc3010eaddf027abfab58fc759d6e239c8005f85ee99d6d01b1ab6394cdee9ca7f8c9213a0cf91d3d8d3350f096123e2caccbcc0924f'

View file

@ -2,12 +2,12 @@ Metamaps::Application.routes.draw do
root to: 'main#home', via: :get root to: 'main#home', via: :get
match 'request', to: 'main#requestinvite', via: :get, as: :request get 'request', to: 'main#requestinvite', as: :request
match 'search/topics', to: 'main#searchtopics', via: :get, as: :searchtopics get 'search/topics', to: 'main#searchtopics', as: :searchtopics
match 'search/maps', to: 'main#searchmaps', via: :get, as: :searchmaps get 'search/maps', to: 'main#searchmaps', as: :searchmaps
match 'search/mappers', to: 'main#searchmappers', via: :get, as: :searchmappers get 'search/mappers', to: 'main#searchmappers', as: :searchmappers
match 'search/synapses', to: 'main#searchsynapses', via: :get, as: :searchsynapses get 'search/synapses', to: 'main#searchsynapses', as: :searchsynapses
resources :mappings, except: [:index, :new, :edit] resources :mappings, except: [:index, :new, :edit]
resources :metacode_sets, :except => [:show] resources :metacode_sets, :except => [:show]
@ -16,28 +16,28 @@ Metamaps::Application.routes.draw do
resources :topics, except: [:index, :new, :edit] do resources :topics, except: [:index, :new, :edit] do
get :autocomplete_topic, :on => :collection get :autocomplete_topic, :on => :collection
end end
match 'topics/:id/network', to: 'topics#network', via: :get, as: :network get 'topics/:id/network', to: 'topics#network', as: :network
match 'topics/:id/relative_numbers', to: 'topics#relative_numbers', via: :get, as: :relative_numbers get 'topics/:id/relative_numbers', to: 'topics#relative_numbers', as: :relative_numbers
match 'topics/:id/relatives', to: 'topics#relatives', via: :get, as: :relatives get 'topics/:id/relatives', to: 'topics#relatives', as: :relatives
match 'explore/active', to: 'maps#index', via: :get, as: :activemaps get 'explore/active', to: 'maps#index', as: :activemaps
match 'explore/featured', to: 'maps#index', via: :get, as: :featuredmaps get 'explore/featured', to: 'maps#index', as: :featuredmaps
match 'explore/mine', to: 'maps#index', via: :get, as: :mymaps get 'explore/mine', to: 'maps#index', as: :mymaps
match 'explore/mapper/:id', to: 'maps#index', via: :get, as: :usermaps get 'explore/mapper/:id', to: 'maps#index', as: :usermaps
resources :maps, except: [:new, :edit] resources :maps, except: [:new, :edit]
match 'maps/:id/contains', to: 'maps#contains', via: :get, as: :contains get 'maps/:id/contains', to: 'maps#contains', as: :contains
match 'maps/:id/upload_screenshot', to: 'maps#screenshot', via: :post, as: :screenshot get 'maps/:id/upload_screenshot', to: 'maps#screenshot', as: :screenshot
devise_for :users, controllers: { registrations: 'users/registrations', passwords: 'users/passwords', sessions: 'devise/sessions' }, :skip => [:sessions] devise_for :users, controllers: { registrations: 'users/registrations', passwords: 'users/passwords', sessions: 'devise/sessions' }, :skip => :sessions
devise_scope :user do devise_scope :user do
get 'login' => 'devise/sessions#new', :as => :new_user_session get 'login' => 'devise/sessions#new', :as => :new_user_session
post 'login' => 'devise/sessions#create', :as => :user_session post 'login' => 'devise/sessions#create', :as => :user_session
get 'logout' => 'devise/sessions#destroy', :as => :destroy_user_session get 'logout' => 'devise/sessions#destroy', :as => :destroy_user_session
get 'join' => 'devise/registrations#new', :as => :new_user_registration get 'join' => 'devise/registrations#new', :as => :new_user_registration_path
end end
match 'users/:id/details', to: 'users#details', via: :get, as: :details get 'users/:id/details', to: 'users#details', as: :details
match 'user/updatemetacodes', to: 'users#updatemetacodes', via: :post, as: :updatemetacodes post 'user/updatemetacodes', to: 'users#updatemetacodes', as: :updatemetacodes
resources :users, except: [:index, :destroy] resources :users, except: [:index, :destroy]
end end

View file

@ -0,0 +1,12 @@
defaults: &defaults
missing_map_png_url: '/assets/missing-map.png'
user_png_url: '/assets/user.png'
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *defaults

View file

@ -0,0 +1,32 @@
class MappingPolymorphism < ActiveRecord::Migration
def up
add_column :mappings, :mappable_id, :integer
add_column :mappings, :mappable_type, :string
add_index :mappings, [:mappable_id, :mappable_type]
Mapping.find_each do |mapping|
if mapping.synapse_id.nil? and mapping.topic_id.nil?
puts "Mapping id=#{mapping.id} has no valid id, skipping!"
next
end
if not mapping.synapse_id.nil? and not mapping.topic_id.nil?
puts "Mapping id=#{mapping.id} has both topic and synapse ids, skipping!"
next
end
unless mapping.synapse_id.nil?
mapping.mappable = Synapse.find(mapping.synapse_id)
else
next if mapping.topic_id == 0
mapping.mappable = Topic.find(mapping.topic_id)
end
mapping.save
end
end
def down
remove_index :mappings, [:mappable_id, :mappable_type]
remove_column :mappings, :mappable_id, :integer
remove_column :mappings, :mappable_type, :string
end
end

View file

@ -0,0 +1,16 @@
class AddMissingIndexes < ActiveRecord::Migration
def change
add_index :topics, :user_id
add_index :topics, :metacode_id
add_index :synapses, [:node2_id, :node2_id]
add_index :synapses, [:node1_id, :node1_id]
add_index :synapses, :user_id
add_index :synapses, :node1_id
add_index :synapses, :node2_id
add_index :mappings, [:map_id, :topic_id]
add_index :mappings, [:map_id, :synapse_id]
add_index :mappings, :map_id
add_index :mappings, :user_id
add_index :maps, :user_id
end
end

View file

@ -0,0 +1,8 @@
class RemoveAssetPathsFromMetacodes < ActiveRecord::Migration
def change
Metacode.all.each do |metacode|
metacode.icon = metacode.icon.gsub(/^\/assets\//, '')
metacode.save
end
end
end

View file

@ -9,21 +9,24 @@
# from scratch. The latter is a flawed and unsustainable approach (the more migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues). # you'll amass, the slower it'll run and the greater likelihood for issues).
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(:version => 20141121204712) do ActiveRecord::Schema.define(version: 20151025083043) do
create_table "in_metacode_sets", :force => true do |t| # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "in_metacode_sets", force: :cascade do |t|
t.integer "metacode_id" t.integer "metacode_id"
t.integer "metacode_set_id" t.integer "metacode_set_id"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
end end
add_index "in_metacode_sets", ["metacode_id"], :name => "index_in_metacode_sets_on_metacode_id" add_index "in_metacode_sets", ["metacode_id"], name: "index_in_metacode_sets_on_metacode_id", using: :btree
add_index "in_metacode_sets", ["metacode_set_id"], :name => "index_in_metacode_sets_on_metacode_set_id" add_index "in_metacode_sets", ["metacode_set_id"], name: "index_in_metacode_sets_on_metacode_set_id", using: :btree
create_table "mappings", :force => true do |t| create_table "mappings", force: :cascade do |t|
t.text "category" t.text "category"
t.integer "xloc" t.integer "xloc"
t.integer "yloc" t.integer "yloc"
@ -31,18 +34,26 @@ ActiveRecord::Schema.define(:version => 20141121204712) do
t.integer "synapse_id" t.integer "synapse_id"
t.integer "map_id" t.integer "map_id"
t.integer "user_id" t.integer "user_id"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
t.integer "mappable_id"
t.string "mappable_type"
end end
create_table "maps", :force => true do |t| add_index "mappings", ["map_id", "synapse_id"], name: "index_mappings_on_map_id_and_synapse_id", using: :btree
add_index "mappings", ["map_id", "topic_id"], name: "index_mappings_on_map_id_and_topic_id", using: :btree
add_index "mappings", ["map_id"], name: "index_mappings_on_map_id", using: :btree
add_index "mappings", ["mappable_id", "mappable_type"], name: "index_mappings_on_mappable_id_and_mappable_type", using: :btree
add_index "mappings", ["user_id"], name: "index_mappings_on_user_id", using: :btree
create_table "maps", force: :cascade do |t|
t.text "name" t.text "name"
t.boolean "arranged" t.boolean "arranged"
t.text "desc" t.text "desc"
t.text "permission" t.text "permission"
t.integer "user_id" t.integer "user_id"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
t.boolean "featured" t.boolean "featured"
t.string "screenshot_file_name" t.string "screenshot_file_name"
t.string "screenshot_content_type" t.string "screenshot_content_type"
@ -50,26 +61,28 @@ ActiveRecord::Schema.define(:version => 20141121204712) do
t.datetime "screenshot_updated_at" t.datetime "screenshot_updated_at"
end end
create_table "metacode_sets", :force => true do |t| add_index "maps", ["user_id"], name: "index_maps_on_user_id", using: :btree
create_table "metacode_sets", force: :cascade do |t|
t.string "name" t.string "name"
t.text "desc" t.text "desc"
t.integer "user_id" t.integer "user_id"
t.boolean "mapperContributed" t.boolean "mapperContributed"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
end end
add_index "metacode_sets", ["user_id"], :name => "index_metacode_sets_on_user_id" add_index "metacode_sets", ["user_id"], name: "index_metacode_sets_on_user_id", using: :btree
create_table "metacodes", :force => true do |t| create_table "metacodes", force: :cascade do |t|
t.text "name" t.text "name"
t.string "icon" t.string "icon"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
t.string "color" t.string "color"
end end
create_table "synapses", :force => true do |t| create_table "synapses", force: :cascade do |t|
t.text "desc" t.text "desc"
t.text "category" t.text "category"
t.text "weight" t.text "weight"
@ -77,19 +90,25 @@ ActiveRecord::Schema.define(:version => 20141121204712) do
t.integer "node1_id" t.integer "node1_id"
t.integer "node2_id" t.integer "node2_id"
t.integer "user_id" t.integer "user_id"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
end end
create_table "topics", :force => true do |t| add_index "synapses", ["node1_id", "node1_id"], name: "index_synapses_on_node1_id_and_node1_id", using: :btree
add_index "synapses", ["node1_id"], name: "index_synapses_on_node1_id", using: :btree
add_index "synapses", ["node2_id", "node2_id"], name: "index_synapses_on_node2_id_and_node2_id", using: :btree
add_index "synapses", ["node2_id"], name: "index_synapses_on_node2_id", using: :btree
add_index "synapses", ["user_id"], name: "index_synapses_on_user_id", using: :btree
create_table "topics", force: :cascade do |t|
t.text "name" t.text "name"
t.text "desc" t.text "desc"
t.text "link" t.text "link"
t.text "permission" t.text "permission"
t.integer "user_id" t.integer "user_id"
t.integer "metacode_id" t.integer "metacode_id"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
t.string "image_file_name" t.string "image_file_name"
t.string "image_content_type" t.string "image_content_type"
t.integer "image_file_size" t.integer "image_file_size"
@ -100,25 +119,28 @@ ActiveRecord::Schema.define(:version => 20141121204712) do
t.datetime "audio_updated_at" t.datetime "audio_updated_at"
end end
create_table "users", :force => true do |t| add_index "topics", ["metacode_id"], name: "index_topics_on_metacode_id", using: :btree
add_index "topics", ["user_id"], name: "index_topics_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "name" t.string "name"
t.string "email" t.string "email"
t.text "settings" t.text "settings"
t.string "code", :limit => 8 t.string "code", limit: 8
t.string "joinedwithcode", :limit => 8 t.string "joinedwithcode", limit: 8
t.string "crypted_password" t.string "crypted_password"
t.string "password_salt" t.string "password_salt"
t.string "persistence_token" t.string "persistence_token"
t.string "perishable_token" t.string "perishable_token"
t.datetime "created_at", :null => false t.datetime "created_at", null: false
t.datetime "updated_at", :null => false t.datetime "updated_at", null: false
t.string "encrypted_password", :limit => 128, :default => "" t.string "encrypted_password", limit: 128, default: ""
t.string "remember_token" t.string "remember_token"
t.datetime "remember_created_at" t.datetime "remember_created_at"
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "last_sign_in_at" t.datetime "last_sign_in_at"
t.string "last_sign_in_ip" t.string "last_sign_in_ip"
t.integer "sign_in_count", :default => 0 t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at" t.datetime "current_sign_in_at"
t.string "current_sign_in_ip" t.string "current_sign_in_ip"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
@ -130,6 +152,6 @@ ActiveRecord::Schema.define(:version => 20141121204712) do
t.integer "generation" t.integer "generation"
end end
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end end

24
metamaps-qa-steps.txt Normal file
View file

@ -0,0 +1,24 @@
Metamaps Test Suite
1) Log in to the interface
2) Create an account using your join code
3) Check your user's "generation"
4) Create three maps: private, public, and another public
5) Change the last map's permissions to commons
6) Change a map's name
7) Create a topic on map #1
8) Verify (in a private window or another browser) that the second user can't acccess map #1
9) Create a topic on map #2
10) Verify that the second user can't edit map #2
11) Create a topic on map #3
12) Verify that the second can edit map #3
13) Pull a topic from map #1 to map #3
14) Create a private topic on map #1
15) Verify that the private topic can be pulled from map #1 by the same user
16) Verify that the private topic can't be pulled from map #1 by another user
17) Login as admin. Change metacode sets.
18) Add a number of topics to one of your maps. Reload to see if they are still there.
19) Add a number of synapses to one of your maps. Reload to see if they are still there.
20) Rearrange one of your maps. Reload to see if the layout is preserved.
21) Set the screenshot for one of your maps, and verify the index of maps is updated.
22) Open two browsers on map #3 and verify that realtime editing works.

View file

@ -26,7 +26,7 @@
} }
body { body {
background: #d8d9da url(/assets/shattered_@2X.png); background: #d8d9da url(https://s3.amazonaws.com/metamaps-assets/site/shattered_%402X.png);
font-family: 'din-regular', helvetica, sans-serif; font-family: 'din-regular', helvetica, sans-serif;
color: #424242; color: #424242;
text-align: justify; text-align: justify;
@ -61,7 +61,7 @@
border-radius: 225px; border-radius: 225px;
-webkit-border-radius: 225px; -webkit-border-radius: 225px;
-moz-border-radius: 225px; -moz-border-radius: 225px;
background: url(/assets/monkeyselfie.jpg) no-repeat; background: url(https://s3.amazonaws.com/metamaps-assets/site/monkeyselfie.jpg) no-repeat;
float: left; float: left;
background-position:50% 20%; background-position:50% 20%;
background-size: 100%; background-size: 100%;

View file

@ -3,6 +3,7 @@
"description": "providing real-time sychronization for ruby on rails", "description": "providing real-time sychronization for ruby on rails",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"socket.io": "0.9.12" "socket.io": "0.9.12",
"node-uuid": "1.2.0"
} }
} }

View file

@ -1,7 +1,12 @@
var io = require('socket.io').listen(5001); var
io = require('socket.io').listen(5001),
signalServer = require('./signal'),
stunservers = [{"url": "stun:stun.l.google.com:19302"}];
function start() { function start() {
signalServer(io, stunservers);
io.on('connection', function (socket) { io.on('connection', function (socket) {
// 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

178
realtime/signal.js Normal file
View file

@ -0,0 +1,178 @@
var uuid = require('node-uuid');
module.exports = function(io, stunservers) {
var
activePeople = 0,
activeRooms = {};
function describeRoom(name) {
var clients = io.sockets.clients(name);
var result = {
clients: {}
};
clients.forEach(function (client) {
result.clients[client.id] = client.resources;
});
return result;
}
function safeCb(cb) {
if (typeof cb === 'function') {
return cb;
} else {
return function () {};
}
}
io.sockets.on('connection', function (client) {
activePeople += 1;
client.on('setDetails', function (details) {
client.profile = {
username: details.username,
image: details.image
};
client.broadcast.emit('presence', client.profile);
});
client.resources = {
screen: false,
video: true,
audio: false
};
// pass a message to another id
client.on('message', function (details) {
if (!details) return;
var otherClient = io.sockets.sockets[details.to];
if (!otherClient) return;
details.from = client.id;
otherClient.emit('message', details);
});
client.on('shareScreen', function () {
client.resources.screen = true;
});
client.on('unshareScreen', function (type) {
client.resources.screen = false;
removeFeed('screen');
});
client.on('join', join);
client.on('requestRoomCount', function(name) {
client.emit('room_count', {
room_id: name,
count: io.sockets.clients(name).length
});
});
client.on('requestActiveRooms', function() {
client.emit('rooms_count', Object.keys(activeRooms).length);
});
function removeFeed(type) {
if (client.room) {
io.sockets.in(client.room).emit('remove', {
id: client.id,
type: type
});
if (!type) {
client.leave(client.room);
}
io.sockets.emit('room_count', {
room_id: client.room,
count: io.sockets.clients(client.room).length
});
if (client.profile) {
client.broadcast.emit('vacated_room', {
room_id: client.room,
profile: client.profile
});
}
if (io.sockets.clients(client.room).length == 0) {
delete activeRooms[client.room];
io.sockets.emit('rooms_count', Object.keys(activeRooms).length);
}
if (!type) {
client.room = undefined;
}
}
}
function join(name, cb) {
// sanity check
if (typeof name !== 'string') return;
// leave any existing rooms
removeFeed();
safeCb(cb)(null, describeRoom(name));
client.join(name);
io.sockets.emit('room_count', {
room_id: name,
count: io.sockets.clients(name).length
});
if (client.profile) {
client.broadcast.emit('presence_room', {
room_id: name,
profile: client.profile
});
}
io.sockets.clients(name).forEach(function (s) {
if (s.profile) {
client.emit('presence_room', {
room_id: name,
profile: s.profile
});
}
});
client.room = name;
activeRooms[name] = true;
io.sockets.emit('rooms_count', Object.keys(activeRooms).length);
}
// we don't want to pass "leave" directly because the
// event type string of "socket end" gets passed too.
client.on('disconnect', function () {
removeFeed();
activePeople -= 1;
io.sockets.emit('users_count', activePeople);
if (client.profile) {
io.sockets.emit('vacated', client.profile);
}
});
client.on('leave', function () {
removeFeed();
});
client.on('create', function (name, cb) {
if (arguments.length == 2) {
cb = (typeof cb == 'function') ? cb : function () {};
name = name || uuid();
} else {
cb = name;
name = uuid();
}
// check if exists
if (io.sockets.clients(name).length) {
safeCb(cb)('taken');
} else {
join(name);
safeCb(cb)(null, name);
}
});
// tell client about stun and turn servers and generate nonces
client.emit('stunservers', stunservers || []);
client.emit('rooms_count', Object.keys(activeRooms).length);
io.sockets.emit('users_count', activePeople);
io.sockets.clients().forEach(function (socket) {
if (socket.id !== client.id && socket.profile) client.emit('presence', socket.profile);
});
});
};

111
tempFILE.js Normal file
View file

@ -0,0 +1,111 @@
socket.emit('setDetails', {
username: authData.twitter.username,
image: authData.twitter.cachedUserProfile.profile_image_url
});
$target.append(room.chat.$container);
room.chat.open();
room.join(function (err, roomDesc) {
attachMediaStream(webrtc.webrtc.localStream, localVideo.$video[0]);
function addVideo(v) {
// random position for now
var top = Math.floor((Math.random() * ($target.height() - 100)) + 1);
//var left = Math.floor((Math.random() * ($target.width() - 100)) + 1);
var right = Math.floor((Math.random() * (468 - 100)) + 1);
v.setParent($target);
$target.append(v.$container);
v.$container.css({
top: top + 'px',
right: right + 'px'
});
}
room.videoAdded(addVideo);
for (peer in room.videos) {
addVideo(room.videos[peer]);
}
});
C("localVideo", ["require", "exports", "module", "VideoView"], function (require, exports, module) {
var VideoView = require("VideoView");
function localVideo(opts, callback) {
var
$video = $('<video></video>').attr('id', opts.id),
localVideo = {
$video: $video,
view: new VideoView($video[0], $('body'), 'me', true, { DOUBLE_CLICK_TOLERANCE: 200 }),
};
return localVideo;
}
module.e = localVideo;
});
webrtc.on('readyToCall', function () {
app.readyToCall = true;
jQuery('body').append(localVideo.view.$container);
});
var
ChatView = c('ChatView'),
RoomTopicView = c('RoomTopicView'),
IOconnection = c("ioconnection"),
authUser = firebase.getAuth() || null,
videoId = 'video-wrapper',
localVideo = c("localVideo")({ id: videoId }),
//socket = new IOconnection({ url: socketUrl }),
webrtc = new SimpleWebRTC({
connection: socket,
localVideoEl: videoId,
remoteVideosEl: '',
detectSpeakingEvents: true,
autoAdjustMic: true,
autoRequestMedia: false,
localVideo: {
autoplay: true,
mirror: true,
muted: true
},
media: {
video: true,
audio: true
}
});
app = {
activeRoom: -1,
stats: {
activeRooms: 0,
activePeople: 0
},
webrtc: webrtc,
localVideo: localVideo,
readyToCall: false,
globalMessages: new Backbone.Collection(),
globalChat: null
};

View file

@ -6,235 +6,235 @@
# #
one: one:
name: Action name: Action
icon: /assets/icons/blueprint_96px/bp_action.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_action.png
color: #BD6C85 color: #BD6C85
two: two:
name: Activity name: Activity
icon: /assets/icons/blueprint_96px/bp_activity.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_activity.png
color: #6EBF65 color: #6EBF65
three: three:
name: Catalyst name: Catalyst
icon: /assets/icons/blueprint_96px/bp_catalyst.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_catalyst.png
color: #EF8964 color: #EF8964
four: four:
name: Closed name: Closed
icon: /assets/icons/blueprint_96px/bp_closedissue.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_closedissue.png
color: #ABB49F color: #ABB49F
five: five:
name: Process name: Process
icon: /assets/icons/blueprint_96px/bp_process.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_process.png
color: #BDB25E color: #BDB25E
six: six:
name: Future Dev name: Future Dev
icon: /assets/icons/blueprint_96px/bp_futuredev.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_futuredev.png
color: #25A17F color: #25A17F
seven: seven:
name: Group name: Group
icon: /assets/icons/blueprint_96px/bp_group.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_group.png
color: #7076BC color: #7076BC
eight: eight:
name: Implication name: Implication
icon: /assets/icons/blueprint_96px/bp_implication.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_implication.png
color: #83DECA color: #83DECA
nine: nine:
name: Insight name: Insight
icon: /assets/icons/blueprint_96px/bp_insight.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_insight.png
color: #B074AD color: #B074AD
ten: ten:
name: Intention name: Intention
icon: /assets/icons/blueprint_96px/bp_intention.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_intention.png
color: #BAEAFF color: #BAEAFF
eleven: eleven:
name: Knowledge name: Knowledge
icon: /assets/icons/blueprint_96px/bp_knowledge.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_knowledge.png
color: #60ACF7 color: #60ACF7
twelve: twelve:
name: Location name: Location
icon: /assets/icons/blueprint_96px/bp_location.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_location.png
color: #ABD9A7 color: #ABD9A7
thirteen: thirteen:
name: Need name: Need
icon: /assets/icons/blueprint_96px/bp_need.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_need.png
color: #D2A7D4 color: #D2A7D4
fourteen: fourteen:
name: Open Issue name: Open Issue
icon: /assets/icons/blueprint_96px/bp_openissue.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_openissue.png
color: #9BBF71 color: #9BBF71
fifteen: fifteen:
name: Opportunity name: Opportunity
icon: /assets/icons/blueprint_96px/bp_opportunity.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_opportunity.png
color: #889F64 color: #889F64
sixteen: sixteen:
name: Person name: Person
icon: /assets/icons/blueprint_96px/bp_person.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_person.png
color: #DE925F color: #DE925F
seventeen: seventeen:
name: Platform name: Platform
icon: /assets/icons/blueprint_96px/bp_platform.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_platform.png
color: #21C8FE color: #21C8FE
eighteen: eighteen:
name: Problem name: Problem
icon: /assets/icons/blueprint_96px/bp_problem.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_problem.png
color: #99CFC4 color: #99CFC4
nineteen: nineteen:
name: Resource name: Resource
icon: /assets/icons/blueprint_96px/bp_resource.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_resource.png
color: #C98C63 color: #C98C63
twenty: twenty:
name: Role name: Role
icon: /assets/icons/blueprint_96px/bp_role.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_role.png
color: #A8595D color: #A8595D
twenty-one: twenty-one:
name: Task name: Task
icon: /assets/icons/blueprint_96px/bp_task.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_task.png
color: #3397C4 color: #3397C4
twenty-two: twenty-two:
name: Trajectory name: Trajectory
icon: /assets/icons/blueprint_96px/bp_trajectory.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/blueprint/96px/bp_trajectory.png
color: #D3AA4C color: #D3AA4C
twenty-three: twenty-three:
name: Argument name: Argument
icon: /assets/icons/generics_96px/gen_argument.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_argument.png
color: #7FAEFD color: #7FAEFD
twenty-four: twenty-four:
name: Con name: Con
icon: /assets/icons/generics_96px/gen_con.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_con.png
color: #CF7C74 color: #CF7C74
twenty-five: twenty-five:
name: Subject name: Subject
icon: /assets/icons/generics_96px/gen_subject.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_subject.png
color: #8293D8 color: #8293D8
twenty-six: twenty-six:
name: Decision name: Decision
icon: /assets/icons/generics_96px/gen_decision.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_decision.png
color: #CCA866 color: #CCA866
twenty-seven: twenty-seven:
name: Event name: Event
icon: /assets/icons/generics_96px/gen_event.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_event.png
color: #F5854B color: #F5854B
twenty-eight: twenty-eight:
name: Example name: Example
icon: /assets/icons/generics_96px/gen_example.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_example.png
color: #618C61 color: #618C61
twenty-nine: twenty-nine:
name: Experience name: Experience
icon: /assets/icons/generics_96px/gen_experience.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_experience.png
color: #BE995F color: #BE995F
thirty: thirty:
name: Feedback name: Feedback
icon: /assets/icons/generics_96px/gen_feedback.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_feedback.png
color: #54A19D color: #54A19D
thirty-one: thirty-one:
name: Aim name: Aim
icon: /assets/icons/generics_96px/gen_aim.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_aim.png
color: #B0B0B0 color: #B0B0B0
thirty-two: thirty-two:
name: Good Practice name: Good Practice
icon: /assets/icons/generics_96px/gen_goodpractice.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_goodpractice.png
color: #BD9E86 color: #BD9E86
thirty-three: thirty-three:
name: Idea name: Idea
icon: /assets/icons/generics_96px/gen_idea.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_idea.png
color: #C4BC5E color: #C4BC5E
thirty-four: thirty-four:
name: List name: List
icon: /assets/icons/generics_96px/gen_list.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_list.png
color: #B7A499 color: #B7A499
thirty-five: thirty-five:
name: Media name: Media
icon: /assets/icons/generics_96px/gen_media.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_media.png
color: #6D94CC color: #6D94CC
thirty-six: thirty-six:
name: Metamap name: Metamap
icon: /assets/icons/generics_96px/gen_metamap.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_metamap.png
color: #AEA9FD color: #AEA9FD
thirty-seven: thirty-seven:
name: Model name: Model
icon: /assets/icons/generics_96px/gen_model.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_model.png
color: #B385BA color: #B385BA
thirty-eight: thirty-eight:
name: Note name: Note
icon: /assets/icons/generics_96px/gen_note.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_note.png
color: #A389A1 color: #A389A1
thirty-nine: thirty-nine:
name: Perspective name: Perspective
icon: /assets/icons/generics_96px/gen_perspective.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_perspective.png
color: #2EB6CC color: #2EB6CC
forty: forty:
name: Pro name: Pro
icon: /assets/icons/generics_96px/gen_pro.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_pro.png
color: #89B879 color: #89B879
forty-one: forty-one:
name: Project name: Project
icon: /assets/icons/generics_96px/gen_project.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_project.png
color: #85A050 color: #85A050
forty-two: forty-two:
name: Question name: Question
icon: /assets/icons/generics_96px/gen_question.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_question.png
color: #5CB3B3 color: #5CB3B3
forty-three: forty-three:
name: Reference name: Reference
icon: /assets/icons/generics_96px/gen_reference.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_reference.png
color: #A7A7A7 color: #A7A7A7
forty-four: forty-four:
name: Research name: Research
icon: /assets/icons/generics_96px/gen_research.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_research.png
color: #CD8E89 color: #CD8E89
forty-five: forty-five:
name: Status update name: Status update
icon: /assets/icons/generics_96px/gen_status.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_status.png
color: #EFA7C0 color: #EFA7C0
forty-six: forty-six:
name: Tool name: Tool
icon: /assets/icons/generics_96px/gen_tool.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_tool.png
color: #828282 color: #828282
forty-seven: forty-seven:
name: Wildcard name: Wildcard
icon: /assets/icons/generics_96px/gen_wildcard.png icon: https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_wildcard.png
color: #73C7DE color: #73C7DE