Compare commits

..

1 commit

Author SHA1 Message Date
Devin Howard ccd537458e update windows docs to use rubyinstaller.org 2016-10-11 15:30:54 +08:00
558 changed files with 24873 additions and 22242 deletions

View file

@ -1 +0,0 @@
app/assets/javascripts/metamaps.secret.bundle.js

View file

@ -8,7 +8,6 @@ engines:
enabled: true enabled: true
config: config:
languages: languages:
count_threshold: 3 # rule of three
ruby: ruby:
mass_threshold: 36 # default: 18 mass_threshold: 36 # default: 18
javascript: javascript:
@ -20,8 +19,6 @@ engines:
enabled: true enabled: true
rubocop: rubocop:
enabled: true enabled: true
exclude_fingerprints:
- 74f18007b920e8d81148d2f6a2756534
ratings: ratings:
paths: paths:
- 'Gemfile.lock' - 'Gemfile.lock'

View file

@ -20,7 +20,6 @@ module.exports = {
"rules": { "rules": {
"react/jsx-uses-react": [2], "react/jsx-uses-react": [2],
"react/jsx-uses-vars": [2], "react/jsx-uses-vars": [2],
"space-before-function-paren": [2, "never"],
"yoda": [2, "never", { "exceptRange": true }] "yoda": [2, "never", { "exceptRange": true }]
} }
} }

View file

@ -1,14 +1,10 @@
# Node JS env
export NODE_REALTIME_PORT='5000' # should match REALTIME_SERVER, below
# Rails env
export DB_USERNAME='postgres' export DB_USERNAME='postgres'
export DB_PASSWORD='3112' export DB_PASSWORD='3112'
export DB_HOST='localhost' export DB_HOST='localhost'
export DB_PORT='5432' export DB_PORT='5432'
export DB_NAME='metamaps' export DB_NAME='metamap002'
export REALTIME_SERVER='http://localhost:5000' export REALTIME_SERVER='http://localhost:5001'
export MAILER_DEFAULT_URL='localhost:3000' export MAILER_DEFAULT_URL='localhost:3000'
export DEVISE_MAILER_SENDER='team@metamaps.cc' export DEVISE_MAILER_SENDER='team@metamaps.cc'
@ -22,6 +18,7 @@ export SECRET_KEY_BASE='267c8a84f63963282f45bc3010eaddf027abfab58fc759d6e239c800
# export S3_BUCKET_NAME # export S3_BUCKET_NAME
# export AWS_ACCESS_KEY_ID # export AWS_ACCESS_KEY_ID
# export AWS_SECRET_ACCESS_KEY # export AWS_SECRET_ACCESS_KEY
# export SSO_KEY
# #
# export SMTP_DOMAIN # export SMTP_DOMAIN
# export SMTP_PASSWORD # export SMTP_PASSWORD

4
.gitignore vendored
View file

@ -15,7 +15,6 @@ app/assets/javascripts/webpacked
#secrets and config #secrets and config
.env .env
*.swp
# Ignore bundler config # Ignore bundler config
.bundle .bundle
@ -23,7 +22,6 @@ app/assets/javascripts/webpacked
# Ignore all logfiles and tempfiles. # Ignore all logfiles and tempfiles.
log/*.log log/*.log
tmp tmp
.tmp
coverage coverage
@ -31,5 +29,3 @@ coverage
*/.DS_Store */.DS_Store
.DS_Store? .DS_Store?
.vagrant .vagrant
gentle/
startserver.sh

View file

@ -12,18 +12,10 @@ Rails:
Enabled: true Enabled: true
Metrics/LineLength: Metrics/LineLength:
Max: 120 Max: 100
Metrics/AbcSize: Metrics/AbcSize:
Max: 16 Max: 16
Style/Documentation: Style/Documentation:
Enabled: false Enabled: false
Style/EmptyMethod:
EnforcedStyle: expanded
# I like this cop, but occasionally code is more readable without a guard clause,
# and I don't want to write rubocop:disable comments every time that happens
Style/GuardClause:
Enabled: false

View file

@ -1,7 +1,3 @@
if ENV['COVERAGE'] == 'on' if ENV['COVERAGE'] == 'on'
SimpleCov.start 'rails' do SimpleCov.start 'rails'
add_group 'Policies', 'app/policies'
add_group 'Services', 'app/services'
add_group 'Serializers', 'app/serializers'
end
end end

View file

@ -22,4 +22,3 @@ script:
addons: addons:
code_climate: code_climate:
repo_token: 479d3bf56798fbc7fff3fc8151a5ed09e8ac368fd5af332c437b9e07dbebb44e repo_token: 479d3bf56798fbc7fff3fc8151a5ed09e8ac368fd5af332c437b9e07dbebb44e
postgresql: "9.4"

18
Gemfile
View file

@ -1,12 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '2.3.0' ruby '2.3.0'
gem 'rails', '~> 5.0.0' gem 'rails', '~> 5.0.0'
gem 'active_model_serializers' gem 'active_model_serializers'
gem 'aws-sdk', '~> 2.7.0' gem 'aws-sdk'
gem 'best_in_place' gem 'best_in_place'
gem 'delayed_job' gem 'delayed_job'
gem 'delayed_job_active_record' gem 'delayed_job_active_record'
@ -17,41 +16,38 @@ gem 'exception_notification'
gem 'httparty' gem 'httparty'
gem 'json' gem 'json'
gem 'kaminari' gem 'kaminari'
gem 'mailboxer'
gem 'paperclip' gem 'paperclip'
gem 'pg' gem 'pg'
gem 'puma'
gem 'pundit' gem 'pundit'
gem 'pundit_extra' gem 'pundit_extra'
gem 'rack-attack' gem 'rack-attack'
gem 'rack-cors' gem 'rack-cors'
gem 'redis', '~> 3.3.3' gem 'redis'
gem 'slack-notifier' gem 'slack-notifier'
gem 'snorlax' gem 'snorlax'
gem 'sucker_punch' gem 'uservoice-ruby'
# asset stuff # asset stuff
gem 'coffee-rails'
gem 'jquery-rails' gem 'jquery-rails'
gem 'jquery-ui-rails' gem 'jquery-ui-rails'
gem 'sass-rails' gem 'sass-rails'
gem 'uglifier' gem 'uglifier'
group :test do group :test do
gem 'brakeman', require: false gem 'factory_girl_rails'
gem 'factory_bot_rails'
gem 'json-schema' gem 'json-schema'
gem 'rspec-rails' gem 'rspec-rails'
gem 'shoulda-matchers' gem 'shoulda-matchers'
gem 'simplecov', require: false gem 'simplecov', require: false
gem 'brakeman', require: false
end end
group :development, :test do group :development, :test do
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'faker'
gem 'pry-byebug' gem 'pry-byebug'
gem 'pry-rails' gem 'pry-rails'
gem 'rubocop', '~> 0.48.1' # match code climate https://github.com/tootsuite/mastodon/issues/1758
gem 'timecop'
gem 'tunemygc' gem 'tunemygc'
gem 'rubocop'
end end

View file

@ -1,297 +1,274 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (5.0.5) actioncable (5.0.0.1)
actionpack (= 5.0.5) actionpack (= 5.0.0.1)
nio4r (>= 1.2, < 3.0) nio4r (~> 1.2)
websocket-driver (~> 0.6.1) websocket-driver (~> 0.6.1)
actionmailer (5.0.5) actionmailer (5.0.0.1)
actionpack (= 5.0.5) actionpack (= 5.0.0.1)
actionview (= 5.0.5) actionview (= 5.0.0.1)
activejob (= 5.0.5) activejob (= 5.0.0.1)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.0.5) actionpack (5.0.0.1)
actionview (= 5.0.5) actionview (= 5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
rack (~> 2.0) rack (~> 2.0)
rack-test (~> 0.6.3) rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.0.5) actionview (5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.0, >= 1.0.2)
active_model_serializers (0.10.6) active_model_serializers (0.10.2)
actionpack (>= 4.1, < 6) actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6) activemodel (>= 4.1, < 6)
case_transform (>= 0.2) jsonapi (~> 0.1.1.beta2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.2) railties (>= 4.1, < 6)
activejob (5.0.5) activejob (5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.0.5) activemodel (5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
activerecord (5.0.5) activerecord (5.0.0.1)
activemodel (= 5.0.5) activemodel (= 5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
arel (~> 7.0) arel (~> 7.0)
activesupport (5.0.5) activesupport (5.0.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7) i18n (~> 0.7)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.5.2) addressable (2.3.8)
public_suffix (>= 2.0.2, < 4.0) arel (7.1.2)
arel (7.1.4)
ast (2.3.0) ast (2.3.0)
aws-sdk (2.7.0) aws-sdk (2.6.3)
aws-sdk-resources (= 2.7.0) aws-sdk-resources (= 2.6.3)
aws-sdk-core (2.7.0) aws-sdk-core (2.6.3)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-resources (2.7.0) aws-sdk-resources (2.6.3)
aws-sdk-core (= 2.7.0) aws-sdk-core (= 2.6.3)
aws-sigv4 (1.0.2)
bcrypt (3.1.11) bcrypt (3.1.11)
best_in_place (3.1.1) best_in_place (3.1.0)
actionpack (>= 3.2) actionpack (>= 3.2)
railties (>= 3.2) railties (>= 3.2)
better_errors (2.3.0) better_errors (2.1.1)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubi (>= 1.0.0) erubis (>= 2.6.6)
rack (>= 0.9.0) rack (>= 0.9.0)
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
brakeman (3.7.2) brakeman (3.4.0)
builder (3.2.3) builder (3.2.2)
byebug (9.1.0) byebug (9.0.5)
carrierwave (1.1.0) climate_control (0.0.3)
activemodel (>= 4.0.0) activesupport (>= 3.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
case_transform (0.2)
activesupport
climate_control (0.2.0)
cocaine (0.5.8) cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
coderay (1.1.2) coderay (1.1.1)
concurrent-ruby (1.0.5) coffee-rails (4.2.1)
debug_inspector (0.0.3) coffee-script (>= 2.2.0)
delayed_job (4.1.3) railties (>= 4.0.0, < 5.2.x)
activesupport (>= 3.0, < 5.2) coffee-script (2.4.1)
delayed_job_active_record (4.1.2) coffee-script-source
activerecord (>= 3.0, < 5.2) execjs
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
delayed_job (4.1.2)
activesupport (>= 3.0, < 5.1)
delayed_job_active_record (4.1.1)
activerecord (>= 3.0, < 5.1)
delayed_job (>= 3.0, < 5) delayed_job (>= 3.0, < 5)
devise (4.3.0) devise (4.2.0)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.2) railties (>= 4.1.0, < 5.1)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
diff-lcs (1.3) diff-lcs (1.2.5)
docile (1.1.5) docile (1.1.5)
doorkeeper (4.2.6) doorkeeper (4.2.0)
railties (>= 4.2) railties (>= 4.2)
dotenv (2.2.1) dotenv (2.1.1)
dotenv-rails (2.2.1) dotenv-rails (2.1.1)
dotenv (= 2.2.1) dotenv (= 2.1.1)
railties (>= 3.2, < 5.2) railties (>= 4.0, < 5.1)
erubi (1.6.1)
erubis (2.7.0) erubis (2.7.0)
exception_notification (4.2.2) exception_notification (4.2.1)
actionmailer (>= 4.0, < 6) actionmailer (>= 4.0, < 6)
activesupport (>= 4.0, < 6) activesupport (>= 4.0, < 6)
execjs (2.7.0) execjs (2.7.0)
factory_bot (4.8.2) ezcrypto (0.7.2)
factory_girl (4.7.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
factory_bot_rails (4.8.2) factory_girl_rails (4.7.0)
factory_bot (~> 4.8.2) factory_girl (~> 4.7.0)
railties (>= 3.0.0) railties (>= 3.0.0)
faker (1.8.4) globalid (0.3.7)
i18n (~> 0.5) activesupport (>= 4.1.0)
ffi (1.9.18) httparty (0.14.0)
globalid (0.4.0)
activesupport (>= 4.2.0)
httparty (0.15.6)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (0.9.3) i18n (0.7.0)
concurrent-ruby (~> 1.0)
jmespath (1.3.1) jmespath (1.3.1)
jquery-rails (4.3.1) jquery-rails (4.2.1)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1) jquery-ui-rails (5.0.5)
railties (>= 3.2.16) railties (>= 3.2.16)
json (2.1.0) json (1.8.3)
json-schema (2.8.0) json-schema (2.6.2)
addressable (>= 2.4) addressable (~> 2.3.8)
jsonapi-renderer (0.1.3) jsonapi (0.1.1.beta2)
kaminari (1.0.1) json (~> 1.8)
activesupport (>= 4.1.0) kaminari (0.17.0)
kaminari-actionview (= 1.0.1) actionpack (>= 3.0.0)
kaminari-activerecord (= 1.0.1) activesupport (>= 3.0.0)
kaminari-core (= 1.0.1)
kaminari-actionview (1.0.1)
actionview
kaminari-core (= 1.0.1)
kaminari-activerecord (1.0.1)
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
loofah (2.0.3) loofah (2.0.3)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.6.6) mail (2.6.4)
mime-types (>= 1.16, < 4) mime-types (>= 1.16, < 4)
mailboxer (0.15.1)
carrierwave (>= 0.5.8)
rails (>= 5.0.0)
method_source (0.8.2) method_source (0.8.2)
mime-types (3.1) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2016.0521)
mimemagic (0.3.2) mimemagic (0.3.2)
mini_portile2 (2.3.0) mini_portile2 (2.1.0)
minitest (5.11.1) minitest (5.9.1)
multi_xml (0.6.0) multi_xml (0.5.5)
nio4r (2.1.0) nio4r (1.2.1)
nokogiri (1.8.1) nokogiri (1.6.8)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
oauth (0.5.1)
orm_adapter (0.5.0) orm_adapter (0.5.0)
paperclip (5.2.0) paperclip (5.1.0)
activemodel (>= 4.2.0) activemodel (>= 4.2.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
cocaine (~> 0.5.5) cocaine (~> 0.5.5)
mime-types mime-types
mimemagic (~> 0.3.0) mimemagic (~> 0.3.0)
parser (2.4.0.2) parser (2.3.1.4)
ast (~> 2.3) ast (~> 2.2)
pg (0.21.0) pg (0.19.0)
pkg-config (1.1.7)
powerpack (0.1.1) powerpack (0.1.1)
pry (0.10.4) pry (0.10.4)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
pry-byebug (3.5.0) pry-byebug (3.4.0)
byebug (~> 9.1) byebug (~> 9.0)
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.6) pry-rails (0.3.4)
pry (>= 0.10.4) pry (>= 0.9.10)
public_suffix (3.0.0)
puma (3.10.0)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
pundit_extra (0.3.0) pundit_extra (0.3.0)
rack (2.0.3) rack (2.0.1)
rack-attack (5.0.1) rack-attack (5.0.1)
rack rack
rack-cors (1.0.1) rack-cors (0.4.0)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (5.0.5) rails (5.0.0.1)
actioncable (= 5.0.5) actioncable (= 5.0.0.1)
actionmailer (= 5.0.5) actionmailer (= 5.0.0.1)
actionpack (= 5.0.5) actionpack (= 5.0.0.1)
actionview (= 5.0.5) actionview (= 5.0.0.1)
activejob (= 5.0.5) activejob (= 5.0.0.1)
activemodel (= 5.0.5) activemodel (= 5.0.0.1)
activerecord (= 5.0.5) activerecord (= 5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
bundler (>= 1.3.0) bundler (>= 1.3.0, < 2.0)
railties (= 5.0.5) railties (= 5.0.0.1)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3) rails-dom-testing (2.0.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0, < 6.0)
nokogiri (>= 1.6) nokogiri (~> 1.6.0)
rails-html-sanitizer (1.0.3) rails-html-sanitizer (1.0.3)
loofah (~> 2.0) loofah (~> 2.0)
railties (5.0.5) railties (5.0.0.1)
actionpack (= 5.0.5) actionpack (= 5.0.0.1)
activesupport (= 5.0.5) activesupport (= 5.0.0.1)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.2.2) rainbow (2.1.0)
rake rake (11.3.0)
rake (12.3.0) redis (3.3.1)
rb-fsevent (0.10.2) responders (2.3.0)
rb-inotify (0.9.10) railties (>= 4.2.0, < 5.1)
ffi (>= 0.5.0, < 2) rspec-core (3.5.3)
redis (3.3.3) rspec-support (~> 3.5.0)
responders (2.4.0) rspec-expectations (3.5.0)
actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3)
rspec-core (3.6.0)
rspec-support (~> 3.6.0)
rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.5.0)
rspec-mocks (3.6.0) rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.5.0)
rspec-rails (3.6.1) rspec-rails (3.5.2)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.5.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.6.0) rspec-mocks (~> 3.5.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.5.0)
rspec-support (3.6.0) rspec-support (3.5.0)
rubocop (0.48.1) rubocop (0.43.0)
parser (>= 2.3.3.1, < 3.0) parser (>= 2.3.1.1, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0) ruby-progressbar (1.8.1)
sass (3.5.1) sass (3.4.22)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.6) sass-rails (5.0.6)
railties (>= 4.0.0, < 6) railties (>= 4.0.0, < 6)
sass (~> 3.1) sass (~> 3.1)
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0) sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3) tilt (>= 1.1, < 3)
shoulda-matchers (3.1.2) shoulda-matchers (3.1.1)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
simplecov (0.15.0) simplecov (0.12.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.2) simplecov-html (0.10.0)
slack-notifier (2.3.1) slack-notifier (1.5.1)
slop (3.6.0) slop (3.6.0)
snorlax (0.1.6) snorlax (0.1.6)
rails (> 4.1) rails (> 4.1)
sprockets (3.7.1) sprockets (3.7.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.1) sprockets-rails (3.2.0)
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sucker_punch (2.0.3) thor (0.19.1)
concurrent-ruby (~> 1.0.0) thread_safe (0.3.5)
thor (0.20.0) tilt (2.0.5)
thread_safe (0.3.6) tunemygc (1.0.68)
tilt (2.0.8) tzinfo (1.2.2)
timecop (0.9.1)
tunemygc (1.0.69)
tzinfo (1.2.4)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (3.2.0) uglifier (3.0.2)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unicode-display_width (1.3.0) unicode-display_width (1.1.1)
warden (1.2.7) uservoice-ruby (0.0.11)
ezcrypto (>= 0.7.2)
json (>= 1.7.5)
oauth (>= 0.4.7)
warden (1.2.6)
rack (>= 1.0) rack (>= 1.0)
websocket-driver (0.6.5) websocket-driver (0.6.4)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2) websocket-extensions (0.1.2)
@ -300,51 +277,48 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_model_serializers active_model_serializers
aws-sdk (~> 2.7.0) aws-sdk
best_in_place best_in_place
better_errors better_errors
binding_of_caller binding_of_caller
brakeman brakeman
coffee-rails
delayed_job delayed_job
delayed_job_active_record delayed_job_active_record
devise devise
doorkeeper doorkeeper
dotenv-rails dotenv-rails
exception_notification exception_notification
factory_bot_rails factory_girl_rails
faker
httparty httparty
jquery-rails jquery-rails
jquery-ui-rails jquery-ui-rails
json json
json-schema json-schema
kaminari kaminari
mailboxer
paperclip paperclip
pg pg
pry-byebug pry-byebug
pry-rails pry-rails
puma
pundit pundit
pundit_extra pundit_extra
rack-attack rack-attack
rack-cors rack-cors
rails (~> 5.0.0) rails (~> 5.0.0)
redis (~> 3.3.3) redis
rspec-rails rspec-rails
rubocop (~> 0.48.1) rubocop
sass-rails sass-rails
shoulda-matchers shoulda-matchers
simplecov simplecov
slack-notifier slack-notifier
snorlax snorlax
sucker_punch
timecop
tunemygc tunemygc
uglifier uglifier
uservoice-ruby
RUBY VERSION RUBY VERSION
ruby 2.3.0p0 ruby 2.3.0p0
BUNDLED WITH BUNDLED WITH
1.16.1 1.13.2

View file

@ -1,3 +1,3 @@
web: bundle exec puma -p $PORT web: bundle exec rails server -p $PORT
worker: bundle exec rake jobs:work worker: bundle exec rake jobs:work

View file

