Compare commits

...

96 commits

Author SHA1 Message Date
Devin Howard
98081097b4 Revert "update rails dependencies"
Original commit broke the build, since some dependencies have breaking
changes.

This reverts commit f753392d49.
2018-11-09 07:42:26 -08:00
Devin Howard
f753392d49 update rails dependencies 2018-10-17 19:51:51 -07:00
Connor Turland
38a209a970 small bug fix (#1174)
if someone besides one of "us" tried to change their password, and their settings, it wouldn't work

in the typical case it would work fine
2018-03-11 21:57:23 -07:00
Devin Howard
bd7bf20810
factory_girl => factory_bot (#1172) 2018-03-10 08:10:09 -08:00
Devin Howard
955ebdd747
Change log level of Metamaps.Debug (#1170)
debug log level is invisible in Chrome by default, which is confusing
2018-02-05 21:35:53 -08:00
Devin Howard
fdcd8a93f1 tag 3.6.1 2018-01-24 20:02:28 -08:00
Devin Howard
b5c52adf5e update to paperclip 5.2.0 2018-01-24 19:52:33 -08:00
Devin Howard
b7761a3627
manual rubocop fixes (#1163) 2018-01-21 14:21:00 -08:00
Devin Howard
e0d72fce14
update nokogiri (#1169) 2018-01-21 14:20:21 -08:00
Devin Howard
139fdf8e2b
update rubocop to 0.48.1. We still want to match Code Climate though (#1168) 2018-01-20 14:10:26 -08:00
Devin Howard
4313f6eff8
TopicCard/Desc.spec.js (#1167)
TopicCard/Desc.spec.js
2018-01-20 13:31:36 -08:00
Devin Howard
91c004ebfd
TopicCard/Permission.spec.js (#1166) 2017-12-04 21:06:09 -08:00
Devin Howard
96056f43ef
TopicCard/Title.spec.js (#1165) 2017-12-02 12:45:05 -08:00
Devin Howard
32e58fa8af
tests for TopicCard/index.js (#1164) 2017-11-26 16:13:17 -08:00
Devin Howard
5ebbd87afc
automatic rubocop fixes (#1162) 2017-11-25 11:23:47 -08:00
Devin Howard
006920b686 fix broken experience if forgot password email isn't found 2017-11-13 07:16:25 -08:00
Devin Howard
97448b389f null check in synapse policy 2017-11-13 07:11:48 -08:00
Connor Turland
f1ecc9eb0b Merge pull request #1160 from metamaps/bug/map.info.box.closing
event listener was getting lost cuz react
2017-10-26 19:17:42 -04:00
Connor Turland
ca2684fcf3 event listener was getting lost cuz react 2017-10-26 19:09:28 -04:00
Connor Turland
d9c53514fe Update pull-changes.md 2017-10-25 06:44:20 -04:00
Connor Turland
e195b89bbd Merge pull request #1155 from metamaps/bug/fix.emails
fix map activity emails
2017-10-17 12:26:20 -04:00
Connor Turland
e66498a861 add logging for delayedJob 2017-10-17 12:20:51 -04:00
Connor Turland
901eb4a513 Update daily_summary.html.erb 2017-10-17 12:06:37 -04:00
Devin Howard
cbf44e3dfe add one view test 2017-10-17 08:28:00 -07:00
Connor Turland
8b492d6dc8 made the mistake of not checking all cases 2017-10-17 01:28:07 -04:00
Connor Turland
b83f366284 Merge pull request #1151 from metamaps/feature/admin.pages
move admin header to react
2017-10-15 16:05:18 -04:00
Connor Turland
1ac06d973c Merge pull request #1153 from metamaps/feature/follow.created
follow created maps as default setting
2017-10-15 14:08:04 -04:00
Connor Turland
9af3754bc8 follow created maps as default setting
if you are the map creator, we'd like to set you up to be following it by default
2017-10-15 14:07:11 -04:00
Connor Turland
8169f24072 Merge pull request #1150 from metamaps/rake-assets-precompile
run perms:fix on assets:precompile
2017-10-15 11:02:59 -04:00
Connor Turland
b9fb4a2829 move admin header to react 2017-10-15 10:56:51 -04:00
Connor Turland
9b52d0e081 fix tests 2017-10-15 10:56:04 -04:00
Devin Howard
14dc3687cd run perms:fix on assets:precompile 2017-10-14 12:02:41 -07:00
Metamaps on Linode
0a6e7918ef fix docs building by reverting raml2html 2017-10-14 14:55:42 -04:00
Metamaps on Linode
4a7595e76d fixup imports 2017-10-14 14:55:42 -04:00
Connor Turland
e899179314 Update first-deploy.md 2017-10-14 14:44:10 -04:00
Connor Turland
44fec58985 Merge pull request #1149 from metamaps/feature/reorg.react
reorg code to distinguish between route components and normal ones
2017-10-14 12:38:57 -04:00
Connor Turland
29a25c28a8 distinguish between route components and reusable components 2017-10-14 12:37:48 -04:00
Connor Turland
76c727cd61 Merge pull request #1148 from metamaps/feature/refactor.nav.bar
rename exploreMapsBar into reusable navBar
2017-10-14 12:30:29 -04:00
Connor Turland
693e6f5e10 bug fixes and make active class auto 2017-10-14 12:03:05 -04:00
Connor Turland
a1d4c99ff6 abstract exploreMapsBar into reusable navBar 2017-10-13 13:58:21 -04:00
Connor Turland
55f2425501 Merge pull request #1142 from metamaps/feature/notifs.box
Notifications Dropdown
2017-10-13 12:29:21 -04:00
Connor Turland
f9c139c19e ruby codeclimate fixes 2017-10-13 12:22:05 -04:00
Connor Turland
d51a22c5a9 eslint fixes 2017-10-13 12:13:36 -04:00
Connor Turland
567bc9d69d Merge pull request #1145 from metamaps/feature/lower.case.headings
Switch junto headings to have normal casing (not all uppercase)
2017-10-04 11:22:33 -04:00
Connor Turland
15f512efef improve notificationbox readability 2017-09-29 14:05:39 -04:00
Connor Turland
5e6fb6290c refactor for clarity 2017-09-29 13:06:33 -04:00
Connor Turland
8695297a0f wasn't using the proper serializer causing frontend error 2017-09-29 13:06:19 -04:00
Connor Turland
216a19476b add hover states and empty case 2017-09-28 12:28:33 -04:00
Connor Turland
a0c9530c91 Update index.js 2017-09-25 16:01:25 -04:00
Connor Turland
277644f59d improve styling, fix index notifs page 2017-09-25 15:21:04 -04:00
Connor Turland
0ffc01b3fb Merge pull request #1144 from metamaps/feature/hide-learn-markdown
hide "learn markdown" unless you're editing the topic card desc
2017-09-25 14:46:44 -04:00
Devin Howard
9471efb6bd hide "learn markdown" unless you're editing the topic card desc 2017-09-23 13:19:43 -07:00
Connor Turland
fc8ac6eef1 nest inconsistent data under data key 2017-09-23 11:20:02 -04:00
Connor Turland
9cc700c64d use decorator pattern for notifs api 2017-09-22 18:38:38 -04:00
Connor Turland
64ffc78f45 add the container for the notifications dropdown 2017-09-19 23:48:46 -04:00
Connor Turland
322da431eb Merge pull request #1139 from metamaps/feature/right.click.react
Right click/context menu redone in React
2017-09-19 11:49:30 -04:00
Connor Turland
3c7c8812a4 tempplate strings and new lines 2017-09-19 11:46:19 -04:00
Connor Turland
0d6963ebb0 eslint 2017-09-19 10:16:14 -04:00
Connor Turland
c4d0bf8ce4 clean up jquery ref and strings 2017-09-19 10:02:05 -04:00
Connor Turland
3406f2e04d make render a callback and use async apply for ease of use 2017-09-19 09:58:59 -04:00
Connor Turland
a4c905df4e move each li into its own function 2017-09-19 09:04:21 -04:00
Connor Turland
5f1fe4dc3f reimplement shifting menu according to click position 2017-09-19 08:37:00 -04:00
Connor Turland
2515073393 replace old edgeRightClick code 2017-09-19 00:46:23 -04:00
Connor Turland
a04cd0d395 call the right callbacks and show in the right context 2017-09-19 00:34:37 -04:00
Connor Turland
da9e44afa0 clear the right click menu the right way 2017-09-18 23:49:35 -04:00
Connor Turland
e290244404 beginning to come together 2017-09-18 23:30:33 -04:00
Connor Turland
6e1878413f wip right click in react 2017-09-18 21:09:35 -04:00
Connor Turland
77846cfcb7 missing period for consistency 2017-09-18 16:59:52 -04:00
Connor Turland
1ffc513617 Merge pull request #1137 from metamaps/feature/improve.desc
make desc edit area larger and resizable
2017-09-17 16:25:53 -04:00
Connor Turland
3886e62a7b make desc edit area larger and resizable 2017-09-17 09:01:44 -04:00
Devin Howard
ad2ba33db6 downgrade redis to 3.3.3
This fixes the following error seen on metamaps.cc:

> *A* `Gem::LoadError` *occurred while* `POST </mappings>` *was processed
> by* `mappings#create`: Specified 'redis' for Action Cable pubsub
> adapter, but the gem is not loaded. Add `gem 'redis'` to your Gemfile
> (and ensure its version is at the minimum required by Action Cable).

Backtrace
----------------

    ```/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/monitor.rb:214:in
    `mon_synchronize'
    /home/metamaps/metamaps.cc/app/models/mapping.rb:32:in `after_created'
    /home/metamaps/metamaps.cc/app/controllers/mappings_controller.rb:24:in
    `create'```
2017-09-16 13:41:50 -07:00
Devin Howard
cf9f54c738 tag v3.5 2017-09-16 12:27:02 -07:00
Connor Turland
f323796030 Merge pull request #1132 from metamaps/feature/mod.follow
add active scope to follows model
2017-09-13 22:45:50 -04:00
Connor Turland
a080b82e7f Merge pull request #1133 from metamaps/feature/topic.follow
Topic Card Design changes (to include 'follows')
2017-09-13 10:32:44 -04:00
Connor Turland
1174123b60 use scss vars and font fallbacks 2017-09-13 10:31:48 -04:00
Connor Turland
35f77129ad email job needs to respect active as well 2017-09-13 10:20:25 -04:00
Connor Turland
a56991aede add exception notifier for failed jobs 2017-09-13 10:18:00 -04:00
Connor Turland
672b456193 add markdown clarifications 2017-09-12 21:37:49 -04:00
Connor Turland
21518c8696 revert react router update and webpack config 2017-09-12 17:07:57 -04:00
Connor Turland
29bf2a23e8 review changes 2017-09-12 17:01:08 -04:00
Connor Turland
61eac509de Merge branch 'develop' into feature/topic.follow 2017-09-10 18:16:11 -04:00
Connor Turland
4cc420eb63 eslint fixes 2017-09-10 18:13:25 -04:00
Connor Turland
ec3e09c578 topic card design changes 2017-09-10 17:17:56 -04:00
Devin Howard
3e03e0ebbf update npm/gem dependencies (#1131)
* update npm/gem dependencies

* move to react prop-types package and fix jsdom usage

* fix sinon

* fix test support

* eslint?
2017-09-09 09:38:18 -07:00
Connor Turland
9ab7e7e170 topic card re-org 2017-09-08 16:58:17 -04:00
Connor Turland
5af2b8f216 add active scope to follows model 2017-09-08 13:42:56 -04:00
Connor Turland
8af66b1b2c Merge pull request #1130 from metamaps/feature/release.notifs
make notifs and follows work for all users
2017-09-03 18:44:33 -04:00
Connor Turland
9b2193ad8c show autofollow on client and mute on unfollow 2017-09-03 15:18:57 -04:00
Connor Turland
1a8c7810be fix eslint issue picked up by codeclimate 2017-09-03 09:13:15 -04:00
Connor Turland
d87bb7c75c make notifs and follows work for all users 2017-09-03 09:07:29 -04:00
Connor Turland
aceb3ff31e Merge pull request #1129 from metamaps/feature/map.activity.improved
improve email styling for release
2017-09-03 08:33:13 -04:00
Connor Turland
f26c6cf0b7 Merge pull request #1128 from metamaps/feature/prevent.notif.fork
dont send notification for each topic of forked map
2017-09-03 08:29:03 -04:00
Connor Turland
42f4ecb37b added bg color to sections 2017-09-03 08:27:05 -04:00
Connor Turland
64f4249f44 add comment 2017-09-02 14:12:07 -04:00
Connor Turland
958bd8c70c improve email styling for release 2017-09-02 14:06:23 -04:00
Connor Turland
3830946723 dont send notif for each topic of forked map 2017-09-02 09:59:21 -04:00
319 changed files with 3319 additions and 1949 deletions

1
.gitignore vendored
View file

@ -15,6 +15,7 @@ app/assets/javascripts/webpacked
#secrets and config
.env
*.swp
# Ignore bundler config
.bundle

View file

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

13
Gemfile
View file

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

View file

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

1
Rakefile Normal file → Executable file
View file

@ -1,5 +1,6 @@
#!/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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

View file

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

View file

@ -826,6 +826,7 @@ label {
font-size: 14px;
line-height: 14px;
color: #757575;
cursor: pointer;
}
.accountListItem:hover {
color: #424242;
@ -1914,14 +1915,10 @@ 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;
@ -2933,136 +2930,6 @@ 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 {
@ -3150,11 +3017,15 @@ script.data-gratipay-username {
}
.topicFollow {
text-align: center;
height: 48px;
line-height: 48px;
border-top: 1px solid #BDBDBD;
background: #FFF;
height: 24px;
line-height: 24px;
cursor: pointer;
font-family: din-regular;
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,9 +1,12 @@
$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;
font-family: helvetica, sans-serif;
color: #727272;
line-height: 11px;
display: none;
@ -42,7 +45,7 @@
z-index:2;
color: #424242;
border-radius:2px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
box-shadow: 2px 3px 3px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16);
}
.text {
@ -64,7 +67,6 @@
display:block;
position:relative;
width:100%;
min-height:360px;
z-index: 25;
}
.CardOnGraph.hasAttachment {
@ -73,11 +75,10 @@
.CardOnGraph .title {
word-break: break-word;
font-size: 18px;
line-height: 22px;
font-size: 20px;
line-height: 24px;
display: table;
padding: 8px 0 16px;
height: 80px;
padding: 20px 0;
text-align: center;
font-family: 'din-regular', sans-serif;
width: 300px;
@ -88,11 +89,6 @@
display: table-cell;
vertical-align: middle;
padding: 0 16px;
&.riek-editing {
position: absolute;
top: 32px;
}
}
.canEdit #titleActivator:hover {
background-image: url(<%= asset_data_uri('edit.png') %>);
@ -104,9 +100,8 @@
.showcard .title .riek-editing {
font-family: 'din-regular', sans-serif;
color: #424242;
font-size: 18px;
line-height: 22px;
height: 3em;
font-size: 20px;
line-height: 24px;
padding: 5px 0;
width: 100%;
margin: 0;
@ -120,11 +115,23 @@
.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;
@ -136,14 +143,12 @@
font-family: helvetica, sans-serif;
color: #424242;
padding: 0;
width: 100%;
width: 258px;
margin: 0;
border: 0;
outline: none;
font-size: 12px;
line-height: 15px;
background: none;
resize: none;
overflow-y: scroll;
}
/*
@ -177,12 +182,9 @@
.CardOnGraph .riek_desc {
display:block;
margin-top:2px;
padding-right: 18px;
margin-right: 8px;
min-height: 7em;
padding-right: 26px;
}
.canEdit .CardOnGraph .riek_desc:hover {
.canEdit .CardOnGraph .riek_desc:not(.riek-editing):hover {
background-image: url(<%= asset_data_uri('edit.png') %>);
background-position: top right;
background-repeat: no-repeat;
@ -195,9 +197,7 @@
.CardOnGraph .links {
position: relative;
border-bottom: 1px solid #BDBDBD;
border-top: 1px solid #BDBDBD;
background-color: #e0e0e0;
z-index: 2;
.linkItem {
float: left;
@ -213,37 +213,52 @@
}
.icon {
position: absolute;
z-index: 1;
padding: 0;
height: 48px;
width: 100%;
margin-right: 10px;
.metacodeImage {
cursor: move;
position: relative;
left: -23px;
top: 1px;
width: 46px;
height: 46px;
background-size:46px 46px;
position: absolute;
left: -18px;
top: 6px;
width: 36px;
height: 36px;
background-size:36px 36px;
background-position:0 0;
background-repeat:no-repeat;
}
}
}
.CardOnGraph .info {
position: relative;
.linkItem {
float: left;
z-index: 1;
position: relative;
color: $mid-gray-opacity;
font-size: 14px;
line-height: 14px;
a {
color: $mid-gray-opacity;
}
}
.contributor {
bottom: 7px;
margin-left: 40px;
margin-left: 16px;
.contributorIcon {
position: relative;
display: inline-block;
vertical-align: middle;
border-radius: 16px;
margin: 5px;
top: 8px;
margin: 5px 5px 5px 0;
top: 11px;
left: 0;
border-radius: 16px;
}
span {
@ -252,52 +267,34 @@
}
.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;
margin-top: 20px;
display: inline-block;
vertical-align: middle;
width: 97px;
padding: 0 8px 0 4px;
white-space: nowrap;
margin-top: 8px;
&: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;
}
}
&:hover .contributorName {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
}
.mapCount {
padding:17px 0 17px 36px;
margin-left: 12px;
padding:17px 38px 17px 0;
width: 22px;
text-align: right;
.mapCountIcon {
position: absolute;
top: 8px;
left: 0;
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 {
@ -306,18 +303,18 @@
.tip, .hoverTip {
top: 44px;
left: 0px;
right: 0px;
font-size: 12px !important;
&:before {
content: '';
position: absolute;
top: 26px;
left: 10px;
right: 10px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid #000000;
border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
@ -327,10 +324,9 @@
white-space: nowrap;
font-family: 'din-regular';
top: 44px;
left: 0px;
font-size: 12px !important;
position: absolute;
background: black;
background: $mid-gray;
color: white;
border-radius: 4px;
line-height: 17px;
@ -362,28 +358,31 @@
}
.synapseCount {
margin-left: 26px;
width: 24px;
padding:17px 0 17px 32px;
width: 22px;
padding:17px 38px 17px 0;
text-align: right;
margin-right: 4px;
.synapseCountIcon {
position: absolute;
top: 8px;
left: 0;
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: black;
background: $mid-gray;
width: auto;
top: 44px;
right: 0px;
color: white;
white-space: nowrap;
border-radius: 2px;
@ -398,10 +397,10 @@
content: '';
position: absolute;
margin-top: -8px;
margin-left: 6px;
right: 12px;
width: 0;
height: 0;
border-bottom: 4px solid black;
border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
@ -413,6 +412,10 @@
color: #4FC059;
}
.linkItem.mapPerm {
margin-right: 8px;
}
.mapPerm {
width: 32px;
height: 32px;
@ -434,14 +437,10 @@
}
.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 {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
background-position: 0 0;
cursor: pointer;
cursor: pointer;
}
.mapPerm .permissionSelect {
list-style: none;
@ -477,32 +476,34 @@ cursor: pointer;
}
.CardOnGraph .metacodeTitle {
font-style: italic;
font-family: 'vinyl';
text-transform: uppercase;
position: absolute;
font-family: 'din-regular';
line-height: 24px;
height: 26px;
font-size: 24px;
display: none;
width: 90%;
padding: 13px 0 9px 10%;
background-color: #E0E0E0;
font-size: 18px;
padding: 13px 24px 9px 24px;
color: #424242;
width: 120px;
max-width: 120px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.permission.canEdit .metacodeTitle {
cursor:pointer;
}
.permission.canEdit .expandMetacodeSelect {
position: absolute;
top: 16px;
right: 16px;
position: relative;
top: 2px;
left: 4px;
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 {
@ -519,8 +520,8 @@ cursor: pointer;
background: #EAEAEA;
white-space: nowrap;
position: absolute;
left: 300px;
top: -1px;
top: 48px;
box-shadow: 2px 2px 2px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16);
}
.CardOnGraph .metacodeSelect ul {
position: relative;
@ -613,9 +614,9 @@ background-color: #E0E0E0;
}
.CardOnGraph .tip {
position: absolute;
background: black;
background: $mid-gray;
top: 35px;
left: 0;
right: 0;
color: white;
border-radius: 4px;
font-size:15px !important;
@ -633,7 +634,6 @@ background-color: #E0E0E0;
width:100%;
height:47px;
position: relative;
border-top: 1px solid #BDBDBD;
}
.link-adder a {
@ -695,9 +695,9 @@ background-color: #E0E0E0;
}
#addLinkInput input{
padding: 9px 7px 9px 31px;
padding: 9px 27px 9px 31px;
height: 12px;
width: 198px;
width: 210px;
margin: 0 0 0 0;
border: none;
outline: none;

View file

@ -668,19 +668,19 @@
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
}
#exploreMapsHeader {
#navBar {
position: absolute;
width: 100%;
}
.exploreMapsBar {
.navBarContainer {
z-index:2;
background-color:#FAFAFA;
height: 42px;
padding-top: 52px;
}
.exploreMapsMenu {
.navBarMenu {
display: block;
width: 100%;
height:42px;
@ -689,30 +689,29 @@
text-align: center;
}
.exploreMapsCenter {
.navBarCenter {
display: block;
}
.exploreMapsButton {
color: #757575;
.navBarButton {
color: #757575;
cursor: default;
font-weight: normal;
font-family: 'din-medium';
font-size: 14px;
height: 14px;
padding: 14px 8px 12px 40px;
border-bottom: 2px solid rgba(0,0,0,0);
padding: 0 8px;
border-bottom: 2px solid rgba(0,0,0,0);
display: inline-block;
cursor: pointer;
position:relative;
cursor: pointer;
position:relative;
}
.exploreMapsButton:hover, .exploreMapsButton.active {
.navBarButton:hover, .navBarButton.active {
text-decoration: none;
color: #424242;
border-bottom: 2px solid #00BCD4;
}
.exploreMapsButton.mapperButton {
.navBarButton.mapperButton {
height: 40px;
padding: 0;
}
@ -729,62 +728,69 @@
}
.exploreMapsButton .exploreMapsIcon {
.navBarButton .navBarIcon {
background-repeat: no-repeat;
width:32px;
height:32px;
position:absolute;
top:5px;
left:5px;
margin-top:5px;
margin-left:5px;
margin-right: 5px;
display: inline-block;
vertical-align: top;
}
.exploreMapsCenter .authedApps .exploreMapsIcon {
.navBarLinkText {
padding: 11px 0 12px 0;
display: inline-block;
}
.navBarCenter .authedApps .navBarIcon {
background-image: url(<%= asset_path('user_sprite.png') %>);
background-position: 0 -32px;
}
.exploreMapsCenter .myMaps .exploreMapsIcon {
.navBarCenter .myMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -32px 0;
}
.exploreMapsCenter .sharedMaps .exploreMapsIcon {
.navBarCenter .sharedMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -128px 0;
}
.exploreMapsCenter .activeMaps .exploreMapsIcon {
.navBarCenter .activeMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: 0 0;
}
.exploreMapsCenter .featuredMaps .exploreMapsIcon {
.navBarCenter .featuredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0;
}
.exploreMapsCenter .starredMaps .exploreMapsIcon {
.navBarCenter .starredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0;
}
.exploreMapsCenter .notificationsLink .exploreMapsIcon {
.navBarCenter .notificationsLink .navBarIcon {
background-image: url(<%= asset_path 'topright_sprite.png' %>);
background-position: -128px 0;
}
.authedApps:hover .exploreMapsIcon, .authedApps.active .exploreMapsIcon {
.authedApps:hover .navBarIcon, .authedApps.active .navBarIcon {
background-position-x: -32px;
}
.myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon {
.myMaps:hover .navBarIcon, .myMaps.active .navBarIcon {
background-position: -32px -32px;
}
.activeMaps:hover .exploreMapsIcon, .activeMaps.active .exploreMapsIcon {
.activeMaps:hover .navBarIcon, .activeMaps.active .navBarIcon {
background-position: 0 -32px;
}
.featuredMaps:hover .exploreMapsIcon, .featuredMaps.active .exploreMapsIcon {
.featuredMaps:hover .navBarIcon, .featuredMaps.active .navBarIcon {
background-position: -96px -32px;
}
.starredMaps:hover .exploreMapsIcon, .starredMaps.active .exploreMapsIcon {
.starredMaps:hover .navBarIcon, .starredMaps.active .navBarIcon {
background-position: -96px -32px;
}
.sharedMaps:hover .exploreMapsIcon, .sharedMaps.active .exploreMapsIcon {
.sharedMaps:hover .navBarIcon, .sharedMaps.active .navBarIcon {
background-position: -128px -32px;
}
.notificationsLink:hover .exploreMapsIcon, .notificationsLink.active .exploreMapsIcon {
.notificationsLink:hover .navBarIcon, .notificationsLink.active .navBarIcon {
background-position-y: -32px;
}

View file

@ -32,7 +32,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, #exploreMapsHeader {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #navBar {
display: none !important;
}

View file

@ -1,4 +1,7 @@
$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;
@ -13,13 +16,72 @@ $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;
@ -47,89 +109,9 @@ $unread_notifications_dot_size: 8px;
.emptyInbox {
padding-top: 15px;
}
.notification {
padding: 10px;
position: relative;
&:hover {
background: #F6F6F6;
.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;
.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;
}
}
}
.notificationPage {
.thirty-two-avatar {
@ -139,14 +121,14 @@ $unread_notifications_dot_size: 8px;
border-radius: 16px;
vertical-align: middle;
}
.button {
line-height: 32px;
img {
margin-top: 8px;
}
&.decline {
background: #DB5D5D;
&:hover {
@ -154,7 +136,7 @@ $unread_notifications_dot_size: 8px;
}
}
}
.notification-body {
p, div {
margin: 1em auto;
@ -163,3 +145,93 @@ $unread_notifications_dot_size: 8px;
}
}
}
ul.notifications {
list-style: none;
li:nth-last-child(2) {
.notification-body {
border-bottom: none !important;
}
}
}
.notification {
padding: 10px 10px 0 10px;
position: relative;
font-family: 'din-regular', Sans-Serif;
&.unread {
background: #EEE;
}
&:hover {
background: $notifications-hover-color;
.notification-read-unread {
display:block;
}
.notification-date {
display: none;
}
}
& > a {
float: left;
width: 85%;
box-sizing: border-box;
padding-right: 10px;
}
.notification-actor {
float: left;
img {
width: 32px;
height: 32px;
border-radius: 16px;
}
}
.notification-body {
margin-left: 50px;
line-height: 20px;
padding-bottom: 10px;
.in-bold {
font-family: 'din-medium', Sans-Serif;
}
.action {
background: #4fb5c0;
color: #FFF;
padding: 2px 6px;
border-radius: 3px;
display: inline-block;
margin: 5px 0;
}
}
.notification-date {
position: absolute;
top: 50%;
right: 10px;
color: #607d8b;
margin-top: -6px;
}
.notification-read-unread {
display: none;
float: left;
width: 15%;
a, div {
position: absolute;
top: 50%;
margin-top: -10px;
text-align: center;
cursor: pointer;
}
}
}

View file

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

View file

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

View file

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

View file

@ -1,11 +1,12 @@
# frozen_string_literal: true
class AccessController < ApplicationController
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]
before_action :require_user, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
before_action :set_map, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
after_action :verify_authorized
# GET maps/:id/request_access

View file

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

View file

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

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true
module Api
module V2
class MapsController < WithUpdatesController
def searchable_columns
[:name, :desc]
%i[name desc]
end
def apply_filters(collection)

View file

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

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Api
module V2
class RestfulController < ActionController::Base
@ -7,7 +8,7 @@ module Api
snorlax_used_rest!
before_action :load_resource, only: [:show, :update, :destroy]
before_action :load_resource, only: %i[show update destroy]
after_action :verify_authorized
def index
@ -91,7 +92,7 @@ module Api
end
def doorkeeper_user
return unless doorkeeper_token.present?
return if doorkeeper_token.blank?
doorkeeper_render_error unless valid_doorkeeper_token?
@doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id)
end

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
include ApplicationHelper
include Pundit

View file

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

View file

@ -1,4 +1,5 @@
# 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,4 +1,5 @@
# frozen_string_literal: true
class MainController < ApplicationController
before_action :authorize_main
after_action :verify_authorized

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class MappingsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy]
before_action :require_user, only: %i[create update destroy]
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index

View file

@ -1,7 +1,10 @@
# frozen_string_literal: true
class MapsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy, :events, :follow, :unfollow]
before_action :set_map, only: [:show, :conversation, :update, :destroy, :contains, :events, :export, :follow, :unfollow, :unfollow_from_email]
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]
after_action :verify_authorized
# GET maps/:id
@ -23,7 +26,7 @@ class MapsController < ApplicationController
format.ttl { redirect_to action: :export, format: :ttl }
end
end
# GET maps/:id/conversation
def conversation
respond_to do |format|
@ -140,7 +143,7 @@ class MapsController < ApplicationController
# POST maps/:id/follow
def follow
follow = FollowService.follow(@map, current_user, 'followed')
follow = FollowService.follow(@map, current_user, 'followed')
respond_to do |format|
format.json do
@ -155,7 +158,7 @@ class MapsController < ApplicationController
# POST maps/:id/unfollow
def unfollow
FollowService.unfollow(@map, current_user)
FollowService.unfollow(@map, current_user)
respond_to do |format|
format.json do

View file

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

View file

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

View file

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

View file

@ -1,18 +1,23 @@
# frozen_string_literal: true
class NotificationsController < ApplicationController
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]
before_action :set_receipts, only: %i[index show mark_read mark_unread]
before_action :set_notification, only: %i[show mark_read mark_unread]
before_action :set_receipt, only: %i[show mark_read mark_unread]
def index
@notifications = current_user.mailbox.notifications.page(params[:page]).per(25)
respond_to do |format|
format.html
format.json do
render json: @notifications.map do |notification|
notifications = @notifications.map do |notification|
receipt = @receipts.find_by(notification_id: notification.id)
notification.as_json.merge(is_read: receipt.is_read)
NotificationDecorator.decorate(notification, receipt)
end
if !notifications.empty?
render json: notifications
else
render json: [].to_json
end
end
end
@ -23,20 +28,18 @@ class NotificationsController < ApplicationController
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)
when MAP_ACCESS_APPROVED, MAP_INVITE_TO_EDIT
redirect_to map_path(@notification.notified_object.map)
when TOPIC_ADDED_TO_MAP
redirect_to map_path(@notification.notified_object.map)
when TOPIC_CONNECTED_1
redirect_to topic_path(@notification.notified_object.topic1)
when TOPIC_CONNECTED_2
redirect_to topic_path(@notification.notified_object.topic2)
end
end
format.json do
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
@ -46,9 +49,7 @@ class NotificationsController < ApplicationController
respond_to do |format|
format.js
format.json do
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
@ -58,9 +59,7 @@ class NotificationsController < ApplicationController
respond_to do |format|
format.js
format.json do
render json: @notification.as_json.merge(
is_read: @receipt.is_read
)
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class SearchController < ApplicationController
include TopicsHelper
include MapsHelper
@ -7,7 +8,7 @@ class SearchController < ApplicationController
before_action :authorize_search
after_action :verify_authorized
after_action :verify_policy_scoped, only: [:maps, :mappers, :synapses, :topics]
after_action :verify_policy_scoped, only: %i[maps mappers synapses topics]
# get /search/topics?term=SOMETERM
def topics
@ -140,13 +141,13 @@ class SearchController < ApplicationController
topic1id = params[:topic1id]
topic2id = params[:topic2id]
if term && !term.empty?
if term.present?
@synapses = policy_scope(Synapse)
.where('LOWER("desc") like ?', '%' + term.downcase.strip + '%')
.order('"desc"')
@synapses = @synapses.uniq(&:desc)
elsif topic1id && !topic1id.empty?
elsif topic1id.present?
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,4 +1,5 @@
# frozen_string_literal: true
class StarsController < ApplicationController
before_action :require_user
before_action :set_map

View file

@ -1,8 +1,9 @@
# frozen_string_literal: true
class SynapsesController < ApplicationController
include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy]
before_action :require_user, only: %i[create update destroy]
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class TokensController < ApplicationController
before_action :require_user, only: [:new]

View file

@ -1,11 +1,12 @@
# frozen_string_literal: true
class TopicsController < ApplicationController
include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy, :follow, :unfollow]
before_action :set_topic, only: [:show, :update, :relative_numbers,
:relatives, :network, :destroy,
:follow, :unfollow, :unfollow_from_email]
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]
after_action :verify_authorized, except: :autocomplete_topic
respond_to :html, :js, :json
@ -13,7 +14,7 @@ class TopicsController < ApplicationController
# GET /topics/autocomplete_topic
def autocomplete_topic
term = params[:term]
if term && !term.empty?
if term.present?
topics = policy_scope(Topic)
.where('LOWER("name") like ?', term.downcase + '%')
.order('"name"')

View file

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

View file

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

View file

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

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :require_user, only: [:edit, :update, :updatemetacodes, :update_metacode_focus]
before_action :require_user, only: %i[edit update updatemetacodes update_metacode_focus]
respond_to :html, :json
@ -23,15 +24,15 @@ 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]) if is_tester(@user)
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1'
@user.save
sign_in(@user, bypass: true)
bypass_sign_in(@user)
respond_to do |format|
format.html { redirect_to root_url, notice: 'Settings updated' }
end
else
sign_in(@user, bypass: true)
bypass_sign_in(@user)
respond_to do |format|
format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] }
end
@ -41,7 +42,7 @@ 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]) if is_tester(@user)
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1'
@user.save
sign_in(@user, bypass: true)
@ -100,7 +101,7 @@ 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

View file

@ -0,0 +1,51 @@
# 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,4 +1,5 @@
# frozen_string_literal: true
module ApplicationHelper
def invite_link
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '')

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module MetacodesHelper
def metacodeset
metacodes = current_user.settings.metacodes

View file

@ -1,4 +1,5 @@
# 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,4 +1,5 @@
# frozen_string_literal: true
module TopicMailerHelper
def added_to_map_subject(topic, map)
topic.name + ' was added to map ' + map.name
@ -7,4 +8,4 @@ module TopicMailerHelper
def connected_subject(topic)
'new synapse to topic ' + topic.name
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module TopicsHelper
## this one is for building our custom JSON autocomplete format for typeahead
def autocomplete_array_json(topics)
@ -16,7 +17,7 @@ module TopicsHelper
rtype: is_map ? 'map' : 'topic',
inmaps: is_map ? [] : t.inmaps(current_user),
inmapsLinks: is_map ? [] : t.inmapsLinks(current_user),
inmapsLinks: is_map ? [] : t.inmaps_links(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,4 +1,5 @@
# frozen_string_literal: true
module UsersHelper
# build custom json autocomplete for typeahead
def autocomplete_user_array_json(users)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class ApplicationMailer < ActionMailer::Base
default from: 'team@metamaps.cc'
layout 'mailer'
@ -6,24 +7,24 @@ class ApplicationMailer < ActionMailer::Base
class << self
def mail_for_notification(notification)
case notification.notification_code
when MAP_ACCESS_REQUEST
request = notification.notified_object
MapMailer.access_request(request)
when MAP_ACCESS_APPROVED
request = notification.notified_object
MapMailer.access_approved(request)
when MAP_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])
when MAP_ACCESS_REQUEST
request = notification.notified_object
MapMailer.access_request(request)
when MAP_ACCESS_APPROVED
request = notification.notified_object
MapMailer.access_approved(request)
when MAP_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])
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class MapActivityMailer < ApplicationMailer
default from: 'team@metamaps.cc'

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class MapMailer < ApplicationMailer
include MapMailerHelper
default from: 'team@metamaps.cc'

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class TopicMailer < ApplicationMailer
include TopicMailerHelper
default from: 'team@metamaps.cc'

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true
class AccessRequest < ApplicationRecord
belongs_to :user
belongs_to :map
has_one :user_map
after_create :after_created_async
def approve
@ -27,9 +28,9 @@ class AccessRequest < ApplicationRecord
Mailboxer::Receipt.where(notification: notification).update_all(is_read: true)
end
end
protected
def after_created_async
NotificationService.access_request(self)
end

View file

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

View file

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

View file

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

View file

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

View file

@ -1,16 +1,17 @@
# 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,4 +1,5 @@
# frozen_string_literal: true
module Events
class ConversationStartedOnMap < Event
# after_create :notify_users!

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Events
class TopicAddedToMap < Event
after_create :notify_users!
@ -10,7 +11,7 @@ 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)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,19 +1,21 @@
# frozen_string_literal: true
class Follow < ApplicationRecord
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
follow_reason = FollowReason.create!(follow: self)
FollowReason.create!(follow: self)
end
end

View file

@ -1,12 +1,13 @@
# frozen_string_literal: true
class FollowReason < ApplicationRecord
REASONS = %w(created commented contributed followed shared_on starred).freeze
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
end

View file

@ -1,4 +1,5 @@
# 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,6 +1,7 @@
# frozen_string_literal: true
class Map < ApplicationRecord
ATTRS_TO_WATCH = %w(name desc permission).freeze
ATTRS_TO_WATCH = %w[name desc permission].freeze
belongs_to :user
belongs_to :source, class_name: :Map
@ -15,7 +16,7 @@ class Map < ApplicationRecord
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 :followers, through: :follows, source: :user
has_many :access_requests, dependent: :destroy
has_many :user_maps, dependent: :destroy
@ -89,10 +90,10 @@ class Map < ApplicationRecord
def as_json(_options = {})
json = super(
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]
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]
)
json[:created_at_clean] = created_at_str
json[:updated_at_clean] = updated_at_str
@ -133,16 +134,16 @@ class Map < ApplicationRecord
end
removed.compact
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, self.user, 'created')
FollowService.follow(self, user, 'created')
# notify users following the map creator
end
@ -150,13 +151,12 @@ class Map < ApplicationRecord
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
if 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
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

View file

@ -1,7 +1,8 @@
# 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
@ -24,7 +25,7 @@ class Mapping < ApplicationRecord
end
def as_json(_options = {})
super(methods: [:user_name, :user_image])
super(methods: %i[user_name user_image])
end
def after_created
@ -52,17 +53,17 @@ class Mapping < ApplicationRecord
handle_asynchronously :after_created_async
def after_updated
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
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)
end
def after_updated_async
if (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
FollowService.follow(map, updated_by, 'contributed')
end
return unless (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
FollowService.follow(map, updated_by, 'contributed')
end
handle_asynchronously :after_updated_async

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class Message < ApplicationRecord
belongs_to :user
belongs_to :resource, polymorphic: true
@ -6,15 +7,14 @@ class Message < ApplicationRecord
delegate :name, to: :user, prefix: true
after_create :after_created
#after_create :after_created_async
# after_create :after_created_async
def user_image
user.image.url
end
def as_json(_options = {})
json = super(methods: [:user_name, :user_image])
json = super(methods: %i[user_name user_image])
json
end

View file

@ -1,17 +1,16 @@
# 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: /\Aimage\/.*\Z/
validates_attachment_content_type :aws_icon, content_type: %r{\Aimage/.*\Z}
validate :aws_xor_manual_icon
validate :manual_icon_https
@ -30,15 +29,13 @@ 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 hasSelected(user)
return true if user.settings.metacodes.include? id.to_s
false
end
def inMetacodeSet(metacode_set)
def in_metacode_set(metacode_set)
return true if metacode_sets.include? metacode_set
false
end
@ -55,10 +52,9 @@ class Metacode < ApplicationRecord
end
def manual_icon_https
if manual_icon.present?
unless manual_icon.starts_with? 'https'
errors.add(:base, 'Manual icon must begin with https')
end
return if manual_icon.blank?
unless manual_icon.starts_with? 'https'
errors.add(:base, 'Manual icon must begin with https')
end
end
end

View file

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

View file

@ -1,13 +1,18 @@
# frozen_string_literal: true
class PermittedParams < Struct.new(:params)
%w(map synapse topic mapping token).each do |kind|
class PermittedParams
%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
@ -15,18 +20,18 @@ class PermittedParams < Struct.new(:params)
end
def map_attributes
[:name, :desc, :permission, :arranged]
%i[name desc permission arranged]
end
def synapse_attributes
[:desc, :category, :weight, :permission, :topic1_id, :topic2_id]
%i[desc category weight permission topic1_id topic2_id]
end
def topic_attributes
[:name, :desc, :link, :permission, :metacode_id]
%i[name desc link permission metacode_id]
end
def mapping_attributes
[:xloc, :yloc, :map_id, :mappable_type, :mappable_id]
%i[xloc yloc map_id mappable_type mappable_id]
end
end

View file

@ -1,20 +1,21 @@
# frozen_string_literal: true
class Star < ActiveRecord::Base
class Star < ApplicationRecord
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
# 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

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Synapse < ApplicationRecord
ATTRS_TO_WATCH = %w(desc category permission defer_to_map_id).freeze
ATTRS_TO_WATCH = %w[desc category permission defer_to_map_id].freeze
belongs_to :user
belongs_to :defer_to_map, class_name: 'Map', foreign_key: 'defer_to_map_id'
@ -21,9 +22,9 @@ class Synapse < ApplicationRecord
validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true }
scope :for_topic, ->(topic_id = nil) {
scope :for_topic, (lambda do |topic_id = nil|
where(topic1_id: topic_id).or(where(topic2_id: topic_id))
}
end)
before_create :set_perm_by_defer
after_create :after_created_async
@ -38,7 +39,7 @@ class Synapse < ApplicationRecord
def collaborator_ids
if defer_to_map
defer_to_map.editors.select { |mapper| mapper != user }.map(&:id)
defer_to_map.editors.reject { |mapper| mapper == user }.map(&:id)
else
[]
end
@ -54,7 +55,7 @@ class Synapse < ApplicationRecord
end
def as_json(_options = {})
super(methods: [:user_name, :user_image, :collaborator_ids])
super(methods: %i[user_name user_image collaborator_ids])
end
def as_rdf
@ -72,7 +73,7 @@ class Synapse < ApplicationRecord
protected
def set_perm_by_defer
permission = defer_to_map.permission if defer_to_map
defer_to_map&.permission
end
def after_created_async
@ -82,21 +83,21 @@ class Synapse < ApplicationRecord
handle_asynchronously :after_created_async
def after_updated
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
old = changed_attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
meta = new.merge(old) # we are prioritizing the old values, keeping them
meta['changed'] = changed_attributes.keys.select { |k| ATTRS_TO_WATCH.include?(k) }
Events::SynapseUpdated.publish!(self, updated_by, meta)
maps.each do |map|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseUpdated', id: id
end
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
old = changed_attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
meta = new.merge(old) # we are prioritizing the old values, keeping them
meta['changed'] = changed_attributes.keys.select { |k| ATTRS_TO_WATCH.include?(k) }
Events::SynapseUpdated.publish!(self, updated_by, meta)
maps.each do |map|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseUpdated', id: id
end
end
def before_destroyed
# hard to know how to do this yet, because the synapse actually gets destroyed
#NotificationService.notify_followers(topic1, 'topic_disconnected', self)
#NotificationService.notify_followers(topic2, 'topic_disconnected', self)
# NotificationService.notify_followers(topic1, 'topic_disconnected', self)
# NotificationService.notify_followers(topic2, 'topic_disconnected', self)
end
end

View file

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

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Topic < ApplicationRecord
ATTRS_TO_WATCH = %w(name desc link metacode_id permission defer_to_map_id).freeze
ATTRS_TO_WATCH = %w[name desc link metacode_id permission defer_to_map_id].freeze
include TopicsHelper
include Attachable
@ -16,7 +17,7 @@ class Topic < ApplicationRecord
has_many :mappings, as: :mappable, dependent: :destroy
has_many :maps, through: :mappings
has_many :follows, as: :followed, dependent: :destroy
has_many :followers, :through => :follows, source: :user
has_many :followers, through: :follows, source: :user
belongs_to :metacode
@ -25,7 +26,7 @@ class Topic < ApplicationRecord
after_create :after_created_async
after_update :after_updated
after_update :after_updated_async
#before_destroy :before_destroyed
# before_destroy :before_destroyed
validates :permission, presence: true
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
@ -38,13 +39,13 @@ class Topic < ApplicationRecord
topics1.or(topics2)
end
scope :relatives, ->(topic_id = nil, user = nil) {
scope :relatives, (lambda do |topic_id = nil, user = nil|
# should only see topics through *visible* synapses
# e.g. Topic A (commons) -> synapse (private) -> Topic B (commons) must be filtered out
topic_ids = Pundit.policy_scope(user, Synapse.where(topic1_id: topic_id)).pluck(:topic2_id)
topic_ids += Pundit.policy_scope(user, Synapse.where(topic2_id: topic_id)).pluck(:topic1_id)
where(id: topic_ids.uniq)
}
end)
delegate :name, to: :user, prefix: true
@ -64,13 +65,13 @@ class Topic < ApplicationRecord
Pundit.policy_scope(user, maps).map(&:name)
end
def inmapsLinks(user)
def inmaps_links(user)
Pundit.policy_scope(user, maps).map(&:id)
end
def as_json(options = {})
super(methods: [:user_name, :user_image, :collaborator_ids])
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmapsLinks(options[:user]),
super(methods: %i[user_name user_image collaborator_ids])
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmaps_links(options[:user]),
map_count: map_count(options[:user]), synapse_count: synapse_count(options[:user]))
end
@ -89,7 +90,7 @@ class Topic < ApplicationRecord
def collaborator_ids
if defer_to_map
defer_to_map.editors.select { |mapper| mapper != user }.map(&:id)
defer_to_map.editors.reject { |mapper| mapper == user }.map(&:id)
else
[]
end
@ -126,14 +127,9 @@ class Topic < ApplicationRecord
end
end
end
if output_format == 'array'
return output
elsif output_format == 'text'
return output.join('; ')
else
raise 'invalid argument to synapses_csv'
end
output
return output if output_format == 'array'
return output.join('; ') if output_format == 'text'
raise 'invalid argument to synapses_csv'
end
def topic_autocomplete_method
@ -143,7 +139,7 @@ class Topic < ApplicationRecord
protected
def set_perm_by_defer
permission = defer_to_map.permission if defer_to_map
self.permission = defer_to_map.permission if defer_to_map
end
def create_metamap?
@ -154,35 +150,35 @@ class Topic < ApplicationRecord
self.link = Rails.application.routes.url_helpers
.map_url(host: ENV['MAILER_DEFAULT_URL'], id: @map.id)
end
def after_created_async
FollowService.follow(self, self.user, 'created')
FollowService.follow(self, user, 'created')
# notify users following the topic creator
end
handle_asynchronously :after_created_async
def after_updated
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
old = changed_attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
meta = new.merge(old) # we are prioritizing the old values, keeping them
meta['changed'] = changed_attributes.keys.select { |k| ATTRS_TO_WATCH.include?(k) }
Events::TopicUpdated.publish!(self, updated_by, meta)
maps.each do |map|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicUpdated', id: id
end
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
old = changed_attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
meta = new.merge(old) # we are prioritizing the old values, keeping them
meta['changed'] = changed_attributes.keys.select { |k| ATTRS_TO_WATCH.include?(k) }
Events::TopicUpdated.publish!(self, updated_by, meta)
maps.each do |map|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicUpdated', id: id
end
end
def after_updated_async
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
FollowService.follow(self, updated_by, 'contributed')
end
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
FollowService.follow(self, updated_by, 'contributed')
end
handle_asynchronously :after_updated_async
def before_destroyed
# hard to know how to do this yet, because the topic actually gets destroyed
#NotificationService.notify_followers(self, 'topic_deleted', ?)
# NotificationService.notify_followers(self, 'topic_deleted', ?)
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require 'open-uri'
class User < ApplicationRecord
@ -51,26 +52,24 @@ class User < ApplicationRecord
validates_attachment_content_type :image, content_type: %r{\Aimage/.*\Z}
# override default as_json
def as_json(_options = {})
def as_json(options = {})
json = { id: id,
name: name,
image: image.url(:sixtyfour),
admin: admin }
if (_options[:follows])
name: name,
image: image.url(:sixtyfour),
admin: admin }
if options[:follows]
json['follows'] = {
topics: following.where(followed_type: 'Topic').to_a.map(&:followed_id),
maps: following.where(followed_type: 'Map').to_a.map(&:followed_id)
topics: following.active.where(followed_type: 'Topic').to_a.map(&:followed_id),
maps: following.active.where(followed_type: 'Map').to_a.map(&:followed_id)
}
end
if (_options[:follow_settings])
json['follow_topic_on_created'] = settings.follow_topic_on_created == "1"
json['follow_topic_on_contributed'] = settings.follow_topic_on_contributed == "1"
json['follow_map_on_created'] = settings.follow_map_on_created == "1"
json['follow_map_on_contributed'] = settings.follow_map_on_contributed == "1"
end
if (_options[:email])
json['email'] = email
if options[:follow_settings]
json['follow_topic_on_created'] = settings.follow_topic_on_created == '1'
json['follow_topic_on_contributed'] = settings.follow_topic_on_contributed == '1'
json['follow_map_on_created'] = settings.follow_map_on_created == '1'
json['follow_map_on_contributed'] = settings.follow_map_on_contributed == '1'
end
json['email'] = email if options[:email]
json
end
@ -107,10 +106,14 @@ class User < ApplicationRecord
end
def most_used_metacodes
topics.to_a.each_with_object(Hash.new(0)) do |topic, memo|
memo[topic.metacode_id] += 1
memo
end.to_a.sort { |a, b| b[1] <=> a[1] }.map { |i| i[0] }.slice(0, 5)
metacode_counts = topics.to_a.each_with_object(Hash.new(0)) do |topic, list_so_far|
list_so_far[topic.metacode_id] += 1
list_so_far
end
id_count_pairs = metacode_counts.to_a
id_count_pairs.sort! { |a, b| b[1] <=> a[1] }
metacode_ids = id_count_pairs.map { |i| i[0] }
metacode_ids.slice(0, 5)
end
# generate a random 8 letter/digit code that they can use to invite people
@ -133,20 +136,20 @@ class User < ApplicationRecord
end
def has_map_open(map)
latestEvent = Event.where(map: map, user: self)
.where(kind: ['user_present_on_map', 'user_not_present_on_map'])
.order(:created_at)
.last
latestEvent && latestEvent.kind == 'user_present_on_map'
latest_event = Event.where(map: map, user: self)
.where(kind: %w[user_present_on_map user_not_present_on_map])
.order(:created_at)
.last
latest_event && latest_event.kind == 'user_present_on_map'
end
def has_map_with_synapse_open(synapse)
synapse.maps.any?{|map| has_map_open(map)}
synapse.maps.any? { |map| has_map_open(map) }
end
def settings
self[:settings] = UserPreference.new if self[:settings].nil?
if not self[:settings].respond_to?(:follow_topic_on_created)
unless self[:settings].respond_to?(:follow_topic_on_created)
self[:settings].initialize_follow_settings
end
self[:settings]

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true
class UserMap < ApplicationRecord
belongs_to :map
belongs_to :user
belongs_to :access_request
after_create :after_created_async
before_destroy :before_destroyed
@ -12,20 +13,20 @@ class UserMap < ApplicationRecord
Mailboxer::Receipt.where(notification: notification).update_all(is_read: true)
end
end
protected
def after_created_async
FollowService.follow(map, user, 'shared_on')
if access_request
NotificationService.access_approved(self.access_request)
NotificationService.access_approved(access_request)
else
NotificationService.invite_to_edit(self)
end
# NotificationService.notify_followers(map, 'map_collaborator_added', self, 'shared_on')
end
handle_asynchronously :after_created_async
def before_destroyed
FollowService.remove_reason(map, user, 'shared_on')
end

View file

@ -1,29 +1,34 @@
# frozen_string_literal: true
class UserPreference
attr_accessor :metacodes, :metacode_focus, :follow_topic_on_created, :follow_topic_on_contributed,
:follow_map_on_created, :follow_map_on_contributed
def initialize
array = []
%w(Action Aim Idea Question Note Wildcard Subject).each do |m|
@metacodes = init_metacodes.compact
@metacode_focus = @metacodes[0]
initialize_follow_settings
end
private
def init_metacodes
%w[Action Aim Idea Question Note Wildcard Subject].map do |m|
begin
metacode = Metacode.find_by(name: m)
array.push(metacode.id.to_s) if metacode
metacode.id.to_s if metacode
rescue ActiveRecord::StatementInvalid
if m == 'Action'
Rails.logger.warn('TODO: remove this travis workaround in user_preference.rb')
end
end
end
@metacodes = array
@metacode_focus = array[0]
initialize_follow_settings
end.compact
end
def initialize_follow_settings
@follow_topic_on_created = false
@follow_topic_on_contributed = false
@follow_map_on_created = false
@follow_map_on_created = true
@follow_map_on_contributed = false
end
end

View file

@ -1,10 +1,11 @@
# frozen_string_literal: true
class Webhook < ApplicationRecord
belongs_to :hookable, polymorphic: true
validates :uri, presence: true
validates :hookable, presence: true
validates :kind, inclusion: { in: %w(slack) }
validates :kind, inclusion: { in: %w[slack] }
validates :event_types, length: { minimum: 1 }
def headers

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
Webhooks::Slack::Base = Struct.new(:webhook, :event) do
include Routing

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
class Webhooks::Slack::ConversationStartedOnMap < Webhooks::Slack::Base
def text
"There is a live conversation starting on map *#{event.map.name}*. #{view_map_on_metamaps('Join in!')}"

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