Compare commits

..

4 commits

Author SHA1 Message Date
Connor Turland
3c0c937c55 fixup after rebase 2017-10-15 21:08:09 -04:00
Connor Turland
ede0adf1fd ensure logo is in front of nodes 2017-10-15 16:09:10 -04:00
Connor Turland
08e03c11f6 homepage work first draft 2017-10-15 16:09:10 -04:00
Connor Turland
292d31aa1e content 2017-10-15 16:09:10 -04:00
235 changed files with 727 additions and 1331 deletions

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

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '2.3.0'
@ -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,10 @@ 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'
gem 'faker'
gem 'timecop'
end

View file

@ -105,10 +105,10 @@ GEM
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)
@ -117,8 +117,7 @@ GEM
activesupport (>= 4.2.0)
httparty (0.15.6)
multi_xml (>= 0.5.2)
i18n (0.9.3)
concurrent-ruby (~> 1.0)
i18n (0.8.6)
jmespath (1.3.1)
jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
@ -154,21 +153,22 @@ GEM
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.2.0)
minitest (5.10.3)
multi_xml (0.6.0)
nio4r (2.1.0)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.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)
parallel (1.12.0)
parser (2.4.0.0)
ast (~> 2.2)
pg (0.21.0)
powerpack (0.1.1)
pry (0.10.4)
@ -216,7 +216,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
rake (12.3.0)
rake (12.0.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
@ -241,13 +241,14 @@ GEM
rspec-mocks (~> 3.6.0)
rspec-support (~> 3.6.0)
rspec-support (3.6.0)
rubocop (0.48.1)
rubocop (0.49.1)
parallel (~> 1.10)
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)
ruby-progressbar (1.8.1)
sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@ -284,7 +285,7 @@ GEM
tilt (2.0.8)
timecop (0.9.1)
tunemygc (1.0.69)
tzinfo (1.2.4)
tzinfo (1.2.3)
thread_safe (~> 0.1)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
@ -311,7 +312,7 @@ DEPENDENCIES
doorkeeper
dotenv-rails
exception_notification
factory_bot_rails
factory_girl_rails
faker
httparty
jquery-rails
@ -332,7 +333,7 @@ DEPENDENCIES
rails (~> 5.0.0)
redis (~> 3.3.3)
rspec-rails
rubocop (~> 0.48.1)
rubocop
sass-rails
shoulda-matchers
simplecov
@ -347,4 +348,4 @@ RUBY VERSION
ruby 2.3.0p0
BUNDLED WITH
1.16.1
1.15.4

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.

File diff suppressed because one or more lines are too long

View file