@ -2,45 +2,58 @@ Metamaps
======= =======
[![Build Status](https://travis-ci.org/metamaps/metamaps.svg?branch=develop)](https://travis-ci.org/metamaps/metamaps) [![Build Status](https://travis-ci.org/metamaps/metamaps.svg?branch=develop)](https://travis-ci.org/metamaps/metamaps)
[![Code Climate](https://codeclimate.com/github/metamaps/metamaps/badges/gpa.svg)](https://codeclimate.com/github/metamaps/metamaps)
## What is Metamaps? ## What is Metamaps?
Metamaps is a free and open-source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence. Metamaps is a free and open source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence.
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in an open beta. You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta.
Metamaps is developed and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch by using whichever of these channels you prefer: Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch by using whichever of these channels you prefer:
## How do I learn more? ## Community
- Contact: [team@metamaps.cc](mailto:team@metamaps.cc) or [@metamapps](https://twitter.com/metamapps) on Twitter - To send us a personal message or request an invite to the open beta, get in touch with us at team@metamaps.cc or @metamapps on Twitter.
- User Documentation: [docs.metamaps.cc](https://docs.metamaps.cc)
- User Community: [hylo.com/c/metamaps](https://www.hylo.com/c/metamaps)
- To see what we're developing, or to weigh in on what you'd like to see developed, see our [Metamaps Feedback and Features](https://trello.com/b/uFOA6a2x/metamaps-feedback-feature-ideas-requests) board on trello
- To follow along with, or contribute,to our design process, see our [Metamaps Design](https://trello.com/b/8HlCikOX/metamaps-design) board on trello
- To follow along with, or contribute to, our development process, see our [Github Issues and Pull Requests](https://github.com/metamaps/metamaps/issues)
- Request an invite to the open beta [here](https://metamaps.cc/request)
<!-- markdown hack to split two lists -->
- To send us a personal message get in touch with us via email, Twitter, or Hylo
- If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing]. - If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing].
- If you would like to get set up as a developer, that's great! Read on for help getting your development environment set up. - If you would like to get set up as a developer, that's great! Read on for help getting your development environment set up.
## Installation for local use or development of Metamaps ## Installation
First off is getting the code downloaded to your computer. You can download a zip file from github, but if you've got `git` you can just run `git clone https://github.com/metamaps/metamaps` in your terminal. If you are on Mac or Ubuntu you can use the following instructions to quickly get a local copy of metamaps up and running using a Vagrant virtualbox. Don't be intimidated, it's easy!
```
git clone git@github.com:metamaps/metamaps.git
```
Now ensure you have VirtualBox and Vagrant installed on your computer
```
cd metamaps
./bin/configure.sh
```
This will do all the setup steps to make Metamaps work with a bit of behind the scenes ninja magick.
There are instructions for setup on various platforms, with particular support for Mac and Ubuntu, which can be found here: To start servers which will run metamaps you can then run:
- [Mac Install Walkthrough][mac-installation] ```
- [Ubuntu Install Walkthrough][ubuntu-installation] ./bin/start
```
To stop them:
```
./bin/stop
```
With your webservers running, open a web browser and go to `http://localhost:3000`
If you prefer to isolate your install in a virtual machine, you may find it simpler to setup using Vagrant: You can sign in with the default account
- [Vagrant installation][vagrant-installation] email: `user@user.com`
password: `toolsplusconsciousness`
OR create a new account at `/join`, and use access code `qwertyui`
We don't promise support for Windows, but at one point we had it running and we've kept those docs available for reference Start mapping and programming!
- [Outdated Windows Walkthrough][windows-installation]
We haven't set up instructions for using Vagrant on Windows, but there are instructions for a manual setup here:
- [For Windows][windows-installation]
## Contributing guidelines
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
## Licensing information ## Licensing information
@ -50,13 +63,11 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
The license can be read [here][license]. The license can be read [here][license].
Copyright (c) 2017 Connor Turland Copyright (c) 2016 Connor Turland
[site-blog]: http://blog.metamaps.cc
[site-beta]: http://metamaps.cc [site-beta]: http://metamaps.cc
[license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE [license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE
[contributing]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md [contributing]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md
[contributing-issues]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md#reporting-bugs-and-other-issues [contributing-issues]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md#reporting-bugs-and-other-issues
[mac-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/MacInstallation.md
[ubuntu-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/UbuntuInstallation.md
[vagrant-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/VagrantInstallation.md
[windows-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/WindowsInstallation.md [windows-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/WindowsInstallation.md

1
Rakefile Executable file → Normal file
View file

@ -1,6 +1,5 @@
#!/usr/bin/env rake #!/usr/bin/env rake
# frozen_string_literal: true # frozen_string_literal: true
# Add your own tasks in files placed in lib/tasks ending in .rake, # Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

2
Vagrantfile vendored
View file

@ -37,7 +37,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = 'trusty64' config.vm.box = 'trusty64'
config.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' config.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box'
config.vm.network :forwarded_port, guest: 3000, host: 3000 config.vm.network :forwarded_port, guest: 3000, host: 3000
config.vm.network :forwarded_port, guest: 5000, host: 5000 config.vm.network :forwarded_port, guest: 5001, host: 5001
config.vm.network 'private_network', ip: '10.0.1.11' config.vm.network 'private_network', ip: '10.0.1.11'
config.vm.synced_folder '.', '/vagrant', nfs: true config.vm.synced_folder '.', '/vagrant', nfs: true

View file

@ -1,4 +1,3 @@
// eslint-disable spaced-comment
// JS and CSS bundles // JS and CSS bundles
//= link_directory ../javascripts .js //= link_directory ../javascripts .js
//= link_directory ../stylesheets .css //= link_directory ../stylesheets .css

BIN
app/assets/images/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
app/assets/images/user_sprite.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

View file

@ -1,21 +0,0 @@
/* global Metamaps */
/* erb variables from rails */
Metamaps.ServerData = Metamaps.ServerData || {}
Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>'
Metamaps.ServerData['user.png'] = '<%= asset_path('user.png') %>'
Metamaps.ServerData['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>'
Metamaps.ServerData['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>'
Metamaps.ServerData['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>'
Metamaps.ServerData['synapse16.png'] = '<%= asset_path('synapse16.png') %>'
Metamaps.ServerData['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>'
Metamaps.ServerData['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>'
Metamaps.ServerData['exploremaps_sprite.png'] = '<%= asset_path 'exploremaps_sprite.png' %>'
Metamaps.ServerData['map_control_sprite.png'] = '<%= asset_path 'map_control_sprite.png' %>'
Metamaps.ServerData['user_sprite.png'] = '<%= asset_path 'user_sprite.png' %>'
Metamaps.ServerData.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %>
Metamaps.ServerData.REALTIME_SERVER = '<%= ENV['REALTIME_SERVER'] %>'
Metamaps.ServerData.RAILS_ENV = '<%= ENV['RAILS_ENV'] %>'
Metamaps.ServerData.VERSION = '<%= METAMAPS_VERSION %>'
Metamaps.ServerData.BUILD = '<%= METAMAPS_BUILD %>'
Metamaps.ServerData.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>'

View file

@ -1,23 +0,0 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
/* eslint-disable spaced-comment */
//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require action_cable
//= require_directory ./lib
//= require ./cloudcarousel-secret
//= require ./metamaps.secret.bundle
//= require ./Metamaps.ServerData
//= require homepageVimeoFallback
/* eslint-enable spaced-comment */

View file

@ -10,13 +10,10 @@
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW. // GO AFTER THE REQUIRES BELOW.
// //
/* eslint-disable spaced-comment */
//= require jquery //= require jquery
//= require jquery-ui //= require jquery-ui
//= require jquery_ujs //= require jquery_ujs
//= require action_cable
//= require_directory ./lib //= require_directory ./lib
//= require ./src/Metamaps.Erb
//= require ./webpacked/metamaps.bundle //= require ./webpacked/metamaps.bundle
//= require ./Metamaps.ServerData //= require ./src/check-canvas-support
//= require homepageVimeoFallback
/* eslint-enable spaced-comment */

View file

@ -1,438 +0,0 @@
//////////////////////////////////////////////////////////////////////////////////
// CloudCarousel V1.0.5
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
// MIT License
//
// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
//
// Please retain this copyright header in all versions of the software
//////////////////////////////////////////////////////////////////////////////////
var matched, browser;
jQuery.uaMatch = function( ua ) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
matched = jQuery.uaMatch( navigator.userAgent );
browser = {};
if ( matched.browser ) {
browser[ matched.browser ] = true;
browser.version = matched.version;
}
// Chrome is Webkit, but Webkit is also Safari.
if ( browser.chrome ) {
browser.webkit = true;
} else if ( browser.webkit ) {
browser.safari = true;
}
jQuery.browser = browser;
(function($) {
// START Reflection object.
// Creates a reflection for underneath an image.
// IE uses an image with IE specific filter properties, other browsers use the Canvas tag.
// The position and size of the reflection gets updated by updateAll() in Controller.
function Reflection(img, reflHeight, opacity) {
var reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;
parent = $(img.parentNode);
this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
if ( !reflection.getContext && $.browser.msie) {
this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
reflection.src = img.src;
reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";
} else {
cntx = reflection.getContext("2d");
try {
$(reflection).attr({width: imageWidth, height: reflHeight});
cntx.save();
cntx.translate(0, imageHeight-1);
cntx.scale(1, -1);
cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
cntx.restore();
cntx.globalCompositeOperation = "destination-out";
gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
cntx.fillStyle = gradient;
cntx.fillRect(0, 0, imageWidth, reflHeight);
} catch(e) {
return;
}
}
// Store a copy of the alt and title attrs into the reflection
$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );
} //END Reflection object
// START Item object.
// A wrapper object for items within the carousel.
var Item = function(imgIn, options)
{
this.orgWidth = imgIn.width;
this.orgHeight = imgIn.height;
this.image = imgIn;
this.reflection = null;
this.alt = imgIn.alt;
this.title = imgIn.title;
this.imageOK = false;
this.options = options;
this.imageOK = true;
if (this.options.reflHeight > 0)
{
this.reflection = new Reflection(this.image, this.options.reflHeight, this.options.reflOpacity);
}
$(this.image).css('position','absolute'); // Bizarre. This seems to reset image width to 0 on webkit!
};// END Item object
// Controller object.
// This handles moving all the items, dealing with mouse clicks etc.
var Controller = function(container, images, options)
{
var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;
this.controlTimer = 0;
this.stopped = false;
//this.imagesLoaded = 0;
this.container = container;
this.xRadius = options.xRadius;
this.yRadius = options.yRadius;
this.showFrontTextTimer = 0;
this.autoRotateTimer = 0;
if (options.xRadius === 0)
{
this.xRadius = ($(container).width()/2.3);
}
if (options.yRadius === 0)
{
this.yRadius = ($(container).height()/6);
}
this.xCentre = options.xPos;
this.yCentre = options.yPos;
this.frontIndex = 0; // Index of the item at the front
// Start with the first item at the front.
this.rotation = this.destRotation = Math.PI/2;
this.timeDelay = 1000/options.FPS;
// Turn on the infoBox
if(options.altBox !== null)
{
$(options.altBox).css('display','block');
$(options.titleBox).css('display','block');
}
// Turn on relative position for container to allow absolutely positioned elements
// within it to work.
$(container).css({ position:'relative', overflow:'hidden'} );
$(options.buttonLeft).css('display','inline');
$(options.buttonRight).css('display','inline');
// Setup the buttons.
$(options.buttonLeft).bind('mouseup',this,function(event){
event.data.rotate(-1);
return false;
});
$(options.buttonRight).bind('mouseup',this,function(event){
event.data.rotate(1);
return false;
});
// START METAMAPS CODE
// Add code that makes tab and shift+tab scroll through metacodes
$('.new_topic').bind('keydown',this,function(event){
if (event.keyCode == 9 && event.shiftKey) {
$(container).show()
event.data.rotate(-1);
event.preventDefault();
event.stopPropagation();
} else if (event.keyCode == 9) {
$(container).show()
event.data.rotate(1);
event.preventDefault();
event.stopPropagation();
}
});
// END METAMAPS CODE
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
if (options.mouseWheel)
{
// START METAMAPS CODE
/*$('body').bind('mousewheel',this,function(event, delta) {
if (Metamaps.Create.newTopic.beingCreated &&
!Metamaps.Create.isSwitchingSet &&
!Metamaps.Create.newTopic.pinned) {
event.data.rotate(delta);
return false;
}
});*/
// END METAMAPS CODE
// ORIGINAL CODE
// $(container).bind('mousewheel',this,function(event, delta) {
// event.data.rotate(delta);
// return false;
// });
//
}
$(container).unbind('mouseover click').bind('mouseover click',this,function(event){
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
var text = $(event.target).attr('alt');
// If we have moved over a carousel item, then show the alt and title text.
if ( text !== undefined && text !== null )
{
clearTimeout(event.data.showFrontTextTimer);
$(options.altBox).html( ($(event.target).attr('alt') ));
//$(options.titleBox).html( ($(event.target).attr('title') ));
if ( options.bringToFront && event.type == 'click' )
{
$(options.titleBox).html( ($(event.target).attr('title') ));
// START METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
// END METAMAPS CODE
var idx = $(event.target).data('itemIndex');
var frontIndex = event.data.frontIndex;
//var diff = idx - frontIndex;
var diff = (idx - frontIndex) % images.length;
if (Math.abs(diff) > images.length / 2) {
diff += (diff > 0 ? -images.length : images.length);
}
event.data.rotate(-diff);
}
}
});
// START METAMAPS CODE - initialize newTopic.metacode
var first = $(this.container).find('img').get(0)
Metamaps.Create.newTopic.metacode = $(first).data('id')
// END METAMAPS CODE
// If we have moved out of a carousel item (or the container itself),
// restore the text of the front item in 1 second.
$(container).bind('mouseout',this,function(event){
var context = event.data;
clearTimeout(context.showFrontTextTimer);
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
context.autoRotate(); // Start auto rotation.
});
// Prevent items from being selected as mouse is moved and clicked in the container.
$(container).bind('mousedown',this,function(event){
event.data.container.focus();
return false;
});
container.onselectstart = function () { return false; }; // For IE.
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
// Shows the text from the front most item.
this.showFrontText = function()
{
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
// METAMAPS CODE
Metamaps.Create.newTopic.setMetacode($(items[this.frontIndex].image).attr('data-id'))
// NOT METAMAPS CODE
//$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
//$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
};
this.go = function()
{
if(this.controlTimer !== 0) { return; }
var context = this;
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
};
this.stop = function()
{
clearTimeout(this.controlTimer);
this.controlTimer = 0;
// METAMAPS CODE
$(container).hide()
// END METAMAPS CODE
};
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
this.rotate = function(direction)
{
this.frontIndex -= direction;
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
this.frontIndex %= items.length;
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
this.showFrontText();
this.go();
};
this.autoRotate = function()
{
if ( options.autoRotate !== 'no' )
{
var dir = (options.autoRotate === 'right')? 1 : -1;
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
}
};
// This is the main loop function that moves everything.
this.updateAll = function()
{
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
var smallRange = (1-minScale) * 0.5;
var w,h,x,y,scale,item,sinVal;
var change = (this.destRotation - this.rotation);
var absChange = Math.abs(change);
this.rotation += change * options.speed;
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
var itemsLen = items.length;
var spacing = (Math.PI / itemsLen) * 2;
//var wrapStyle = null;
var radians = this.rotation;
var isMSIE = $.browser.msie;
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
this.innerWrapper.style.display = 'none';
var style;
var px = 'px', reflHeight;
var context = this;
for (var i = 0; i<itemsLen ;i++)
{
item = items[i];
sinVal = funcSin(radians);
scale = ((sinVal+1) * smallRange) + minScale;
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
if (item.imageOK)
{
var img = item.image;
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
w = img.width = item.orgWidth * scale;
h = img.height = item.orgHeight * scale;
img.style.left = x + px ;
img.style.top = y + px;
if (item.reflection !== null)
{
reflHeight = options.reflHeight * scale;
style = item.reflection.element.style;
style.left = x + px;
style.top = y + h + options.reflGap * scale + px;
style.width = w + px;
if (isMSIE)
{
style.filter.finishy = (reflHeight / h * 100);
}else
{
style.height = reflHeight + px;
}
}
}
radians += spacing;
}
// Turn display back on.
this.innerWrapper.style.display = 'block';
// If we have a preceptable change in rotation then loop again next frame.
if ( absChange >= 0.001 )
{
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
}else
{
// Otherwise just stop completely.
this.stop();
}
}; // END updateAll
// Create an Item object for each image
// func = function(){return;ctx.updateAll();} ;
// Check if images have loaded. We need valid widths and heights for the reflections.
this.checkImagesLoaded = function()
{
var i;
for(i=0;i<images.length;i++) {
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
{
return;
}
}
for(i=0;i<images.length;i++) {
items.push( new Item( images[i], options ) );
$(images[i]).data('itemIndex',i);
}
// If all images have valid widths and heights, we can stop checking.
clearInterval(this.tt);
// METAMAPS COMMENT this.showFrontText();
this.autoRotate();
this.updateAll();
};
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
}; // END Controller object
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
$.fn.CloudCarousel = function(options) {
this.each( function() {
options = $.extend({}, {
reflHeight:0,
reflOpacity:0.5,
reflGap:0,
minScale:0.5,
xPos:0,
yPos:0,
xRadius:0,
yRadius:0,
altBox:null,
titleBox:null,
FPS: 30,
autoRotate: 'no',
autoRotateDelay: 1500,
speed:0.2,
mouseWheel: false,
bringToFront: false
},options );
// Create a Controller for each carousel.
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
});
return this;
};
})(jQuery);

View file

@ -1,29 +0,0 @@
/* global $ */
$(document).ready(function() {
if (window.location.pathname === '/') {
$.ajax({
type: 'GET',
url: 'https://i.vimeocdn.com/video/',
error: function(e) {
$('.homeVideo').hide()
$('.homeVideo').replaceWith($('<video/>', {
poster: '<%= asset_path('metamaps-intro-poster.webp') %>',
width: '560',
height: '315',
class: 'homeVideo',
controls: ''
}))
$('.homeVideo').append($('<source/>', {
src: 'https://metamaps.cc/videos/metamaps-intro.mp4',
type: 'video/mp4'
}))
$('.homeVideo').append(
'<p>You can watch our instruction video at ' +
'<a href="https://metamaps.cc/videos/metamaps-intro.mp4">' +
'https://metamaps.cc/videos/metamaps-intro.mp4</a>.'
)
}
})
}// if
})

Binary file not shown.

Binary file not shown.

View file

@ -1,161 +0,0 @@
// AjaxQ jQuery Plugin
// Copyright (c) 2012 Foliotek Inc.
// MIT License
// https://github.com/Foliotek/ajaxq
// Uses CommonJS, AMD or browser globals to create a jQuery plugin.
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var queues = {};
var activeReqs = {};
// Register an $.ajaxq function, which follows the $.ajax interface, but allows a queue name which will force only one request per queue to fire.
// opts can be the regular $.ajax settings plainObject, or a callback returning the settings object, to be evaluated just prior to the actual call to $.ajax.
$.ajaxq = function(qname, opts) {
if (typeof opts === "undefined") {
throw ("AjaxQ: queue name is not provided");
}
// Will return a Deferred promise object extended with success/error/callback, so that this function matches the interface of $.ajax
var deferred = $.Deferred(),
promise = deferred.promise();
promise.success = promise.done;
promise.error = promise.fail;
promise.complete = promise.always;
// Check whether options are to be evaluated at call time or not.
var deferredOpts = typeof opts === 'function';
// Create a deep copy of the arguments, and enqueue this request.
var clonedOptions = !deferredOpts ? $.extend(true, {}, opts) : null;
enqueue(function() {
// Send off the ajax request now that the item has been removed from the queue
var jqXHR = $.ajax.apply(window, [deferredOpts ? opts() : clonedOptions]);
// Notify the returned deferred object with the correct context when the jqXHR is done or fails
// Note that 'always' will automatically be fired once one of these are called: http://api.jquery.com/category/deferred-object/.
jqXHR.done(function() {
deferred.resolve.apply(this, arguments);
});
jqXHR.fail(function() {
deferred.reject.apply(this, arguments);
});
jqXHR.always(dequeue); // make sure to dequeue the next request AFTER the done and fail callbacks are fired
return jqXHR;
});
return promise;
// If there is no queue, create an empty one and instantly process this item.
// Otherwise, just add this item onto it for later processing.
function enqueue(cb) {
if (!queues[qname]) {
queues[qname] = [];
var xhr = cb();
activeReqs[qname] = xhr;
}
else {
queues[qname].push(cb);
}
}
// Remove the next callback from the queue and fire it off.
// If the queue was empty (this was the last item), delete it from memory so the next one can be instantly processed.
function dequeue() {
if (!queues[qname]) {
return;
}
var nextCallback = queues[qname].shift();
if (nextCallback) {
var xhr = nextCallback();
activeReqs[qname] = xhr;
}
else {
delete queues[qname];
delete activeReqs[qname];
}
}
};
// Register a $.postq and $.getq method to provide shortcuts for $.get and $.post
// Copied from jQuery source to make sure the functions share the same defaults as $.get and $.post.
$.each( [ "getq", "postq" ], function( i, method ) {
$[ method ] = function( qname, url, data, callback, type ) {
if ( $.isFunction( data ) ) {
type = type || callback;
callback = data;
data = undefined;
}
return $.ajaxq(qname, {
type: method === "postq" ? "post" : "get",
url: url,
data: data,
success: callback,
dataType: type
});
};
});
var isQueueRunning = function(qname) {
return (queues.hasOwnProperty(qname) && queues[qname].length > 0) || activeReqs.hasOwnProperty(qname);
};
var isAnyQueueRunning = function() {
for (var i in queues) {
if (isQueueRunning(i)) return true;
}
return false;
};
$.ajaxq.isRunning = function(qname) {
if (qname) return isQueueRunning(qname);
else return isAnyQueueRunning();
};
$.ajaxq.getActiveRequest = function(qname) {
if (!qname) throw ("AjaxQ: queue name is required");
return activeReqs[qname];
};
$.ajaxq.abort = function(qname) {
if (!qname) throw ("AjaxQ: queue name is required");
var current = $.ajaxq.getActiveRequest(qname);
delete queues[qname];
delete activeReqs[qname];
if (current) current.abort();
};
$.ajaxq.clear = function(qname) {
if (!qname) {
for (var i in queues) {
if (queues.hasOwnProperty(i)) {
queues[i] = [];
}
}
}
else {
if (queues[qname]) {
queues[qname] = [];
}
}
};
}));

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;
};

View file

@ -1,2 +0,0 @@
!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,o=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),n=o&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,a=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,i=(o||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,l,u,b,c,d,B,f;if(e=t.match(a),!e)throw new Error("invalid data URI");for(i=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),l=!!e[4],u=t.slice(e[0].length),b=l?atob(u):decodeURIComponent(u),c=new ArrayBuffer(b.length),d=new Uint8Array(c),B=0;B<b.length;B+=1)d[B]=b.charCodeAt(B);return o?new Blob([n?d:c],{type:i}):(f=new r,f.append(c),f.getBlob(i))};t.HTMLCanvasElement&&!e.toBlob&&(e.mozGetAsFile?e.toBlob=function(t,o,n){t(n&&e.toDataURL&&i?i(this.toDataURL(o,n)):this.mozGetAsFile("blob",o))}:e.toDataURL&&i&&(e.toBlob=function(t,e,o){t(i(this.toDataURL(e,o)))})),"function"==typeof define&&define.amd?define(function(){return i}):"object"==typeof module&&module.exports?module.exports=i:t.dataURLtoBlob=i}(window);
//# sourceMappingURL=canvas-to-blob.min.js.map

View file

@ -161,43 +161,40 @@ jQuery.browser = browser;
return false; return false;
}); });
// START METAMAPS CODE
// Add code that makes tab and shift+tab scroll through metacodes // Add code that makes tab and shift+tab scroll through metacodes
$('.new_topic').bind('keydown',this,function(event){ $('.new_topic').bind('keydown',this,function(event){
if (event.keyCode == 9) { if (event.keyCode == 9 && event.shiftKey) {
if (event.shiftKey) { event.data.rotate(-1);
event.data.rotate(-1) event.preventDefault();
} else { event.stopPropagation();
event.data.rotate(1) } else if (event.keyCode == 9) {
} event.data.rotate(1);
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
Metamaps.Create.newTopic.metacode = $(items[event.data.frontIndex].image).attr('data-id'); }
}
}); });
// END METAMAPS CODE
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel // You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
if (options.mouseWheel) if (options.mouseWheel)
{ {
// START METAMAPS CODE // START METAMAPS CODE
$('body').bind('mousewheel',this,function(event, delta) { $('body').bind('mousewheel',this,function(event, delta) {
if (Metamaps.Create.newTopic.beingCreated && if (Metamaps.Create.newTopic.beingCreated &&
!Metamaps.Create.isSwitchingSet && !Metamaps.Create.isSwitchingSet &&
!Metamaps.Create.newTopic.pinned) { !Metamaps.Create.newTopic.pinned) {
event.data.rotate(delta); event.data.rotate(delta);
return false; return false;
} }
}); });
// END METAMAPS CODE // END METAMAPS CODE
// ORIGINAL CODE /* ORIGINAL CODE
// $(container).bind('mousewheel',this,function(event, delta) { $(container).bind('mousewheel',this,function(event, delta) {
// event.data.rotate(delta); event.data.rotate(delta);
// return false; return false;
// }); });
// */
} }
$(container).unbind('mouseover click').bind('mouseover click',this,function(event){ $(container).bind('mouseover click',this,function(event){
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over. clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
var text = $(event.target).attr('alt'); var text = $(event.target).attr('alt');
@ -211,27 +208,22 @@ jQuery.browser = browser;
//$(options.titleBox).html( ($(event.target).attr('title') )); //$(options.titleBox).html( ($(event.target).attr('title') ));
if ( options.bringToFront && event.type == 'click' ) if ( options.bringToFront && event.type == 'click' )
{ {
$(options.titleBox).html( ($(event.target).attr('title') )); $(options.titleBox).html( ($(event.target).attr('title') ));
// START METAMAPS CODE // METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id'); Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
// END METAMAPS CODE // NOT METAMAPS CODE
var idx = $(event.target).data('itemIndex'); var idx = $(event.target).data('itemIndex');
var frontIndex = event.data.frontIndex; var frontIndex = event.data.frontIndex;
//var diff = idx - frontIndex; //var diff = idx - frontIndex;
var diff = (idx - frontIndex) % images.length; var diff = (idx - frontIndex) % images.length;
if (Math.abs(diff) > images.length / 2) { if (Math.abs(diff) > images.length / 2) {
diff += (diff > 0 ? -images.length : images.length); diff += (diff > 0 ? -images.length : images.length);
} }
event.data.rotate(-diff); event.data.rotate(-diff);
} }
} }
}); });
// START METAMAPS CODE - initialize newTopic.metacode
var first = $(this.container).find('img').get(0)
Metamaps.Create.newTopic.metacode = $(first).data('id')
// END METAMAPS CODE
// If we have moved out of a carousel item (or the container itself), // If we have moved out of a carousel item (or the container itself),
// restore the text of the front item in 1 second. // restore the text of the front item in 1 second.
$(container).bind('mouseout',this,function(event){ $(container).bind('mouseout',this,function(event){
@ -255,6 +247,11 @@ jQuery.browser = browser;
this.showFrontText = function() this.showFrontText = function()
{ {
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet. if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
// METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(items[this.frontIndex].image).attr('data-id');
//$('img.cloudcarousel').css({"background":"none", "width":"","height":""});
//$(items[this.frontIndex].image).css({"width":"45px","height":"45px"});
// NOT METAMAPS CODE
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title')); $(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt')); $(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
}; };

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();
};

View file

@ -0,0 +1,41 @@
var USERVOICE;
if(USERVOICE == undefined) {
USERVOICE = {};
}
USERVOICE.load = function (name, id, email, sso_token) {
// Include the UserVoice JavaScript SDK (only needed once on a page)
UserVoice=window.UserVoice||[];(function(){var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/wybK0nSMNuhlWkIKzTyWg.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s)})();
//
// UserVoice Javascript SDK developer documentation:
// https://www.uservoice.com/o/javascript-sdk
//
// Set colors
UserVoice.push(['set', {
accent_color: '#448dd6',
trigger_color: 'white',
trigger_background_color: 'rgba(46, 49, 51, 0.6)'
}]);
// Identify the user and pass traits
// To enable, replace sample data with actual user traits and uncomment the line
if (name) {
UserVoice.push(['setSSO', sso_token]);
UserVoice.push(['identify', {
'email': email, // Users email address
'name': name, // Users real name
'id': id, // Optional: Unique id of the user
}]);
}
// Add default trigger to the bottom-left corner of the window:
UserVoice.push(['addTrigger', { mode: 'contact', trigger_position: 'bottom-left' }]);
// Or, use your own custom trigger:
//UserVoice.push(['addTrigger', '#barometer_tab', { mode: 'contact' }]);
// Autoprompt for Satisfaction and SmartVote (only displayed under certain conditions)
UserVoice.push(['autoprompt', {}]);
};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,24 @@
/* global Metamaps */
/*
* Metamaps.Erb.js.erb
*/
/* erb variables from rails */
window.Metamaps = window.Metamaps || {}
Metamaps.Erb = {}
Metamaps.Erb['REALTIME_SERVER'] = '<%= ENV['REALTIME_SERVER'] %>'
Metamaps.Erb['RAILS_ENV'] = '<%= ENV['RAILS_ENV'] %>'
Metamaps.Erb['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>'
Metamaps.Erb['user.png'] = '<%= asset_path('user.png') %>'
Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>'
Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>'
Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>'
Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>'
Metamaps.Erb['import-example.png'] = '<%= asset_path('import-example.png') %>'
Metamaps.Erb['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>'
Metamaps.Erb['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>'
Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %>
Metamaps.VERSION = '<%= METAMAPS_VERSION %>'
Metamaps.BUILD = '<%= METAMAPS_BUILD %>'
Metamaps.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>'

View file

@ -0,0 +1,15 @@
// TODO document this user agent function
var labelType, useGradients, nativeTextSupport, animate
;(function () {
var ua = navigator.userAgent,
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
typeOfCanvas = typeof HTMLCanvasElement,
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
textSupport = nativeCanvasSupport && (typeof document.createElement('canvas').getContext('2d').fillText == 'function')
// I'm setting this based on the fact that ExCanvas provides text support for IE
// and that as of today iPhone/iPad current text support is lame
labelType = (!nativeCanvasSupport || (textSupport && !iStuff)) ? 'Native' : 'HTML'
nativeTextSupport = labelType == 'Native'
useGradients = nativeCanvasSupport
animate = !(iStuff || !nativeCanvasSupport)
})()

View file

@ -1,12 +0,0 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require ./special
*/

View file

@ -1,109 +0,0 @@
#metacodeSelector {
display: none;
}
.metacodeSelect {
border-top: 1px solid #DDD;
padding: 0;
background: #FFF;
.metacodeFilterInput {
width: 100px;
outline: none;
border: 0;
padding: 8px;
font-size: 14px;
line-height: 14px;
color: #424242;
font-family: 'din-medium', helvetica, sans-serif;
}
.metacodeList {
list-style: none;
background: #FFF;
li {
padding: 8px;
cursor: pointer;
&:hover, &.keySelect {
background: #4CAF50;
}
}
img {
width: 24px;
height: 24px;
display: inline-block;
vertical-align: middle;
padding-right: 6px;
}
}
}
.selectedMetacode {
float: left;
background: #FFF;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
padding: 5px 10px 5px 6px;
vertical-align: top;
border-right: 1px solid #DDD;
cursor: pointer;
}
.selectedMetacode:hover, .selectedMetacode.isBeingSelected {
background: #EDEDED;
}
.selectedMetacode img {
width: 24px;
height: 24px;
display: inline-block;
vertical-align: middle;
}
.selectedMetacode span {
vertical-align: middle;
}
.selectedMetacode .downArrow {
display: inline-block;
vertical-align: middle;
width: 0;
height: 0;
border-style: solid;
border-width: 8px 6px 0 6px;
border-color: #777 transparent transparent transparent;
margin-left: 2px;
margin-top: 4px;
}
.new_topic {
margin: 0;
margin-top: -17px;
white-space: nowrap;
}
#new_topic .twitter-typeahead {
position: relative !important;
top: 0;
left: 0;
}
.new_topic #topic_name,
.new_topic .tt-hint {
border-radius: none;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
.openMetacodeSwitcher {
top: -16px;
left: -16px;
}
#metacodeImg {
height: 120px;
width: 380px;
display: none;
position: absolute !important;
top: -30px;
z-index: -1;
}
#metacodeImgTitle {
display: none;
float: left;
width: 120px;
text-align: center;
margin-left: 110px;
}

View file

@ -56,15 +56,16 @@
} }
li.toggledOff { li.toggledOff {
opacity: 0.6; opacity: 0.4;
} }
} }
.centerContent { .blackBox {
width: 760px; width: 760px;
margin: 0 auto; margin: 0 auto;
padding: 80px 0 60px 20px; padding: 80px 0 60px 20px;
background: rgba(125, 125, 125, 0.4); background: rgba(0, 0, 0, 0.4);
color: white;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
@ -84,10 +85,10 @@
display: table-row; display: table-row;
} }
tr:nth-child(odd) { tr:nth-child(odd) {
background: rgba(125, 125, 125, 0.2); background: rgba(0, 0, 0, 0.2);
} }
tr:nth-child(even) { tr:nth-child(even) {
background: rgba(125, 125, 125, 0.3); background: rgba(0, 0, 0, 0.3);
} }
th, th,
td { td {

View file

@ -78,18 +78,11 @@ html {
} }
body { body {
background: #d8d9da url(<%= asset_path('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;
overflow-x: hidden; overflow-x: hidden;
&.controller-main,
&.controller-maps,
&.controller-topics,
&.controller-explore {
overflow-y: hidden;
}
} }
h1, h1,
h2, h2,
@ -193,6 +186,10 @@ button.button.btn-no:hover {
display: block; display: block;
width: 830px; width: 830px;
} }
.requestInvite {
display: block;
margin: -720px auto 0;
}
.new_session, .new_session,
.new_user, .new_user,
.edit_user, .edit_user,
@ -527,12 +524,10 @@ button.button.btn-no:hover {
left: -1000px; left: -1000px;
display: block; display: block;
position: absolute; position: absolute;
width: 340px;
margin: -40px 0 0 -35px; margin: -40px 0 0 -35px;
z-index: 1; z-index: 1;
} }
body:not(.action-conversation) .new_topic {
width: 340px;
}
#new_topic .twitter-typeahead { #new_topic .twitter-typeahead {
position: absolute !important; position: absolute !important;
@ -668,21 +663,9 @@ label {
position: relative; position: relative;
/*overflow:hidden; */ /*overflow:hidden; */
} }
.compressed { .main.compressed {
.upperRightUI { width: calc(100% - 300px);
right: 324px;
}
.upperRightMapButtons {
right: 434px;
}
.mapControls {
right: 324px;
}
.infoAndHelp {
right: 370px;
}
} }
#infovis-canvas { #infovis-canvas {
-webkit-touch-callout: none; -webkit-touch-callout: none;
-webkit-user-select: none; -webkit-user-select: none;
@ -783,9 +766,9 @@ label {
} }
.sidebarAccountIcon img { .sidebarAccountIcon img {
border-radius: 16px; border-radius: 16px;
width: 32px;
} }
.sidebarAccountBox { .sidebarAccountBox {
display: none;
height: auto; height: auto;
} }
.authenticated .sidebarAccountBox { .authenticated .sidebarAccountBox {
@ -826,7 +809,6 @@ label {
font-size: 14px; font-size: 14px;
line-height: 14px; line-height: 14px;
color: #757575; color: #757575;
cursor: pointer;
} }
.accountListItem:hover { .accountListItem:hover {
color: #424242; color: #424242;
@ -837,7 +819,7 @@ label {
position:absolute; position:absolute;
pointer-events:none; pointer-events:none;
background-repeat:no-repeat; background-repeat:no-repeat;
background-image: url(<%= asset_path('user_sprite.png') %>); background-image: url(<%= asset_data_uri('user_sprite.png') %>);
} }
.accountSettings .accountIcon { .accountSettings .accountIcon {
background-position: 0 0; background-position: 0 0;
@ -845,9 +827,6 @@ label {
.accountAdmin .accountIcon { .accountAdmin .accountIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.accountApps .accountIcon {
background-position: 0 -32px;
}
.accountInvite .accountIcon { .accountInvite .accountIcon {
background-position: 0 -64px; background-position: 0 -64px;
} }
@ -1048,6 +1027,7 @@ label[for="user_remember_me"] {
} }
.sidebarFilterBox { .sidebarFilterBox {
display:none;
width: 319px; width: 319px;
padding: 16px 0; padding: 16px 0;
overflow-y: auto; overflow-y: auto;
@ -1258,7 +1238,7 @@ h3.filterBox {
box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24); box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24);
} }
.rightclickmenu .rc-permission:hover > ul, .rightclickmenu .rc-permission:hover > ul,
.rightclickmenu .rc-metacode:hover #metacodeOptions > ul, .rightclickmenu .rc-metacode:hover > ul,
.rightclickmenu .rc-siblings:hover > ul { .rightclickmenu .rc-siblings:hover > ul {
display: block; display: block;
} }
@ -1287,7 +1267,7 @@ h3.filterBox {
.rightclickmenu li.toPrivate .rc-perm-icon { .rightclickmenu li.toPrivate .rc-perm-icon {
background-position: -24px 0; background-position: -24px 0;
} }
.rightclickmenu .rc-metacode #metacodeOptions > ul > li, .rightclickmenu .rc-metacode > ul > li,
.rightclickmenu .rc-siblings > ul > li { .rightclickmenu .rc-siblings > ul > li {
padding: 6px 24px 6px 8px; padding: 6px 24px 6px 8px;
white-space: nowrap; white-space: nowrap;
@ -1568,7 +1548,6 @@ h3.filterBox {
box-sizing: border-box; box-sizing: border-box;
margin: 0.75em; margin: 0.75em;
padding: 0.75em; padding: 0.75em;
padding-top: 0.85em;
height: 3em; height: 3em;
background-color: #AAB0FB; background-color: #AAB0FB;
border-radius: 0.3em; border-radius: 0.3em;
@ -1915,10 +1894,14 @@ input.collaboratorSearchField {
background-position: -32px 0; background-position: -32px 0;
} }
.yourMap .mapPermission:hover { .yourMap .mapPermission:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
cursor: pointer; cursor: pointer;
background-position: -32px 0;
} }
.yourMap .mapPermission.minimize { .yourMap .mapPermission.minimize {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
cursor: pointer; cursor: pointer;
background-position: 0 0;
} }
.mapInfoBox .mapPermission .permissionSelect { .mapInfoBox .mapPermission .permissionSelect {
list-style: none; list-style: none;
@ -2019,7 +2002,6 @@ input.collaboratorSearchField {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
display: none; display: none;
padding: 0 2px;
} }
.mapInfoShareIcon { .mapInfoShareIcon {
width: 24px; width: 24px;
@ -2059,43 +2041,6 @@ and it won't be important on password protected instances */
.yourMap .mapInfoDelete { .yourMap .mapInfoDelete {
display: block; display: block;
} }
.mapInfoButtonsWrapper .mapInfoThumbnail {
display: block;
background-image: url(<%= asset_path('screenshot_sprite.png') %>);
width: 32px;
height: 32px;
& > span {
bottom: -8px;
right: 2px;
font-size: 12px;
color: #e0e0e0;
&:hover {
color: white;
}
}
.tooltip {
display: none;
}
&:hover {
background-position: -32px 0;
.tooltip {
display: block;
position: absolute;
bottom: 30px;
background: black;
color: white;
border-radius: 2px;
padding: 3px 5px 2px 5px;
}
}
}
.mapInfoButtonsWrapper span { .mapInfoButtonsWrapper span {
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -2160,6 +2105,7 @@ and it won't be important on password protected instances */
} }
#lightbox_content { #lightbox_content {
width: 800px; width: 800px;
height: 500px;
max-height: 90vh; max-height: 90vh;
box-sizing: border-box; box-sizing: border-box;
overflow-y: auto; overflow-y: auto;
@ -2244,34 +2190,41 @@ and it won't be important on password protected instances */
color: #00bcd4; color: #00bcd4;
} }
.lightbox_links .lightboxAboutIcon { .lightbox_links .lightboxAboutIcon {
background-image: url(<%= asset_data_uri('about_sprite.png') %>);
background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
margin:10px auto; margin:10px auto;
} }
.icon_twitter .lightboxAboutIcon, #lightbox_metamapps .lightboxAboutIcon {
.icon_source_code .lightboxAboutIcon,
.icon_terms .lightboxAboutIcon {
background-image: url(<%= asset_data_uri('about_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
} }
.icon_twitter .lightboxAboutIcon { #lightbox_community .lightboxAboutIcon {
background-position: 0 0; background-position: -32px 0;
&:hover { }
#lightbox_source .lightboxAboutIcon {
background-position: -64px 0;
}
#lightbox_blog .lightboxAboutIcon {
background-position: -96px 0;
}
#lightbox_term .lightboxAboutIcon {
background-position: -128px 0;
}
#lightbox_metamapps:hover .lightboxAboutIcon {
background-position: 0 -32px; background-position: 0 -32px;
}
} }
.icon_source_code .lightboxAboutIcon { #lightbox_community:hover .lightboxAboutIcon {
background-position: -64px 0; background-position: -32px -32px;
&:hover { }
#lightbox_source:hover .lightboxAboutIcon {
background-position: -64px -32px; background-position: -64px -32px;
}
} }
.icon_terms .lightboxAboutIcon { #lightbox_blog:hover .lightboxAboutIcon {
background-position: -128px 0; background-position: -96px -32px;
&:hover { }
#lightbox_term:hover .lightboxAboutIcon {
background-position: -128px -32px; background-position: -128px -32px;
}
} }
/* jquery ui tabs */ /* jquery ui tabs */
@ -2315,9 +2268,6 @@ and it won't be important on password protected instances */
} }
/* switch metacode set */ /* switch metacode set */
#switchMetacodes > p {
margin: 16px 0 16px 0;
}
#metacodeSwitchTabs { #metacodeSwitchTabs {
width: 100%; width: 100%;
font-size: 17px; font-size: 17px;
@ -2325,43 +2275,28 @@ and it won't be important on password protected instances */
border: none; border: none;
background: none; background: none;
padding: 0; padding: 0;
}
.setDesc, #metacodeSwitchTabs .setDesc {
.selectAll, margin-bottom: 5px;
.selectNone { font-family: 'din-medium', helvetica, sans-serif;
margin-bottom: 5px; color: #424242;
font-family: 'din-medium', helvetica, sans-serif; font-size: 14px;
color: #424242; text-align: justify;
font-size: 14px; padding-right: 16px;
text-align: justify; }
padding-right: 16px; #switchMetacodes > p {
display: inline-block; margin: 16px 0 16px 0;
} }
#metacodeSwitchTabs > ul {
.selectAll, width: 130px;
.selectNone { }
float: right; #metacodeSwitchTabs > ul li {
cursor: pointer; font-size: 14px;
text-transform: uppercase;
&:hover, }
&.selected { #metacodeSwitchTabs li.ui-state-active a {
color: #00bcd4; color: #00BCD4;
} cursor: pointer;
}
& > ul {
width: 130px;
li {
font-size: 14px;
text-transform: uppercase;
}
}
li.ui-state-active a {
color: #00BCD4;
cursor: pointer;
}
} }
.metacodeSwitchTab { .metacodeSwitchTab {
max-height: 300px; max-height: 300px;
@ -2930,18 +2865,146 @@ and it won't be important on password protected instances */
color: #424242; color: #424242;
} }
/* Admin Pages */
.blackBox {
width: 760px;
margin: 0 auto;
padding: 20px 0 60px 20px;
background: rgba(0, 0, 0, 0.4);
color: white;
overflow: hidden;
position: relative;
}
.blackBox .metacodeSetsDescription {
width: 314px;
}
.blackBox td.metacodeSetDesc {
width: 314px;
word-wrap: break-word;
}
.blackBox .metacodeSetImage {
width: 36px;
height: 36px;
float: left;
}
.blackBox tr {
display: table-row;
}
.blackBox tr:nth-child(odd) {
background: rgba(0, 0, 0, 0.2);
}
.blackBox tr:nth-child(even) {
background: rgba(0, 0, 0, 0.3);
}
.blackBox th,
.blackBox td {
padding: 10px;
}
.blackBox td.iconURL {
max-width: 415px;
word-wrap: break-word;
}
.blackBox td.iconColor {
}
.blackBox .field {
margin: 15px 0 5px;
}
.blackBox label {
float: left;
width: 100px;
margin-right: 15px;
}
.blackBox input[type="text"] {
width: 336px;
height: 32px;
font-size: 15px;
direction: ltr;
-webkit-appearance: none;
appearance: none;
display: inline-block;
margin: 0;
padding: 0 8px;
background: #fff;
border: 1px solid #d9d9d9;
border-top: 1px solid #c0c0c0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
font: -webkit-small-control;
color: initial;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
display: inline-block;
text-align: start;
font-family: arial;
}
.blackBox input[type="text"]:hover,
.blackBox textarea:hover {
border: 1px solid #b9b9b9;
border-top: 1px solid #a0a0a0;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.blackBox textarea {
padding: 8px;
border: 1px solid #d9d9d9;
border-top: 1px solid #c0c0c0;
resize: none;
font: -webkit-small-control;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
text-align: start;
font-family: arial;
font-size: 15px;
line-height: 17px;
width: 318px;
}
.blackBox .allMetacodes {
padding: 5px 0;
}
.blackBox a.button {
margin-right: 20px;
line-height: 40px;
}
.blackBox a.button,
.blackBox input.add {
float: left;
margin-top: 5px;
height: 40px;
font-size: 17px;
width: auto;
padding: 0 30px;
cursor: pointer;
font-weight: normal;
}
.blackBox a.button:hover,
.blackBox input.add:hover {
-webkit-box-shadow: none;
box-shadow: none;
}
/* request */ /* request */
.requestInvite { #wrapper .requestInvite {
width: 700px; width: 700px;
margin: 0 auto;
padding: 0 0 60px 0;
background: #FFFFFF; background: #FFFFFF;
color: white; color: white;
height: calc(100% - 52px); height: 100%;
z-index: 1; overflow: hidden;
position: relative;
left: 50%;
margin-left: -350px;
margin-top: 52px;
} }
.home_bg { .home_bg {
@ -3011,21 +3074,3 @@ script.data-gratipay-username {
display: inline; display: inline;
float: left; float: left;
} }
.inline {
display: inline-block;
}
.topicFollow {
height: 24px;
line-height: 24px;
cursor: pointer;
font-family: helvetica, sans-serif;
float: left;
width: 72px;
text-align: right;
padding: 12px 0;
color: #4fb5c0;
font-size: 13px;
font-weight: bold;
}

View file

@ -1,14 +1,17 @@
.centerContent { .centerContent {
position: relative; position: relative;
margin: 0 auto; margin: 92px auto 0 auto;
width: auto; padding: 20px 0 60px 20px;
max-width: 800px; width: 760px;
overflow: hidden; overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);
background: #fff; background: #fff;
box-sizing: border-box; -webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #dcdcdc;
margin-bottom: 10px;
padding: 15px; padding: 15px;
font-family: 'din-regular', sans-serif;
} }
.centerContent .page-header { .centerContent .page-header {
@ -126,9 +129,3 @@
box-sizing: border-box; box-sizing: border-box;
border-radius: 2px; border-radius: 2px;
} }
.centerContent.withPadding {
margin-top: 1em;
margin-bottom: 1em;
}

