Compare commits

..

38 commits

Author SHA1 Message Date
Connor Turland f49a674566 tweaks for developing on this branch 2017-02-06 03:41:28 +00:00
Connor Turland 7951f08e45 Merge branch 'develop' into feature/convo.algo 2017-02-06 03:36:26 +00:00
Connor Turland 9c65d2df09 for special conversation url 2017-02-05 07:05:25 +00:00
Connor Turland a84815aaed tiny merge with develop 2017-02-05 06:39:55 +00:00
Connor Turland 9b0ead24a3 more merges with develop 2017-02-05 06:37:37 +00:00
Connor Turland 3a4fa90c49 Merge branch 'develop' into feature/convo.algo 2017-02-05 06:28:49 +00:00
Connor Turland 0a52de714e make it match develop 2017-02-05 05:41:29 +00:00
Connor Turland 597efb36e1 add this back in 2017-02-05 05:31:37 +00:00
Connor Turland 72fd2717b6 Merge branch 'develop' into feature/convo.algo 2017-02-05 05:26:58 +00:00
Connor Turland 500a74bd5f don't include the controller yet 2017-02-05 04:15:51 +00:00
Connor Turland 2423608fd3 actually optimize the island layout 2017-02-05 04:08:36 +00:00
Connor Turland 0929380e91 divide up the islands to the north and south 2017-02-05 03:34:59 +00:00
Connor Turland 6e347dc33a fixup synapse creation 2017-02-05 03:26:18 +00:00
Connor Turland 96f66a2f8c fix up topic creator 2017-02-04 04:27:08 +00:00
Connor Turland 74dd20f02e got topic and synapse creation working 2017-02-04 04:13:59 +00:00
Connor Turland 04036882ab do the bounds and translate 2017-02-03 20:58:49 +00:00
Connor Turland fd54eb718a its workking 2017-02-03 19:58:15 +00:00
Connor Turland ba230e1eed only find parents for parents and children for children 2017-02-01 21:30:48 +00:00
Connor Turland 274b86532a its vorkingg.... 2017-02-01 18:08:02 +00:00
Connor Turland 6ed9796e05 no more matter 2017-02-01 17:49:16 +00:00
Connor Turland 08d2cbb00d running algo each time an edge is added 2017-02-01 17:47:45 +00:00
Connor Turland fc2604376a add the gitignore 2017-01-31 03:23:01 +00:00
Connor Turland e7a52dc14e bugs 2017-01-12 14:11:01 -05:00
Connor Turland 149b7ecbd6 include matter-js in package json 2017-01-12 12:37:16 -05:00
Connor Turland b2b5090b28 still make it work for logged out users 2017-01-12 12:31:08 -05:00
Connor Turland 38c01c4e8f fix the carousel 2017-01-12 12:19:54 -05:00
Connor Turland b13ac98c9f chat iss working 2017-01-12 04:55:57 -05:00
Connor Turland 4a17d00123 stuff with metacodes working well again 2017-01-12 04:00:52 -05:00
Connor Turland 9c13f5a281 metacode selector working nicely 2017-01-12 00:04:49 -05:00
Connor Turland 616a489ae4 Merge branch 'feature/better.select' into feature/particles 2017-01-11 23:18:26 -05:00
Connor Turland 816815d1b5 awesome 2017-01-11 23:17:57 -05:00
Connor Turland 3ff102b228 initial particle test 2017-01-05 00:05:18 -05:00
Connor Turland bf9b25da9f merge develop 2017-01-04 10:50:59 -05:00
Connor Turland 5ba7ba9355 don't commit swp 2016-09-20 12:28:41 -04:00
Connor Turland ce7c88c78c add more space between nodes using auto-layout 2016-09-20 12:27:46 -04:00
Connor Turland 74630c2631 messed up comment 2016-09-20 12:04:42 -04:00
Connor Turland 966dd79187 Merge branch 'develop' into feature/better.select 2016-09-20 11:55:25 -04:00
Connor Turland 5d04d16590 create MetacodeSelect component 2016-09-18 15:22:51 +00:00
422 changed files with 5276 additions and 8741 deletions

View file

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

4
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,4 @@
============
100BD/C = (100)(__)(__)/(__)=__

2
.gitignore vendored
View file