@ -18,10 +18,26 @@
font-weight: normal;
font-style: normal;
}
.backface-visible {
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
@font-face {
font-family: 'noto-sans-regular';
src: url(<%= asset_path 'Fonts/notosansui-regular-webfont.woff2' %>) format('woff2'),
url(<%= asset_path 'Fonts/notosansui-regular-webfont.woff' %>) format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'noto-sans-bold';
src: url(<%= asset_path 'Fonts/notosansui-bold-webfont.woff2' %>) format('woff2'),
url(<%= asset_path 'Fonts/notosansui-bold-webfont.woff' %>) format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'noto-sans-bold-italic';
src: url(<%= asset_path 'Fonts/notosansui-bolditalic-webfont.woff2' %>) format('woff2'),
url(<%= asset_path 'Fonts/notosansui-bolditalic-webfont.woff' %>) format('woff');
font-weight: normal;
font-style: normal;
}
#yield {
@ -227,119 +243,106 @@
/* end map wrapper */
/* yield */
/* homepage */
.famousYield {
overflow-y:auto;
body.unauthenticated.action-home {
background: white;
font-family: 'noto-sans', sans-serif;
font-weight: 200;
}
/* homepage */
.home {
position: absolute;
width: 100%;
height: 100%;
}
.homeLogo {
position: fixed;
top: 10px;
left: 20px;
font-family: 'noto-sans-bold-italic', sans-serif;
font-size: 22px;
color: #6D6D6D;
z-index: 1;
}
#particles-bg {
position: absolute;
top: 0;
width: 100%;
height: 100%;
}
.homeWrapper.homeText {
margin-top: 5%;
}
.fullWidthWrapper {
width: 100%;
}
.fullWidthWrapper.withVideo {
height: 315px;
background: #757575;
}
.homeWrapper {
box-sizing: border-box;
position: relative;
z-index: 1;
border-radius: 3px;
color: #6D6D6D;
text-align: center;
padding: 30px;
background: white;
opacity: 0.8;
}
@media only screen and (max-width : 800px) {
.homeWrapper {
width: 90%;
margin: 0 5%;
}
}
@media only screen and (min-width : 801px) {
.homeWrapper {
width: 800px;
margin: 0 auto;
color: #424242;
}
}
.homeTitle {
font-size: 64px;
line-height: 48px;
text-align: center;
line-height: 70px;
margin-bottom: 20px;
font-family: 'noto-sans-bold', sans-serif;
}
.homeIntro {
font-size: 22px;
line-height: 26px;
text-align: justify;
margin: 32px 0 20px;
font-family: 'din-regular', helvetica, sans-serif;
}
.homeIntro div {
margin: 20px 0;
}
.homeWrapper .green {
color: #4fc059;
}
.homeWrapper .din-medium {
font-family: 'din-medium', helvetica, sans-serif;
.homeWrapper .purple {
color: #a354cd;
}
.homeWrapper .yellow {
color: #dab539;
}
.homeVideo {
margin-bottom: 20px;
float: left;
}
.homeWrapper .callToAction {
float: left;
width: 216px;
padding: 8px 0 8px 24px;
color: #F5F5F5;
}
.callToAction h3 {
font-size: 24px;
}
.callToAction p {
margin: 8px 0 16px;
font-size: 13px;
line-height: 16px;
font-family: 'din-regular', helvetica, sans-serif;
text-align: left;
}
.callToAction a, .callToAction button {
.requestInviteCTA {
display: block;
width: 220px;
height: 12px;
font-size: 20px;
padding: 16px 0;
text-align: center;
border-radius: 2px;
font-size: 12px;
box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
margin: 0 auto;
color: #FFFFFF;
box-sizing: content-box;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
}
.callToAction .requestInviteCTA {
background-color: #4fc059;
margin-bottom: 12px;
}
.callToAction .requestInviteCTA:hover {
background-color: #49ad4e;
}
.callToAction .exploreFeaturedCTA {
background-color: #a354cd;
margin-bottom: 12px;
}
.callToAction .exploreFeaturedCTA:hover {
background-color: #9150bc;
}
.callToAction .learnMoreCTA {
background-color: #4fb5c0;
margin-bottom: 12px;
}
.callToAction .learnMoreCTA:hover {
background-color: #419599;
border-radius: 3px;
border: 2px solid #a354cd;
margin: 12px auto;
color: #a354cd;
font-family: 'noto-sans-bold', sans-serif;
}
.requestInviteCTA:hover {
.fullWidthWrapper.withPartners {
background: url(<%= asset_path('homepage_bg_fade.png') %>) no-repeat center -300px;
}
.homeWrapper.homePartners {
padding: 64px 0 280px;
height: 96px;
}
/* end home page */

View file

@ -60,19 +60,6 @@
.homeIntro {
text-align: left;
}
.fullWidthWrapper.withVideo {
height: auto;
}
.homeVideo {
width: 100% !important;
height: auto;
}
.fullWidthWrapper.withPartners {
display: none;
}
.learnMoreCTA {
display: none !important;
}
#yield {
padding-top: 50px;

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

View file

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

View file

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

View file

@ -1,10 +1,9 @@
# frozen_string_literal: true
module Api
module V2
class MapsController < WithUpdatesController
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,5 +1,4 @@
# frozen_string_literal: true
module Api
module V2
class RestfulController < ActionController::Base
@ -8,7 +7,7 @@ module Api
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
@ -92,7 +91,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,5 +1,4 @@
# frozen_string_literal: true
module Api
module V2
class SynapsesController < WithUpdatesController

View file

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

View file

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

View file

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

View file

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

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

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, :follow, :unfollow]
before_action :set_map, only: [:show, :conversation, :update, :destroy, :contains, :events, :export, :follow, :unfollow, :unfollow_from_email]
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|
@ -143,7 +140,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
@ -158,7 +155,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,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,9 +1,8 @@
# 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)
@ -28,14 +27,14 @@ 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

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

View file

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

View file

@ -1,12 +1,11 @@
# 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, :follow, :unfollow]
before_action :set_topic, only: [:show, :update, :relative_numbers,
:relatives, :network, :destroy,
:follow, :unfollow, :unfollow_from_email]
after_action :verify_authorized, except: :autocomplete_topic
respond_to :html, :js, :json
@ -14,7 +13,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"')

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
@ -42,7 +41,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])
update_follow_settings(@user, params[:settings]) if is_tester(@user)
@user.image = nil if params[:remove_image] == '1'
@user.save
sign_in(@user, bypass: true)
@ -101,7 +100,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

@ -1,5 +1,4 @@
# frozen_string_literal: true
class NotificationDecorator
class << self
def decorate(notification, receipt)

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
module ApplicationHelper
def invite_link
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '')

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,5 +1,3 @@
# frozen_string_literal: true
module MapMailerHelper
def access_approved_subject(map)
map.name + ' - access approved'
@ -7,9 +5,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,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

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

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,5 +1,4 @@
# frozen_string_literal: true
module TopicMailerHelper
def added_to_map_subject(topic, map)
topic.name + ' was added to map ' + map.name
@ -8,4 +7,4 @@ module TopicMailerHelper
def connected_subject(topic)
'new synapse to topic ' + topic.name
end
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,5 +1,4 @@
# frozen_string_literal: true
class ApplicationMailer < ActionMailer::Base
default from: 'team@metamaps.cc'
layout 'mailer'
@ -7,24 +6,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,5 +1,4 @@
# frozen_string_literal: true
class MapActivityMailer < ApplicationMailer
default from: 'team@metamaps.cc'