View file

@ -1,19 +1,11 @@
$mid-gray: #8A8A8A;
$mid-gray-opacity: rgba(66, 66, 66, 0.6);
.nameCounter { .nameCounter {
position: absolute; position: absolute;
bottom: 1px; bottom: 1px;
right: 2px; right: 2px;
font-size: 11px; font-size: 11px;
font-family: helvetica, sans-serif; font-family: helvetica;
color: #727272; color: #727272;
line-height: 11px; line-height: 11px;
display: none;
}
.riek-editing + .nameCounter {
display: block;
} }
.nameCounter.forMap { .nameCounter.forMap {
@ -25,6 +17,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
} }
#center-container { #center-container {
position:relative; position:relative;
height:100%; height:100%;
@ -36,6 +29,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
.showcard { .showcard {
position:absolute; position:absolute;
display:none;
top:100px; top:100px;
left:100px; left:100px;
width:300px; width:300px;
@ -45,7 +39,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
z-index:2; z-index:2;
color: #424242; color: #424242;
border-radius:2px; border-radius:2px;
box-shadow: 2px 3px 3px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
.text { .text {
@ -56,6 +50,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
width:100%; width:100%;
height:100%; height:100%;
position: absolute; position: absolute;
display: none;
} }
.showcard .permission { .showcard .permission {
@ -67,6 +62,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
display:block; display:block;
position:relative; position:relative;
width:100%; width:100%;
min-height:360px;
z-index: 25; z-index: 25;
} }
.CardOnGraph.hasAttachment { .CardOnGraph.hasAttachment {
@ -74,11 +70,11 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
} }
.CardOnGraph .title { .CardOnGraph .title {
word-break: break-word; font-size: 18px;
font-size: 20px; line-height: 22px;
line-height: 24px;
display: table; display: table;
padding: 20px 0; padding: 8px 0 16px;
height: 80px;
text-align: center; text-align: center;
font-family: 'din-regular', sans-serif; font-family: 'din-regular', sans-serif;
width: 300px; width: 300px;
@ -97,11 +93,12 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
cursor: text; cursor: text;
} }
.showcard .title .riek-editing { .showcard .best_in_place_name textarea, .showcard .best_in_place_name input {
font-family: 'din-regular', sans-serif; font-family: 'din-regular', sans-serif;
color: #424242; color: #424242;
font-size: 20px; font-size: 18px;
line-height: 24px; line-height: 22px;
height: 15px;
padding: 5px 0; padding: 5px 0;
width: 100%; width: 100%;
margin: 0; margin: 0;
@ -115,76 +112,54 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
.CardOnGraph .scroll { .CardOnGraph .scroll {
display:block; display:block;
padding: 8px 0 8px 16px; padding: 8px 0 8px 16px;
height: 152px;
font-size: 13px; font-size: 13px;
line-height:15px; line-height:15px;
font-family: helvetica, sans-serif; font-family: helvetica, sans-serif;
overflow-y: auto; overflow-y: auto;
p.emptyDesc {
color: $mid-gray-opacity;
}
a.mdSupport {
color: #4fb5c0;
font-size: 11px;
display: none;
}
.riek-editing + .mdSupport {
display: block;
}
} }
.CardOnGraph.hasAttachment .scroll { .CardOnGraph.hasAttachment .scroll {
height: auto; height: auto;
} }
.CardOnGraph .desc .riek-editing { .CardOnGraph .best_in_place_desc textarea {
font-size: 13px; font-size: 13px;
line-height:15px; line-height:15px;
font-family: helvetica, sans-serif; font-family: helvetica, sans-serif;
color: #424242; color: #424242;
padding: 0; padding: 0;
width: 258px; width: 100%;
margin: 0; margin: 0;
border: 0; border: 0;
outline: none; outline: none;
font-size: 12px;
line-height: 15px;
background: none; background: none;
overflow-y: scroll; resize: none;
} }
/* .CardOnGraph .desc h3 {
* Styling for Markdown in topic cards font-style:normal;
*/ margin-top:5px;
.CardOnGraph .desc {
p, ol, ul {
padding: 0.15em 0;
}
h1, h2, h3, h4, h5, h6 {
font-style: normal;
padding: 0.25em 0;
}
ol,
ul {
margin-left: 1em;
}
a:hover {
text-decoration: underline;
opacity: 0.9;
}
} }
/* .CardOnGraph .desc ol,
* End Markdown styling .CardOnGraph .desc ul {
*/ margin-left: 1em;
.CardOnGraph .riek_desc { }
.CardOnGraph .desc a:hover {
text-decoration: underline;
opacity: 0.9;
}
.CardOnGraph .best_in_place_desc {
display:block; display:block;
padding-right: 26px; margin-top:2px;
padding-right: 18px;
margin-right: 8px;
} }
.canEdit .CardOnGraph .riek_desc:not(.riek-editing):hover { .canEdit .CardOnGraph .best_in_place_desc:hover {
background-image: url(<%= asset_data_uri('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;
@ -196,215 +171,155 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
} }
.CardOnGraph .links { .CardOnGraph .links {
position: relative; position:relative;
z-index: 2; border-bottom: 1px solid #BDBDBD;
border-top: 1px solid #BDBDBD;
.linkItem { background-color: #e0e0e0;
float: left;
z-index: 1;
position: relative;
color: #424242;
font-size: 14px;
line-height: 14px;
a {
color: #424242;
}
}
.icon {
padding: 0;
height: 48px;
margin-right: 10px;
.metacodeImage {
cursor: move;
position: absolute;
left: -18px;
top: 6px;
width: 36px;
height: 36px;
background-size:36px 36px;
background-position:0 0;
background-repeat:no-repeat;
}
}
} }
.CardOnGraph .info { .linkItem {
float:left;
height:46px;
z-index: 1;
position: relative; position: relative;
color: #424242;
font-size: 14px;
line-height:14px;
height:12px;
padding:17px 0;
}
.linkItem a {
color: #424242;
}
.linkItem { .CardOnGraph .icon {
float: left; position:absolute;
z-index: 1; width:100%;
position: relative; z-index:1;
color: $mid-gray-opacity; padding: 0;
font-size: 14px; height: 48px;
line-height: 14px; }
.linkItem.contributor {
margin-left:40px;
z-index:1;
padding:17px 16px 17px 30px;
position: relative;
}
.contributor .contributorIcon {
position: absolute;
top: 8px;
left: 0;
border-radius: 16px;
}
a { .contributor:hover .contributorName {
color: $mid-gray-opacity; display: block;
} }
}
.contributor { .contributorName {
bottom: 7px; display: none;
margin-left: 16px; position: absolute;
background: black;
text-align: center;
color: white;
border-radius: 2px;
font-family: din-regular;
line-height: 15px;
font-size: 12px;
padding: 3px 5px 2px;
white-space: nowrap;
margin-top: 36px;
margin-left: -32px;
}
.contributorIcon { .contributor div:before {
position: relative; content: '';
display: inline-block; position: absolute;
vertical-align: middle; top: 128%;
border-radius: 16px; left: 13px;
margin: 5px 5px 5px 0; margin-top: -30px;
top: 11px; width: 0;
left: 0; height: 0;
} border-bottom: 4px solid #000000;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
span { .linkItem.mapCount {
font-family: 'din-regular', sans-serif; margin-left: 12px;
font-size: 14px; width: 24px;
} padding:17px 0 17px 36px;
}
.linkItem.mapCount .mapCountIcon {
position: absolute;
top: 8px;
left: 0;
width: 32px;
height: 32px;
background-image: url(<%= asset_data_uri('map32_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0;
cursor: pointer;
}
.linkItem.mapCount:hover .mapCountIcon {
background-position: 0 -32px;
}
.contributorName { .linkItem.mapCount:hover .hoverTip {
font-family: din-regular; display: block;
margin-top: 20px; }
display: inline-block; .CardOnGraph .mapCount .tip, .CardonGraph .mapCount .hoverTip {
vertical-align: middle; top: 44px;
width: 97px; left: 0px;
padding: 0 8px 0 4px; font-size: 12px !important;
white-space: nowrap; }
overflow: hidden;
text-overflow: ellipsis;
}
}
.mapCount { .hoverTip {
padding:17px 38px 17px 0; white-space: nowrap;
width: 22px; font-family: 'din-regular';
text-align: right; top: 44px;
left: 0px;
font-size: 12px !important;
display: none;
position: absolute;
background: black;
color: white;
border-radius: 4px;
line-height: 17px;
padding: 3px 5px 2px;
z-index: 100;
}
.mapCountIcon {
position: absolute;
top: 8px;
right: 0;
width: 32px;
height: 32px;
background-image: url(<%= asset_data_uri('map32_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0;
cursor: pointer;
opacity: 0.6;
}
&:hover .mapCountIcon { .CardOnGraph .mapCount .tip:before, .CardOnGraph .mapCount .hoverTip:before {
background-position: 0 -32px; content: '';
} position: absolute;
top: 26px;
left: 10px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid #000000;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.tip, .hoverTip { .CardOnGraph .mapCount .tip li {
top: 44px; list-style-type: none;
right: 0px; white-space: nowrap;
font-size: 12px !important; overflow: hidden;
text-overflow: ellipsis;
padding: 6px 10px;
display: block;
height: 14px;
font-family: 'din-regular', helvetica, sans-serif;
font-size: 14px;
line-height: 14px;
position: relative;
}
&:before { .CardOnGraph .mapCount li.hideExtra {
content: ''; display: none;
position: absolute;
top: 26px;
right: 10px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
}
.hoverTip {
white-space: nowrap;
font-family: 'din-regular';
top: 44px;
font-size: 12px !important;
position: absolute;
background: $mid-gray;
color: white;
border-radius: 4px;
line-height: 17px;
padding: 3px 5px 2px;
z-index: 100;
}
.tip a {
color: white;
}
.tip a:hover {
color: #757575;
}
.tip li {
list-style-type: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 6px 10px;
display: block;
height: 14px;
font-family: 'din-regular', helvetica, sans-serif;
font-size: 14px;
line-height: 14px;
position: relative;
}
}
.synapseCount {
width: 22px;
padding:17px 38px 17px 0;
text-align: right;
margin-right: 4px;
.synapseCountIcon {
position: absolute;
top: 8px;
right: 0;
width: 32px;
height: 32px;
background-image: url(<%= asset_data_uri('synapse32_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0;
opacity: 0.6;
}
hover .synapseCountIcon {
background-position: 0 -32px;
}
.tip {
position: absolute;
background: $mid-gray;
width: auto;
top: 44px;
right: 0px;
color: white;
white-space: nowrap;
border-radius: 2px;
font-size: 12px !important;
font-family: 'din-regular';
line-height: 12px;
padding: 4px 4px 4px;
z-index: 100;
}
.tip:before {
content: '';
position: absolute;
margin-top: -8px;
right: 12px;
width: 0;
height: 0;
border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
}
} }
.showMore { .showMore {
@ -412,10 +327,66 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
color: #4FC059; color: #4FC059;
} }
.linkItem.mapPerm { .mapCount .tip a {
margin-right: 8px; color: white;
} }
.mapCount .tip a:hover {
color: #757575;
}
.linkItem.synapseCount {
margin-left: 2px;
width: 24px;
padding:17px 0 17px 32px;
}
.linkItem.synapseCount .synapseCountIcon {
position: absolute;
top: 8px;
left: 0;
width: 32px;
height: 32px;
background-image: url(<%= asset_data_uri('synapse32_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0;
}
.linkItem.synapseCount:hover .synapseCountIcon {
background-position: 0 -32px;
}
.CardOnGraph .synapseCount .tip {
position: absolute;
background: black;
width: auto;
top: 44px;
color: white;
white-space: nowrap;
border-radius: 2px;
font-size: 12px !important;
font-family: 'din-regular';
line-height: 12px;
padding: 4px 4px 4px;
z-index: 100;
}
.CardOnGraph .synapseCount:hover .tip {
display: block;
}
.CardOnGraph .synapseCount .tip:before {
content: '';
position: absolute;
margin-top: -8px;
margin-left: 6px;
width: 0;
height: 0;
border-bottom: 4px solid black;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.mapPerm { .mapPerm {
width: 32px; width: 32px;
height: 32px; height: 32px;
@ -437,10 +408,14 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
} }
.yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover { .yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
background-position: -32px 0;
cursor:pointer; cursor:pointer;
} }
.yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize { .yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize {
cursor: pointer; background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
background-position: 0 0;
cursor: pointer;
} }
.mapPerm .permissionSelect { .mapPerm .permissionSelect {
list-style: none; list-style: none;
@ -476,52 +451,60 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
} }
.CardOnGraph .metacodeTitle { .CardOnGraph .metacodeTitle {
font-family: 'din-regular'; font-style: italic;
font-family: 'vinyl';
text-transform: uppercase;
position: absolute;
line-height: 24px; line-height: 24px;
height: 26px; height:24px;
font-size: 18px; font-size: 24px;
padding: 13px 24px 9px 24px; display: none;
width: 90%;
padding: 13px 0 9px 10%;
background-color: #E0E0E0;
color: #424242; color: #424242;
width: 120px;
max-width: 120px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
} }
.permission.canEdit .metacodeTitle { .permission.canEdit .metacodeTitle {
cursor:pointer; cursor:pointer;
} }
.permission.canEdit .expandMetacodeSelect { .permission.canEdit .expandMetacodeSelect {
position: relative; position: absolute;
top: 2px; top: 16px;
left: 4px; right: 16px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(<%= asset_data_uri('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;
display: inline-block;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
} }
.permission.canEdit .minimize .expandMetacodeSelect { .permission.canEdit .minimize .expandMetacodeSelect {
} }
.CardOnGraph .metacodeName { .CardOnGraph .metacodeImage {
display: inline-block; cursor:move;
width:46px;
height:46px;
position:absolute;
left:-23px;
top:0;
background-size:46px 46px;
background-position:0 0;
background-repeat:no-repeat;
} }
#metacodeOptions {
display:none;
}
.CardOnGraph .metacodeSelect { .CardOnGraph .metacodeSelect {
display:none; display:none;
width:auto; width:auto;
z-index: 2; z-index: 2;
background: #EAEAEA;
white-space: nowrap;
position: absolute; position: absolute;
top: 48px; background: #EAEAEA;
box-shadow: 2px 2px 2px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16); left: 300px;
white-space: nowrap;
} }
.CardOnGraph .metacodeSelect ul { .CardOnGraph .metacodeSelect ul {
position: relative; position: relative;
@ -609,14 +592,15 @@ background-color: #E0E0E0;
position: relative; position: relative;
} }
.CardOnGraph .hoverForTip:hover .tip, #mapContribs:hover .tip { .CardOnGraph .hoverForTip:hover .tip, .mapCard .hoverForTip:hover .tip, #mapContribs:hover .tip {
display:block; display:block;
} }
.CardOnGraph .tip { .CardOnGraph .tip, .mapCard .tip {
display:none;
position: absolute; position: absolute;
background: $mid-gray; background: black;
top: 35px; top: 35px;
right: 0; left: 0;
color: white; color: white;
border-radius: 4px; border-radius: 4px;
font-size:15px !important; font-size:15px !important;
@ -625,18 +609,21 @@ background-color: #E0E0E0;
z-index:100; z-index:100;
} }
#embedlyLink {
display: none;
}
#embedlyLinkLoader { #embedlyLinkLoader {
margin: 0 auto; margin: 0 auto;
width: 28px; width: 28px;
} }
.CardOnGraph .link-adder { .CardOnGraph .attachments {
border-top: 1px solid #BDBDBD;
width:100%; width:100%;
height:47px; height:47px;
position: relative;
} }
.link-adder a { .attachments a {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -695,9 +682,9 @@ background-color: #E0E0E0;
} }
#addLinkInput input{ #addLinkInput input{
padding: 9px 27px 9px 31px; padding: 9px 7px 9px 31px;
height: 12px; height: 12px;
width: 210px; width: 198px;
margin: 0 0 0 0; margin: 0 0 0 0;
border: none; border: none;
outline: none; outline: none;
@ -751,6 +738,7 @@ font-family: 'din-regular', helvetica, sans-serif;
-moz-border-radius-bottomright: 8px; -moz-border-radius-bottomright: 8px;
-webkit-border-bottom-right-radius: 8px; -webkit-border-bottom-right-radius: 8px;
border-bottom-right-radius: 8px; border-bottom-right-radius: 8px;
display: none;
margin: 8px; margin: 8px;
} }
@ -837,10 +825,10 @@ font-family: 'din-regular', helvetica, sans-serif;
line-height: 16px; line-height: 16px;
} }
.canEdit span.titleWrapper:hover { .canEdit #edit_synapse_desc:hover {
background-image: url(<%= asset_data_uri('edit.png') %>); background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 95% 95%; background-position: 164px center;
cursor: text; cursor: text;
} }
@ -964,14 +952,160 @@ font-family: 'din-regular', helvetica, sans-serif;
background-position: 0 -24px; background-position: 0 -24px;
} }
/* Map Cards */
.map {
display:inline-block;
width:220px;
height:340px;
font-size: 12px;
text-align: left;
overflow: visible;
background: #e8e8e8;
border-radius:2px;
margin:16px 16px 16px 19px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
}
.map:hover {
background: #dcdcdc;
}
.map.newMap {
float: left;
position: relative;
}
.map.newMap a {
height: 340px;
display: block;
position: relative;
}
.newMap .newMapImage {
display: block;
width: 72px;
height: 72px;
background-image: url("<%= asset_data_uri('newmap_sprite.png') %>");
background-repeat: no-repeat;
background-position: 0 0;
position: absolute;
left: 50%;
margin-left: -36px;
top: 50%;
margin-top: -36px;
}
.map:hover .newMapImage {
background-position: 0 -72px;
}
.newMap span {
font-family: 'din-regular', sans-serif;
font-size: 18px;
line-height: 22px;
text-align: center;
display: block;
padding-top: 220px;
}
.mapCard {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-box-direction: normal;
-moz-box-direction: normal;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
position:relative;
width:100%;
height:308px;
padding: 16px 0;
color: #424242;
}
.mapCard .title {
word-wrap: break-word;
font-size:18px;
line-height:22px;
height: 44px;
display:block;
padding: 0 16px;
text-align: center;
-webkit-box-flex: none; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: none; /* OLD - Firefox 19- */
-webkit-flex: none; /* Chrome */
-ms-flex: none; /* IE 10 */
flex: none; /* NEW, Spec - Opera 12.1, Firefox 20+ */
font-family: 'din-regular', sans-serif;
}
.mapCard .mapScreenshot {
width: 188px;
height: 126px;
padding: 8px 16px;
}
.mapCard .mapScreenshot img {
width: 188px;
height: 126px;
border-radius: 2px;
}
.mapCard .scroll {
display:block;
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
padding:0 16px 8px;
font-family: helvetica, sans-serif;
font-style: italic;
font-size: 12px;
word-wrap: break-word;
}
.mCS_no_scrollbar {
padding-right: 5px;
}
.mapCard .mapMetadata {
font-family: 'din-regular', sans-serif;
font-size: 12px;
position:relative;
border-top: 1px solid #BDBDBD;
-webkit-box-flex: none; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: none; /* OLD - Firefox 19- */
-webkit-flex: none; /* Chrome */
-ms-flex: none; /* IE 10 */
flex: none; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.mapCard .metadataSection {
padding: 8px 16px 0 16px;
width: 78px;
float: left;
}
.mapPermission {
font-family: 'din-medium', sans-serif;
}
.cCountColor {
font-family: 'din-medium', sans-serif;
color: #DB5D5D;
}
.tCountColor {
font-family: 'din-medium', sans-serif;
color: #4FC059;
}
.sCountColor {
font-family: 'din-medium', sans-serif;
color: #DAB539;
}
/* mapper card */ /* mapper card */
.mapper { .mapper {
display: inline-block; float: left;
vertical-align: bottom;
width:220px; width:220px;
height:340px; height:340px;
font-size: 12px; font-size: 12px;
@ -979,7 +1113,7 @@ font-family: 'din-regular', helvetica, sans-serif;
overflow: visible; overflow: visible;
background: #E0E0E0; background: #E0E0E0;
border-radius:2px; border-radius:2px;
margin:16px; margin:16px 16px 16px 19px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
@ -1003,10 +1137,10 @@ font-family: 'din-regular', helvetica, sans-serif;
font-size: 24px; font-size: 24px;
text-align: center; text-align: center;
margin-top: 24px; margin-top: 24px;
padding: 0 5%; padding: 0 16px;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
width: 90%; width: 189px;
overflow: hidden; overflow: hidden;
} }

View file

@ -28,9 +28,6 @@
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box;
padding-top: 92px;
overflow-y: auto;
} }
/*.animations { /*.animations {
@ -47,9 +44,23 @@
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
}*/ }*/
.mapElement {
display: none;
}
.mapPage .mapElement, .topicPage .mapElement {
display: block;
}
.mapPage .mapElementHidden {
display:none;
}
.topicPage .starMap {
display: none;
}
/* loading */ /* loading */
#loading { #loading {
display: none;
width: 28px; width: 28px;
height: 28px; height: 28px;
position: fixed; position: fixed;
@ -168,14 +179,10 @@
} }
.upperRightMapButtons { .upperRightMapButtons {
right: 138px; top: -42px; /* puts it just offscreen */
padding-right: 7px;
border-right: 1px solid #747474;
} }
.unauthenticated .upperRightMapButtons { .mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons {
right: 115px; top: 0;
padding-right: 0;
border-right: none;
} }
.upperRightIcon { .upperRightIcon {
@ -185,47 +192,30 @@
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
} }
.sidebarFilterIcon { .sidebarFilterIcon {
background-position: -32px 0;
}
.sidebarForkIcon {
background-position: -64px 0; background-position: -64px 0;
} }
.addMap { .sidebarForkIcon {
background-position: -96px 0; background-position: -96px 0;
} }
.notificationsIcon { .addMap {
background-position: -128px 0; background-position: -128px 0;
margin-right: 10px; // make it look more natural next to the account menu icon margin-right:10px;
}
.notificationsIcon:hover {
background-position: -128px -32px;
}
.importDialog:hover {
background-position: 0 -32px;
} }
.sidebarFilterIcon:hover { .sidebarFilterIcon:hover {
background-position: -32px -32px;
}
.sidebarForkIcon:hover {
background-position: -64px -32px; background-position: -64px -32px;
} }
.addMap:hover { .sidebarForkIcon:hover {
background-position: -96px -32px; background-position: -96px -32px;
} }
.addMap:hover {
background-position: -128px -32px;
margin-right:10px;
}
/* end upperRightUI */ /* end upperRightUI */
/* map wrapper */
.mapWrapper {
position:absolute;
width: 100%;
height: 100%;
}
/* end map wrapper */
/* yield */ /* yield */
@ -346,15 +336,22 @@
/* infoAndHelp */ /* infoAndHelp */
.openCheatsheet .tooltipsAbove { .mapPage .infoAndHelp, .topicPage .infoAndHelp {
right: 70px;
}
.mapPage .openCheatsheet .tooltipsAbove, .topicPage .openCheatsheet .tooltipsAbove {
right: 1px; right: 1px;
left: auto; left: auto;
} }
.unauthenticated .homePage .infoAndHelp {
display:none;
}
.infoAndHelp { .infoAndHelp {
position: absolute; position: absolute;
bottom: 20px; bottom: 20px;
right: 70px; right: 20px;
z-index: 3; z-index: 3;
width: auto; width: auto;
font-style: italic; font-style: italic;
@ -375,13 +372,22 @@
} }
.mapInfoIcon { .mapInfoIcon {
position: relative; position: relative;
background-image: url(<%= asset_path('mapinfo_sprite.png') %>); top: 56px; /* puts it just offscreen */
background-repeat:no-repeat; background-image: url(<%= asset_path('mapinfo_sprite.png') %>);
background-repeat:no-repeat;
} }
.mapInfoIcon:hover { .mapInfoIcon:hover {
background-position: 0 -32px; background-position: 0 -32px;
} }
.mapPage .mapInfoIcon {
top: 0;
}
.importDialog {
background-image: url(<%= asset_path('import.png') %>);
background-position: 0 0;
background-repeat: no-repeat;
width: 32px;
}
.starMap { .starMap {
background-image: url(<%= asset_path('starmap_sprite.png') %>); background-image: url(<%= asset_path('starmap_sprite.png') %>);
background-position: 0 0; background-position: 0 0;
@ -398,6 +404,9 @@
background-position: 0 0; background-position: 0 0;
} }
.unauthenticated .mapPage .starMap {
display: none;
}
/* end infoAndHelp */ /* end infoAndHelp */
@ -406,17 +415,24 @@
.mapControls { .mapControls {
position: absolute; position: absolute;
bottom: 24px; bottom: 24px;
right:24px; right:-32px; /* puts it just offscreen */
width:32px; width:32px;
z-index: 3; z-index: 3;
} }
.mapPage .mapControls, .topicPage .mapControls {
right: 24px;
}
.topicPage .zoomExtents {
display: none;
}
.mapControl { .mapControl {
width:32px; width:32px;
height:32px; height:32px;
background-color: #424242; background-color: #424242;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
cursor:pointer; cursor:pointer;
} }
@ -424,6 +440,19 @@
z-index: 4; z-index: 4;
} }
.takeScreenshot {
margin-bottom: 5px;
border-radius: 2px;
background-image: url(<%= asset_path 'screenshot_sprite.png' %>);
display: none;
}
.takeScreenshot:hover {
background-position: -32px 0;
}
.canEditMap .takeScreenshot {
display: block;
}
.zoomExtents { .zoomExtents {
margin-bottom:5px; margin-bottom:5px;
border-radius: 2px; border-radius: 2px;
@ -434,8 +463,8 @@
background-position: -32px 0; background-position: -32px 0;
} }
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .notificationsIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder, .zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .takeScreenshot:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
.mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips, .importDialog:hover .tooltipsUnder, .starMap:hover .tooltipsAbove, .openMetacodeSwitcher:hover .tooltipsAbove, .pinCarousel:not(.isPinned):hover .tooltipsAbove.helpPin, .pinCarousel.isPinned:hover .tooltipsAbove.helpUnpin { .mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips, importDialog:hover .tooltipsAbove, .starMap:hover .tooltipsAbove, .openMetacodeSwitcher:hover .tooltipsAbove, .pinCarousel:not(.isPinned):hover .tooltipsAbove.helpPin, .pinCarousel.isPinned:hover .tooltipsAbove.helpUnpin {
display: block; display: block;
} }
@ -491,16 +520,9 @@
font-style: normal; font-style: normal;
} }
.importDialog .tooltipsUnder {
left: -22px;
}
.sidebarFilterIcon .tooltipsUnder { .sidebarFilterIcon .tooltipsUnder {
margin-left: -4px; margin-left: -4px;
} }
.notificationsIcon .tooltipsUnder {
left: -20px;
}
.sidebarForkIcon .tooltipsUnder { .sidebarForkIcon .tooltipsUnder {
margin-left: -34px; margin-left: -34px;
@ -556,12 +578,16 @@
left: -8px; left: -8px;
} }
.openCheatsheet .tooltipsAbove {
left: -4px;
}
.sidebarAccountIcon .tooltipsUnder { .sidebarAccountIcon .tooltipsUnder {
margin-left: -12px; margin-left: -12px;
margin-top: 40px; margin-top: 40px;
} }
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .chat-button div.tooltips::after { .zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .takeScreenshot div:after, .chat-button div.tooltips::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 57%; top: 57%;
@ -574,12 +600,7 @@
border-bottom: 5px solid transparent; border-bottom: 5px solid transparent;
} }
.addMap div:after, .sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after {
.importDialog div:after,
.sidebarForkIcon div:after,
.sidebarFilterIcon div:after,
.notificationsIcon div:after,
.sidebarAccountIcon .tooltipsUnder:after {
content: ''; content: '';
position: absolute; position: absolute;
right: 40%; right: 40%;
@ -590,15 +611,9 @@
border-left: 5px solid transparent; border-left: 5px solid transparent;
border-right: 5px solid transparent; border-right: 5px solid transparent;
} }
.notificationsIcon .unread-notifications-dot:after {
content: none;
}
.sidebarFilterIcon div:after { .sidebarFilterIcon div:after {
right: 37% !important; right: 37% !important;
} }
.notificationsIcon div:after {
right: 46% !important;
}
.mapInfoIcon div:after, .openCheatsheet div:after, .starMap div:after, .openMetacodeSwitcher div:after, .pinCarousel div:after { .mapInfoIcon div:after, .openCheatsheet div:after, .starMap div:after, .openMetacodeSwitcher div:after, .pinCarousel div:after {
content: ''; content: '';
@ -636,22 +651,20 @@
/* explore maps */ /* explore maps */
#react-app { #explore {
position: absolute; display: none;
height: 100%;
width: 100%;
overflow-y: auto;
} }
#exploreMaps { #exploreMaps {
padding: 0 5%;
position: absolute; position: absolute;
width: 90%;
height: 100%; height: 100%;
width: 100%;
overflow-y: auto; overflow-y: auto;
} }
#exploreMaps > div { #exploreMaps > div {
margin: 110px auto 0 auto; margin-top: 110px;
} }
.button.loadMore { .button.loadMore {
@ -659,28 +672,23 @@
display: block; display: block;
} }
.requestInviteHeader { .appsPage #exploreMapsHeader {
position: absolute; display: block;
width: 100%;
z-index:2;
background-color:#FAFAFA;
height: 52px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
#navBar { #exploreMapsHeader {
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
.navBarContainer { .exploreMapsBar {
z-index:2; z-index:2;
background-color:#FAFAFA; background-color:#FAFAFA;
height: 42px; height: 42px;
padding-top: 52px; padding-top: 52px;
} }
.navBarMenu { .exploreMapsMenu {
display: block; display: block;
width: 100%; width: 100%;
height:42px; height:42px;
@ -689,29 +697,30 @@
text-align: center; text-align: center;
} }
.navBarCenter { .exploreMapsCenter {
display: block; display: block;
} }
.navBarButton { .exploreMapsButton {
color: #757575; color: #757575;
cursor: default; cursor: default;
font-weight: normal; font-weight: normal;
font-family: 'din-medium'; font-family: 'din-medium';
font-size: 14px; font-size: 14px;
padding: 0 8px; height: 14px;
border-bottom: 2px solid rgba(0,0,0,0); padding: 14px 8px 12px 40px;
border-bottom: 2px solid rgba(0,0,0,0);
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
position:relative; position:relative;
} }
.navBarButton:hover, .navBarButton.active { .exploreMapsButton:hover, .exploreMapsButton.active {
text-decoration: none; text-decoration: none;
color: #424242; color: #424242;
border-bottom: 2px solid #00BCD4; border-bottom: 2px solid #00BCD4;
} }
.navBarButton.mapperButton { .exploreMapsButton.mapperButton {
height: 40px; height: 40px;
padding: 0; padding: 0;
} }
@ -728,71 +737,49 @@
} }
.navBarButton .navBarIcon { .exploreMapsButton .exploreMapsIcon {
background-repeat: no-repeat; background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
margin-top:5px; position:absolute;
margin-left:5px; top:5px;
margin-right: 5px; left:5px;
display: inline-block;
vertical-align: top;
} }
.exploreMapsCenter .myMaps .exploreMapsIcon {
.navBarLinkText {
padding: 11px 0 12px 0;
display: inline-block;
}
.navBarCenter .authedApps .navBarIcon {
background-image: url(<%= asset_path('user_sprite.png') %>);
background-position: 0 -32px;
}
.navBarCenter .myMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -32px 0; background-position: -32px 0;
} }
.navBarCenter .sharedMaps .navBarIcon { .exploreMapsCenter .sharedMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -128px 0; background-position: -128px 0;
} }
.navBarCenter .activeMaps .navBarIcon { .exploreMapsCenter .activeMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: 0 0; background-position: 0 0;
} }
.navBarCenter .featuredMaps .navBarIcon { .exploreMapsCenter .featuredMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.navBarCenter .starredMaps .navBarIcon { .exploreMapsCenter .starredMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.navBarCenter .notificationsLink .navBarIcon { .myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon {
background-image: url(<%= asset_path 'topright_sprite.png' %>);
background-position: -128px 0;
}
.authedApps:hover .navBarIcon, .authedApps.active .navBarIcon {
background-position-x: -32px;
}
.myMaps:hover .navBarIcon, .myMaps.active .navBarIcon {
background-position: -32px -32px; background-position: -32px -32px;
} }
.activeMaps:hover .navBarIcon, .activeMaps.active .navBarIcon { .activeMaps:hover .exploreMapsIcon, .activeMaps.active .exploreMapsIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.featuredMaps:hover .navBarIcon, .featuredMaps.active .navBarIcon { .featuredMaps:hover .exploreMapsIcon, .featuredMaps.active .exploreMapsIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.starredMaps:hover .navBarIcon, .starredMaps.active .navBarIcon { .starredMaps:hover .exploreMapsIcon, .starredMaps.active .exploreMapsIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.sharedMaps:hover .navBarIcon, .sharedMaps.active .navBarIcon { .sharedMaps:hover .exploreMapsIcon, .sharedMaps.active .exploreMapsIcon {
background-position: -128px -32px; background-position: -128px -32px;
} }
.notificationsLink:hover .navBarIcon, .notificationsLink.active .navBarIcon {
background-position-y: -32px;
}
.mapsWrapper { .mapsWrapper {
/*overflow-y: auto; */ /*overflow-y: auto; */
@ -808,6 +795,7 @@
height: 80px; height: 80px;
font-family: 'din-regular', helvetica, sans-serif; font-family: 'din-regular', helvetica, sans-serif;
font-size: 32px; font-size: 32px;
display: none;
text-align: center; text-align: center;
color: #999999; color: #999999;
z-index: 0; z-index: 0;
@ -823,6 +811,7 @@
/* toast */ /* toast */
.toast { .toast {
display: none;
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 20px; left: 20px;

View file

@ -1,263 +0,0 @@
.emoji-mart,
.emoji-mart * {
box-sizing: border-box;
line-height: 1.15;
}
.emoji-mart {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
font-size: 16px;
display: inline-block;
color: #222427;
border: 1px solid #d9d9d9;
border-radius: 5px;
background: #fff;
}
.emoji-mart .emoji-mart-emoji {
padding: 6px;
}
.emoji-mart-bar:first-child {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.emoji-mart-bar:last-child {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.emoji-mart-anchors {
display: flex;
justify-content: space-between;
padding: 0 6px;
color: #858585;
line-height: 0;
}
.emoji-mart-anchor {
position: relative;
flex: 1;
text-align: center;
padding: 12px 4px;
overflow: hidden;
transition: color .1s ease-out;
}
.emoji-mart-anchor:hover,
.emoji-mart-anchor-selected {
color: #464646;
}
.emoji-mart-anchor-selected .emoji-mart-anchor-bar {
bottom: 0;
}
.emoji-mart-anchor-bar {
position: absolute;
bottom: -3px; left: 0;
width: 100%; height: 3px;
background-color: #464646;
}
.emoji-mart-anchors i {
display: inline-block;
width: 100%;
max-width: 22px;
}
.emoji-mart-anchors svg {
fill: currentColor;
}
.emoji-mart-scroll {
overflow-y: scroll;
height: 270px;
padding: 0 6px 6px 6px;
border: solid #d9d9d9;
border-width: 1px 0;
}
.emoji-mart-search {
font-size: 16px;
display: block;
width: 100%;
padding: .2em .6em;
margin-top: 6px;
border-radius: 25px;
border: 1px solid #d9d9d9;
outline: 0;
}
.emoji-mart-category .emoji-mart-emoji span {
z-index: 1;
position: relative;
}
.emoji-mart-category .emoji-mart-emoji:hover:before {
z-index: 0;
content: "";
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: #f4f4f4;
border-radius: 100%;
}
.emoji-mart-category-label {
z-index: 2;
position: relative;
position: -webkit-sticky;
top: 0;
}
.emoji-mart-category-label span {
display: block;
width: 100%;
font-weight: 500;
padding: 5px 6px;
background-color: #fff;
background-color: rgba(255, 255, 255, .95);
}
.emoji-mart-emoji {
position: relative;
display: inline-block;
font-size: 0;
}
.emoji-mart-no-results {
font-size: 14px;
text-align: center;
padding-top: 70px;
color: #858585;
}
.emoji-mart-no-results span {
display: inline-block;
vertical-align: middle;
}
.emoji-mart-preview {
position: relative;
height: 70px;
}
.emoji-mart-preview-emoji,
.emoji-mart-preview-data,
.emoji-mart-preview-skins {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.emoji-mart-preview-emoji {
left: 12px;
}
.emoji-mart-preview-data {
left: 68px; right: 12px;
word-break: break-word;
}
.emoji-mart-preview-skins {
right: 30px;
text-align: right;
}
.emoji-mart-preview-name {
font-size: 14px;
}
.emoji-mart-preview-shortname {
font-size: 12px;
color: #888;
}
.emoji-mart-preview-shortname + .emoji-mart-preview-shortname,
.emoji-mart-preview-shortname + .emoji-mart-preview-emoticon,
.emoji-mart-preview-emoticon + .emoji-mart-preview-emoticon {
margin-left: .5em;
}
.emoji-mart-preview-emoticon {
font-size: 11px;
color: #bbb;
}
.emoji-mart-title span {
display: inline-block;
vertical-align: middle;
}
.emoji-mart-title .emoji-mart-emoji {
padding: 0;
}
.emoji-mart-title-label {
color: #999A9C;
font-size: 26px;
font-weight: 300;
}
.emoji-mart-skin-swatches {
font-size: 0;
padding: 2px 0;
border: 1px solid #d9d9d9;
border-radius: 12px;
background-color: #fff;
}
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch {
width: 16px;
padding: 0 2px;
}
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch-selected:after {
opacity: .75;
}
.emoji-mart-skin-swatch {
display: inline-block;
width: 0;
vertical-align: middle;
transition-property: width, padding;
transition-duration: .125s;
transition-timing-function: ease-out;
}
.emoji-mart-skin-swatch:nth-child(1) { transition-delay: 0 }
.emoji-mart-skin-swatch:nth-child(2) { transition-delay: .03s }
.emoji-mart-skin-swatch:nth-child(3) { transition-delay: .06s }
.emoji-mart-skin-swatch:nth-child(4) { transition-delay: .09s }
.emoji-mart-skin-swatch:nth-child(5) { transition-delay: .12s }
.emoji-mart-skin-swatch:nth-child(6) { transition-delay: .15s }
.emoji-mart-skin-swatch-selected {
position: relative;
width: 16px;
padding: 0 2px;
}
.emoji-mart-skin-swatch-selected:after {
content: "";
position: absolute;
top: 50%; left: 50%;
width: 4px; height: 4px;
margin: -2px 0 0 -2px;
background-color: #fff;
border-radius: 100%;
pointer-events: none;
opacity: 0;
transition: opacity .2s ease-out;
}
.emoji-mart-skin {
display: inline-block;
width: 100%; padding-top: 100%;
max-width: 12px;
border-radius: 100%;
}
.emoji-mart-skin-tone-1 { background-color: #ffc93a }
.emoji-mart-skin-tone-2 { background-color: #fadcbc }
.emoji-mart-skin-tone-3 { background-color: #e0bb95 }
.emoji-mart-skin-tone-4 { background-color: #bf8f68 }
.emoji-mart-skin-tone-5 { background-color: #9b643d }
.emoji-mart-skin-tone-6 { background-color: #594539 }

View file

@ -0,0 +1,348 @@
.collaborator-video {
z-index: 1;
position: absolute;
width: 150px;
height: 150px;
cursor: default;
color: #FFF;
}
.collaborator-video .video-receive {
position: absolute;
width: 160px;
padding: 20px 20px 20px 170px;
background: #424242;
height: 110px;
border-top-left-radius: 75px;
border-bottom-left-radius: 75px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
.collaborator-video .video-receive .video-statement {
margin-bottom: 10px;
}
.collaborator-video .video-receive .btn-group .btn-yes {
margin-right: 10px;
}
.collaborator-video .video-receive .btn-group .btn-no {
background-color: #c04f4f;
}
.collaborator-video .video-receive .btn-group .btn-no:hover {
background-color: #A54242;
}
.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(<%= asset_path '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(<%= asset_path '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: 30px;
top: 72px;
}
.chat-box {
position: relative;
display: flex;
flex-direction: column;
z-index: 1;
width: 300px;
float: right;
height: 100%;
background: #424242;
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
}
.chat-box .chat-button {
position: absolute;
top: 50%;
left: -36px;
width: 36px;
height: 49px;
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
cursor: pointer;
}
.chat-box .chat-button.active {
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
}
.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: 276px;
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);
}
.chat-box .junto-header .cursor-toggle {
width: 32px;
height: 32px;
margin-right: 8px;
margin-top: -8px;
float: right;
background: url(<%= asset_path '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: 10px;
margin-top: -8px;
float: right;
background: url(<%= asset_path '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%;
min-height: 150px;
padding: 16px 0px 16px 0px;
text-align: left;
color: #f5f5f5;
overflow-y: auto;
}
.chat-box .participants .conversation-live {
display: none;
padding: 5px 10px 5px 10px;
background: #c04f4f;
margin: 5px 10px;
border-radius: 2px;
}
.chat-box .participants .conversation-live .call-action {
float: right;
cursor: pointer;
color: #EBFF00;
}
.chat-box .participants .conversation-live .leave {
display: none;
}
.chat-box .participants.is-participating .conversation-live .leave {
display: block;
}
.chat-box .participants.is-participating .conversation-live .join {
display: none;
}
.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 {
width: 32px;
height: 32px;
border-radius: 18px;
}
.chat-box .participants .participant .chat-participant-name {
width: 53%;
float: left;
font-size: 13px;
font-weight: bold;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-box .participants .participant.is-self .chat-participant-invite-call,
.chat-box .participants .participant.is-self .chat-participant-invite-join {
display: none !important;
}
.chat-box .participants.is-live .participant .chat-participant-invite-call {
display: none;
}
.chat-box .participants .participant .chat-participant-invite-join {
display: none;
}
.chat-box .participants.is-live.is-participating .participant:not(.active) .chat-participant-invite-join {
display: block;
}
.chat-box .participants .participant .chat-participant-invite-call,
.chat-box .participants .participant .chat-participant-invite-join
{
float: right;
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
}
.chat-box .participants .participant.pending .chat-participant-invite-call,
.chat-box .participants .participant.pending .chat-participant-invite-join {
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
}
.chat-box .participants .participant .chat-participant-participating {
float: right;
display: none;
margin-top: 14px;
}
.chat-box .participants .participant .chat-participant-participating .green-dot {
background: #4fc059;
width: 12px;
height: 12px;
border-radius: 6px;
}
.chat-box .participants .participant.active .chat-participant-participating {
display: block;
}
.chat-box .chat-header {
width: 276px;
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);
}
.chat-box .chat-header .sound-toggle {
width: 24px;
height: 24px;
margin-right: 10px;
margin-top: -2px;
float: right;
background: url(<%= asset_path '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 {
min-height: 80px;
width: 94%;
padding: 8px 3% 8px 3%;
font-size: 13px;
outline: none;
resize: none;
}
.chat-box .chat-messages {
width: 100%;
padding: 16px 0px 0px 0px;
overflow-y: auto;
flex-grow: 1;
}
.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;
}
.chat-box .chat-messages .chat-message .chat-message-text {
width: 73%;
float: left;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
word-wrap: break-word;
}
.chat-box .chat-messages .chat-message .chat-message-time {
float: right;
font-size: 10px;
color: #757575;
}

View file

@ -1,375 +0,0 @@
.collaborator-video {
z-index: 1;
position: absolute;
width: 150px;
height: 150px;
cursor: default;
color: #FFF;
.video-receive {
position: absolute;
width: 160px;
padding: 20px 20px 20px 170px;
background: #424242;
height: 110px;
border-top-left-radius: 75px;
border-bottom-left-radius: 75px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
.video-statement {
margin-bottom: 10px;
}
.btn-group {
.btn-yes {
margin-right: 10px;
}
.btn-no {
background-color: #c04f4f;
&:hover {
background-color: #A54242;
}
}
}
}
.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);
video {
height: 150px;
margin-left: -25px;
}
.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;
}
}
.video-audio {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
right: 0px;
cursor: pointer;
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
}
.video-audio:hover {
background-position-x: -24px;
}
.video-audio.active {
background-position-y: -24px;
}
.video-video {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
left: 0px;
cursor: pointer;
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
}
.video-video:hover {
background-position-x: -24px;
}
.video-video.active {
background-position-y: -24px;
}
}
.collaborator-video.my-video {
left: 30px;
top: 72px;
}
.chat-box {
position: absolute;
right: 0;
z-index: 1;
height: 100%;
background: #424242;
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
.chat-panel {
width: 300px;
display: flex;
flex-direction: column;
height: 100%;
}
.chat-button {
position: absolute;
top: 50%;
left: -36px;
width: 36px;
height: 49px;
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
cursor: pointer;
&.active {
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
}
.chat-unread {
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;
}
}
.junto-header {
width: 276px;
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);
.cursor-toggle {
width: 32px;
height: 32px;
margin-right: 8px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
}
.cursor-toggle:hover {
background-position-x: -32px;
}
.cursor-toggle.active {
background-position-y: -32px;
}
.video-toggle {
width: 32px;
height: 32px;
margin-right: 10px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
}
.video-toggle:hover {
background-position-x: -32px;
}
.video-toggle.active {
background-position-y: -32px;
}
}
.participants {
width: 100%;
min-height: 150px;
padding: 16px 0px 16px 0px;
text-align: left;
color: #f5f5f5;
overflow-y: auto;
.conversation-live {
padding: 5px 10px 5px 10px;
background: #c04f4f;
margin: 5px 10px;
border-radius: 2px;
}
.conversation-live .call-action {
float: right;
cursor: pointer;
color: #EBFF00;
}
.participant {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
.chat-participant-image {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-participant-image img {
width: 32px;
height: 32px;
border-radius: 18px;
}
.chat-participant-name {
width: 53%;
float: left;
font-size: 13px;
font-weight: bold;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-participant-invite-call,
.chat-participant-invite-join
{
float: right;
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
}
.chat-participant-invite-call.pending,
.chat-participant-invite-join.pending {
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
}
.chat-participant-participating {
float: right;
margin-top: 14px;
}
.chat-participant-participating .green-dot {
background: #4fc059;
width: 12px;
height: 12px;
border-radius: 6px;
}
}
}
.chat-header {
width: 276px;
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);
.sound-toggle {
width: 24px;
height: 24px;
margin-right: 10px;
margin-top: -2px;
float: right;
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
}
.sound-toggle:hover {
background-position-x: -24px;
}
.sound-toggle.active {
background-position-y: -24px;
}
}
$chat_font_size: 16px;
.chat-input {
min-height: 80px;
width: 88%;
padding: 8px 9% 8px 3%;
font-size: $chat_font_size;
outline: none;
resize: none;
}
.chat-messages {
width: 100%;
padding: 16px 0px;
overflow-y: auto;
flex-grow: 1;
.chat-message {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: $chat_font_size;
line-height: $chat_font_size + 1px;
a:link {
color: #4fb5c0;
text-decoration: underline;
}
a:visited {
color: #aea9fd;
text-decoration: underline;
}
a:hover {
color: #dab539;
text-decoration: underline;
}
.chat-message-user {
width: 12%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-message-user img {
border: 2px solid #424242;
width: 28px;
height: 28px;
border-radius: 16px;
}
.chat-message-meta {
padding: 0 8px;
float: left;
}
.chat-message-username {
color: #4fc059;
}
.chat-message-text {
width: 80%;
float: left;
padding: 2px 8px 0;
text-align: left;
word-wrap: break-word;
}
.chat-message-time {
font-size: 12px;
color: #757575;
}
}
}
.new-message-area {
position: relative;
.emoji-mart {
position: absolute;
bottom: 98px;
}
.extra-message-options {
height: 20px;
position: absolute;
right: 2px;
bottom: 74px;
.emoji-picker-button {
font-size: 16px;
line-height: 20px;
cursor: pointer;
padding: 4px;
}
}
}
}

View file

@ -1,288 +0,0 @@
/* Map Cards */
.map {
display:inline-block;
width:220px;
height:340px;
font-size: 12px;
text-align: left;
overflow: visible;
background: #e8e8e8;
border-radius:2px;
margin:16px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
&.newMap {
float: left;
position: relative;
&:hover {
background: #dcdcdc;
.newMapImage {
background-position: 0 -72px;
}
}
a {
height: 340px;
display: block;
position: relative;
}
.newMapImage {
display: block;
width: 72px;
height: 72px;
background-image: url("<%= asset_data_uri('newmap_sprite.png') %>");
background-repeat: no-repeat;
background-position: 0 0;
position: absolute;
left: 50%;
margin-left: -36px;
top: 50%;
margin-top: -36px;
}
span {
font-family: 'din-regular', sans-serif;
font-size: 18px;
line-height: 22px;
text-align: center;
display: block;
padding-top: 220px;
}
}
.mapCard {
position:relative;
width:100%;
height:308px;
padding: 0 0 16px 0;
color: #424242;
&:hover {
.dropdownMenu .menuToggle .circle {
background-color: #FFF;
}
.dropdownMenu .menuToggle:hover .circle {
background-color: #DDD;
}
.mainContent {
filter: blur(2px);
}
.mapMetadata {
display: block;
}
}
.mapHasMapper, .mapHasConversation {
position: absolute;
top: 8px;
left: 8px;
min-width: 32px;
min-height: 32px;
&:hover {
background-color: #FFF;
border-radius: 2px;
.mapperList {
display: block;
}
}
.mapperList {
display: none;
padding: 8px;
list-style-type: none;
li {
&.live {
height: 32px;
padding-left: 32px;
font-size: 16px;
}
img {
width: 24px;
height: 24px;
border-radius: 12px;
display: inline-block;
vertical-align: middle;
}
span {
padding-left: 10px;
font-size: 14px;
}
}
}
}
.mapHasMapper {
background: url('<%= asset_path('junto.png') %>') no-repeat 4px 0;
}
.mapHasConversation {
background: url('<%= asset_path('junto.gif') %>') no-repeat 4px 0;
}
.dropdownMenu {
position: absolute;
top: 8px;
right: 8px;
cursor: pointer;
.menuToggle {
width: 30px;
height: 10px;
.circle {
display: inline-block;
background-color: #454545;
width: 6px;
height: 6px;
border-radius: 3px;
margin: 2px;
}
&:hover .circle {
background-color: #222;
}
}
.menuItems {
position: absolute;
top: 18px;
right: 0px;
background: #FFF;
border-radius: 2px;
list-style-type: none;
color: #454545;
li {
white-space: nowrap;
padding: 6px;
&:hover {
background-color: #DDD;
}
}
}
}
.mapScreenshot {
width: 100%;
height: 220px;
}
.mapScreenshot img {
width: 100%;
}
.title {
word-wrap: break-word;
font-size:18px;
line-height:22px;
height: 71px;
display:table;
padding: 0 16px;
font-family: 'din-regular', sans-serif;
margin: 0 auto;
.innerTitle {
display: table-cell;
vertical-align: middle;
text-align: center;
}
}
.creatorAndPerm {
padding: 8px;
}
.creatorImage {
display: inline-block;
border-radius: 16px;
vertical-align: middle;
width: 32px;
height: 32px;
}
span.creatorName {
margin-left: 8px;
max-width: 162px;
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
}
.creatorAndPerm.cardHasViewOnly span.creatorName {
max-width: 95px;
}
.cardViewOnly {
float: right;
line-height: 32px;
padding-right: 10px;
color: #454545;
}
.scroll {
display:block;
font-family: helvetica, sans-serif;
font-size: 12px;
word-wrap: break-word;
text-align: center;
margin-top: 16px;
}
.mapMetadata {
display: none;
position: absolute;
top: 0;
left: 0;
padding: 40px 20px 0;
height: 300px;
font-family: 'din-regular', sans-serif;
font-size: 12px;
color: #FFF;
background: -moz-linear-gradient(top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.43) 81%, rgba(0,0,0,0) 100%);
background: -webkit-linear-gradient(top, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
background: linear-gradient(to bottom, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a6000000', endColorstr='#00000000',GradientType=0 );
}
.metadataSection {
padding: 16px 0;
width: 90px;
float: left;
font-family: 'din-medium', sans-serif;
text-align: center;
div {
background: url('<%= asset_path('metadata.png') %>') no-repeat;
width: 32px;
height: 32px;
margin: 0 auto;
}
.numTopicsIcon {
background-position: 0 -32px;
}
.numStarsIcon {
background-position: 0 0;
}
.numSynapsesIcon {
background-position: -32px -32px;
}
.numContributorsIcon {
background-position: -32px 0;
}
}
}
}

View file

@ -1,50 +1,15 @@
@media only screen and (max-width : 752px) and (min-width : 504px) { #mobile_header {
.sidebarSearch .tt-hint, .sidebarSearch .sidebarSearchField { display: none;
width: 160px !important;
}
} }
/* when this switches to two lines */ /* Smartphones (portrait and landscape) ----------- */
@media only screen and (max-width : 728px) { @media only screen and (max-device-width : 480px) {
.controller-notifications .notificationsPage .notification .notification-read-unread a { .upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .uv-icon, .chat-box, #exploreMapsHeader {
margin-top: -20px !important;
}
}
@media only screen and (max-width : 390px) {
.map .mapCard .mobileMetadata {
width: 190px;
}
}
@media only screen and (min-width : 390px) {
.map .mapCard .mobileMetadata {
width: 390px;
}
}
/* 800 is the max-width for centerContent */
@media only screen and (max-width : 800px) {
.centerContent.withPadding {
margin-top: 0;
margin-bottom: 0;
}
}
/* Smartphones (portrait and landscape) ----------- the minimum space that two map cards can fit side by side */
@media only screen and (max-width : 504px) {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #navBar {
display: none !important; display: none !important;
} }
.notificationsPage .page-header { #mobile_header {
display: none; display: block;
}
.controller-notifications .notificationsPage .notification .notification-read-unread {
display: block !important;
}
.controller-notifications .notificationsPage .notification .notification-date {
display: none;
} }
.homeWrapper { .homeWrapper {
@ -64,7 +29,7 @@
height: auto; height: auto;
} }
.homeVideo { .homeVideo {
width: 100% !important; width: 100%;
height: auto; height: auto;
} }
.fullWidthWrapper.withPartners { .fullWidthWrapper.withPartners {
@ -75,7 +40,7 @@
} }
#yield { #yield {
padding-top: 50px; height: 100%;
} }
.new_session, .new_user, .edit_user, .login, .forgotPassword { .new_session, .new_user, .edit_user, .login, .forgotPassword {
@ -84,7 +49,7 @@
left: auto; left: auto;
width: 78%; width: 78%;
padding: 16px 10%; padding: 16px 10%;
margin: 0 auto; margin: 50px auto 0 auto;
} }
.centerGreyForm input[type="text"], .centerGreyForm input[type="email"], .centerGreyForm input[type="password"] { .centerGreyForm input[type="text"], .centerGreyForm input[type="email"], .centerGreyForm input[type="password"] {
@ -100,28 +65,15 @@
max-width: 360px; max-width: 360px;
} }
.requestInviteHeader { #wrapper .requestInvite {
display: none;
}
.requestInvite {
width: 100%; width: 100%;
height: calc(100% - 50px); padding: 0;
z-index: 1;
position: relative;
left: 0;
margin-left: 0px;
margin-top: 50px;
} }
#exploreMaps > div { #exploreMaps > div {
margin-top: 70px; margin-top: 70px;
} }
.mapper {
width: 100%;
margin: 0 0 30px 0;
}
.map.newMap { .map.newMap {
a { a {
height: auto; height: auto;
@ -148,67 +100,29 @@
.map.newMap:hover .newMapImage { .map.newMap:hover .newMapImage {
background-position: 0 -40px; background-position: 0 -40px;
} }
}
/* Smartphones (portrait) ----------- */
@media only screen and (max-width : 400px) {
.map { .map {
width: 100%; width: 100%;
margin: 0 0 30px 0; margin: 0 0 30px 0;
height: auto; height: auto;
.mapCard {
height: auto;
padding: 0;
&:hover {
.mainContent {
filter: none;
}
}
.mobileHasMapper, .mobileHasConversation {
.mapperList {
padding: 8px 16px;
list-style-type: none;
li {
&.live {
height: 32px;
padding-left: 32px;
font-size: 16px;
}
img {
width: 24px;
height: 24px;
border-radius: 12px;
display: inline-block;
vertical-align: middle;
}
span {
padding-left: 10px;
font-size: 14px;
}
}
}
}
.mobileHasMapper {
background: url('<%= asset_path('junto.png') %>') no-repeat 12px 0;
}
.mobileHasConversation {
background: url('<%= asset_path('junto.gif') %>') no-repeat 12px 0;
}
.mobileMetadata {
margin: 0 auto;
}
.title {
text-align: left;
display: block;
height: auto;
padding: 16px;
}
.desc {
padding: 0 16px;
}
}
} }
.mapCard {
height: auto;
}
.mapCard .title {
text-align: left;
}
.mapCard .mapScreenshot {
display: none;
}
} }
#mobile_header { #mobile_header {
@ -217,7 +131,6 @@
width: 100%; width: 100%;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
position: fixed; position: fixed;
z-index: 1;
} }
#menu_icon { #menu_icon {
@ -240,16 +153,8 @@
line-height: 50px; line-height: 50px;
} }
#mobile_header #menu_icon .unread-notifications-dot {
top: 5px;
left: 29px;
width: 12px;
height: 12px;
border: 3px solid #eee;
border-radius: 9px;
}
#mobile_menu { #mobile_menu {
display: none;
background: #EEE; background: #EEE;
position: fixed; position: fixed;
top: 50px; top: 50px;
@ -257,30 +162,11 @@
padding: 10px; padding: 10px;
width: 200px; width: 200px;
box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16); box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16);
z-index: 2; }
li { #mobile_menu li {
padding: 7px 10px; padding: 10px;
list-style: none; list-style: none;
font-family: 'din-regular', arial, sans-serif;
.sprite {
margin-right: 6px;
margin-top: -2px;
display: inline-block;
vertical-align: middle;
}
&.notifications {
position: relative;
.unread-notifications-dot {
top: 50%;
left: 0px;
margin-top: -4px;
}
}
}
} }
li.mobileMenuUser { li.mobileMenuUser {

View file

@ -1,237 +0,0 @@
$notifications-border-color: #DDDDDD;
$notifications-hover-color: #F6F6F6;
$unread_notifications_dot_size: 8px;
.unread-notifications-dot {
width: $unread_notifications_dot_size;
height: $unread_notifications_dot_size;
background-color: #e22;
border-radius: $unread_notifications_dot_size / 2;
position: absolute;
top: 0;
right: 0;
}
.upperRightUI {
.notificationsIcon {
position: relative;
}
.notificationsBox {
position: absolute;
background: #FFFFFF;
border-radius: 2px;
width: 350px;
right: 0;
top: 50px;
box-shadow: 0 3px 6px rgba(0,0,0,0.16);
border: 1px solid $notifications-border-color;
.notificationsBoxTriangle {
min-width: 0 !important;
display: block;
position: absolute;
right: 48px;
width: 20px !important;
height: 20px !important;
margin-left: -10px;
top: -11px;
border-left: 1px solid $notifications-border-color;
border-top: 1px solid $notifications-border-color;
border-bottom: 0 !important;
border-right: 0 !important;
background-color: #fff;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
ul.notifications {
max-height: 500px;
overflow-y: auto;
.notification {
font-size: 13px;
.notification-body {
border-bottom: 1px solid $notifications-border-color;
}
}
.notificationsEmpty {
font-family: din-regular, helvetica, sans-serif;
margin: 50px 10px;
text-align: center;
}
}
.notificationsBoxSeeAll {
display: block;
width: 100%;
text-align: center;
padding: 6px 0;
font-family: din-regular, helvetica, sans-serif;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:hover {
color: #333;
background: $notifications-hover-color;
}
}
}
}
.controller-notifications {
.notificationPage,
.notificationsPage {
font-family: 'din-regular', Sans-Serif;
& a:hover {
text-decoration: none;
}
& > .notification-title {
border-bottom: 1px solid #eee;
padding-bottom: 0.25em;
margin-bottom: 0.5em;
}
.back {
margin-top: 1em;
}
}
.notificationsPage {
header {
margin-bottom: 0;
}
.emptyInbox {
padding-top: 15px;
}
}
.notificationPage {
.thirty-two-avatar {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 16px;
vertical-align: middle;
}
.button {
line-height: 32px;
img {
margin-top: 8px;
}
&.decline {
background: #DB5D5D;
&:hover {
background: #DC4B4B;
}
}
}
.notification-body {
p, div {
margin: 1em auto;
line-height: 20px;
}
}
}
}
ul.notifications {
list-style: none;
li:nth-last-child(2) {
.notification-body {
border-bottom: none !important;
}
}
}
.notification {
padding: 10px 10px 0 10px;
position: relative;
font-family: 'din-regular', Sans-Serif;
&.unread {
background: #EEE;
}
&:hover {
background: $notifications-hover-color;
.notification-read-unread {
display:block;
}
.notification-date {
display: none;
}
}
& > a {
float: left;
width: 85%;
box-sizing: border-box;
padding-right: 10px;
}
.notification-actor {
float: left;
img {
width: 32px;
height: 32px;
border-radius: 16px;
}
}
.notification-body {
margin-left: 50px;
line-height: 20px;
padding-bottom: 10px;
.in-bold {
font-family: 'din-medium', Sans-Serif;
}
.action {
background: #4fb5c0;
color: #FFF;
padding: 2px 6px;
border-radius: 3px;
display: inline-block;
margin: 5px 0;
}
}
.notification-date {
position: absolute;
top: 50%;
right: 10px;
color: #607d8b;
margin-top: -6px;
}
.notification-read-unread {
display: none;
float: left;
width: 15%;
a, div {
position: absolute;
top: 50%;
margin-top: -10px;
text-align: center;
cursor: pointer;
}
}
}

View file

@ -1,87 +0,0 @@
.viewOnly {
float: left;
margin-left: 16px;
height: 32px;
border: 1px solid #BDBDBD;
border-radius: 2px;
background-color: #424242;
color: #FFF;
font-size: 14px;
line-height: 32px;
&.isViewOnly {
display: block;
}
.eyeball {
background: url('<%= asset_path('view-only.png') %>') no-repeat 4px 0;
padding-left: 40px;
border-right: #747474;
padding-right: 10px;
display: inline-block;
}
.requestNotice {
display: inline-block;
padding: 0 8px;
}
.requestAccess {
background-color: #a354cd;
&:hover {
background-color: #9150bc;
}
cursor: pointer;
}
.requestPending {
background-color: #4fc059;
}
.requestNotAccepted {
background-color: #c04f4f;
}
}
.request_access {
position: absolute;
width: 90%;
margin: 0 5%;
.monkey {
width: 250px;
height: 250px;
border: 6px solid #424242;
border-radius: 125px;
background: url(https://s3.amazonaws.com/metamaps-assets/site/monkeyselfie.jpg) no-repeat;
background-position: 50% 20%;
background-size: 100%;
margin: 80px auto 20px auto;
}
.explainer_text {
padding: 0 20% 0 20%;
font-size: 24px;
line-height: 30px;
margin-bottom: 20px;
text-align: center;
}
.make_request {
background-color: #a354cd;
display: block;
width: 220px;
height: 14px;
padding: 16px 0;
margin-bottom: 16px;
text-align: center;
border-radius: 2px;
font-size: 14px;
box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
margin: 0 auto 20px auto;
text-decoration: none;
color: #FFFFFF !important;
cursor: pointer;
}
}

View file

@ -93,7 +93,7 @@
.sidebarSearchField { .sidebarSearchField {
float: left; float: left;
width: 379px; width: 380px;
padding: 7px 10px 3px 10px; padding: 7px 10px 3px 10px;
height: 20px; height: 20px;
border-top: 1px solid #BDBDBD; border-top: 1px solid #BDBDBD;

View file

@ -1,9 +1,11 @@
.unauthenticated .feedback-icon { /* =USERVOICE ICON DEFINE
--------------------------------------------------------*/
.unauthenticated .uv-icon {
display: none; display: none;
} }
.feedback-icon { div.uv-icon.uv-bottom-left {
position: fixed;
background-image: url(<%= asset_data_uri 'feedback_sprite.png' %>); background-image: url(<%= asset_data_uri 'feedback_sprite.png' %>);
background-repeat: no-repeat; background-repeat: no-repeat;
color:#FFFFFF; color:#FFFFFF;
@ -18,8 +20,6 @@
opacity: 1; opacity: 1;
} }
.feedback-icon:hover { div.uv-icon.uv-bottom-left:hover {
background-position: 0 -110px; background-position: 0 -110px;
} }

View file

@ -1,6 +0,0 @@
# frozen_string_literal: true
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View file

@ -1,23 +0,0 @@
# frozen_string_literal: true
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.name
end
protected
def find_verified_user
verified_user = User.find_by(id: cookies.signed['user.id'])
if verified_user && cookies.signed['user.expires_at'] > Time.now.getlocal
verified_user
else
reject_unauthorized_connection
end
end
end
end

View file

@ -1,18 +0,0 @@
# frozen_string_literal: true
class MapChannel < ApplicationCable::Channel
# Called when the consumer has successfully
# become a subscriber of this channel.
def subscribed
map = Map.find(params[:id])
return unless Pundit.policy(current_user, map).show?
stream_from "map_#{params[:id]}"
Events::UserPresentOnMap.publish!(map, current_user)
end
def unsubscribed
map = Map.find(params[:id])
return unless Pundit.policy(current_user, map).show?
Events::UserNotPresentOnMap.publish!(map, current_user)
end
end

View file

@ -1,90 +0,0 @@
# frozen_string_literal: true
class AccessController < ApplicationController
before_action :require_user, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
before_action :set_map, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
after_action :verify_authorized
# GET maps/:id/request_access
def request_access
@map = nil
respond_to do |format|
format.html do
render 'maps/request_access'
end
end
end
# POST maps/:id/access_request
def access_request
AccessRequest.create(user: current_user, map: @map)
respond_to do |format|
format.json { head :ok }
end
end
# POST maps/:id/access
def access
user_ids = params[:access].to_a.map(&:to_i) || []
@map.add_new_collaborators(user_ids)
@map.remove_old_collaborators(user_ids)
respond_to do |format|
format.json { head :ok }
end
end
# GET maps/:id/approve_access/:request_id
def approve_access
request = AccessRequest.find(params[:request_id])
request.approve # also marks mailboxer notification as read
respond_to do |format|
format.html { redirect_to map_path(@map), notice: 'Request was approved' }
end
end
# GET maps/:id/deny_access/:request_id
def deny_access
request = AccessRequest.find(params[:request_id])
request.deny # also marks mailboxer notification as read
respond_to do |format|
format.html { redirect_to map_path(@map), notice: 'Request was turned down' }
end
end
# POST maps/:id/approve_access/:request_id
def approve_access_post
request = AccessRequest.find(params[:request_id])
request.approve
respond_to do |format|
format.js
format.json do
head :ok
end
end
end
# POST maps/:id/deny_access/:request_id
def deny_access_post
request = AccessRequest.find(params[:request_id])
request.deny
respond_to do |format|
format.js
format.json do
head :ok
end
end
end
private
def set_map
@map = Map.find(params[:id])
authorize @map
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V1 module V1
class DeprecatedController < ApplicationController class DeprecatedController < ApplicationController

View file

@ -1,8 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MappingsController < WithUpdatesController class MappingsController < RestfulController
def searchable_columns def searchable_columns
[] []
end end

View file

@ -1,15 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MapsController < WithUpdatesController class MapsController < RestfulController
def searchable_columns def searchable_columns
%i[name desc] [:name, :desc]
end
def apply_filters(collection)
collection = collection.where(user_id: params[:user_id]) if params[:user_id]
collection
end end
end end
end end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MetacodesController < RestfulController class MetacodesController < RestfulController

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class RestfulController < ActionController::Base class RestfulController < ActionController::Base
@ -8,7 +7,7 @@ module Api
snorlax_used_rest! snorlax_used_rest!
before_action :load_resource, only: %i[show update destroy] before_action :load_resource, only: [:show, :update, :destroy]
after_action :verify_authorized after_action :verify_authorized
def index def index
@ -46,7 +45,7 @@ module Api
end end
def current_user def current_user
token_user || doorkeeper_user super || token_user || doorkeeper_user || nil
end end
def load_resource def load_resource
@ -87,12 +86,12 @@ module Api
def token_user def token_user
token = params[:access_token] token = params[:access_token]
access_token = Token.find_by(token: token) access_token = Token.find_by_token(token)
@token_user ||= access_token.user if access_token @token_user ||= access_token.user if access_token
end end
def doorkeeper_user def doorkeeper_user
return if doorkeeper_token.blank? return unless doorkeeper_token.present?
doorkeeper_render_error unless valid_doorkeeper_token? doorkeeper_render_error unless valid_doorkeeper_token?
@doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id) @doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id)
end end
@ -142,7 +141,6 @@ module Api
collection = accessible_records collection = accessible_records
collection = yield collection if block_given? collection = yield collection if block_given?
collection = search_by_q(collection) if params[:q] collection = search_by_q(collection) if params[:q]
collection = apply_filters(collection)
collection = order_by_sort(collection) if params[:sort] collection = order_by_sort(collection) if params[:sort]
collection = collection.page(params[:page]).per(params[:per]) collection = collection.page(params[:page]).per(params[:per])
self.collection = collection self.collection = collection
@ -150,41 +148,25 @@ module Api
# override this method to explicitly set searchable columns # override this method to explicitly set searchable columns
def searchable_columns def searchable_columns
return @searchable_columns unless @searchable_columns.nil?
columns = resource_class.columns.select do |column| columns = resource_class.columns.select do |column|
column.type == :text || column.type == :string column.type == :text || column.type == :string
end end
@searchable_columns = columns.map(&:name) columns.map(&:name)
end
# e.g. ?q=test&searchfields=name,desc
def searchfields
return searchable_columns if params[:searchfields].blank?
searchfields = params[:searchfields].split(',')
searchfields.select! { |f| searchable_columns.include?(f.to_sym) }
searchfields.empty? ? searchable_columns : searchfields
end end
# thanks to http://stackoverflow.com/questions/4430578 # thanks to http://stackoverflow.com/questions/4430578
def search_by_q(collection) def search_by_q(collection)
table = resource_class.arel_table table = resource_class.arel_table
safe_query = "%#{params[:q].gsub(/[%_]/, '\\\\\0')}%" safe_query = "%#{params[:q].gsub(/[%_]/, '\\\\\0')}%"
search_column = ->(column) { table[column].matches(safe_query) } search_column = -> (column) { table[column].matches(safe_query) }
condition = searchfields.reduce(nil) do |prev, column| condition = searchable_columns.reduce(nil) do |prev, column|
next search_column.call(column) if prev.nil? next search_column.call(column) if prev.nil?
search_column.call(column).or(prev) search_column.call(column).or(prev)
end end
collection.where(condition) collection.where(condition)
end end
def apply_filters(collection)
# override this function for specific filters
collection
end
def order_by_sort(collection) def order_by_sort(collection)
builder = collection builder = collection
sorts = params[:sort].split(',') sorts = params[:sort].split(',')

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class SessionsController < ApplicationController class SessionsController < ApplicationController

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class StarsController < RestfulController class StarsController < RestfulController

View file

@ -1,8 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class SynapsesController < WithUpdatesController class SynapsesController < RestfulController
def searchable_columns def searchable_columns
[:desc] [:desc]
end end

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class TokensController < RestfulController class TokensController < RestfulController
protect_from_forgery
def searchable_columns def searchable_columns
[:description] [:description]
end end
@ -22,10 +19,10 @@ module Api
respond_with_resource respond_with_resource
end end
private def my_tokens
authorize resource_class
def current_user instantiate_collection
token_user || doorkeeper_user || method(:current_user).super_method.super_method.call respond_with_collection
end end
end end
end end

View file

@ -1,10 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class TopicsController < WithUpdatesController class TopicsController < RestfulController
def searchable_columns def searchable_columns
%i[name desc link] [:name, :desc, :link]
end end
end end
end end

View file

@ -1,10 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class UsersController < RestfulController class UsersController < RestfulController
def current def current
raise Pundit::NotAuthorizedError if current_user.nil?
@user = current_user @user = current_user
authorize @user authorize @user
show # delegate to the normal show function show # delegate to the normal show function
@ -19,7 +17,7 @@ module Api
# only ask serializer to return is_admin field if we're on the # only ask serializer to return is_admin field if we're on the
# current_user action # current_user action
def default_scope def default_scope
super.merge(show_full_user: action_name == 'current') super.merge(show_is_admin: action_name == 'current')
end end
end end
end end

View file

@ -1,28 +0,0 @@
# frozen_string_literal: true
module Api
module V2
class WithUpdatesController < RestfulController
def create
instantiate_resource
resource.user = current_user if current_user.present?
resource.updated_by = current_user if current_user.present?
authorize resource
create_action
respond_with_resource
end
def update
resource.updated_by = current_user if current_user.present?
update_action
respond_with_resource
end
def destroy
resource.updated_by = current_user if current_user.present?
destroy_action
head :no_content
end
end
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
include ApplicationHelper include ApplicationHelper
include Pundit include Pundit
@ -22,14 +21,23 @@ class ApplicationController < ActionController::Base
helper_method :authenticated? helper_method :authenticated?
helper_method :admin? helper_method :admin?
def after_sign_in_path_for(resource)
sign_in_url = url_for(action: 'new', controller: 'sessions', only_path: false)
if request.referer == sign_in_url
super
elsif params[:uv_login] == '1'
'http://support.metamaps.cc/login_success?sso=' + current_sso_token
else
stored_location_for(resource) || request.referer || root_path
end
end
def handle_unauthorized def handle_unauthorized
if authenticated? && (params[:controller] == 'maps') && (params[:action] == 'show') if authenticated?
redirect_to request_access_map_path(params[:id])
elsif authenticated?
redirect_to root_path, notice: "You don't have permission to see that page." redirect_to root_path, notice: "You don't have permission to see that page."
else else
store_location_for(resource, request.fullpath) redirect_to new_user_session_path, notice: 'Try signing in to do that.'
redirect_to sign_in_path, notice: 'Try signing in to do that.'
end end
end end
@ -42,13 +50,13 @@ class ApplicationController < ActionController::Base
def require_no_user def require_no_user
return true unless authenticated? return true unless authenticated?
redirect_to edit_user_path(user), notice: 'You must be logged out.' redirect_to edit_user_path(user), notice: 'You must be logged out.'
false return false
end end
def require_user def require_user
return true if authenticated? return true if authenticated?
redirect_to sign_in_path, notice: 'You must be logged in.' redirect_to new_user_session_path, notice: 'You must be logged in.'
false return false
end end
def require_admin def require_admin

View file

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class ExploreController < ApplicationController class ExploreController < ApplicationController
before_action :require_authentication, only: %i[mine shared starred] before_action :require_authentication, only: [:mine, :shared, :starred]
before_action :authorize_explore before_action :authorize_explore
after_action :verify_authorized after_action :verify_authorized
after_action :verify_policy_scoped after_action :verify_policy_scoped

View file

@ -1,18 +1,17 @@
# frozen_string_literal: true
# bad code that should be checked over before entering one of the # bad code that should be checked over before entering one of the
# nice files from the right side of this repo # nice files from the right side of this repo
class HacksController < ApplicationController class HacksController < ApplicationController
include ActionView::Helpers::TextHelper # string truncate method include ActionView::Helpers::TextHelper # string truncate method
# rate limited by rack-attack - currently 5r/s # rate limited by rack-attack - currently 5r/s
# TODO: what else can we do to make get_with_redirects safer?
def load_url_title def load_url_title
authorize :Hack authorize :Hack
url = params[:url] url = params[:url]
response, url = get_with_redirects(url) response, url = get_with_redirects(url)
title = get_encoded_title(response) title = get_encoded_title(response)
render json: { success: true, title: title, url: url } render json: { success: true, title: title, url: url }
rescue StandardError rescue StandardError => e
render json: { success: false } render json: { success: false }
end end
@ -29,13 +28,7 @@ class HacksController < ApplicationController
end end
def get_encoded_title(http_response) def get_encoded_title(http_response)
# ensure there's actually an html title tag title = http_response.body.sub(/.*<title>(.*)<\/title>.*/m, '\1')
title = http_response.body.sub(%r{.*(<title>.*</title>).*}m, '\1')
return '' unless title.starts_with?('<title>')
return '' unless title.ends_with?('</title>')
title = title.sub('<title>', '').sub(%r{</title>$}, '')
# encode and trim the title to 140 usable characters
charset = http_response['content-type'].sub(/.*charset=(.*);?.*/, '\1') charset = http_response['content-type'].sub(/.*charset=(.*);?.*/, '\1')
charset = nil if charset == 'text/html' charset = nil if charset == 'text/html'
title = title.force_encoding(charset) if charset title = title.force_encoding(charset) if charset

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class MainController < ApplicationController class MainController < ApplicationController
before_action :authorize_main before_action :authorize_main
after_action :verify_authorized after_action :verify_authorized

View file

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class MappingsController < ApplicationController class MappingsController < ApplicationController
before_action :require_user, only: %i[create update destroy] before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized, except: :index after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index after_action :verify_policy_scoped, only: :index
@ -20,10 +19,10 @@ class MappingsController < ApplicationController
@mapping = Mapping.new(mapping_params) @mapping = Mapping.new(mapping_params)
authorize @mapping authorize @mapping
@mapping.user = current_user @mapping.user = current_user
@mapping.updated_by = current_user
if @mapping.save if @mapping.save
render json: @mapping, status: :created render json: @mapping, status: :created
Events::NewMapping.publish!(@mapping, current_user)
else else
render json: @mapping.errors, status: :unprocessable_entity render json: @mapping.errors, status: :unprocessable_entity
end end
@ -33,11 +32,8 @@ class MappingsController < ApplicationController
def update def update
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize @mapping authorize @mapping
@mapping.updated_by = current_user
@mapping.map.updated_by = current_user
@mapping.assign_attributes(mapping_params)
if @mapping.save 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,8 +44,14 @@ class MappingsController < ApplicationController
def destroy def destroy
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize @mapping authorize @mapping
@mapping.updated_by = current_user
@mapping.map.updated_by = current_user mappable = @mapping.mappable
if mappable.defer_to_map
mappable.permission = mappable.defer_to_map.permission
mappable.defer_to_map_id = nil
mappable.save
end
@mapping.destroy @mapping.destroy
head :no_content head :no_content

View file

@ -1,17 +1,14 @@
# frozen_string_literal: true # frozen_string_literal: true
class MapsController < ApplicationController class MapsController < ApplicationController
before_action :require_user, only: %i[create update destroy events follow unfollow] before_action :require_user, only: [:create, :update, :destroy, :access, :events]
before_action :set_map, only: %i[show conversation update destroy before_action :set_map, only: [:show, :update, :destroy, :access, :contains,
contains events export :events, :export]
follow unfollow unfollow_from_email]
after_action :verify_authorized after_action :verify_authorized
# GET maps/:id # GET maps/:id
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
UserMap.where(map: @map, user: current_user).map(&:mark_invite_notifications_as_read)
@allmappers = @map.contributors @allmappers = @map.contributors
@allcollaborators = @map.editors @allcollaborators = @map.editors
@alltopics = policy_scope(@map.topics) @alltopics = policy_scope(@map.topics)
@ -19,28 +16,9 @@ class MapsController < ApplicationController
@allmappings = policy_scope(@map.mappings) @allmappings = policy_scope(@map.mappings)
@allmessages = @map.messages.sort_by(&:created_at) @allmessages = @map.messages.sort_by(&:created_at)
@allstars = @map.stars @allstars = @map.stars
@allrequests = @map.access_requests
end end
format.json { render json: @map } format.json { render json: @map }
format.csv { redirect_to action: :export, format: :csv } format.csv { redirect_to action: :export, format: :csv }
format.ttl { redirect_to action: :export, format: :ttl }
end
end
# GET maps/:id/conversation
def conversation
respond_to do |format|
format.html do
UserMap.where(map: @map, user: current_user).map(&:mark_invite_notifications_as_read)
@allmappers = @map.contributors
@allcollaborators = @map.editors
@alltopics = policy_scope(@map.topics)
@allsynapses = policy_scope(@map.synapses)
@allmappings = policy_scope(@map.mappings)
@allmessages = @map.messages.sort_by(&:created_at)
@allstars = @map.stars
@allrequests = @map.access_requests
end
end end
end end
@ -62,7 +40,6 @@ class MapsController < ApplicationController
def create def create
@map = Map.new(create_map_params) @map = Map.new(create_map_params)
@map.user = current_user @map.user = current_user
@map.updated_by = current_user
@map.arranged = false @map.arranged = false
authorize @map authorize @map
@ -83,11 +60,8 @@ class MapsController < ApplicationController
# PUT maps/:id # PUT maps/:id
def update def update
@map.updated_by = current_user
@map.assign_attributes(update_map_params)
respond_to do |format| respond_to do |format|
if @map.save if @map.update_attributes(update_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 }
@ -97,8 +71,7 @@ class MapsController < ApplicationController
# DELETE maps/:id # DELETE maps/:id
def destroy def destroy
@map.updated_by = current_user @map.delete
@map.destroy
respond_to do |format| respond_to do |format|
format.json do format.json do
@ -107,21 +80,37 @@ class MapsController < ApplicationController
end end
end end
# POST maps/:id/access
def access
user_ids = params[:access] || []
@map.add_new_collaborators(user_ids).each do |user_id|
# add_new_collaborators returns array of added users,
# who we then send an email to
MapMailer.invite_to_edit_email(@map, current_user, User.find(user_id)).deliver_later
end
@map.remove_old_collaborators(user_ids)
respond_to do |format|
format.json do
render json: { message: 'Successfully altered edit permissions' }
end
end
end
# GET maps/:id/contains # GET maps/:id/contains
def contains def contains
respond_to do |format| respond_to do |format|
format.json { render json: @map.contains(current_user).as_json(user: current_user) } format.json { render json: @map.contains(current_user) }
end end
end end
# GET maps/:id/export # GET maps/:id/export
def export def export
exporter = MapExportService.new(current_user, @map, base_url: request.base_url) exporter = MapExportService.new(current_user, @map)
respond_to do |format| respond_to do |format|
format.json { render json: exporter.json } format.json { render json: exporter.json }
format.csv { send_data exporter.csv } format.csv { send_data exporter.csv }
format.ttl { render text: exporter.rdf }
end end
end end
@ -131,6 +120,9 @@ class MapsController < ApplicationController
if params[:event] == 'conversation' if params[:event] == 'conversation'
Events::ConversationStartedOnMap.publish!(@map, current_user) Events::ConversationStartedOnMap.publish!(@map, current_user)
valid_event = true valid_event = true
elsif params[:event] == 'user_presence'
Events::UserPresentOnMap.publish!(@map, current_user)
valid_event = true
end end
respond_to do |format| respond_to do |format|
@ -141,43 +133,6 @@ class MapsController < ApplicationController
end end
end end
# POST maps/:id/follow
def follow
follow = FollowService.follow(@map, current_user, 'followed')
respond_to do |format|
format.json do
if follow
head :ok
else
head :bad_request
end
end
end
end
# POST maps/:id/unfollow
def unfollow
FollowService.unfollow(@map, current_user)
respond_to do |format|
format.json do
head :ok
end
end
end
# GET maps/:id/unfollow_from_email
def unfollow_from_email
FollowService.unfollow(@map, current_user)
respond_to do |format|
format.html do
redirect_to map_path(@map), notice: 'You are no longer following this map'
end
end
end
private private
def set_map def set_map
@ -186,7 +141,7 @@ class MapsController < ApplicationController
end end
def create_map_params def create_map_params
params.permit(:name, :desc, :permission, :source_id) params.permit(:name, :desc, :permission)
end end
def update_map_params def update_map_params

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class MessagesController < ApplicationController class MessagesController < ApplicationController
before_action :require_user, except: [:show] before_action :require_user, except: [:show]
after_action :verify_authorized after_action :verify_authorized

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class MetacodeSetsController < ApplicationController class MetacodeSetsController < ApplicationController
before_action :require_admin before_action :require_admin
@ -56,13 +55,8 @@ class MetacodeSetsController < ApplicationController
@metacodes.each do |m| @metacodes.each do |m|
InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id) InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id)
end end
format.html do format.html { redirect_to metacode_sets_url, notice: 'Metacode set was successfully created.' }
redirect_to metacode_sets_url, format.json { render json: @metacode_set, status: :created, location: metacode_sets_url }
notice: 'Metacode set was successfully created.'
end
format.json do
render json: @metacode_set, status: :created, location: metacode_sets_url
end
else else
format.html { render action: 'new' } format.html { render action: 'new' }
format.json { render json: @metacode_set.errors, status: :unprocessable_entity } format.json { render json: @metacode_set.errors, status: :unprocessable_entity }
@ -79,20 +73,20 @@ class MetacodeSetsController < ApplicationController
if @metacode_set.update_attributes(metacode_set_params) 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
current_metacodes = @metacode_set.metacodes.map { |m| m.id.to_s } @currentMetacodes = @metacode_set.metacodes.map { |m| m.id.to_s }
# get the list of desired metacodes for the set from the user input and build an array out of it # get the list of desired metacodes for the set from the user input and build an array out of it
new_metacodes = params[:metacodes][:value].split(',') @newMetacodes = params[:metacodes][:value].split(',')
# remove the metacodes that were in it, but now aren't # remove the metacodes that were in it, but now aren't
removed_metacodes = current_metacodes - new_metacodes @removedMetacodes = @currentMetacodes - @newMetacodes
removed_metacodes.each do |m| @removedMetacodes.each do |m|
inmetacodeset = InMetacodeSet.find_by(metacode_id: m, metacode_set_id: @metacode_set.id) @inmetacodeset = InMetacodeSet.find_by_metacode_id_and_metacode_set_id(m, @metacode_set.id)
inmetacodeset.destroy @inmetacodeset.destroy
end end
# add the new metacodes # add the new metacodes
added_metacodes = new_metacodes - current_metacodes @addedMetacodes = @newMetacodes - @currentMetacodes
added_metacodes.each do |m| @addedMetacodes.each do |m|
InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id) InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id)
end end

View file

@ -1,8 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class MetacodesController < ApplicationController class MetacodesController < ApplicationController
before_action :require_admin, except: %i[index show] before_action :require_admin, except: [:index, :show]
before_action :set_metacode, only: %i[edit update] before_action :set_metacode, only: [:edit, :update]
# GET /metacodes # GET /metacodes
# GET /metacodes.json # GET /metacodes.json

View file

@ -1,107 +0,0 @@
# frozen_string_literal: true
class NotificationsController < ApplicationController
before_action :set_receipts, only: %i[index show mark_read mark_unread]
before_action :set_notification, only: %i[show mark_read mark_unread]
before_action :set_receipt, only: %i[show mark_read mark_unread]
def index
@notifications = current_user.mailbox.notifications.page(params[:page]).per(25)
respond_to do |format|
format.html
format.json do
notifications = @notifications.map do |notification|
receipt = @receipts.find_by(notification_id: notification.id)
NotificationDecorator.decorate(notification, receipt)
end
if !notifications.empty?
render json: notifications
else
render json: [].to_json
end
end
end
end
def show
@receipt.update(is_read: true)
respond_to do |format|
format.html do
case @notification.notification_code
when MAP_ACCESS_APPROVED, MAP_INVITE_TO_EDIT
redirect_to map_path(@notification.notified_object.map)
when TOPIC_ADDED_TO_MAP
redirect_to map_path(@notification.notified_object.map)
when TOPIC_CONNECTED_1
redirect_to topic_path(@notification.notified_object.topic1)
when TOPIC_CONNECTED_2
redirect_to topic_path(@notification.notified_object.topic2)
end
end
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def mark_read
@receipt.update(is_read: true)
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def mark_unread
@receipt.update(is_read: false)
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def unsubscribe
unsubscribe_redirect_if_logged_out!
check_if_already_unsubscribed!
return if performed? # if one of these checks already redirected, we're done
if current_user.update(emails_allowed: false)
redirect_to edit_user_path(current_user),
notice: 'You will no longer receive emails from Metamaps.'
else
flash[:alert] = 'Sorry, something went wrong. You have not been unsubscribed from emails.'
redirect_to edit_user_path(current_user)
end
end
private
def unsubscribe_redirect_if_logged_out!
return if current_user.present?
flash[:notice] = 'Continue to unsubscribe from emails by logging in.'
redirect_to "#{sign_in_path}?redirect_to=#{unsubscribe_notifications_path}"
end
def check_if_already_unsubscribed!
return if current_user.emails_allowed
redirect_to edit_user_path(current_user), notice: 'You were already unsubscribed from emails.'
end
def set_receipts
@receipts = current_user.mailboxer_notification_receipts
end
def set_notification
@notification = current_user.mailbox.notifications.find_by(id: params[:id])
end
def set_receipt
@receipt = @receipts.find_by(notification_id: params[:id])
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class SearchController < ApplicationController class SearchController < ApplicationController
include TopicsHelper include TopicsHelper
include MapsHelper include MapsHelper
@ -8,15 +7,14 @@ class SearchController < ApplicationController
before_action :authorize_search before_action :authorize_search
after_action :verify_authorized after_action :verify_authorized
after_action :verify_policy_scoped, only: %i[maps mappers synapses topics] after_action :verify_policy_scoped, only: [:maps, :mappers, :synapses, :topics]
# get /search/topics?term=SOMETERM # get /search/topics?term=SOMETERM
def topics def topics
term = params[:term] term = params[:term]
user = params[:user] ? params[:user] : false user = params[:user] ? params[:user] : false
if term.present? && term.downcase[0..3] != 'map:' && if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero?
term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero?
# remove "topic:" if appended at beginning # remove "topic:" if appended at beginning
term = term[6..-1] if term.downcase[0..5] == 'topic:' term = term[6..-1] if term.downcase[0..5] == 'topic:'
@ -36,28 +34,28 @@ class SearchController < ApplicationController
end end
# check whether there's a filter by metacode as part of the query # check whether there's a filter by metacode as part of the query
filter_by_metacode = false filterByMetacode = false
Metacode.all.each do |m| Metacode.all.each do |m|
length_one = m.name.length + 1 lOne = m.name.length + 1
length_two = m.name.length lTwo = m.name.length
if term.downcase[0..length_two] == m.name.downcase + ':' if term.downcase[0..lTwo] == m.name.downcase + ':'
term = term[length_one..-1] term = term[lOne..-1]
filter_by_metacode = m filterByMetacode = m
end end
end end
search = '%' + term.downcase.strip + '%' search = '%' + term.downcase + '%'
builder = policy_scope(Topic) builder = policy_scope(Topic)
if filter_by_metacode if filterByMetacode
if term == '' if term == ''
builder = builder.none builder = builder.none
else else
builder = builder.where('LOWER("name") like ? OR builder = builder.where('LOWER("name") like ? OR
LOWER("desc") like ? OR LOWER("desc") like ? OR
LOWER("link") like ?', search, search, search) LOWER("link") like ?', search, search, search)
builder = builder.where(metacode_id: filter_by_metacode.id) builder = builder.where(metacode_id: filterByMetacode.id)
end end
elsif desc elsif desc
builder = builder.where('LOWER("desc") like ?', search) builder = builder.where('LOWER("desc") like ?', search)
@ -72,7 +70,6 @@ class SearchController < ApplicationController
builder = builder.where(user: user) if user builder = builder.where(user: user) if user
@topics = builder.order(:name) @topics = builder.order(:name)
else else
skip_policy_scope
@topics = [] @topics = []
end end
@ -84,8 +81,7 @@ class SearchController < ApplicationController
term = params[:term] term = params[:term]
user = params[:user] ? params[:user] : nil user = params[:user] ? params[:user] : nil
if term.present? && term.downcase[0..5] != 'topic:' && if term && !term.empty? && term.downcase[0..5] != 'topic:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero?
term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero?
# remove "map:" if appended at beginning # remove "map:" if appended at beginning
term = term[4..-1] if term.downcase[0..3] == 'map:' term = term[4..-1] if term.downcase[0..3] == 'map:'
@ -97,7 +93,7 @@ class SearchController < ApplicationController
desc = true desc = true
end end
search = '%' + term.downcase.strip + '%' search = '%' + term.downcase + '%'
builder = policy_scope(Map) builder = policy_scope(Map)
builder = if desc builder = if desc
@ -108,7 +104,6 @@ class SearchController < ApplicationController
builder = builder.where(user: user) if user builder = builder.where(user: user) if user
@maps = builder.order(:name) @maps = builder.order(:name)
else else
skip_policy_scope
@maps = [] @maps = []
end end
@ -118,17 +113,16 @@ class SearchController < ApplicationController
# get /search/mappers?term=SOMETERM # get /search/mappers?term=SOMETERM
def mappers def mappers
term = params[:term] term = params[:term]
if term.present? && term.downcase[0..3] != 'map:' && if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero?
term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero?
# remove "mapper:" if appended at beginning # remove "mapper:" if appended at beginning
term = term[7..-1] if term.downcase[0..6] == 'mapper:' term = term[7..-1] if term.downcase[0..6] == 'mapper:'
search = term.downcase.strip + '%' search = term.downcase + '%'
builder = policy_scope(User).where('LOWER("name") like ?', search) skip_policy_scope # TODO: builder = policy_scope(User)
builder = User.where('LOWER("name") like ?', search)
@mappers = builder.order(:name) @mappers = builder.order(:name)
else else
skip_policy_scope
@mappers = [] @mappers = []
end end
render json: autocomplete_user_array_json(@mappers).to_json render json: autocomplete_user_array_json(@mappers).to_json
@ -141,19 +135,16 @@ class SearchController < ApplicationController
topic1id = params[:topic1id] topic1id = params[:topic1id]
topic2id = params[:topic2id] topic2id = params[:topic2id]
if term.present? if term && !term.empty?
@synapses = policy_scope(Synapse) @synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"')
.where('LOWER("desc") like ?', '%' + term.downcase.strip + '%')
.order('"desc"')
@synapses = @synapses.uniq(&:desc) @synapses = @synapses.uniq(&:desc)
elsif topic1id.present? elsif topic1id && !topic1id.empty?
one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id) @one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id)
two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id) @two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id)
@synapses = one + two @synapses = @one + @two
@synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a @synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a
else else
skip_policy_scope
@synapses = [] @synapses = []
end end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
class StarsController < ApplicationController class StarsController < ApplicationController
before_action :require_user before_action :require_user
before_action :set_map before_action :set_map