@ -15,7 +15,6 @@ app/assets/javascripts/webpacked
#secrets and config
.env
*.swp
# Ignore bundler config
.bundle
@ -23,7 +22,6 @@ app/assets/javascripts/webpacked
# Ignore all logfiles and tempfiles.
log/*.log
tmp
.tmp
coverage

View file

@ -12,7 +12,7 @@ Rails:
Enabled: true
Metrics/LineLength:
Max: 120
Max: 100
Metrics/AbcSize:
Max: 16
@ -22,8 +22,3 @@ Style/Documentation:
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

11
Gemfile
View file

@ -1,12 +1,11 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '2.3.0'
gem 'rails', '~> 5.0.0'
gem 'active_model_serializers'
gem 'aws-sdk', '~> 2.7.0'
gem 'aws-sdk'
gem 'best_in_place'
gem 'delayed_job'
gem 'delayed_job_active_record'
@ -25,7 +24,7 @@ gem 'pundit'
gem 'pundit_extra'
gem 'rack-attack'
gem 'rack-cors'
gem 'redis', '~> 3.3.3'
gem 'redis'
gem 'slack-notifier'
gem 'snorlax'
gem 'sucker_punch'
@ -38,7 +37,7 @@ gem 'uglifier'
group :test do
gem 'brakeman', require: false
gem 'factory_bot_rails'
gem 'factory_girl_rails'
gem 'json-schema'
gem 'rspec-rails'
gem 'shoulda-matchers'
@ -48,10 +47,8 @@ end
group :development, :test do
gem 'better_errors'
gem 'binding_of_caller'
gem 'faker'
gem 'pry-byebug'
gem 'pry-rails'
gem 'rubocop', '~> 0.48.1' # match code climate https://github.com/tootsuite/mastodon/issues/1758
gem 'timecop'
gem 'rubocop'
gem 'tunemygc'
end

View file

@ -1,50 +1,50 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (5.0.5)
actionpack (= 5.0.5)
nio4r (>= 1.2, < 3.0)
actioncable (5.0.1)
actionpack (= 5.0.1)
nio4r (~> 1.2)
websocket-driver (~> 0.6.1)
actionmailer (5.0.5)
actionpack (= 5.0.5)
actionview (= 5.0.5)
activejob (= 5.0.5)
actionmailer (5.0.1)
actionpack (= 5.0.1)
actionview (= 5.0.1)
activejob (= 5.0.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.0.5)
actionview (= 5.0.5)
activesupport (= 5.0.5)
actionpack (5.0.1)
actionview (= 5.0.1)
activesupport (= 5.0.1)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.0.5)
activesupport (= 5.0.5)
actionview (5.0.1)
activesupport (= 5.0.1)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.10.6)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
active_model_serializers (0.10.4)
actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
activejob (5.0.5)
activesupport (= 5.0.5)
jsonapi (= 0.1.1.beta6)
activejob (5.0.1)
activesupport (= 5.0.1)
globalid (>= 0.3.6)
activemodel (5.0.5)
activesupport (= 5.0.5)
activerecord (5.0.5)
activemodel (= 5.0.5)
activesupport (= 5.0.5)
activemodel (5.0.1)
activesupport (= 5.0.1)
activerecord (5.0.1)
activemodel (= 5.0.1)
activesupport (= 5.0.1)
arel (~> 7.0)
activesupport (5.0.5)
activesupport (5.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
arel (7.1.4)
ast (2.3.0)
aws-sdk (2.7.0)
@ -54,82 +54,81 @@ GEM
jmespath (~> 1.0)
aws-sdk-resources (2.7.0)
aws-sdk-core (= 2.7.0)
aws-sigv4 (1.0.2)
aws-sigv4 (1.0.0)
bcrypt (3.1.11)
best_in_place (3.1.1)
best_in_place (3.1.0)
actionpack (>= 3.2)
railties (>= 3.2)
better_errors (2.3.0)
better_errors (2.1.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
erubis (>= 2.6.6)
rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
brakeman (3.7.2)
brakeman (3.4.1)
builder (3.2.3)
byebug (9.1.0)
carrierwave (1.1.0)
byebug (9.0.6)
carrierwave (1.0.0)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
case_transform (0.2)
activesupport
climate_control (0.2.0)
climate_control (0.1.0)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
coderay (1.1.2)
concurrent-ruby (1.0.5)
debug_inspector (0.0.3)
delayed_job (4.1.3)
activesupport (>= 3.0, < 5.2)
delayed_job_active_record (4.1.2)
activerecord (>= 3.0, < 5.2)
coderay (1.1.1)
concurrent-ruby (1.0.4)
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)
devise (4.3.0)
devise (4.2.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.2)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
diff-lcs (1.3)
docile (1.1.5)
doorkeeper (4.2.6)
doorkeeper (4.2.0)
railties (>= 4.2)
dotenv (2.2.1)
dotenv-rails (2.2.1)
dotenv (= 2.2.1)
railties (>= 3.2, < 5.2)
erubi (1.6.1)
dotenv (2.1.2)
dotenv-rails (2.1.2)
dotenv (= 2.1.2)
railties (>= 3.2, < 5.1)
erubis (2.7.0)
exception_notification (4.2.2)
exception_notification (4.2.1)
actionmailer (>= 4.0, < 6)
activesupport (>= 4.0, < 6)
execjs (2.7.0)
factory_bot (4.8.2)
factory_girl (4.8.0)
activesupport (>= 3.0.0)
factory_bot_rails (4.8.2)
factory_bot (~> 4.8.2)
factory_girl_rails (4.8.0)
factory_girl (~> 4.8.0)
railties (>= 3.0.0)
faker (1.8.4)
i18n (~> 0.5)
ffi (1.9.18)
globalid (0.4.0)
activesupport (>= 4.2.0)
httparty (0.15.6)
globalid (0.3.7)
activesupport (>= 4.1.0)
httparty (0.14.0)
multi_xml (>= 0.5.2)
i18n (0.9.3)
concurrent-ruby (~> 1.0)
i18n (0.7.0)
jmespath (1.3.1)
jquery-rails (4.3.1)
jquery-rails (4.2.2)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
json (2.1.0)
json-schema (2.8.0)
json (2.0.3)
json-schema (2.7.0)
addressable (>= 2.4)
jsonapi-renderer (0.1.3)
jsonapi (0.1.1.beta6)
jsonapi-parser (= 0.1.1.beta3)
jsonapi-renderer (= 0.1.1.beta1)
jsonapi-parser (0.1.1.beta3)
jsonapi-renderer (0.1.1.beta1)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
@ -144,154 +143,144 @@ GEM
kaminari-core (1.0.1)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.6)
mail (2.6.4)
mime-types (>= 1.16, < 4)
mailboxer (0.15.1)
mailboxer (0.14.0)
carrierwave (>= 0.5.8)
rails (>= 5.0.0)
rails (>= 4.2.0)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.3.0)
minitest (5.11.1)
mini_portile2 (2.1.0)
minitest (5.10.1)
multi_xml (0.6.0)
nio4r (2.1.0)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
nio4r (1.2.1)
nokogiri (1.7.0.1)
mini_portile2 (~> 2.1.0)
orm_adapter (0.5.0)
paperclip (5.2.0)
paperclip (5.1.0)
activemodel (>= 4.2.0)
activesupport (>= 4.2.0)
cocaine (~> 0.5.5)
mime-types
mimemagic (~> 0.3.0)
parser (2.4.0.2)
ast (~> 2.3)
pg (0.21.0)
parser (2.3.3.1)
ast (~> 2.2)
pg (0.19.0)
powerpack (0.1.1)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-byebug (3.5.0)
byebug (~> 9.1)
pry-byebug (3.4.2)
byebug (~> 9.0)
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
public_suffix (3.0.0)
puma (3.10.0)
pry-rails (0.3.4)
pry (>= 0.9.10)
public_suffix (2.0.5)
puma (3.6.2)
pundit (1.1.0)
activesupport (>= 3.0.0)
pundit_extra (0.3.0)
rack (2.0.3)
rack (2.0.1)
rack-attack (5.0.1)
rack
rack-cors (1.0.1)
rack-cors (0.4.0)
rack-test (0.6.3)
rack (>= 1.0)
rails (5.0.5)
actioncable (= 5.0.5)
actionmailer (= 5.0.5)
actionpack (= 5.0.5)
actionview (= 5.0.5)
activejob (= 5.0.5)
activemodel (= 5.0.5)
activerecord (= 5.0.5)
activesupport (= 5.0.5)
bundler (>= 1.3.0)
railties (= 5.0.5)
rails (5.0.1)
actioncable (= 5.0.1)
actionmailer (= 5.0.1)
actionpack (= 5.0.1)
actionview (= 5.0.1)
activejob (= 5.0.1)
activemodel (= 5.0.1)
activerecord (= 5.0.1)
activesupport (= 5.0.1)
bundler (>= 1.3.0, < 2.0)
railties (= 5.0.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-dom-testing (2.0.2)
activesupport (>= 4.2.0, < 6.0)
nokogiri (~> 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
railties (5.0.5)
actionpack (= 5.0.5)
activesupport (= 5.0.5)
railties (5.0.1)
actionpack (= 5.0.1)
activesupport (= 5.0.1)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
rake (12.3.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
redis (3.3.3)
responders (2.4.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)
rainbow (2.2.1)
rake (12.0.0)
redis (3.3.2)
responders (2.3.0)
railties (>= 4.2.0, < 5.1)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-mocks (3.6.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-rails (3.6.1)
rspec-support (~> 3.5.0)
rspec-rails (3.5.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.6.0)
rspec-support (~> 3.6.0)
rspec-support (3.6.0)
rubocop (0.48.1)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
rubocop (0.47.1)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0)
sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby-progressbar (1.8.1)
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
shoulda-matchers (3.1.2)
shoulda-matchers (3.1.1)
activesupport (>= 4.0.0)
simplecov (0.15.0)
simplecov (0.12.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
slack-notifier (2.3.1)
simplecov-html (0.10.0)
slack-notifier (2.0.0)
slop (3.6.0)
snorlax (0.1.6)
rails (> 4.1)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sucker_punch (2.0.3)
sucker_punch (2.0.2)
concurrent-ruby (~> 1.0.0)
thor (0.20.0)
thread_safe (0.3.6)
tilt (2.0.8)
timecop (0.9.1)
thor (0.19.4)
thread_safe (0.3.5)
tilt (2.0.5)
tunemygc (1.0.69)
tzinfo (1.2.4)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (3.2.0)
uglifier (3.0.4)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.3.0)
warden (1.2.7)
unicode-display_width (1.1.3)
warden (1.2.6)
rack (>= 1.0)
websocket-driver (0.6.5)
websocket-driver (0.6.4)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
@ -300,7 +289,7 @@ PLATFORMS
DEPENDENCIES
active_model_serializers
aws-sdk (~> 2.7.0)
aws-sdk
best_in_place
better_errors
binding_of_caller
@ -311,8 +300,7 @@ DEPENDENCIES
doorkeeper
dotenv-rails
exception_notification
factory_bot_rails
faker
factory_girl_rails
httparty
jquery-rails
jquery-ui-rails
@ -330,16 +318,15 @@ DEPENDENCIES
rack-attack
rack-cors
rails (~> 5.0.0)
redis (~> 3.3.3)
redis
rspec-rails
rubocop (~> 0.48.1)
rubocop
sass-rails
shoulda-matchers
simplecov
slack-notifier
snorlax
sucker_punch
timecop
tunemygc
uglifier
@ -347,4 +334,4 @@ RUBY VERSION
ruby 2.3.0p0
BUNDLED WITH
1.16.1
1.13.7

View file

@ -28,19 +28,39 @@ Metamaps is developed and maintained by a distributed, nomadic community compris
- 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.
## 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:
- [Mac Install Walkthrough][mac-installation]
- [Ubuntu Install Walkthrough][ubuntu-installation]
To start servers which will run metamaps you can then run:
```
./bin/start
```
To stop them:
```
./bin/stop
```
With your webservers running, open a web browser and go to `http://localhost:3000`
If you prefer to isolate your install in a virtual machine, you may find it simpler to setup using Vagrant:
- [Vagrant installation][vagrant-installation]
You can sign in with the default account
email: `user@user.com`
password: `toolsplusconsciousness`
OR create a new account at `/join`, and use access code `qwertyui`
We don't promise support for Windows, but at one point we had it running and we've kept those docs available for reference
- [Outdated Windows Walkthrough][windows-installation]
Start mapping and programming!
We haven't set up instructions for using Vagrant on Windows, but there are instructions for a manual setup here:
- [For Windows][windows-installation]
## Licensing information
@ -56,7 +76,4 @@ Copyright (c) 2017 Connor Turland
[license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE
[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
[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

1
Rakefile Executable file → Normal file
View file

@ -1,6 +1,5 @@
#!/usr/bin/env rake
# frozen_string_literal: true
# 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.

2
Vagrantfile vendored
View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

View file

@ -10,9 +10,6 @@ Metamaps.ServerData['topic_link_signifier.png'] = '<%= asset_path('topic_link_si
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'] %>'

View file

@ -4,11 +4,11 @@ $(document).ready(function() {
if (window.location.pathname === '/') {
$.ajax({
type: 'GET',
url: 'https://i.vimeocdn.com/video/',
url: 'https://player.vimeo.com',
error: function(e) {
$('.homeVideo').hide()
$('.homeVideo').replaceWith($('<video/>', {
poster: '<%= asset_path('metamaps-intro-poster.webp') %>',
poster: '/assets/metamaps-intro-poster.webp',
width: '560',
height: '315',
class: 'homeVideo',

View file

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

View file

@ -193,6 +193,10 @@ button.button.btn-no:hover {
display: block;
width: 830px;
}
.requestInvite {
display: block;
margin: -720px auto 0;
}
.new_session,
.new_user,
.edit_user,
@ -668,21 +672,9 @@ label {
position: relative;
/*overflow:hidden; */
}
.compressed {
.upperRightUI {
right: 324px;
}
.upperRightMapButtons {
right: 434px;
}
.mapControls {
right: 324px;
}
.infoAndHelp {
right: 370px;
}
.main.compressed {
width: calc(100% - 300px);
}
#infovis-canvas {
-webkit-touch-callout: none;
-webkit-user-select: none;
@ -783,9 +775,9 @@ label {
}
.sidebarAccountIcon img {
border-radius: 16px;
width: 32px;
}
.sidebarAccountBox {
display: none;
height: auto;
}
.authenticated .sidebarAccountBox {
@ -826,7 +818,6 @@ label {
font-size: 14px;
line-height: 14px;
color: #757575;
cursor: pointer;
}
.accountListItem:hover {
color: #424242;
@ -1048,6 +1039,7 @@ label[for="user_remember_me"] {
}
.sidebarFilterBox {
display:none;
width: 319px;
padding: 16px 0;
overflow-y: auto;
@ -1258,7 +1250,7 @@ h3.filterBox {
box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24);
}
.rightclickmenu .rc-permission:hover > ul,
.rightclickmenu .rc-metacode:hover #metacodeOptions > ul,
.rightclickmenu .rc-metacode:hover > ul,
.rightclickmenu .rc-siblings:hover > ul {
display: block;
}
@ -1287,7 +1279,7 @@ h3.filterBox {
.rightclickmenu li.toPrivate .rc-perm-icon {
background-position: -24px 0;
}
.rightclickmenu .rc-metacode #metacodeOptions > ul > li,
.rightclickmenu .rc-metacode > ul > li,
.rightclickmenu .rc-siblings > ul > li {
padding: 6px 24px 6px 8px;
white-space: nowrap;
@ -1915,10 +1907,14 @@ input.collaboratorSearchField {
background-position: -32px 0;
}
.yourMap .mapPermission:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
cursor: pointer;
background-position: -32px 0;
}
.yourMap .mapPermission.minimize {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
cursor: pointer;
background-position: 0 0;
}
.mapInfoBox .mapPermission .permissionSelect {
list-style: none;
@ -2315,9 +2311,6 @@ and it won't be important on password protected instances */
}
/* switch metacode set */
#switchMetacodes > p {
margin: 16px 0 16px 0;
}
#metacodeSwitchTabs {
width: 100%;
font-size: 17px;
@ -2325,43 +2318,28 @@ and it won't be important on password protected instances */
border: none;
background: none;
padding: 0;
.setDesc,
.selectAll,
.selectNone {
margin-bottom: 5px;
font-family: 'din-medium', helvetica, sans-serif;
color: #424242;
font-size: 14px;
text-align: justify;
padding-right: 16px;
display: inline-block;
}
.selectAll,
.selectNone {
float: right;
cursor: pointer;
&:hover,
&.selected {
color: #00bcd4;
}
}
& > ul {
width: 130px;
li {
font-size: 14px;
text-transform: uppercase;
}
}
li.ui-state-active a {
color: #00BCD4;
cursor: pointer;
}
}
#metacodeSwitchTabs .setDesc {
margin-bottom: 5px;
font-family: 'din-medium', helvetica, sans-serif;
color: #424242;
font-size: 14px;
text-align: justify;
padding-right: 16px;
}
#switchMetacodes > p {
margin: 16px 0 16px 0;
}
#metacodeSwitchTabs > ul {
width: 130px;
}
#metacodeSwitchTabs > ul li {
font-size: 14px;
text-transform: uppercase;
}
#metacodeSwitchTabs li.ui-state-active a {
color: #00BCD4;
cursor: pointer;
}
.metacodeSwitchTab {
max-height: 300px;
@ -2930,18 +2908,146 @@ and it won't be important on password protected instances */
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 */
.requestInvite {
#wrapper .requestInvite {
width: 700px;
margin: 0 auto;
padding: 0 0 60px 0;
background: #FFFFFF;
color: white;
height: calc(100% - 52px);
z-index: 1;
position: relative;
left: 50%;
margin-left: -350px;
margin-top: 52px;
height: 100%;
overflow: hidden;
}
.home_bg {
@ -3015,17 +3121,3 @@ script.data-gratipay-username {
.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,19 +1,11 @@
$mid-gray: #8A8A8A;
$mid-gray-opacity: rgba(66, 66, 66, 0.6);
.nameCounter {
position: absolute;
bottom: 1px;
right: 2px;
font-size: 11px;
font-family: helvetica, sans-serif;
font-family: helvetica;
color: #727272;
line-height: 11px;
display: none;
}
.riek-editing + .nameCounter {
display: block;
}
.nameCounter.forMap {
@ -22,20 +14,21 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
}
.nameCounter.forTopic {
}
#center-container {
position:relative;
height:100%;
width:100%;
/* background-color:#031924; */
color:#444;
}
.showcard {
position:absolute;
display:none;
top:100px;
left:100px;
width:300px;
@ -45,7 +38,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
z-index:2;
color: #424242;
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 {
@ -56,6 +49,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
width:100%;
height:100%;
position: absolute;
display: none;
}
.showcard .permission {
@ -67,6 +61,7 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
display:block;
position:relative;
width:100%;
min-height:360px;
z-index: 25;
}
.CardOnGraph.hasAttachment {
@ -75,10 +70,11 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
.CardOnGraph .title {
word-break: break-word;
font-size: 20px;
line-height: 24px;
font-size: 18px;
line-height: 22px;
display: table;
padding: 20px 0;
padding: 8px 0 16px;
height: 80px;
text-align: center;
font-family: 'din-regular', sans-serif;
width: 300px;
@ -97,11 +93,12 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
cursor: text;
}
.showcard .title .riek-editing {
.showcard .best_in_place_name textarea, .showcard .best_in_place_name input {
font-family: 'din-regular', sans-serif;
color: #424242;
font-size: 20px;
line-height: 24px;
font-size: 18px;
line-height: 22px;
height: 15px;
padding: 5px 0;
width: 100%;
margin: 0;
@ -115,40 +112,30 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
.CardOnGraph .scroll {
display:block;
padding: 8px 0 8px 16px;
height: 152px;
font-size: 13px;
line-height:15px;
font-family: helvetica, sans-serif;
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 {
height: auto;
}
.CardOnGraph .desc .riek-editing {
.CardOnGraph .best_in_place_desc textarea {
font-size: 13px;
line-height:15px;
font-family: helvetica, sans-serif;
color: #424242;
padding: 0;
width: 258px;
width: 100%;
margin: 0;
border: 0;
outline: none;
font-size: 12px;
line-height: 15px;
background: none;
overflow-y: scroll;
resize: none;
}
/*
@ -180,11 +167,13 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
* End Markdown styling
*/
.CardOnGraph .riek_desc {
.CardOnGraph .best_in_place_desc {
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-position: top right;
background-repeat: no-repeat;
@ -196,215 +185,155 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
}
.CardOnGraph .links {
position: relative;
z-index: 2;
.linkItem {
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;
}
}
position:relative;
border-bottom: 1px solid #BDBDBD;
border-top: 1px solid #BDBDBD;
background-color: #e0e0e0;
}
.CardOnGraph .info {
.linkItem {
float:left;
height:46px;
z-index: 1;
position: relative;
color: #424242;
font-size: 14px;
line-height:14px;
height:12px;
padding:17px 0;
}
.linkItem a {
color: #424242;
}
.linkItem {
float: left;
z-index: 1;
position: relative;
color: $mid-gray-opacity;
font-size: 14px;
line-height: 14px;
.CardOnGraph .icon {
position:absolute;
width:100%;
z-index:1;
padding: 0;
height: 48px;
}
.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 {
color: $mid-gray-opacity;
}
}
.contributor:hover .contributorName {
display: block;
}
.contributor {
bottom: 7px;
margin-left: 16px;
.contributorName {
display: none;
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 {
position: relative;
display: inline-block;
vertical-align: middle;
border-radius: 16px;
margin: 5px 5px 5px 0;
top: 11px;
left: 0;
}
.contributor div:before {
content: '';
position: absolute;
top: 128%;
left: 13px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid #000000;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
span {
font-family: 'din-regular', sans-serif;
font-size: 14px;
}
.linkItem.mapCount {
margin-left: 12px;
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 {
font-family: din-regular;
margin-top: 20px;
display: inline-block;
vertical-align: middle;
width: 97px;
padding: 0 8px 0 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.linkItem.mapCount:hover .hoverTip {
display: block;
}
.CardOnGraph .mapCount .tip, .CardonGraph .mapCount .hoverTip {
top: 44px;
left: 0px;
font-size: 12px !important;
}
.mapCount {
padding:17px 38px 17px 0;
width: 22px;
text-align: right;
.hoverTip {
white-space: nowrap;
font-family: 'din-regular';
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 {
background-position: 0 -32px;
}
.CardOnGraph .mapCount .tip:before, .CardOnGraph .mapCount .hoverTip:before {
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 {
top: 44px;
right: 0px;
font-size: 12px !important;
.CardOnGraph .mapCount .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;
}
&:before {
content: '';
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;
}
}
.CardOnGraph .mapCount li.hideExtra {
display: none;
}
.showMore {
@ -412,10 +341,66 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
color: #4FC059;
}
.linkItem.mapPerm {
margin-right: 8px;
.mapCount .tip a {
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 {
width: 32px;
height: 32px;
@ -437,10 +422,14 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
}
.yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
background-position: -32px 0;
cursor:pointer;
}
.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 {
list-style: none;
@ -476,55 +465,63 @@ $mid-gray-opacity: rgba(66, 66, 66, 0.6);
}
.CardOnGraph .metacodeTitle {
font-family: 'din-regular';
font-style: italic;
font-family: 'vinyl';
text-transform: uppercase;
position: absolute;
line-height: 24px;
height: 26px;
font-size: 18px;
padding: 13px 24px 9px 24px;
height:24px;
font-size: 24px;
display: none;
width: 90%;
padding: 13px 0 9px 10%;
background-color: #E0E0E0;
color: #424242;
width: 120px;
max-width: 120px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.permission.canEdit .metacodeTitle {
cursor:pointer;
}
.permission.canEdit .expandMetacodeSelect {
position: relative;
top: 2px;
left: 4px;
position: absolute;
top: 16px;
right: 16px;
width: 16px;
height: 16px;
background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 -32px;
display: inline-block;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.permission.canEdit .minimize .expandMetacodeSelect {
}
.CardOnGraph .metacodeName {
display: inline-block;
.CardOnGraph .metacodeImage {
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 {
display:none;
width:auto;
z-index: 2;
background: #EAEAEA;
white-space: nowrap;
position: absolute;
top: 48px;
box-shadow: 2px 2px 2px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16);
background: #EAEAEA;
left: 300px;
white-space: nowrap;
}
.CardOnGraph .metacodeSelect ul {
position: relative;
position: relative;
line-height: 14px;
font-size: 14px;
font-family: helvetica, sans-serif;
@ -613,10 +610,11 @@ background-color: #E0E0E0;
display:block;
}
.CardOnGraph .tip {
display:none;
position: absolute;
background: $mid-gray;
background: black;
top: 35px;
right: 0;
left: 0;
color: white;
border-radius: 4px;
font-size:15px !important;
@ -625,23 +623,26 @@ background-color: #E0E0E0;
z-index:100;
}
#embedlyLink {
display: none;
}
#embedlyLinkLoader {
margin: 0 auto;
width: 28px;
}
.CardOnGraph .link-adder {
.CardOnGraph .attachments {
border-top: 1px solid #BDBDBD;
width:100%;
height:47px;
position: relative;
}
.link-adder a {
.attachments a {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
margin-left: 40px;
margin-left: 40px;
padding-top:9px;
font-size: 16px;
line-height: 16px;
@ -651,7 +652,7 @@ background-color: #E0E0E0;
display: inline-block;
width: 102px;
height: 12px;
text-align: left;
text-align: left;
padding: 18px 0 18px 48px;
font-size: 12px;
color: #9e9e9e;
@ -695,9 +696,9 @@ background-color: #E0E0E0;
}
#addLinkInput input{
padding: 9px 27px 9px 31px;
padding: 9px 7px 9px 31px;
height: 12px;
width: 210px;
width: 198px;
margin: 0 0 0 0;
border: none;
outline: none;
@ -751,6 +752,7 @@ font-family: 'din-regular', helvetica, sans-serif;
-moz-border-radius-bottomright: 8px;
-webkit-border-bottom-right-radius: 8px;
border-bottom-right-radius: 8px;
display: none;
margin: 8px;
}
@ -837,10 +839,10 @@ font-family: 'din-regular', helvetica, sans-serif;
line-height: 16px;
}
.canEdit span.titleWrapper:hover {
.canEdit #edit_synapse_desc:hover {
background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat;
background-position: 95% 95%;
background-position: 164px center;
cursor: text;
}
@ -948,11 +950,11 @@ font-family: 'din-regular', helvetica, sans-serif;
}
#edit_synapse_right {
background-image: url(<%= asset_data_uri('synapsedirectionright_sprite.png') %>);
right: 16px;
right: 16px;
}
#edit_synapse_left {
background-image: url(<%= asset_data_uri('synapsedirectionleft_sprite.png') %>);
right: 56px;
right: 56px;
}
#edit_synapse_left.checked, #edit_synapse_right.checked {
background-position: 0 -48px;

View file

@ -30,7 +30,6 @@
height: 100%;
box-sizing: border-box;
padding-top: 92px;
overflow-y: auto;
}
/*.animations {
@ -47,9 +46,26 @@
transition-timing-function: ease-in-out;
}*/
.mapElement {
display: none;
}
.mapPage .mapElement,
.topicPage .mapElement {
display: block;
}
.mapPage .mapElementHidden,
.topicPage .mapElement.mapInfoBox,
.topicPage .mapElement.importDialog {
display:none;
}
.topicPage .starMap {
display: none;
}
/* loading */
#loading {
display: none;
width: 28px;
height: 28px;
position: fixed;
@ -168,14 +184,10 @@
}
.upperRightMapButtons {
right: 138px;
padding-right: 7px;
border-right: 1px solid #747474;
top: -42px; /* puts it just offscreen */
}
.unauthenticated .upperRightMapButtons {
right: 115px;
padding-right: 0;
border-right: none;
.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons {
top: 0;
}
.upperRightIcon {
@ -185,7 +197,13 @@
background-repeat: no-repeat;
cursor: pointer;
}
.mapPage .mapElement .importDialog {
display: none;
background-position: 0 0;
}
.mapPage.canEditMap .mapElement .importDialog {
display: block;
}
.sidebarFilterIcon {
background-position: -32px 0;
}
@ -218,14 +236,6 @@
/* end upperRightUI */
/* map wrapper */
.mapWrapper {
position:absolute;
width: 100%;
height: 100%;
}
/* end map wrapper */
/* yield */
@ -346,15 +356,22 @@
/* infoAndHelp */
.openCheatsheet .tooltipsAbove {
.mapPage .infoAndHelp, .topicPage .infoAndHelp {
right: 70px;
}
.mapPage .openCheatsheet .tooltipsAbove, .topicPage .openCheatsheet .tooltipsAbove {
right: 1px;
left: auto;
}
.unauthenticated .homePage .infoAndHelp {
display:none;
}
.infoAndHelp {
position: absolute;
bottom: 20px;
right: 70px;
right: 20px;
z-index: 3;
width: auto;
font-style: italic;
@ -375,12 +392,16 @@
}
.mapInfoIcon {
position: relative;
background-image: url(<%= asset_path('mapinfo_sprite.png') %>);
background-repeat:no-repeat;
top: 56px; /* puts it just offscreen */
background-image: url(<%= asset_path('mapinfo_sprite.png') %>);
background-repeat:no-repeat;
}
.mapInfoIcon:hover {
background-position: 0 -32px;
}
.mapPage .mapInfoIcon {
top: 0;
}
.starMap {
background-image: url(<%= asset_path('starmap_sprite.png') %>);
@ -398,6 +419,9 @@
background-position: 0 0;
}
.unauthenticated .mapPage .starMap {
display: none;
}
/* end infoAndHelp */
@ -406,17 +430,24 @@
.mapControls {
position: absolute;
bottom: 24px;
right:24px;
right:-32px; /* puts it just offscreen */
width:32px;
z-index: 3;
}
.mapPage .mapControls, .topicPage .mapControls {
right: 24px;
}
.topicPage .zoomExtents {
display: none;
}
.mapControl {
width:32px;
height:32px;
background-color: #424242;
background-repeat: no-repeat;
background-position: 0 0;
background-repeat: no-repeat;
background-position: 0 0;
cursor:pointer;
}
@ -424,6 +455,19 @@
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 {
margin-bottom:5px;
border-radius: 2px;
@ -434,7 +478,7 @@
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, .notificationsIcon: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 {
display: block;
}
@ -556,12 +600,16 @@
left: -8px;
}
.openCheatsheet .tooltipsAbove {
left: -4px;
}
.sidebarAccountIcon .tooltipsUnder {
margin-left: -12px;
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: '';
position: absolute;
top: 57%;
@ -636,11 +684,8 @@
/* explore maps */
#react-app {
position: absolute;
height: 100%;
width: 100%;
overflow-y: auto;
#explore {
display: none;
}
#exploreMaps {
@ -659,28 +704,23 @@
display: block;
}
.requestInviteHeader {
position: absolute;
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);
.appsPage #exploreMapsHeader {
display: block;
}
#navBar {
#exploreMapsHeader {
position: absolute;
width: 100%;
}
.navBarContainer {
.exploreMapsBar {
z-index:2;
background-color:#FAFAFA;
height: 42px;
padding-top: 52px;
}
.navBarMenu {
.exploreMapsMenu {
display: block;
width: 100%;
height:42px;
@ -689,29 +729,30 @@
text-align: center;
}
.navBarCenter {
.exploreMapsCenter {
display: block;
}
.navBarButton {
color: #757575;
.exploreMapsButton {
color: #757575;
cursor: default;
font-weight: normal;
font-family: 'din-medium';
font-size: 14px;
padding: 0 8px;
border-bottom: 2px solid rgba(0,0,0,0);
height: 14px;
padding: 14px 8px 12px 40px;
border-bottom: 2px solid rgba(0,0,0,0);
display: inline-block;
cursor: pointer;
position:relative;
cursor: pointer;
position:relative;
}
.navBarButton:hover, .navBarButton.active {
.exploreMapsButton:hover, .exploreMapsButton.active {
text-decoration: none;
color: #424242;
border-bottom: 2px solid #00BCD4;
}
.navBarButton.mapperButton {
.exploreMapsButton.mapperButton {
height: 40px;
padding: 0;
}
@ -728,69 +769,62 @@
}
.navBarButton .navBarIcon {
.exploreMapsButton .exploreMapsIcon {
background-repeat: no-repeat;
width:32px;
height:32px;
margin-top:5px;
margin-left:5px;
margin-right: 5px;
display: inline-block;
vertical-align: top;
position:absolute;
top:5px;
left:5px;
}
.navBarLinkText {
padding: 11px 0 12px 0;
display: inline-block;
}
.navBarCenter .authedApps .navBarIcon {
.exploreMapsCenter .authedApps .exploreMapsIcon {
background-image: url(<%= asset_path('user_sprite.png') %>);
background-position: 0 -32px;
}
.navBarCenter .myMaps .navBarIcon {
.exploreMapsCenter .myMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -32px 0;
}
.navBarCenter .sharedMaps .navBarIcon {
.exploreMapsCenter .sharedMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -128px 0;
}
.navBarCenter .activeMaps .navBarIcon {
.exploreMapsCenter .activeMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: 0 0;
}
.navBarCenter .featuredMaps .navBarIcon {
.exploreMapsCenter .featuredMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0;
}
.navBarCenter .starredMaps .navBarIcon {
.exploreMapsCenter .starredMaps .exploreMapsIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0;
}
.navBarCenter .notificationsLink .navBarIcon {
.exploreMapsCenter .notificationsLink .exploreMapsIcon {
background-image: url(<%= asset_path 'topright_sprite.png' %>);
background-position: -128px 0;
}
.authedApps:hover .navBarIcon, .authedApps.active .navBarIcon {
.authedApps:hover .exploreMapsIcon, .authedApps.active .exploreMapsIcon {
background-position-x: -32px;
}
.myMaps:hover .navBarIcon, .myMaps.active .navBarIcon {
.myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon {
background-position: -32px -32px;
}
.activeMaps:hover .navBarIcon, .activeMaps.active .navBarIcon {
.activeMaps:hover .exploreMapsIcon, .activeMaps.active .exploreMapsIcon {
background-position: 0 -32px;
}
.featuredMaps:hover .navBarIcon, .featuredMaps.active .navBarIcon {
.featuredMaps:hover .exploreMapsIcon, .featuredMaps.active .exploreMapsIcon {
background-position: -96px -32px;
}
.starredMaps:hover .navBarIcon, .starredMaps.active .navBarIcon {
.starredMaps:hover .exploreMapsIcon, .starredMaps.active .exploreMapsIcon {
background-position: -96px -32px;
}
.sharedMaps:hover .navBarIcon, .sharedMaps.active .navBarIcon {
.sharedMaps:hover .exploreMapsIcon, .sharedMaps.active .exploreMapsIcon {
background-position: -128px -32px;
}
.notificationsLink:hover .navBarIcon, .notificationsLink.active .navBarIcon {
.notificationsLink:hover .exploreMapsIcon, .notificationsLink.active .exploreMapsIcon {
background-position-y: -32px;
}
@ -808,6 +842,7 @@
height: 80px;
font-family: 'din-regular', helvetica, sans-serif;
font-size: 32px;
display: none;
text-align: center;
color: #999999;
z-index: 0;
@ -823,6 +858,7 @@
/* toast */
.toast {
display: none;
position: fixed;
bottom: 20px;
left: 20px;

View file

@ -98,21 +98,21 @@
top: 72px;
}
#chat-box-wrapper {
height: 100%;
float: right;
}
.chat-box {
position: absolute;
right: 0;
position: relative;
display: flex;
flex-direction: column;
z-index: 1;
width: 300px;
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%;

View file

@ -1,3 +1,7 @@
#mobile_header {
display: none;
}
@media only screen and (max-width : 752px) and (min-width : 504px) {
.sidebarSearch .tt-hint, .sidebarSearch .sidebarSearchField {
width: 160px !important;
@ -32,7 +36,7 @@
/* 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 {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #exploreMapsHeader {
display: none !important;
}
@ -47,6 +51,10 @@
display: none;
}
#mobile_header {
display: block;
}
.homeWrapper {
width: 96%;
padding: 0 2%;
@ -64,7 +72,7 @@
height: auto;
}
.homeVideo {
width: 100% !important;
width: 100%;
height: auto;
}
.fullWidthWrapper.withPartners {
@ -100,23 +108,15 @@
max-width: 360px;
}
.requestInviteHeader {
display: none;
}
.requestInvite {
#wrapper .requestInvite {
width: 100%;
height: calc(100% - 50px);
z-index: 1;
position: relative;
left: 0;
margin-left: 0px;
margin-top: 50px;
padding: 0;
}
#exploreMaps > div {
margin-top: 70px;
}
.mapper {
width: 100%;
margin: 0 0 30px 0;
@ -217,7 +217,6 @@
width: 100%;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
position: fixed;
z-index: 1;
}
#menu_icon {
@ -250,6 +249,7 @@
}
#mobile_menu {
display: none;
background: #EEE;
position: fixed;
top: 50px;
@ -257,19 +257,10 @@
padding: 10px;
width: 200px;
box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16);
z-index: 2;
li {
padding: 7px 10px;
padding: 10px;
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;
@ -283,6 +274,16 @@
}
}
/*
* the mobile menu, even if it's been opened by a user, should
* not show up if they resize their browser back to full size
*/
@media only screen and (max-width : 504px) {
#mobile_menu.visible {
display: block;
}
}
li.mobileMenuUser {
border-bottom: 1px solid #BBB;
}

View file

@ -1,7 +1,4 @@
$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;
@ -16,72 +13,13 @@ $unread_notifications_dot_size: 8px;
.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 {
ul.notifications {
list-style: none;
}
.notificationPage,
.notificationsPage {
font-family: 'din-regular', Sans-Serif;
@ -109,129 +47,92 @@ $unread_notifications_dot_size: 8px;
.emptyInbox {
padding-top: 15px;
}
}
.notification {
padding: 10px;
position: relative;
&:hover {
background: #F6F6F6;
.notificationPage {
.thirty-two-avatar {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 16px;
vertical-align: middle;
}
.notification-read-unread {
display:block;
}
.button {
line-height: 32px;
img {
margin-top: 8px;
}
&.decline {
background: #DB5D5D;
&:hover {
background: #DC4B4B;
.notification-date {
display: none;
}
}
}
.notification-body {
p, div {
margin: 1em auto;
line-height: 20px;
& > 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;
.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;
font-size: 13px;
line-height: 13px;
margin-top: -6px;
}
.notification-read-unread {
display: none;
float: left;
width: 15%;
a {
position: absolute;
top: 50%;
margin-top: -10px;
text-align: center;
}
}
&.unread {
background: #EEE;
}
}
}
}
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;
.notificationPage .notification-body {
p, div {
margin: 1em auto;
}
}
}

View file

@ -1,6 +1,7 @@
.viewOnly {
float: left;
margin-left: 16px;
display: none;
height: 32px;
border: 1px solid #BDBDBD;
border-radius: 2px;
@ -22,7 +23,7 @@
}
.requestNotice {
display: inline-block;
display: none;
padding: 0 8px;
}
@ -41,6 +42,16 @@
.requestNotAccepted {
background-color: #c04f4f;
}
&.sendRequest .requestAccess {
display: inline-block;
}
&.sentRequest .requestPending {
display: inline-block;
}
&.requestDenied .requestNotAccepted {
display: inline-block;
}
}
.request_access {

View file

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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class MapChannel < ApplicationCable::Channel
# Called when the consumer has successfully
# become a subscriber of this channel.

View file

@ -1,12 +1,11 @@
# 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]
before_action :require_user, only: [:access, :access_request,
:approve_access, :approve_access_post,
:deny_access, :deny_access_post, :request_access]
before_action :set_map, only: [:access, :access_request,
:approve_access, :approve_access_post,
:deny_access, :deny_access_post, :request_access]
after_action :verify_authorized
# GET maps/:id/request_access
@ -21,7 +20,9 @@ class AccessController < ApplicationController
# POST maps/:id/access_request
def access_request
AccessRequest.create(user: current_user, map: @map)
request = AccessRequest.create(user: current_user, map: @map)
NotificationService.access_request(request)
respond_to do |format|
format.json { head :ok }
end
@ -31,7 +32,12 @@ class AccessController < ApplicationController
def access
user_ids = params[:access].to_a.map(&:to_i) || []
@map.add_new_collaborators(user_ids)
@map.add_new_collaborators(user_ids).each do |user_id|
# add_new_collaborators returns array of added users,
# who we then send a notification to
user = User.find(user_id)
NotificationService.invite_to_edit(@map, current_user, user)
end
@map.remove_old_collaborators(user_ids)
respond_to do |format|
@ -62,7 +68,6 @@ class AccessController < ApplicationController
request = AccessRequest.find(params[:request_id])
request.approve
respond_to do |format|
format.js
format.json do
head :ok
end
@ -74,7 +79,6 @@ class AccessController < ApplicationController
request = AccessRequest.find(params[:request_id])
request.deny
respond_to do |format|
format.js
format.json do
head :ok
end

View file

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

View file

@ -1,11 +1,31 @@
# frozen_string_literal: true
module Api
module V2
class MappingsController < WithUpdatesController
class MappingsController < RestfulController
def searchable_columns
[]
end
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,10 +1,9 @@
# frozen_string_literal: true
module Api
module V2
class MapsController < WithUpdatesController
class MapsController < RestfulController
def searchable_columns
%i[name desc]
[:name, :desc]
end
def apply_filters(collection)

View file

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

View file

@ -1,14 +1,14 @@
# frozen_string_literal: true
module Api
module V2
class RestfulController < ActionController::Base
include Pundit
include PunditExtra
protect_from_forgery with: :exception
snorlax_used_rest!
before_action :load_resource, only: %i[show update destroy]
before_action :load_resource, only: [:show, :update, :destroy]
after_action :verify_authorized
def index
@ -46,7 +46,7 @@ module Api
end
def current_user
token_user || doorkeeper_user
token_user || doorkeeper_user || super
end
def load_resource
@ -92,7 +92,7 @@ module Api
end
def doorkeeper_user
return if doorkeeper_token.blank?
return unless doorkeeper_token.present?
doorkeeper_render_error unless valid_doorkeeper_token?
@doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id)
end

View file

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

View file

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

View file

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

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true
module Api
module V2
class TokensController < RestfulController
protect_from_forgery
def searchable_columns
[:description]
end
@ -21,12 +18,6 @@ module Api
create_action
respond_with_resource
end
private
def current_user
token_user || doorkeeper_user || method(:current_user).super_method.super_method.call
end
end
end
end

View file

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

View file

@ -1,10 +1,8 @@
# frozen_string_literal: true
module Api
module V2
class UsersController < RestfulController
def current
raise Pundit::NotAuthorizedError if current_user.nil?
@user = current_user
authorize @user
show # delegate to the normal show function

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
class ApplicationController < ActionController::Base
include ApplicationHelper
include Pundit

View file

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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
# bad code that should be checked over before entering one of the
# nice files from the right side of this repo
class HacksController < ApplicationController

View file

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

View file

@ -1,7 +1,6 @@
# frozen_string_literal: true
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_policy_scoped, only: :index
@ -34,7 +33,6 @@ class MappingsController < ApplicationController
@mapping = Mapping.find(params[:id])
authorize @mapping
@mapping.updated_by = current_user
@mapping.map.updated_by = current_user
@mapping.assign_attributes(mapping_params)
if @mapping.save
@ -49,7 +47,6 @@ class MappingsController < ApplicationController
@mapping = Mapping.find(params[:id])
authorize @mapping
@mapping.updated_by = current_user
@mapping.map.updated_by = current_user
@mapping.destroy
head :no_content

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true
class MapsController < ApplicationController
before_action :require_user, only: %i[create update destroy events follow unfollow]
before_action :set_map, only: %i[show conversation update destroy
contains events export
follow unfollow unfollow_from_email]
before_action :require_user, only: [:create, :update, :destroy, :events]
before_action :set_map, only: [:show, :conversation, :update, :destroy, :contains, :events, :export]
after_action :verify_authorized
# GET maps/:id
@ -26,7 +23,7 @@ class MapsController < ApplicationController
format.ttl { redirect_to action: :export, format: :ttl }
end
end
# GET maps/:id/conversation
def conversation
respond_to do |format|
@ -62,7 +59,6 @@ class MapsController < ApplicationController
def create
@map = Map.new(create_map_params)
@map.user = current_user
@map.updated_by = current_user
@map.arranged = false
authorize @map
@ -83,11 +79,8 @@ class MapsController < ApplicationController
# PUT maps/:id
def update
@map.updated_by = current_user
@map.assign_attributes(update_map_params)
respond_to do |format|
if @map.save
if @map.update_attributes(update_map_params)
format.json { head :no_content }
else
format.json { render json: @map.errors, status: :unprocessable_entity }
@ -97,8 +90,7 @@ class MapsController < ApplicationController
# DELETE maps/:id
def destroy
@map.updated_by = current_user
@map.destroy
@map.delete
respond_to do |format|
format.json do
@ -141,43 +133,6 @@ class MapsController < ApplicationController
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
def set_map

View file

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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class MetacodeSetsController < ApplicationController
before_action :require_admin

View file

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

View file

@ -1,23 +1,18 @@
# 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]
before_action :set_receipts, only: [:index, :show, :mark_read, :mark_unread]
before_action :set_notification, only: [:show, :mark_read, :mark_unread]
before_action :set_receipt, only: [: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|
render json: @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
notification.as_json.merge(is_read: receipt.is_read)
end
end
end
@ -26,20 +21,11 @@ class NotificationsController < ApplicationController
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.html
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
end
end
end
@ -49,7 +35,9 @@ class NotificationsController < ApplicationController
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
end
end
end
@ -59,7 +47,9 @@ class NotificationsController < ApplicationController
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
end
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class SearchController < ApplicationController
include TopicsHelper
include MapsHelper
@ -8,7 +7,7 @@ class SearchController < ApplicationController
before_action :authorize_search
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
def topics
@ -141,13 +140,13 @@ class SearchController < ApplicationController
topic1id = params[:topic1id]
topic2id = params[:topic2id]
if term.present?
if term && !term.empty?
@synapses = policy_scope(Synapse)
.where('LOWER("desc") like ?', '%' + term.downcase.strip + '%')
.order('"desc"')
@synapses = @synapses.uniq(&:desc)
elsif topic1id.present?
elsif topic1id && !topic1id.empty?
one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id)
two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id)
@synapses = one + two

View file

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

View file

@ -1,9 +1,8 @@
# frozen_string_literal: true
class SynapsesController < ApplicationController
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_policy_scoped, only: :index
@ -23,8 +22,6 @@ class SynapsesController < ApplicationController
@synapse = Synapse.new(synapse_params)
@synapse.desc = '' if @synapse.desc.nil?
@synapse.desc.strip! # no trailing/leading whitespace
@synapse.user = current_user
@synapse.updated_by = current_user
# we want invalid params to return :unprocessable_entity
# so we have to authorize AFTER saving. But if authorize
@ -50,11 +47,9 @@ class SynapsesController < ApplicationController
@synapse = Synapse.find(params[:id])
@synapse.desc = '' if @synapse.desc.nil?
authorize @synapse
@synapse.updated_by = current_user
@synapse.assign_attributes(synapse_params)
respond_to do |format|
if @synapse.save
if @synapse.update_attributes(synapse_params)
format.json { head :no_content }
else
format.json { render json: @synapse.errors, status: :unprocessable_entity }
@ -66,7 +61,6 @@ class SynapsesController < ApplicationController
def destroy
@synapse = Synapse.find(params[:id])
authorize @synapse
@synapse.updated_by = current_user
@synapse.destroy
respond_to do |format|
@ -78,7 +72,7 @@ class SynapsesController < ApplicationController
def synapse_params
params.require(:synapse).permit(
:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id
:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id, :user_id
)
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
class TopicsController < ApplicationController
include TopicsHelper
before_action :require_user, only: %i[create update destroy follow unfollow]
before_action :set_topic, only: %i[show update relative_numbers
relatives network destroy
follow unfollow unfollow_from_email]
before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized, except: :autocomplete_topic
respond_to :html, :js, :json
@ -14,7 +10,7 @@ class TopicsController < ApplicationController
# GET /topics/autocomplete_topic
def autocomplete_topic
term = params[:term]
if term.present?
if term && !term.empty?
topics = policy_scope(Topic)
.where('LOWER("name") like ?', term.downcase + '%')
.order('"name"')
@ -35,6 +31,9 @@ class TopicsController < ApplicationController
# GET topics/:id
def show
@topic = Topic.find(params[:id])
authorize @topic
respond_to do |format|
format.html do
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@ -50,6 +49,9 @@ class TopicsController < ApplicationController
# GET topics/:id/network
def network
@topic = Topic.find(params[:id])
authorize @topic
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@allsynapses = policy_scope(Synapse.for_topic(@topic.id))
@ -69,6 +71,9 @@ class TopicsController < ApplicationController
# GET topics/:id/relative_numbers
def relative_numbers
@topic = Topic.find(params[:id])
authorize @topic
topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
@ -89,6 +94,9 @@ class TopicsController < ApplicationController
# GET topics/:id/relatives
def relatives
@topic = Topic.find(params[:id])
authorize @topic
topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
@ -126,8 +134,6 @@ class TopicsController < ApplicationController
def create
@topic = Topic.new(topic_params)
authorize @topic
@topic.user = current_user
@topic.updated_by = current_user
respond_to do |format|
if @topic.save
@ -141,11 +147,11 @@ class TopicsController < ApplicationController
# PUT /topics/1
# PUT /topics/1.json
def update
@topic.updated_by = current_user
@topic.assign_attributes(topic_params)
@topic = Topic.find(params[:id])
authorize @topic
respond_to do |format|
if @topic.save
if @topic.update_attributes(topic_params)
format.json { head :no_content }
else
format.json { render json: @topic.errors, status: :unprocessable_entity }
@ -155,58 +161,18 @@ class TopicsController < ApplicationController
# DELETE topics/:id
def destroy
@topic.updated_by = current_user
@topic = Topic.find(params[:id])
authorize @topic
@topic.destroy
respond_to do |format|
format.json { head :no_content }
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
def set_topic
@topic = Topic.find(params[:id])
authorize @topic
end
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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Users
class PasswordsController < Devise::PasswordsController
protected

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Users
class RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
@ -30,7 +29,7 @@ module Users
end
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: %i[name joinedwithcode])
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :joinedwithcode])
end
def configure_account_update_params

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Users
class SessionsController < Devise::SessionsController
after_action :store_location, only: [:new]

View file

@ -1,7 +1,6 @@
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :require_user, only: %i[edit update updatemetacodes update_metacode_focus]
before_action :require_user, only: [:edit, :update, :updatemetacodes, :update_metacode_focus]
respond_to :html, :json
@ -24,15 +23,14 @@ class UsersController < ApplicationController
if user_params[:password] == '' && user_params[:password_confirmation] == ''
# not trying to change the password
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.save
bypass_sign_in(@user)
sign_in(@user, bypass: true)
respond_to do |format|
format.html { redirect_to root_url, notice: 'Settings updated' }
format.html { redirect_to root_url, notice: 'Account updated!' }
end
else
bypass_sign_in(@user)
sign_in(@user, bypass: true)
respond_to do |format|
format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] }
end
@ -42,12 +40,11 @@ class UsersController < ApplicationController
correct_pass = @user.valid_password?(params[:current_password])
if correct_pass && @user.update_attributes(user_params)
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1'
@user.save
sign_in(@user, bypass: true)
respond_to do |format|
format.html { redirect_to root_url, notice: 'Settings updated' }
format.html { redirect_to root_url, notice: 'Account updated!' }
end
else
respond_to do |format|
@ -101,22 +98,15 @@ class UsersController < ApplicationController
@user.settings.metacode_focus = params[:value]
@user.save
respond_to do |format|
format.json { render json: { success: 'success' } }
format.json { render json: { success: "success" }}
end
end
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
params.require(:user).permit(
:name, :email, :image, :password, :password_confirmation, :emails_allowed, :settings
:name, :email, :image, :password, :password_confirmation, :emails_allowed
)
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,6 +1,55 @@
# frozen_string_literal: true
module ApplicationHelper
def metacodeset
metacodes = current_user.settings.metacodes
return false unless metacodes[0].include?('metacodeset')
return 'Most' if metacodes[0].sub('metacodeset-', '') == 'Most'
return 'Recent' if metacodes[0].sub('metacodeset-', '') == 'Recent'
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.most_used_metacodes).to_a
elsif set && set == 'Recent'
Metacode.where(id: current_user.recent_metacodes).to_a
elsif set
set.metacodes.to_a
else
Metacode.where(id: @m).to_a
end
focus_code = user_metacode()
if focus_code != nil && @metacodes.index{|m| m.id == focus_code.id} == nil
@metacodes.push(focus_code)
end
@metacodes
.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }
if focus_code != nil
@metacodes.rotate!(@metacodes.index{|m| m.id == focus_code.id})
else
@metacodes.rotate!(-1)
end
end
def user_metacode
current_user.settings.metacode_focus ? Metacode.find(current_user.settings.metacode_focus.to_i) : nil
end
def user_most_used_metacodes
@metacodes = current_user.most_used_metacodes.map { |id| Metacode.find(id) }
end
def user_recent_metacodes
@metacodes = current_user.recent_metacodes.map { |id| Metacode.find(id) }
end
def invite_link
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '')
end

View file

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

View file

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

View file

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

View file

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

View file

@ -1,15 +0,0 @@
# frozen_string_literal: true
module MapMailerHelper
def access_approved_subject(map)
map.name + ' - access approved'
end
def access_request_subject(map)
map.name + ' - request to edit'
end
def invite_to_edit_subject(map)
map.name + ' - invited to edit'
end
end

View file

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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module MapsHelper
# JSON autocomplete format for typeahead
def autocomplete_map_array_json(maps)

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
module MetacodeSetsHelper
end

View file

@ -1,79 +1,3 @@
# frozen_string_literal: true
module MetacodesHelper
def metacodeset
metacodes = current_user.settings.metacodes
return false unless metacodes[0].include?('metacodeset')
return 'Most' if metacodes[0].sub('metacodeset-', '') == 'Most'
return 'Recent' if metacodes[0].sub('metacodeset-', '') == 'Recent'
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.most_used_metacodes).to_a
elsif set && set == 'Recent'
Metacode.where(id: current_user.recent_metacodes).to_a
elsif set
set.metacodes.to_a
else
Metacode.where(id: @m).to_a
end
focus_code = user_metacode
if !focus_code.nil? && @metacodes.index { |m| m.id == focus_code.id }.nil?
@metacodes.push(focus_code)
end
@metacodes.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }
if !focus_code.nil?
@metacodes.rotate!(@metacodes.index { |m| m.id == focus_code.id })
else
@metacodes.rotate!(-1)
end
end
def user_metacode
current_user.settings.metacode_focus ? Metacode.find(current_user.settings.metacode_focus.to_i) : nil
end
def user_most_used_metacodes
@metacodes = current_user.most_used_metacodes.map { |id| Metacode.find(id) }
end
def user_recent_metacodes
@metacodes = current_user.recent_metacodes.map { |id| Metacode.find(id) }
end
def metacode_sets_json
metacode_sets = []
metacode_sets << {
name: 'Recently Used',
metacodes: user_recent_metacodes
.map { |m| { id: m.id, icon_path: asset_path(m.icon), name: m.name } }
}
metacode_sets << {
name: 'Most Used',
metacodes: user_most_used_metacodes
.map { |m| { id: m.id, icon_path: asset_path(m.icon), name: m.name } }
}
metacode_sets += MetacodeSet.order('name').all.map do |set|
{
name: set.name,
metacodes: set.metacodes.order('name')
.map { |m| { id: m.id, icon_path: asset_path(m.icon), name: m.name } }
}
end
metacode_sets << {
name: 'All',
metacodes: Metacode.order('name').all
.map { |m| { id: m.id, icon_path: asset_path(m.icon), name: m.name } }
}
metacode_sets.to_json
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module SynapsesHelper
## this one is for building our custom JSON autocomplete format for typeahead
def autocomplete_synapse_generic_json(unique)

View file

@ -1,11 +0,0 @@
# frozen_string_literal: true
module TopicMailerHelper
def added_to_map_subject(topic, map)
topic.name + ' was added to map ' + map.name
end
def connected_subject(topic)
'new synapse to topic ' + topic.name
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module TopicsHelper
## this one is for building our custom JSON autocomplete format for typeahead
def autocomplete_array_json(topics)
@ -17,7 +16,7 @@ module TopicsHelper
rtype: is_map ? 'map' : 'topic',
inmaps: is_map ? [] : t.inmaps(current_user),
inmapsLinks: is_map ? [] : t.inmaps_links(current_user),
inmapsLinks: is_map ? [] : t.inmapsLinks(current_user),
type: is_map ? metamap_metacode.name : t.metacode.name,
typeImageURL: is_map ? metamap_metacode.icon : t.metacode.icon,
mapCount: is_map ? 0 : t.maps.count,

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module UsersHelper
# build custom json autocomplete for typeahead
def autocomplete_user_array_json(users)

View file

@ -1,30 +1,23 @@
# frozen_string_literal: true
class ApplicationMailer < ActionMailer::Base
default from: 'team@metamaps.cc'
layout 'mailer'
def deliver
raise NotImplementedError('Please use Mailboxer to send your emails.')
end
class << self
def mail_for_notification(notification)
case notification.notification_code
when MAP_ACCESS_REQUEST
if notification.notification_code == MAILBOXER_CODE_ACCESS_REQUEST
request = notification.notified_object
MapMailer.access_request(request)
when MAP_ACCESS_APPROVED
MapMailer.access_request_email(request)
elsif notification.notification_code == MAILBOXER_CODE_ACCESS_APPROVED
request = notification.notified_object
MapMailer.access_approved(request)
when MAP_INVITE_TO_EDIT
MapMailer.access_approved_email(request)
elsif notification.notification_code == MAILBOXER_CODE_INVITE_TO_EDIT
user_map = notification.notified_object
MapMailer.invite_to_edit(user_map)
when TOPIC_ADDED_TO_MAP
event = notification.notified_object
TopicMailer.added_to_map(event, notification.recipients[0])
when TOPIC_CONNECTED_1
synapse = notification.notified_object
TopicMailer.connected(synapse, synapse.topic1, notification.recipients[0])
when TOPIC_CONNECTED_2
synapse = notification.notified_object
TopicMailer.connected(synapse, synapse.topic2, notification.recipients[0])
MapMailer.invite_to_edit_email(user_map.map, user_map.map.user, user_map.user)
end
end
end

View file

@ -1,12 +0,0 @@
# frozen_string_literal: true
class MapActivityMailer < ApplicationMailer
default from: 'team@metamaps.cc'
def daily_summary(user, map, summary_data)
@user = user
@map = map
@summary_data = summary_data
mail(to: user.email, subject: MapActivityService.subject_line(map))
end
end

View file

@ -1,24 +1,22 @@
# frozen_string_literal: true
class MapMailer < ApplicationMailer
include MapMailerHelper
default from: 'team@metamaps.cc'
def access_approved(request)
def access_request_email(request)
@request = request
@map = request.map
mail(to: request.user.email, subject: access_approved_subject(@map))
mail(to: @map.user.email, subject: request.requested_text)
end
def access_request(request)
def access_approved_email(request)
@request = request
@map = request.map
mail(to: @map.user.email, subject: access_request_subject(@map))
mail(to: request.user, subject: request.approved_text)
end
def invite_to_edit(user_map)
@inviter = user_map.map.user
@map = user_map.map
mail(to: user_map.user.email, subject: invite_to_edit_subject(@map))
def invite_to_edit_email(map, inviter, invitee)
@inviter = inviter
@map = map
mail(to: invitee.email, subject: map.invited_text)
end
end

View file

@ -1,18 +0,0 @@
# frozen_string_literal: true
class TopicMailer < ApplicationMailer
include TopicMailerHelper
default from: 'team@metamaps.cc'
def added_to_map(event, user)
@entity = event.eventable
@event = event
mail(to: user.email, subject: added_to_map_subject(@entity, event.map))
end
def connected(synapse, topic, user)
@entity = topic
@event = synapse
mail(to: user.email, subject: connected_subject(topic))
end
end

View file

@ -1,11 +1,7 @@
# frozen_string_literal: true
class AccessRequest < ApplicationRecord
belongs_to :user
belongs_to :map
has_one :user_map
after_create :after_created_async
def approve
self.approved = true
@ -16,7 +12,8 @@ class AccessRequest < ApplicationRecord
Mailboxer::Receipt.where(notification: notification).update_all(is_read: true)
end
UserMap.create(user: user, map: map, access_request: self)
UserMap.create(user: user, map: map)
NotificationService.access_approved(self)
end
def deny
@ -29,10 +26,11 @@ class AccessRequest < ApplicationRecord
end
end
protected
def after_created_async
NotificationService.access_request(self)
def requested_text
map.name + ' - request to edit'
end
def approved_text
map.name + ' - access approved'
end
handle_asynchronously :after_created_async
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class Attachment < ApplicationRecord
belongs_to :attachable, polymorphic: true

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Attachable
extend ActiveSupport::Concern

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Routing
extend ActiveSupport::Concern
include Rails.application.routes.url_helpers

View file

@ -1,17 +1,16 @@
# frozen_string_literal: true
class Event < ApplicationRecord
KINDS = %w[user_present_on_map user_not_present_on_map
KINDS = %w(user_present_on_map user_not_present_on_map
conversation_started_on_map
topic_added_to_map topic_moved_on_map topic_removed_from_map
synapse_added_to_map synapse_removed_from_map
topic_updated synapse_updated].freeze
topic_updated synapse_updated).freeze
belongs_to :eventable, polymorphic: true
belongs_to :map
belongs_to :user
scope :chronologically, (-> { order('created_at asc') })
scope :chronologically, -> { order('created_at asc') }
after_create :notify_webhooks!, if: :map

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class ConversationStartedOnMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class SynapseAddedToMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class SynapseRemovedFromMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class SynapseUpdated < Event
# after_create :notify_users!

View file

@ -1,8 +1,7 @@
# frozen_string_literal: true
module Events
class TopicAddedToMap < Event
after_create :notify_users!
# after_create :notify_users!
def self.publish!(topic, map, user, meta)
create!(kind: 'topic_added_to_map',
@ -11,12 +10,5 @@ module Events
user: user,
meta: meta)
end
def notify_users!
# in the future, notify followers of both the topic, and the map
NotificationService.notify_followers(eventable, TOPIC_ADDED_TO_MAP, self)
# NotificationService.notify_followers(map, MAP_RECEIVED_TOPIC, self)
end
handle_asynchronously :notify_users!
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class TopicMovedOnMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class TopicRemovedFromMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class TopicUpdated < Event
# after_create :notify_users!
@ -10,9 +9,5 @@ module Events
user: user,
meta: meta)
end
def notify_users!
NotificationService.notify_followers(eventable, 'topic_updated', self)
end
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class UserNotPresentOnMap < Event
# after_create :notify_users!

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module Events
class UserPresentOnMap < Event
# after_create :notify_users!

View file

@ -1,21 +0,0 @@
# frozen_string_literal: true
class Follow < ApplicationRecord
belongs_to :user
belongs_to :followed, polymorphic: true
has_one :follow_reason, dependent: :destroy
validates :user, presence: true
validates :followed, presence: true
validates :user, uniqueness: { scope: :followed, message: 'This entity is already followed by this user' }
after_create :add_subsetting
scope :active, (-> { where(muted: false) })
private
def add_subsetting
FollowReason.create!(follow: self)
end
end

View file

@ -1,13 +0,0 @@
# frozen_string_literal: true
class FollowReason < ApplicationRecord
REASONS = %w[created commented contributed followed shared_on starred].freeze
belongs_to :follow
validates :follow, presence: true
def has_reason
created || commented || contributed || followed || shared_on || starred
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class InMetacodeSet < ApplicationRecord
belongs_to :metacode, class_name: 'Metacode', foreign_key: 'metacode_id'
belongs_to :metacode_set, class_name: 'MetacodeSet', foreign_key: 'metacode_set_id'

View file

@ -1,11 +1,7 @@
# frozen_string_literal: true
class Map < ApplicationRecord
ATTRS_TO_WATCH = %w[name desc permission].freeze
belongs_to :user
belongs_to :source, class_name: :Map
belongs_to :updated_by, class_name: 'User'
has_many :topicmappings, -> { Mapping.topicmapping },
class_name: :Mapping, dependent: :destroy
@ -14,9 +10,7 @@ class Map < ApplicationRecord
has_many :topics, through: :topicmappings, source: :mappable, source_type: 'Topic'
has_many :synapses, through: :synapsemappings, source: :mappable, source_type: 'Synapse'
has_many :messages, as: :resource, dependent: :destroy
has_many :stars, dependent: :destroy
has_many :follows, as: :followed, dependent: :destroy
has_many :followers, through: :follows, source: :user
has_many :stars
has_many :access_requests, dependent: :destroy
has_many :user_maps, dependent: :destroy
@ -40,10 +34,8 @@ class Map < ApplicationRecord
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :screenshot, content_type: %r{\Aimage/.*\Z}
after_create :after_created
after_update :after_updated
after_save :update_deferring_topics_and_synapses, if: :permission_changed?
before_destroy :before_destroyed
delegate :count, to: :topics, prefix: :topic # same as `def topic_count; topics.count; end`
delegate :count, to: :synapses, prefix: :synapse
@ -90,10 +82,10 @@ class Map < ApplicationRecord
def as_json(_options = {})
json = super(
methods: %i[user_name user_image star_count topic_count synapse_count
contributor_count collaborator_ids screenshot_url],
except: %i[screenshot_content_type screenshot_file_size screenshot_file_name
screenshot_updated_at]
methods: [:user_name, :user_image, :star_count, :topic_count, :synapse_count,
:contributor_count, :collaborator_ids, :screenshot_url],
except: [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name,
:screenshot_updated_at]
)
json[:created_at_clean] = created_at_str
json[:updated_at_clean] = updated_at_str
@ -135,34 +127,18 @@ class Map < ApplicationRecord
removed.compact
end
def after_updated
attrs = %w(name desc permission)
return unless attrs.any? { |k| changed_attributes.key?(k) }
ActionCable.server.broadcast 'map_' + id.to_s, type: 'mapUpdated'
end
def update_deferring_topics_and_synapses
Topic.where(defer_to_map_id: id).update(permission: permission)
Synapse.where(defer_to_map_id: id).update(permission: permission)
end
protected
def after_created
FollowService.follow(self, user, 'created')
# notify users following the map creator
end
def after_updated
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
ActionCable.server.broadcast 'map_' + id.to_s, type: 'mapUpdated'
end
def after_updated_async
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
FollowService.follow(self, updated_by, 'contributed')
# NotificationService.notify_followers(self, 'map_updated', changed_attributes)
# or better yet publish an event
end
handle_asynchronously :after_updated_async
def before_destroyed
Map.where(source_id: id).find_each do |forked_map|
forked_map.update(source_id: nil)
end
def invited_text
name + ' - invited to edit'
end
end

View file

@ -1,8 +1,7 @@
# frozen_string_literal: true
class Mapping < ApplicationRecord
scope :topicmapping, (-> { where(mappable_type: :Topic) })
scope :synapsemapping, (-> { where(mappable_type: :Synapse) })
scope :topicmapping, -> { where(mappable_type: :Topic) }
scope :synapsemapping, -> { where(mappable_type: :Synapse) }
belongs_to :mappable, polymorphic: true
belongs_to :map, class_name: 'Map', foreign_key: 'map_id', touch: true
@ -15,9 +14,7 @@ class Mapping < ApplicationRecord
delegate :name, to: :user, prefix: true
after_create :after_created
after_create :after_created_async
after_update :after_updated
after_update :after_updated_async
before_destroy :before_destroyed
def user_image
@ -25,48 +22,35 @@ class Mapping < ApplicationRecord
end
def as_json(_options = {})
super(methods: %i[user_name user_image])
super(methods: [:user_name, :user_image])
end
def after_created
if mappable_type == 'Topic'
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicAdded', topic: mappable.filtered, mapping_id: id
meta = { 'x': xloc, 'y': yloc, 'mapping_id': id }
Events::TopicAddedToMap.publish!(mappable, map, user, meta)
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicAdded', topic: mappable.filtered, mapping_id: id
elsif mappable_type == 'Synapse'
Events::SynapseAddedToMap.publish!(mappable, map, user, meta)
ActionCable.server.broadcast(
'map_' + map.id.to_s,
type: 'synapseAdded',
synapse: mappable.filtered,
topic1: mappable.topic1&.filtered,
topic2: mappable.topic2&.filtered,
topic1: mappable.topic1.filtered,
topic2: mappable.topic2.filtered,
mapping_id: id
)
meta = { 'mapping_id': id }
Events::SynapseAddedToMap.publish!(mappable, map, user, meta)
end
end
def after_created_async
FollowService.follow(map, user, 'contributed')
end
handle_asynchronously :after_created_async
def after_updated
return unless (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
meta = { 'x': xloc, 'y': yloc, 'mapping_id': id }
Events::TopicMovedOnMap.publish!(mappable, map, updated_by, meta)
ActionCable.server.broadcast('map_' + map.id.to_s, type: 'topicMoved',
id: mappable.id, mapping_id: id,
x: xloc, y: yloc)
if (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
meta = { 'x': xloc, 'y': yloc, 'mapping_id': id }
Events::TopicMovedOnMap.publish!(mappable, map, updated_by, meta)
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicMoved', id: mappable.id, mapping_id: id, x: xloc, y: yloc
end
end
def after_updated_async
return unless (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
FollowService.follow(map, updated_by, 'contributed')
end
handle_asynchronously :after_updated_async
def before_destroyed
if mappable.defer_to_map
mappable.permission = mappable.defer_to_map.permission
@ -82,6 +66,5 @@ class Mapping < ApplicationRecord
Events::SynapseRemovedFromMap.publish!(mappable, map, updated_by, meta)
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseRemoved', id: mappable.id, mapping_id: id
end
FollowService.follow(map, updated_by, 'contributed')
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class Message < ApplicationRecord
belongs_to :user
belongs_to :resource, polymorphic: true
@ -7,24 +6,17 @@ class Message < ApplicationRecord
delegate :name, to: :user, prefix: true
after_create :after_created
# after_create :after_created_async
def user_image
user.image.url
end
def as_json(_options = {})
json = super(methods: %i[user_name user_image])
json = super(methods: [:user_name, :user_image])
json
end
def after_created
ActionCable.server.broadcast 'map_' + resource.id.to_s, type: 'messageCreated', message: as_json
end
def after_created_async
FollowService.follow(resource, user, 'commented')
NotificationService.notify_followers(resource, 'map_message', self)
end
handle_asynchronously :after_created_async
end

View file

@ -1,16 +1,17 @@
# frozen_string_literal: true
class Metacode < ApplicationRecord
has_many :in_metacode_sets
has_many :metacode_sets, through: :in_metacode_sets
has_many :topics
# This method associates the attribute ":aws_icon" with a file attachment
has_attached_file :aws_icon, styles: { ninetysix: ['96x96#', :png] },
has_attached_file :aws_icon, styles: {
ninetysix: ['96x96#', :png]
},
default_url: 'https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_wildcard.png'
# Validate the attached icon is image/jpg, image/png, etc
validates_attachment_content_type :aws_icon, content_type: %r{\Aimage/.*\Z}
validates_attachment_content_type :aws_icon, content_type: /\Aimage\/.*\Z/
validate :aws_xor_manual_icon
validate :manual_icon_https
@ -29,13 +30,15 @@ class Metacode < ApplicationRecord
def as_json(options = {})
default = super(options)
default[:icon] = icon
default.except(
'aws_icon_file_name', 'aws_icon_content_type', 'aws_icon_file_size', 'aws_icon_updated_at',
'manual_icon'
)
default.except('aws_icon_file_name', 'aws_icon_content_type', 'aws_icon_file_size', 'aws_icon_updated_at', 'manual_icon')
end
def in_metacode_set(metacode_set)
def hasSelected(user)
return true if user.settings.metacodes.include? id.to_s
false
end
def inMetacodeSet(metacode_set)
return true if metacode_sets.include? metacode_set
false
end
@ -52,9 +55,10 @@ class Metacode < ApplicationRecord
end
def manual_icon_https
return if manual_icon.blank?
unless manual_icon.starts_with? 'https'
errors.add(:base, 'Manual icon must begin with https')
if manual_icon.present?
unless manual_icon.starts_with? 'https'
errors.add(:base, 'Manual icon must begin with https')
end
end
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class MetacodeSet < ApplicationRecord
belongs_to :user
has_many :in_metacode_sets

View file

@ -1,18 +1,13 @@
# frozen_string_literal: true
class PermittedParams
%w[map synapse topic mapping token].each do |kind|
class PermittedParams < Struct.new(:params)
%w(map synapse topic mapping token).each do |kind|
define_method(kind) do
permitted_attributes = send("#{kind}_attributes")
@params.require(kind).permit(*permitted_attributes)
params.require(kind).permit(*permitted_attributes)
end
alias_method :"api_#{kind}", kind.to_sym
end
def initialize(params)
@params = params
end
alias read_attribute_for_serialization send
def token_attributes
@ -20,18 +15,18 @@ class PermittedParams
end
def map_attributes
%i[name desc permission arranged]
[:name, :desc, :permission, :arranged]
end
def synapse_attributes
%i[desc category weight permission topic1_id topic2_id]
[:desc, :category, :weight, :permission, :topic1_id, :topic2_id]
end
def topic_attributes
%i[name desc link permission metacode_id]
[:name, :desc, :link, :permission, :metacode_id]
end
def mapping_attributes
%i[xloc yloc map_id mappable_type mappable_id]
[:xloc, :yloc, :map_id, :mappable_type, :mappable_id]
end
end

View file

@ -1,22 +1,6 @@
# frozen_string_literal: true
class Star < ApplicationRecord
class Star < ActiveRecord::Base
belongs_to :user
belongs_to :map
validates :map, uniqueness: { scope: :user, message: 'You have already starred this map' }
# after_create :after_created_async
# before_destroy :before_destroyed
protected
def after_created_async
FollowService.follow(map, user, 'starred')
NotificationService.notify_followers(map, 'map_starred', self, 'created')
end
handle_asynchronously :after_created_async
def before_destroyed
FollowService.remove_reason(map, user, 'starred')
end
end

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