View file

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

View file

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

View file

@ -1,10 +1,9 @@
# frozen_string_literal: true
class AccessRequest < ApplicationRecord
belongs_to :user
belongs_to :map
has_one :user_map
after_create :after_created_async
def approve
@ -28,9 +27,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,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,5 +1,4 @@
# frozen_string_literal: true
module Events
class TopicAddedToMap < Event
after_create :notify_users!
@ -11,7 +10,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,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,8 +1,7 @@
# 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',
@ -10,7 +9,7 @@ module Events
user: user,
meta: meta)
end
def notify_users!
NotificationService.notify_followers(eventable, 'topic_updated', self)
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 +1,23 @@
# 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) })
scope :active, -> {
where(muted: false)
}
private
def add_subsetting
FollowReason.create!(follow: self)
follow_reason = FollowReason.create!(follow: self)
end
end

View file

@ -1,13 +1,12 @@
# 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,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,7 +1,6 @@
# 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
@ -16,7 +15,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
@ -90,10 +89,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
@ -134,16 +133,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, user, 'created')
FollowService.follow(self, self.user, 'created')
# notify users following the map creator
end
@ -151,12 +150,13 @@ 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
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
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
end
handle_asynchronously :after_updated_async

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
@ -25,7 +24,7 @@ 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
@ -53,17 +52,17 @@ class Mapping < ApplicationRecord
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')
if (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
FollowService.follow(map, updated_by, 'contributed')
end
end
handle_asynchronously :after_updated_async

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
class Message < ApplicationRecord
belongs_to :user
belongs_to :resource, polymorphic: true
@ -7,14 +6,15 @@ 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: %i[user_name user_image])
json = super(methods: [:user_name, :user_image])
json
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,21 +1,20 @@
# 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
#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,7 +1,6 @@
# 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'
@ -22,9 +21,9 @@ class Synapse < ApplicationRecord
validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true }
scope :for_topic, (lambda do |topic_id = nil|
scope :for_topic, ->(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
@ -39,7 +38,7 @@ class Synapse < ApplicationRecord
def collaborator_ids
if defer_to_map
defer_to_map.editors.reject { |mapper| mapper == user }.map(&:id)
defer_to_map.editors.select { |mapper| mapper != user }.map(&:id)
else
[]
end
@ -55,7 +54,7 @@ class Synapse < ApplicationRecord
end
def as_json(_options = {})
super(methods: %i[user_name user_image collaborator_ids])
super(methods: [:user_name, :user_image, :collaborator_ids])
end
def as_rdf
@ -73,7 +72,7 @@ class Synapse < ApplicationRecord
protected
def set_perm_by_defer
defer_to_map&.permission
permission = defer_to_map.permission if defer_to_map
end
def after_created_async
@ -83,21 +82,21 @@ class Synapse < ApplicationRecord
handle_asynchronously :after_created_async
def after_updated
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
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
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,5 +1,4 @@
# frozen_string_literal: true
class Token < ApplicationRecord
belongs_to :user

View file

@ -1,7 +1,6 @@
# 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
@ -17,7 +16,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
@ -26,7 +25,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) }
@ -39,13 +38,13 @@ class Topic < ApplicationRecord
topics1.or(topics2)
end
scope :relatives, (lambda do |topic_id = nil, user = nil|
scope :relatives, ->(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
@ -65,13 +64,13 @@ class Topic < ApplicationRecord
Pundit.policy_scope(user, maps).map(&:name)
end
def inmaps_links(user)
def inmapsLinks(user)
Pundit.policy_scope(user, maps).map(&:id)
end
def as_json(options = {})
super(methods: %i[user_name user_image collaborator_ids])
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmaps_links(options[:user]),
super(methods: [:user_name, :user_image, :collaborator_ids])
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmapsLinks(options[:user]),
map_count: map_count(options[:user]), synapse_count: synapse_count(options[:user]))
end
@ -90,7 +89,7 @@ class Topic < ApplicationRecord
def collaborator_ids
if defer_to_map
defer_to_map.editors.reject { |mapper| mapper == user }.map(&:id)
defer_to_map.editors.select { |mapper| mapper != user }.map(&:id)
else
[]
end
@ -127,9 +126,14 @@ class Topic < ApplicationRecord
end
end
end
return output if output_format == 'array'
return output.join('; ') if output_format == 'text'
raise 'invalid argument to synapses_csv'
if output_format == 'array'
return output
elsif output_format == 'text'
return output.join('; ')
else
raise 'invalid argument to synapses_csv'
end
output
end
def topic_autocomplete_method
@ -139,7 +143,7 @@ class Topic < ApplicationRecord
protected
def set_perm_by_defer
self.permission = defer_to_map.permission if defer_to_map
permission = defer_to_map.permission if defer_to_map
end
def create_metamap?
@ -150,35 +154,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, user, 'created')
FollowService.follow(self, self.user, 'created')
# notify users following the topic creator
end
handle_asynchronously :after_created_async
def after_updated
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
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
end
end
def after_updated_async
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
FollowService.follow(self, updated_by, 'contributed')
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
FollowService.follow(self, updated_by, 'contributed')
end
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,5 +1,4 @@
# frozen_string_literal: true
require 'open-uri'
class User < ApplicationRecord
@ -52,24 +51,26 @@ 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.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'
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
end
json['email'] = email if options[:email]
json
end
@ -106,14 +107,10 @@ class User < ApplicationRecord
end
def most_used_metacodes
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)
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)
end
# generate a random 8 letter/digit code that they can use to invite people
@ -136,20 +133,20 @@ class User < ApplicationRecord
end
def has_map_open(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'
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'
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?
unless self[:settings].respond_to?(:follow_topic_on_created)
if not self[:settings].respond_to?(:follow_topic_on_created)
self[:settings].initialize_follow_settings
end
self[:settings]

View file

@ -1,10 +1,9 @@
# 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
@ -13,20 +12,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(access_request)
NotificationService.access_approved(self.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,28 +1,23 @@
# 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
@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|
array = []
%w(Action Aim Idea Question Note Wildcard Subject).each do |m|
begin
metacode = Metacode.find_by(name: m)
metacode.id.to_s if metacode
array.push(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.compact
end
@metacodes = array
@metacode_focus = array[0]
initialize_follow_settings
end
def initialize_follow_settings

View file

@ -1,11 +1,10 @@
# 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,5 +1,4 @@
# frozen_string_literal: true
Webhooks::Slack::Base = Struct.new(:webhook, :event) do
include Routing

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