View file

@ -1,9 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class SynapsesController < ApplicationController class SynapsesController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: %i[create update destroy] before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized, except: :index after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index after_action :verify_policy_scoped, only: :index
@ -23,20 +22,10 @@ class SynapsesController < ApplicationController
@synapse = Synapse.new(synapse_params) @synapse = Synapse.new(synapse_params)
@synapse.desc = '' if @synapse.desc.nil? @synapse.desc = '' if @synapse.desc.nil?
@synapse.desc.strip! # no trailing/leading whitespace @synapse.desc.strip! # no trailing/leading whitespace
@synapse.user = current_user authorize @synapse
@synapse.updated_by = current_user
# we want invalid params to return :unprocessable_entity
# so we have to authorize AFTER saving. But if authorize
# fails, we need to rollback the SQL transaction
success = nil
ActiveRecord::Base.transaction do
success = @synapse.save
success ? authorize(@synapse) : skip_authorization
end
respond_to do |format| respond_to do |format|
if success if @synapse.save
format.json { render json: @synapse, status: :created } format.json { render json: @synapse, status: :created }
else else
format.json { render json: @synapse.errors, status: :unprocessable_entity } format.json { render json: @synapse.errors, status: :unprocessable_entity }
@ -50,11 +39,9 @@ class SynapsesController < ApplicationController
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
@synapse.desc = '' if @synapse.desc.nil? @synapse.desc = '' if @synapse.desc.nil?
authorize @synapse authorize @synapse
@synapse.updated_by = current_user
@synapse.assign_attributes(synapse_params)
respond_to do |format| respond_to do |format|
if @synapse.save 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 }
@ -66,7 +53,6 @@ class SynapsesController < ApplicationController
def destroy def destroy
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
authorize @synapse authorize @synapse
@synapse.updated_by = current_user
@synapse.destroy @synapse.destroy
respond_to do |format| respond_to do |format|
@ -77,8 +63,6 @@ class SynapsesController < ApplicationController
private private
def synapse_params def synapse_params
params.require(:synapse).permit( params.require(:synapse).permit(:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id, :user_id)
:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id
)
end end
end end

View file

@ -1,10 +0,0 @@
# frozen_string_literal: true
class TokensController < ApplicationController
before_action :require_user, only: [:new]
def new
@token = Token.new(user: current_user)
render :new, layout: false
end
end

View file

@ -1,12 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class TopicsController < ApplicationController class TopicsController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: %i[create update destroy follow unfollow] before_action :require_user, only: [:create, :update, :destroy]
before_action :set_topic, only: %i[show update relative_numbers
relatives network destroy
follow unfollow unfollow_from_email]
after_action :verify_authorized, except: :autocomplete_topic after_action :verify_authorized, except: :autocomplete_topic
respond_to :html, :js, :json respond_to :html, :js, :json
@ -14,27 +10,26 @@ class TopicsController < ApplicationController
# GET /topics/autocomplete_topic # GET /topics/autocomplete_topic
def autocomplete_topic def autocomplete_topic
term = params[:term] term = params[:term]
if term.present? if term && !term.empty?
topics = policy_scope(Topic) @topics = policy_scope(Topic.where('LOWER("name") like ?', term.downcase + '%')).order('"name"')
.where('LOWER("name") like ?', term.downcase + '%') @mapTopics = @topics.select { |t| t.metacode.name == 'Metamap' }
.order('"name"')
map_topics = topics.select { |t| t&.metacode&.name == 'Metamap' }
# prioritize topics which point to maps, over maps # prioritize topics which point to maps, over maps
exclude = map_topics.length.positive? ? map_topics.map(&:name) : [''] @exclude = @mapTopics.length > 0 ? @mapTopics.map(&:name) : ['']
maps = policy_scope(Map) @maps = policy_scope(Map.where('LOWER("name") like ? AND name NOT IN (?)', term.downcase + '%', @exclude)).order('"name"')
.where('LOWER("name") like ? AND name NOT IN (?)', term.downcase + '%', exclude)
.order('"name"')
else else
topics = [] @topics = []
maps = [] @maps = []
end end
@all = topics.to_a.concat(maps.to_a).sort_by(&:name) @all= @topics.to_a.concat(@maps.to_a).sort { |a, b| a.name <=> b.name }
render json: autocomplete_array_json(@all).to_json render json: autocomplete_array_json(@all)
end end
# GET topics/:id # GET topics/:id
def show def show
@topic = Topic.find(params[:id])
authorize @topic
respond_to do |format| respond_to do |format|
format.html do format.html do
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a) @alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@ -44,12 +39,15 @@ class TopicsController < ApplicationController
respond_with(@allsynapses, @alltopics, @allcreators, @topic) respond_with(@allsynapses, @alltopics, @allcreators, @topic)
end end
format.json { render json: @topic.as_json(user: current_user).to_json } format.json { render json: @topic }
end end
end end
# GET topics/:id/network # GET topics/:id/network
def network def network
@topic = Topic.find(params[:id])
authorize @topic
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a) @alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@allsynapses = policy_scope(Synapse.for_topic(@topic.id)) @allsynapses = policy_scope(Synapse.for_topic(@topic.id))
@ -57,9 +55,9 @@ class TopicsController < ApplicationController
@allcreators += @allsynapses.map(&:user).uniq @allcreators += @allsynapses.map(&:user).uniq
@json = {} @json = {}
@json['topic'] = @topic.as_json(user: current_user) @json['topic'] = @topic
@json['creators'] = @allcreators @json['creators'] = @allcreators
@json['relatives'] = @alltopics.as_json(user: current_user) @json['relatives'] = @alltopics
@json['synapses'] = @allsynapses @json['synapses'] = @allsynapses
respond_to do |format| respond_to do |format|
@ -69,13 +67,16 @@ class TopicsController < ApplicationController
# GET topics/:id/relative_numbers # GET topics/:id/relative_numbers
def relative_numbers def relative_numbers
topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : [] @topic = Topic.find(params[:id])
authorize @topic
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
if params[:metacode].present? alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i } if params[:metacode].present?
alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i } alltopics.delete_if do |topic|
!topicsAlreadyHas.index(topic.id).nil?
end end
alltopics.delete_if { |topic| !topics_already_has.index(topic.id).nil? }
@json = Hash.new(0) @json = Hash.new(0)
alltopics.each do |t| alltopics.each do |t|
@ -89,14 +90,15 @@ class TopicsController < ApplicationController
# GET topics/:id/relatives # GET topics/:id/relatives
def relatives def relatives
topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : [] @topic = Topic.find(params[:id])
authorize @topic
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
if params[:metacode].present? alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i } if params[:metacode].present?
alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i }
end
alltopics.delete_if do |topic| alltopics.delete_if do |topic|
!topics_already_has.index(topic.id.to_s).nil? !topicsAlreadyHas.index(topic.id.to_s).nil?
end end
# find synapses between topics in alltopics array # find synapses between topics in alltopics array
@ -106,13 +108,13 @@ class TopicsController < ApplicationController
!synapse_ids.index(synapse.id).nil? !synapse_ids.index(synapse.id).nil?
end end
creators_already_has = params[:creators] ? params[:creators].split(',').map(&:to_i) : [] creatorsAlreadyHas = params[:creators] ? params[:creators].split(',').map(&:to_i) : []
allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user| allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user|
!creators_already_has.index(user.id).nil? !creatorsAlreadyHas.index(user.id).nil?
end end
@json = {} @json = {}
@json['topics'] = alltopics.as_json(user: current_user) @json['topics'] = alltopics
@json['synapses'] = allsynapses @json['synapses'] = allsynapses
@json['creators'] = allcreators @json['creators'] = allcreators
@ -126,12 +128,10 @@ class TopicsController < ApplicationController
def create def create
@topic = Topic.new(topic_params) @topic = Topic.new(topic_params)
authorize @topic authorize @topic
@topic.user = current_user
@topic.updated_by = current_user
respond_to do |format| respond_to do |format|
if @topic.save if @topic.save
format.json { render json: @topic.as_json(user: current_user), status: :created } format.json { render json: @topic, status: :created }
else else
format.json { render json: @topic.errors, status: :unprocessable_entity } format.json { render json: @topic.errors, status: :unprocessable_entity }
end end
@ -141,11 +141,11 @@ class TopicsController < ApplicationController
# PUT /topics/1 # PUT /topics/1
# PUT /topics/1.json # PUT /topics/1.json
def update def update
@topic.updated_by = current_user @topic = Topic.find(params[:id])
@topic.assign_attributes(topic_params) authorize @topic
respond_to do |format| respond_to do |format|
if @topic.save 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 }
@ -155,58 +155,18 @@ class TopicsController < ApplicationController
# DELETE topics/:id # DELETE topics/:id
def destroy def destroy
@topic.updated_by = current_user @topic = Topic.find(params[:id])
authorize @topic
@topic.destroy @topic.destroy
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }
end end
end end
# POST topics/:id/follow
def follow
follow = FollowService.follow(@topic, current_user, 'followed')
respond_to do |format|
format.json do
if follow
head :ok
else
head :bad_request
end
end
end
end
# POST topics/:id/unfollow
def unfollow
FollowService.unfollow(@topic, current_user)
respond_to do |format|
format.json do
head :ok
end
end
end
# GET topics/:id/unfollow_from_email
def unfollow_from_email
FollowService.unfollow(@topic, current_user)
respond_to do |format|
format.html do
redirect_to topic_path(@topic), notice: 'You are no longer following this topic'
end
end
end
private private
def set_topic
@topic = Topic.find(params[:id])
authorize @topic
end
def topic_params def topic_params
params.require(:topic).permit(:id, :name, :desc, :link, :permission, :metacode_id, :defer_to_map_id) params.require(:topic).permit(:id, :name, :desc, :link, :permission, :user_id, :metacode_id, :defer_to_map_id)
end end
end end

View file

@ -1,15 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
class Users::PasswordsController < Devise::PasswordsController
protected
module Users def after_resetting_password_path_for(resource)
class PasswordsController < Devise::PasswordsController signed_in_root_path(resource)
protected end
def after_resetting_password_path_for(resource) def after_sending_reset_password_instructions_path_for(_resource_name)
signed_in_root_path(resource) new_user_session_path if is_navigational_format?
end
def after_sending_reset_password_instructions_path_for(_resource_name)
sign_in_path if is_navigational_format?
end
end end
end end

View file

@ -1,40 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
module Users protected
class RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
after_action :store_location, only: [:new]
protected def after_sign_up_path_for(resource)
signed_in_root_path(resource)
end
def after_update_path_for(resource) def after_update_path_for(resource)
signed_in_root_path(resource) signed_in_root_path(resource)
end end
def after_sign_in_path_for(resource) private
stored = stored_location_for(User)
return stored if stored
if request.referer&.match(sign_in_url) || request.referer&.match(sign_up_url) def configure_sign_up_params
super devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :joinedwithcode])
else end
request.referer || root_path
end
end
private def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:image])
def store_location
store_location_for(User, params[:redirect_to]) if params[:redirect_to]
end
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: %i[name joinedwithcode])
end
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:image])
end
end end
end end

View file

@ -1,26 +0,0 @@
# frozen_string_literal: true
module Users
class SessionsController < Devise::SessionsController
after_action :store_location, only: [:new]
protected
def after_sign_in_path_for(resource)
stored = stored_location_for(User)
return stored if stored
if request.referer&.match(sign_in_url) || request.referer&.match(sign_up_url)
super
else
request.referer || root_path
end
end
private
def store_location
store_location_for(User, params[:redirect_to]) if params[:redirect_to]
end
end
end

View file

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class UsersController < ApplicationController class UsersController < ApplicationController
before_action :require_user, only: %i[edit update updatemetacodes update_metacode_focus] before_action :require_user, only: [:edit, :update, :updatemetacodes]
respond_to :html, :json respond_to :html, :json
@ -14,25 +13,25 @@ class UsersController < ApplicationController
# GET /users/:id/edit # GET /users/:id/edit
def edit def edit
@user = User.find(current_user.id) @user = current_user
respond_with(@user)
end end
# PUT /users/:id # PUT /users/:id
def update def update
@user = User.find(current_user.id) @user = current_user
if user_params[:password] == '' && user_params[:password_confirmation] == '' if user_params[:password] == '' && user_params[:password_confirmation] == ''
# not trying to change the password # not trying to change the password
if @user.update_attributes(user_params.except(:password, :password_confirmation)) if @user.update_attributes(user_params.except(:password, :password_confirmation))
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1' @user.image = nil if params[:remove_image] == '1'
@user.save @user.save
bypass_sign_in(@user) sign_in(@user, bypass: true)
respond_to do |format| respond_to do |format|
format.html { redirect_to root_url, notice: 'Settings updated' } format.html { redirect_to root_url, notice: 'Account updated!' }
end end
else else
bypass_sign_in(@user) sign_in(@user, bypass: true)
respond_to do |format| respond_to do |format|
format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] } format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] }
end end
@ -42,12 +41,11 @@ class UsersController < ApplicationController
correct_pass = @user.valid_password?(params[:current_password]) correct_pass = @user.valid_password?(params[:current_password])
if correct_pass && @user.update_attributes(user_params) if correct_pass && @user.update_attributes(user_params)
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1' @user.image = nil if params[:remove_image] == '1'
@user.save @user.save
sign_in(@user, bypass: true) sign_in(@user, bypass: true)
respond_to do |format| respond_to do |format|
format.html { redirect_to root_url, notice: 'Settings updated' } format.html { redirect_to root_url, notice: 'Account updated!' }
end end
else else
respond_to do |format| respond_to do |format|
@ -95,28 +93,9 @@ class UsersController < ApplicationController
end end
end end
# PUT /user/update_metacode_focus
def update_metacode_focus
@user = current_user
@user.settings.metacode_focus = params[:value]
@user.save
respond_to do |format|
format.json { render json: { success: 'success' } }
end
end
private private
def update_follow_settings(user, settings)
user.settings.follow_topic_on_created = settings[:follow_topic_on_created]
user.settings.follow_topic_on_contributed = settings[:follow_topic_on_contributed]
user.settings.follow_map_on_created = settings[:follow_map_on_created]
user.settings.follow_map_on_contributed = settings[:follow_map_on_contributed]
end
def user_params def user_params
params.require(:user).permit( params.require(:user).permit(:name, :email, :image, :password, :password_confirmation)
:name, :email, :image, :password, :password_confirmation, :emails_allowed, :settings
)
end end
end end

View file

@ -1,51 +0,0 @@
# frozen_string_literal: true
class NotificationDecorator
class << self
def decorate(notification, receipt)
result = {
id: notification.id,
type: notification.notification_code,
subject: notification.subject,
is_read: receipt.is_read,
created_at: notification.created_at,
actor: notification.sender,
data: {
object: notification.notified_object
}
}
case notification.notification_code
when MAP_ACCESS_APPROVED, MAP_ACCESS_REQUEST, MAP_INVITE_TO_EDIT
map = notification.notified_object&.map
result[:data][:map] = {
id: map&.id,
name: map&.name
}
when TOPIC_ADDED_TO_MAP
topic = notification.notified_object&.eventable
map = notification.notified_object&.map
result[:data][:topic] = {
id: topic&.id,
name: topic&.name
}
result[:data][:map] = {
id: map&.id,
name: map&.name
}
when TOPIC_CONNECTED_1, TOPIC_CONNECTED_2
topic1 = notification.notified_object&.topic1
topic2 = notification.notified_object&.topic2
result[:data][:topic1] = {
id: topic1&.id,
name: topic1&.name
}
result[:data][:topic2] = {
id: topic2&.id,
name: topic2&.name
}
end
result
end
end
end

View file

@ -1,14 +1,40 @@
# frozen_string_literal: true # frozen_string_literal: true
module ApplicationHelper module ApplicationHelper
def metacodeset
metacodes = current_user.settings.metacodes
return false unless metacodes[0].include?('metacodeset')
if metacodes[0].sub('metacodeset-', '') == 'Most'
return 'Most'
elsif metacodes[0].sub('metacodeset-', '') == 'Recent'
return 'Recent'
end
MetacodeSet.find(metacodes[0].sub('metacodeset-', '').to_i)
end
def user_metacodes
@m = current_user.settings.metacodes
set = metacodeset
@metacodes = if set && set == 'Most'
Metacode.where(id: current_user.mostUsedMetacodes).to_a
elsif set && set == 'Recent'
Metacode.where(id: current_user.recentMetacodes).to_a
elsif set
set.metacodes.to_a
else
Metacode.where(id: @m).to_a
end
@metacodes.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
end
def user_most_used_metacodes
@metacodes = current_user.mostUsedMetacodes.map { |id| Metacode.find(id) }
end
def user_recent_metacodes
@metacodes = current_user.recentMetacodes.map { |id| Metacode.find(id) }
end
def invite_link def invite_link
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '') "#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '')
end end
def user_unread_notification_count
return 0 if current_user.nil?
@uunc ||= current_user.mailboxer_notification_receipts.reduce(0) do |total, receipt|
receipt.is_read ? total : total + 1
end
end
end end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module ContentHelper module ContentHelper
def resource_name def resource_name
:user :user

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module DeviseHelper module DeviseHelper
def devise_error_messages! def devise_error_messages!
resource.errors.to_a[0] resource.errors.to_a[0]

View file

@ -1,4 +1,3 @@
# frozen_string_literal: true # frozen_string_literal: true
module InMetacodeSetsHelper module InMetacodeSetsHelper
end end

View file

@ -1,4 +1,3 @@
# frozen_string_literal: true # frozen_string_literal: true
module MainHelper module MainHelper
end end

Some files were not shown because too many files have changed in this diff Show more