Compare commits
15 commits
rubocop-fi
...
develop
Author | SHA1 | Date | |
---|---|---|---|
|
98081097b4 | ||
|
f753392d49 | ||
|
38a209a970 | ||
|
bd7bf20810 | ||
|
955ebdd747 | ||
|
fdcd8a93f1 | ||
|
b5c52adf5e | ||
|
b7761a3627 | ||
|
e0d72fce14 | ||
|
139fdf8e2b | ||
|
4313f6eff8 | ||
|
91c004ebfd | ||
|
96056f43ef | ||
|
32e58fa8af | ||
|
5ebbd87afc |
83 changed files with 723 additions and 290 deletions
|
@ -12,7 +12,7 @@ Rails:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
Metrics/LineLength:
|
Metrics/LineLength:
|
||||||
Max: 100
|
Max: 120
|
||||||
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 16
|
Max: 16
|
||||||
|
@ -22,3 +22,8 @@ Style/Documentation:
|
||||||
|
|
||||||
Style/EmptyMethod:
|
Style/EmptyMethod:
|
||||||
EnforcedStyle: expanded
|
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
|
||||||
|
|
4
Gemfile
4
Gemfile
|
@ -38,7 +38,7 @@ gem 'uglifier'
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'brakeman', require: false
|
gem 'brakeman', require: false
|
||||||
gem 'factory_girl_rails'
|
gem 'factory_bot_rails'
|
||||||
gem 'json-schema'
|
gem 'json-schema'
|
||||||
gem 'rspec-rails'
|
gem 'rspec-rails'
|
||||||
gem 'shoulda-matchers'
|
gem 'shoulda-matchers'
|
||||||
|
@ -51,7 +51,7 @@ group :development, :test do
|
||||||
gem 'faker'
|
gem 'faker'
|
||||||
gem 'pry-byebug'
|
gem 'pry-byebug'
|
||||||
gem 'pry-rails'
|
gem 'pry-rails'
|
||||||
gem 'rubocop', '~> 0.46.0' # match code climate https://github.com/tootsuite/mastodon/issues/1758
|
gem 'rubocop', '~> 0.48.1' # match code climate https://github.com/tootsuite/mastodon/issues/1758
|
||||||
gem 'timecop'
|
gem 'timecop'
|
||||||
gem 'tunemygc'
|
gem 'tunemygc'
|
||||||
end
|
end
|
||||||
|
|
37
Gemfile.lock
37
Gemfile.lock
|
@ -105,10 +105,10 @@ GEM
|
||||||
actionmailer (>= 4.0, < 6)
|
actionmailer (>= 4.0, < 6)
|
||||||
activesupport (>= 4.0, < 6)
|
activesupport (>= 4.0, < 6)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
factory_girl (4.8.0)
|
factory_bot (4.8.2)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
factory_girl_rails (4.8.0)
|
factory_bot_rails (4.8.2)
|
||||||
factory_girl (~> 4.8.0)
|
factory_bot (~> 4.8.2)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
faker (1.8.4)
|
faker (1.8.4)
|
||||||
i18n (~> 0.5)
|
i18n (~> 0.5)
|
||||||
|
@ -117,7 +117,8 @@ GEM
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
httparty (0.15.6)
|
httparty (0.15.6)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
i18n (0.8.6)
|
i18n (0.9.3)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
jmespath (1.3.1)
|
jmespath (1.3.1)
|
||||||
jquery-rails (4.3.1)
|
jquery-rails (4.3.1)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
|
@ -153,21 +154,21 @@ GEM
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2016.0521)
|
mime-types-data (3.2016.0521)
|
||||||
mimemagic (0.3.2)
|
mimemagic (0.3.2)
|
||||||
mini_portile2 (2.2.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.10.3)
|
minitest (5.11.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
nio4r (2.1.0)
|
nio4r (2.1.0)
|
||||||
nokogiri (1.8.0)
|
nokogiri (1.8.1)
|
||||||
mini_portile2 (~> 2.2.0)
|
mini_portile2 (~> 2.3.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
paperclip (5.1.0)
|
paperclip (5.2.0)
|
||||||
activemodel (>= 4.2.0)
|
activemodel (>= 4.2.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
cocaine (~> 0.5.5)
|
cocaine (~> 0.5.5)
|
||||||
mime-types
|
mime-types
|
||||||
mimemagic (~> 0.3.0)
|
mimemagic (~> 0.3.0)
|
||||||
parser (2.4.0.0)
|
parser (2.4.0.2)
|
||||||
ast (~> 2.2)
|
ast (~> 2.3)
|
||||||
pg (0.21.0)
|
pg (0.21.0)
|
||||||
powerpack (0.1.1)
|
powerpack (0.1.1)
|
||||||
pry (0.10.4)
|
pry (0.10.4)
|
||||||
|
@ -215,7 +216,7 @@ GEM
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.2.2)
|
rainbow (2.2.2)
|
||||||
rake
|
rake
|
||||||
rake (12.0.0)
|
rake (12.3.0)
|
||||||
rb-fsevent (0.10.2)
|
rb-fsevent (0.10.2)
|
||||||
rb-inotify (0.9.10)
|
rb-inotify (0.9.10)
|
||||||
ffi (>= 0.5.0, < 2)
|
ffi (>= 0.5.0, < 2)
|
||||||
|
@ -240,8 +241,8 @@ GEM
|
||||||
rspec-mocks (~> 3.6.0)
|
rspec-mocks (~> 3.6.0)
|
||||||
rspec-support (~> 3.6.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-support (3.6.0)
|
rspec-support (3.6.0)
|
||||||
rubocop (0.46.0)
|
rubocop (0.48.1)
|
||||||
parser (>= 2.3.1.1, < 3.0)
|
parser (>= 2.3.3.1, < 3.0)
|
||||||
powerpack (~> 0.1)
|
powerpack (~> 0.1)
|
||||||
rainbow (>= 1.99.1, < 3.0)
|
rainbow (>= 1.99.1, < 3.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
|
@ -283,7 +284,7 @@ GEM
|
||||||
tilt (2.0.8)
|
tilt (2.0.8)
|
||||||
timecop (0.9.1)
|
timecop (0.9.1)
|
||||||
tunemygc (1.0.69)
|
tunemygc (1.0.69)
|
||||||
tzinfo (1.2.3)
|
tzinfo (1.2.4)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (3.2.0)
|
uglifier (3.2.0)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
|
@ -310,7 +311,7 @@ DEPENDENCIES
|
||||||
doorkeeper
|
doorkeeper
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
exception_notification
|
exception_notification
|
||||||
factory_girl_rails
|
factory_bot_rails
|
||||||
faker
|
faker
|
||||||
httparty
|
httparty
|
||||||
jquery-rails
|
jquery-rails
|
||||||
|
@ -331,7 +332,7 @@ DEPENDENCIES
|
||||||
rails (~> 5.0.0)
|
rails (~> 5.0.0)
|
||||||
redis (~> 3.3.3)
|
redis (~> 3.3.3)
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rubocop (~> 0.46.0)
|
rubocop (~> 0.48.1)
|
||||||
sass-rails
|
sass-rails
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
simplecov
|
simplecov
|
||||||
|
@ -346,4 +347,4 @@ RUBY VERSION
|
||||||
ruby 2.3.0p0
|
ruby 2.3.0p0
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.15.4
|
1.16.1
|
||||||
|
|
0
Rakefile
Normal file → Executable file
0
Rakefile
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AccessController < ApplicationController
|
class AccessController < ApplicationController
|
||||||
before_action :require_user, only: %i(access access_request
|
before_action :require_user, only: %i[access access_request
|
||||||
approve_access approve_access_post
|
approve_access approve_access_post
|
||||||
deny_access deny_access_post request_access)
|
deny_access deny_access_post request_access]
|
||||||
before_action :set_map, only: %i(access access_request
|
before_action :set_map, only: %i[access access_request
|
||||||
approve_access approve_access_post
|
approve_access approve_access_post
|
||||||
deny_access deny_access_post request_access)
|
deny_access deny_access_post request_access]
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
# GET maps/:id/request_access
|
# GET maps/:id/request_access
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Api
|
||||||
module V2
|
module V2
|
||||||
class MapsController < WithUpdatesController
|
class MapsController < WithUpdatesController
|
||||||
def searchable_columns
|
def searchable_columns
|
||||||
%i(name desc)
|
%i[name desc]
|
||||||
end
|
end
|
||||||
|
|
||||||
def apply_filters(collection)
|
def apply_filters(collection)
|
||||||
|
|
|
@ -8,7 +8,7 @@ module Api
|
||||||
|
|
||||||
snorlax_used_rest!
|
snorlax_used_rest!
|
||||||
|
|
||||||
before_action :load_resource, only: %i(show update destroy)
|
before_action :load_resource, only: %i[show update destroy]
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Api
|
||||||
module V2
|
module V2
|
||||||
class TopicsController < WithUpdatesController
|
class TopicsController < WithUpdatesController
|
||||||
def searchable_columns
|
def searchable_columns
|
||||||
%i(name desc link)
|
%i[name desc link]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ExploreController < ApplicationController
|
class ExploreController < ApplicationController
|
||||||
before_action :require_authentication, only: %i(mine shared starred)
|
before_action :require_authentication, only: %i[mine shared starred]
|
||||||
before_action :authorize_explore
|
before_action :authorize_explore
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
after_action :verify_policy_scoped
|
after_action :verify_policy_scoped
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MappingsController < ApplicationController
|
class MappingsController < ApplicationController
|
||||||
before_action :require_user, only: %i(create update destroy)
|
before_action :require_user, only: %i[create update destroy]
|
||||||
after_action :verify_authorized, except: :index
|
after_action :verify_authorized, except: :index
|
||||||
after_action :verify_policy_scoped, only: :index
|
after_action :verify_policy_scoped, only: :index
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MapsController < ApplicationController
|
class MapsController < ApplicationController
|
||||||
before_action :require_user, only: %i(create update destroy events follow unfollow)
|
before_action :require_user, only: %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 :set_map, only: %i[show conversation update destroy
|
||||||
|
contains events export
|
||||||
|
follow unfollow unfollow_from_email]
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
# GET maps/:id
|
# GET maps/:id
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MetacodesController < ApplicationController
|
class MetacodesController < ApplicationController
|
||||||
before_action :require_admin, except: %i(index show)
|
before_action :require_admin, except: %i[index show]
|
||||||
before_action :set_metacode, only: %i(edit update)
|
before_action :set_metacode, only: %i[edit update]
|
||||||
|
|
||||||
# GET /metacodes
|
# GET /metacodes
|
||||||
# GET /metacodes.json
|
# GET /metacodes.json
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class NotificationsController < ApplicationController
|
class NotificationsController < ApplicationController
|
||||||
before_action :set_receipts, only: %i(index 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_notification, only: %i[show mark_read mark_unread]
|
||||||
before_action :set_receipt, only: %i(show mark_read mark_unread)
|
before_action :set_receipt, only: %i[show mark_read mark_unread]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@notifications = current_user.mailbox.notifications.page(params[:page]).per(25)
|
@notifications = current_user.mailbox.notifications.page(params[:page]).per(25)
|
||||||
|
|
|
@ -8,7 +8,7 @@ class SearchController < ApplicationController
|
||||||
|
|
||||||
before_action :authorize_search
|
before_action :authorize_search
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
after_action :verify_policy_scoped, only: %i(maps mappers synapses topics)
|
after_action :verify_policy_scoped, only: %i[maps mappers synapses topics]
|
||||||
|
|
||||||
# get /search/topics?term=SOMETERM
|
# get /search/topics?term=SOMETERM
|
||||||
def topics
|
def topics
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class SynapsesController < ApplicationController
|
class SynapsesController < ApplicationController
|
||||||
include TopicsHelper
|
include TopicsHelper
|
||||||
|
|
||||||
before_action :require_user, only: %i(create update destroy)
|
before_action :require_user, only: %i[create update destroy]
|
||||||
after_action :verify_authorized, except: :index
|
after_action :verify_authorized, except: :index
|
||||||
after_action :verify_policy_scoped, only: :index
|
after_action :verify_policy_scoped, only: :index
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
class TopicsController < ApplicationController
|
class TopicsController < ApplicationController
|
||||||
include TopicsHelper
|
include TopicsHelper
|
||||||
|
|
||||||
before_action :require_user, only: %i(create update destroy follow unfollow)
|
before_action :require_user, only: %i[create update destroy follow unfollow]
|
||||||
before_action :set_topic, only: %i(show update relative_numbers
|
before_action :set_topic, only: %i[show update relative_numbers
|
||||||
relatives network destroy
|
relatives network destroy
|
||||||
follow unfollow unfollow_from_email)
|
follow unfollow unfollow_from_email]
|
||||||
after_action :verify_authorized, except: :autocomplete_topic
|
after_action :verify_authorized, except: :autocomplete_topic
|
||||||
|
|
||||||
respond_to :html, :js, :json
|
respond_to :html, :js, :json
|
||||||
|
|
|
@ -30,7 +30,7 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_sign_up_params
|
def configure_sign_up_params
|
||||||
devise_parameter_sanitizer.permit(:sign_up, keys: %i(name joinedwithcode))
|
devise_parameter_sanitizer.permit(:sign_up, keys: %i[name joinedwithcode])
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_account_update_params
|
def configure_account_update_params
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
before_action :require_user, only: %i(edit update updatemetacodes update_metacode_focus)
|
before_action :require_user, only: %i[edit update updatemetacodes update_metacode_focus]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class UsersController < ApplicationController
|
||||||
correct_pass = @user.valid_password?(params[:current_password])
|
correct_pass = @user.valid_password?(params[:current_password])
|
||||||
|
|
||||||
if correct_pass && @user.update_attributes(user_params)
|
if correct_pass && @user.update_attributes(user_params)
|
||||||
update_follow_settings(@user, params[:settings]) if is_tester(@user)
|
update_follow_settings(@user, params[:settings])
|
||||||
@user.image = nil if params[:remove_image] == '1'
|
@user.image = nil if params[:remove_image] == '1'
|
||||||
@user.save
|
@user.save
|
||||||
sign_in(@user, bypass: true)
|
sign_in(@user, bypass: true)
|
||||||
|
|
|
@ -17,7 +17,7 @@ module TopicsHelper
|
||||||
|
|
||||||
rtype: is_map ? 'map' : 'topic',
|
rtype: is_map ? 'map' : 'topic',
|
||||||
inmaps: is_map ? [] : t.inmaps(current_user),
|
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,
|
type: is_map ? metamap_metacode.name : t.metacode.name,
|
||||||
typeImageURL: is_map ? metamap_metacode.icon : t.metacode.icon,
|
typeImageURL: is_map ? metamap_metacode.icon : t.metacode.icon,
|
||||||
mapCount: is_map ? 0 : t.maps.count,
|
mapCount: is_map ? 0 : t.maps.count,
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Event < ApplicationRecord
|
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
|
conversation_started_on_map
|
||||||
topic_added_to_map topic_moved_on_map topic_removed_from_map
|
topic_added_to_map topic_moved_on_map topic_removed_from_map
|
||||||
synapse_added_to_map synapse_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 :eventable, polymorphic: true
|
||||||
belongs_to :map
|
belongs_to :map
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
scope :chronologically, -> { order('created_at asc') }
|
scope :chronologically, (-> { order('created_at asc') })
|
||||||
|
|
||||||
after_create :notify_webhooks!, if: :map
|
after_create :notify_webhooks!, if: :map
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,11 @@ class Follow < ApplicationRecord
|
||||||
|
|
||||||
after_create :add_subsetting
|
after_create :add_subsetting
|
||||||
|
|
||||||
scope :active, -> {
|
scope :active, (-> { where(muted: false) })
|
||||||
where(muted: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_subsetting
|
def add_subsetting
|
||||||
follow_reason = FollowReason.create!(follow: self)
|
FollowReason.create!(follow: self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class FollowReason < ApplicationRecord
|
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
|
belongs_to :follow
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Map < ApplicationRecord
|
class Map < ApplicationRecord
|
||||||
ATTRS_TO_WATCH = %w(name desc permission).freeze
|
ATTRS_TO_WATCH = %w[name desc permission].freeze
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :source, class_name: :Map
|
belongs_to :source, class_name: :Map
|
||||||
|
@ -90,10 +90,10 @@ class Map < ApplicationRecord
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
json = super(
|
json = super(
|
||||||
methods: %i(user_name user_image star_count topic_count synapse_count
|
methods: %i[user_name user_image star_count topic_count synapse_count
|
||||||
contributor_count collaborator_ids screenshot_url),
|
contributor_count collaborator_ids screenshot_url],
|
||||||
except: %i(screenshot_content_type screenshot_file_size screenshot_file_name
|
except: %i[screenshot_content_type screenshot_file_size screenshot_file_name
|
||||||
screenshot_updated_at)
|
screenshot_updated_at]
|
||||||
)
|
)
|
||||||
json[:created_at_clean] = created_at_str
|
json[:created_at_clean] = created_at_str
|
||||||
json[:updated_at_clean] = updated_at_str
|
json[:updated_at_clean] = updated_at_str
|
||||||
|
@ -153,12 +153,11 @@ class Map < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_updated_async
|
def after_updated_async
|
||||||
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
||||||
FollowService.follow(self, updated_by, 'contributed')
|
FollowService.follow(self, updated_by, 'contributed')
|
||||||
# NotificationService.notify_followers(self, 'map_updated', changed_attributes)
|
# NotificationService.notify_followers(self, 'map_updated', changed_attributes)
|
||||||
# or better yet publish an event
|
# or better yet publish an event
|
||||||
end
|
end
|
||||||
end
|
|
||||||
handle_asynchronously :after_updated_async
|
handle_asynchronously :after_updated_async
|
||||||
|
|
||||||
def before_destroyed
|
def before_destroyed
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Mapping < ApplicationRecord
|
class Mapping < ApplicationRecord
|
||||||
scope :topicmapping, -> { where(mappable_type: :Topic) }
|
scope :topicmapping, (-> { where(mappable_type: :Topic) })
|
||||||
scope :synapsemapping, -> { where(mappable_type: :Synapse) }
|
scope :synapsemapping, (-> { where(mappable_type: :Synapse) })
|
||||||
|
|
||||||
belongs_to :mappable, polymorphic: true
|
belongs_to :mappable, polymorphic: true
|
||||||
belongs_to :map, class_name: 'Map', foreign_key: 'map_id', touch: true
|
belongs_to :map, class_name: 'Map', foreign_key: 'map_id', touch: true
|
||||||
|
@ -25,7 +25,7 @@ class Mapping < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
super(methods: %i(user_name user_image))
|
super(methods: %i[user_name user_image])
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_created
|
def after_created
|
||||||
|
@ -53,18 +53,18 @@ class Mapping < ApplicationRecord
|
||||||
handle_asynchronously :after_created_async
|
handle_asynchronously :after_created_async
|
||||||
|
|
||||||
def after_updated
|
def after_updated
|
||||||
if (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
|
return unless (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
|
||||||
meta = { 'x': xloc, 'y': yloc, 'mapping_id': id }
|
meta = { 'x': xloc, 'y': yloc, 'mapping_id': id }
|
||||||
Events::TopicMovedOnMap.publish!(mappable, map, updated_by, meta)
|
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
|
ActionCable.server.broadcast('map_' + map.id.to_s, type: 'topicMoved',
|
||||||
end
|
id: mappable.id, mapping_id: id,
|
||||||
|
x: xloc, y: yloc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_updated_async
|
def after_updated_async
|
||||||
if (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
|
return unless (mappable_type == 'Topic') && (xloc_changed? || yloc_changed?)
|
||||||
FollowService.follow(map, updated_by, 'contributed')
|
FollowService.follow(map, updated_by, 'contributed')
|
||||||
end
|
end
|
||||||
end
|
|
||||||
handle_asynchronously :after_updated_async
|
handle_asynchronously :after_updated_async
|
||||||
|
|
||||||
def before_destroyed
|
def before_destroyed
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Message < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
json = super(methods: %i(user_name user_image))
|
json = super(methods: %i[user_name user_image])
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,11 @@ class Metacode < ApplicationRecord
|
||||||
has_many :topics
|
has_many :topics
|
||||||
|
|
||||||
# This method associates the attribute ":aws_icon" with a file attachment
|
# This method associates the attribute ":aws_icon" with a file attachment
|
||||||
has_attached_file :aws_icon, styles: {
|
has_attached_file :aws_icon, styles: { ninetysix: ['96x96#', :png] },
|
||||||
ninetysix: ['96x96#', :png]
|
|
||||||
},
|
|
||||||
default_url: 'https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_wildcard.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
|
# 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 :aws_xor_manual_icon
|
||||||
validate :manual_icon_https
|
validate :manual_icon_https
|
||||||
|
@ -31,15 +29,13 @@ class Metacode < ApplicationRecord
|
||||||
def as_json(options = {})
|
def as_json(options = {})
|
||||||
default = super(options)
|
default = super(options)
|
||||||
default[:icon] = icon
|
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
|
end
|
||||||
|
|
||||||
def hasSelected(user)
|
def in_metacode_set(metacode_set)
|
||||||
return true if user.settings.metacodes.include? id.to_s
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def inMetacodeSet(metacode_set)
|
|
||||||
return true if metacode_sets.include? metacode_set
|
return true if metacode_sets.include? metacode_set
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -56,10 +52,9 @@ class Metacode < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def manual_icon_https
|
def manual_icon_https
|
||||||
if manual_icon.present?
|
return if manual_icon.blank?
|
||||||
unless manual_icon.starts_with? 'https'
|
unless manual_icon.starts_with? 'https'
|
||||||
errors.add(:base, 'Manual icon must begin with https')
|
errors.add(:base, 'Manual icon must begin with https')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class PermittedParams < Struct.new(:params)
|
class PermittedParams
|
||||||
%w(map synapse topic mapping token).each do |kind|
|
%w[map synapse topic mapping token].each do |kind|
|
||||||
define_method(kind) do
|
define_method(kind) do
|
||||||
permitted_attributes = send("#{kind}_attributes")
|
permitted_attributes = send("#{kind}_attributes")
|
||||||
params.require(kind).permit(*permitted_attributes)
|
@params.require(kind).permit(*permitted_attributes)
|
||||||
end
|
end
|
||||||
alias_method :"api_#{kind}", kind.to_sym
|
alias_method :"api_#{kind}", kind.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
alias read_attribute_for_serialization send
|
alias read_attribute_for_serialization send
|
||||||
|
|
||||||
def token_attributes
|
def token_attributes
|
||||||
|
@ -16,18 +20,18 @@ class PermittedParams < Struct.new(:params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def map_attributes
|
def map_attributes
|
||||||
%i(name desc permission arranged)
|
%i[name desc permission arranged]
|
||||||
end
|
end
|
||||||
|
|
||||||
def synapse_attributes
|
def synapse_attributes
|
||||||
%i(desc category weight permission topic1_id topic2_id)
|
%i[desc category weight permission topic1_id topic2_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_attributes
|
def topic_attributes
|
||||||
%i(name desc link permission metacode_id)
|
%i[name desc link permission metacode_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def mapping_attributes
|
def mapping_attributes
|
||||||
%i(xloc yloc map_id mappable_type mappable_id)
|
%i[xloc yloc map_id mappable_type mappable_id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Synapse < ApplicationRecord
|
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 :user
|
||||||
belongs_to :defer_to_map, class_name: 'Map', foreign_key: 'defer_to_map_id'
|
belongs_to :defer_to_map, class_name: 'Map', foreign_key: 'defer_to_map_id'
|
||||||
|
@ -22,9 +22,9 @@ class Synapse < ApplicationRecord
|
||||||
|
|
||||||
validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true }
|
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))
|
where(topic1_id: topic_id).or(where(topic2_id: topic_id))
|
||||||
}
|
end)
|
||||||
|
|
||||||
before_create :set_perm_by_defer
|
before_create :set_perm_by_defer
|
||||||
after_create :after_created_async
|
after_create :after_created_async
|
||||||
|
@ -55,7 +55,7 @@ class Synapse < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
super(methods: %i(user_name user_image collaborator_ids))
|
super(methods: %i[user_name user_image collaborator_ids])
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_rdf
|
def as_rdf
|
||||||
|
@ -73,7 +73,7 @@ class Synapse < ApplicationRecord
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def set_perm_by_defer
|
def set_perm_by_defer
|
||||||
permission = defer_to_map.permission if defer_to_map
|
defer_to_map&.permission
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_created_async
|
def after_created_async
|
||||||
|
@ -83,7 +83,8 @@ class Synapse < ApplicationRecord
|
||||||
handle_asynchronously :after_created_async
|
handle_asynchronously :after_created_async
|
||||||
|
|
||||||
def after_updated
|
def after_updated
|
||||||
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
||||||
|
|
||||||
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
|
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
|
||||||
old = changed_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 = new.merge(old) # we are prioritizing the old values, keeping them
|
||||||
|
@ -93,7 +94,6 @@ class Synapse < ApplicationRecord
|
||||||
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseUpdated', id: id
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseUpdated', id: id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def before_destroyed
|
def before_destroyed
|
||||||
# hard to know how to do this yet, because the synapse actually gets destroyed
|
# hard to know how to do this yet, because the synapse actually gets destroyed
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Topic < ApplicationRecord
|
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 TopicsHelper
|
||||||
include Attachable
|
include Attachable
|
||||||
|
|
||||||
|
@ -39,13 +39,13 @@ class Topic < ApplicationRecord
|
||||||
topics1.or(topics2)
|
topics1.or(topics2)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope :relatives, ->(topic_id = nil, user = nil) {
|
scope :relatives, (lambda do |topic_id = nil, user = nil|
|
||||||
# should only see topics through *visible* synapses
|
# should only see topics through *visible* synapses
|
||||||
# e.g. Topic A (commons) -> synapse (private) -> Topic B (commons) must be filtered out
|
# 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(topic1_id: topic_id)).pluck(:topic2_id)
|
||||||
topic_ids += Pundit.policy_scope(user, Synapse.where(topic2_id: topic_id)).pluck(:topic1_id)
|
topic_ids += Pundit.policy_scope(user, Synapse.where(topic2_id: topic_id)).pluck(:topic1_id)
|
||||||
where(id: topic_ids.uniq)
|
where(id: topic_ids.uniq)
|
||||||
}
|
end)
|
||||||
|
|
||||||
delegate :name, to: :user, prefix: true
|
delegate :name, to: :user, prefix: true
|
||||||
|
|
||||||
|
@ -65,13 +65,13 @@ class Topic < ApplicationRecord
|
||||||
Pundit.policy_scope(user, maps).map(&:name)
|
Pundit.policy_scope(user, maps).map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inmapsLinks(user)
|
def inmaps_links(user)
|
||||||
Pundit.policy_scope(user, maps).map(&:id)
|
Pundit.policy_scope(user, maps).map(&:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(options = {})
|
def as_json(options = {})
|
||||||
super(methods: %i(user_name user_image collaborator_ids))
|
super(methods: %i[user_name user_image collaborator_ids])
|
||||||
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmapsLinks(options[:user]),
|
.merge(inmaps: inmaps(options[:user]), inmapsLinks: inmaps_links(options[:user]),
|
||||||
map_count: map_count(options[:user]), synapse_count: synapse_count(options[:user]))
|
map_count: map_count(options[:user]), synapse_count: synapse_count(options[:user]))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -127,15 +127,10 @@ class Topic < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if output_format == 'array'
|
return output if output_format == 'array'
|
||||||
return output
|
return output.join('; ') if output_format == 'text'
|
||||||
elsif output_format == 'text'
|
|
||||||
return output.join('; ')
|
|
||||||
else
|
|
||||||
raise 'invalid argument to synapses_csv'
|
raise 'invalid argument to synapses_csv'
|
||||||
end
|
end
|
||||||
output
|
|
||||||
end
|
|
||||||
|
|
||||||
def topic_autocomplete_method
|
def topic_autocomplete_method
|
||||||
"Get: #{name}"
|
"Get: #{name}"
|
||||||
|
@ -144,7 +139,7 @@ class Topic < ApplicationRecord
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def set_perm_by_defer
|
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
|
end
|
||||||
|
|
||||||
def create_metamap?
|
def create_metamap?
|
||||||
|
@ -163,7 +158,8 @@ class Topic < ApplicationRecord
|
||||||
handle_asynchronously :after_created_async
|
handle_asynchronously :after_created_async
|
||||||
|
|
||||||
def after_updated
|
def after_updated
|
||||||
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
||||||
|
|
||||||
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
|
new = attributes.select { |k| ATTRS_TO_WATCH.include?(k) }
|
||||||
old = changed_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 = new.merge(old) # we are prioritizing the old values, keeping them
|
||||||
|
@ -173,13 +169,12 @@ class Topic < ApplicationRecord
|
||||||
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicUpdated', id: id
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicUpdated', id: id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def after_updated_async
|
def after_updated_async
|
||||||
if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
||||||
|
|
||||||
FollowService.follow(self, updated_by, 'contributed')
|
FollowService.follow(self, updated_by, 'contributed')
|
||||||
end
|
end
|
||||||
end
|
|
||||||
handle_asynchronously :after_updated_async
|
handle_asynchronously :after_updated_async
|
||||||
|
|
||||||
def before_destroyed
|
def before_destroyed
|
||||||
|
|
|
@ -52,24 +52,24 @@ class User < ApplicationRecord
|
||||||
validates_attachment_content_type :image, content_type: %r{\Aimage/.*\Z}
|
validates_attachment_content_type :image, content_type: %r{\Aimage/.*\Z}
|
||||||
|
|
||||||
# override default as_json
|
# override default as_json
|
||||||
def as_json(_options = {})
|
def as_json(options = {})
|
||||||
json = { id: id,
|
json = { id: id,
|
||||||
name: name,
|
name: name,
|
||||||
image: image.url(:sixtyfour),
|
image: image.url(:sixtyfour),
|
||||||
admin: admin }
|
admin: admin }
|
||||||
if _options[:follows]
|
if options[:follows]
|
||||||
json['follows'] = {
|
json['follows'] = {
|
||||||
topics: following.active.where(followed_type: 'Topic').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)
|
maps: following.active.where(followed_type: 'Map').to_a.map(&:followed_id)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if _options[:follow_settings]
|
if options[:follow_settings]
|
||||||
json['follow_topic_on_created'] = settings.follow_topic_on_created == '1'
|
json['follow_topic_on_created'] = settings.follow_topic_on_created == '1'
|
||||||
json['follow_topic_on_contributed'] = settings.follow_topic_on_contributed == '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_created'] = settings.follow_map_on_created == '1'
|
||||||
json['follow_map_on_contributed'] = settings.follow_map_on_contributed == '1'
|
json['follow_map_on_contributed'] = settings.follow_map_on_contributed == '1'
|
||||||
end
|
end
|
||||||
json['email'] = email if _options[:email]
|
json['email'] = email if options[:email]
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -106,10 +106,14 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def most_used_metacodes
|
def most_used_metacodes
|
||||||
topics.to_a.each_with_object(Hash.new(0)) do |topic, memo|
|
metacode_counts = topics.to_a.each_with_object(Hash.new(0)) do |topic, list_so_far|
|
||||||
memo[topic.metacode_id] += 1
|
list_so_far[topic.metacode_id] += 1
|
||||||
memo
|
list_so_far
|
||||||
end.to_a.sort { |a, b| b[1] <=> a[1] }.map { |i| i[0] }.slice(0, 5)
|
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
|
end
|
||||||
|
|
||||||
# generate a random 8 letter/digit code that they can use to invite people
|
# generate a random 8 letter/digit code that they can use to invite people
|
||||||
|
@ -132,11 +136,11 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_map_open(map)
|
def has_map_open(map)
|
||||||
latestEvent = Event.where(map: map, user: self)
|
latest_event = Event.where(map: map, user: self)
|
||||||
.where(kind: %w(user_present_on_map user_not_present_on_map))
|
.where(kind: %w[user_present_on_map user_not_present_on_map])
|
||||||
.order(:created_at)
|
.order(:created_at)
|
||||||
.last
|
.last
|
||||||
latestEvent && latestEvent.kind == 'user_present_on_map'
|
latest_event && latest_event.kind == 'user_present_on_map'
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_map_with_synapse_open(synapse)
|
def has_map_with_synapse_open(synapse)
|
||||||
|
|
|
@ -5,20 +5,24 @@ class UserPreference
|
||||||
:follow_map_on_created, :follow_map_on_contributed
|
:follow_map_on_created, :follow_map_on_contributed
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
array = []
|
@metacodes = init_metacodes.compact
|
||||||
%w(Action Aim Idea Question Note Wildcard Subject).each do |m|
|
@metacode_focus = @metacodes[0]
|
||||||
|
initialize_follow_settings
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def init_metacodes
|
||||||
|
%w[Action Aim Idea Question Note Wildcard Subject].map do |m|
|
||||||
begin
|
begin
|
||||||
metacode = Metacode.find_by(name: m)
|
metacode = Metacode.find_by(name: m)
|
||||||
array.push(metacode.id.to_s) if metacode
|
metacode.id.to_s if metacode
|
||||||
rescue ActiveRecord::StatementInvalid
|
rescue ActiveRecord::StatementInvalid
|
||||||
if m == 'Action'
|
if m == 'Action'
|
||||||
Rails.logger.warn('TODO: remove this travis workaround in user_preference.rb')
|
Rails.logger.warn('TODO: remove this travis workaround in user_preference.rb')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end.compact
|
||||||
@metacodes = array
|
|
||||||
@metacode_focus = array[0]
|
|
||||||
initialize_follow_settings
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_follow_settings
|
def initialize_follow_settings
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Webhook < ApplicationRecord
|
||||||
|
|
||||||
validates :uri, presence: true
|
validates :uri, presence: true
|
||||||
validates :hookable, presence: true
|
validates :hookable, presence: true
|
||||||
validates :kind, inclusion: { in: %w(slack) }
|
validates :kind, inclusion: { in: %w[slack] }
|
||||||
validates :event_types, length: { minimum: 1 }
|
validates :event_types, length: { minimum: 1 }
|
||||||
|
|
||||||
def headers
|
def headers
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base
|
class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base
|
||||||
def text
|
def text
|
||||||
connector = eventable.desc.empty? ? '->' : eventable.desc
|
connector = eventable.desc.empty? ? '->' : eventable.desc
|
||||||
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\" was added as a connection by *#{event.user.name}* to the map *#{view_map_on_metamaps}*"
|
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\"" \
|
||||||
|
" was added as a connection by *#{event.user.name}*" \
|
||||||
|
" to the map *#{view_map_on_metamaps}*"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
class Webhooks::Slack::SynapseRemovedFromMap < Webhooks::Slack::Base
|
class Webhooks::Slack::SynapseRemovedFromMap < Webhooks::Slack::Base
|
||||||
def text
|
def text
|
||||||
connector = eventable.desc.empty? ? '->' : eventable.desc
|
connector = eventable.desc.empty? ? '->' : eventable.desc
|
||||||
|
|
||||||
# TODO: express correct directionality of arrows when desc is empty
|
# TODO: express correct directionality of arrows when desc is empty
|
||||||
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\" was removed by *#{event.user.name}* as a connection from the map *#{view_map_on_metamaps}*"
|
|
||||||
|
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\"" \
|
||||||
|
" was removed by *#{event.user.name}* as a connection" \
|
||||||
|
" from the map *#{view_map_on_metamaps}*"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class MapPolicy < ApplicationPolicy
|
class MapPolicy < ApplicationPolicy
|
||||||
class Scope < Scope
|
class Scope < Scope
|
||||||
def resolve
|
def resolve
|
||||||
visible = %w(public commons)
|
visible = %w[public commons]
|
||||||
return scope.where(permission: visible) unless user
|
return scope.where(permission: visible) unless user
|
||||||
|
|
||||||
scope.where(permission: visible)
|
scope.where(permission: visible)
|
||||||
|
@ -17,13 +17,13 @@ class MapPolicy < ApplicationPolicy
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
record.permission.in?(%w(commons public)) ||
|
record.permission.in?(%w[commons public]) ||
|
||||||
record.collaborators.include?(user) ||
|
record.collaborators.include?(user) ||
|
||||||
record.user == user
|
record.user == user
|
||||||
end
|
end
|
||||||
|
|
||||||
def conversation?
|
def conversation?
|
||||||
show? && %w(connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com ishanshapiro@gmail.com).include?(user.email)
|
show? && is_tester(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
|
|
|
@ -7,7 +7,7 @@ class MappingPolicy < ApplicationPolicy
|
||||||
# it would be nice if we could also base this on the mappable, but that
|
# it would be nice if we could also base this on the mappable, but that
|
||||||
# gets really complicated. Devin thinks it's OK to SHOW a mapping for
|
# gets really complicated. Devin thinks it's OK to SHOW a mapping for
|
||||||
# a private topic, since you can't see the private topic anyways
|
# a private topic, since you can't see the private topic anyways
|
||||||
visible = %w(public commons)
|
visible = %w[public commons]
|
||||||
permission = 'maps.permission IN (?)'
|
permission = 'maps.permission IN (?)'
|
||||||
return scope.joins(:map).where(permission, visible) unless user
|
return scope.joins(:map).where(permission, visible) unless user
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class MessagePolicy < ApplicationPolicy
|
class MessagePolicy < ApplicationPolicy
|
||||||
class Scope < Scope
|
class Scope < Scope
|
||||||
def resolve
|
def resolve
|
||||||
visible = %w(public commons)
|
visible = %w[public commons]
|
||||||
permission = 'maps.permission IN (?)'
|
permission = 'maps.permission IN (?)'
|
||||||
return scope.joins(:map).where(permission, visible) unless user
|
return scope.joins(:map).where(permission, visible) unless user
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,21 @@
|
||||||
class SynapsePolicy < ApplicationPolicy
|
class SynapsePolicy < ApplicationPolicy
|
||||||
class Scope < Scope
|
class Scope < Scope
|
||||||
def resolve
|
def resolve
|
||||||
return scope.where(permission: %w(public commons)) unless user
|
return authenticated_scope if user
|
||||||
|
unauthenticated_scope
|
||||||
|
end
|
||||||
|
|
||||||
scope.where(permission: %w(public commons))
|
private
|
||||||
|
|
||||||
|
def authenticated_scope
|
||||||
|
scope.where(permission: %w[public commons])
|
||||||
.or(scope.where(defer_to_map_id: user.all_accessible_maps.map(&:id)))
|
.or(scope.where(defer_to_map_id: user.all_accessible_maps.map(&:id)))
|
||||||
.or(scope.where(user_id: user.id))
|
.or(scope.where(user_id: user.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unauthenticated_scope
|
||||||
|
scope.where(permission: %w[public commons])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def index?
|
def index?
|
||||||
|
|
|
@ -3,12 +3,21 @@
|
||||||
class TopicPolicy < ApplicationPolicy
|
class TopicPolicy < ApplicationPolicy
|
||||||
class Scope < Scope
|
class Scope < Scope
|
||||||
def resolve
|
def resolve
|
||||||
return scope.where(permission: %w(public commons)) unless user
|
return authenticated_scope if user
|
||||||
|
unauthenticated_scope
|
||||||
|
end
|
||||||
|
|
||||||
scope.where(permission: %w(public commons))
|
private
|
||||||
|
|
||||||
|
def authenticated_scope
|
||||||
|
scope.where(permission: %w[public commons])
|
||||||
.or(scope.where(defer_to_map_id: user.all_accessible_maps.map(&:id)))
|
.or(scope.where(defer_to_map_id: user.all_accessible_maps.map(&:id)))
|
||||||
.or(scope.where(user_id: user.id))
|
.or(scope.where(user_id: user.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unauthenticated_scope
|
||||||
|
scope.where(permission: %w[public commons])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def index?
|
def index?
|
||||||
|
@ -23,7 +32,7 @@ class TopicPolicy < ApplicationPolicy
|
||||||
if record.defer_to_map.present?
|
if record.defer_to_map.present?
|
||||||
map_policy.show?
|
map_policy.show?
|
||||||
else
|
else
|
||||||
record.permission.in?(%w(commons public)) || record.user == user
|
record.permission.in?(%w[commons public]) || record.user == user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ module Api
|
||||||
object.image.url(:sixtyfour)
|
object.image.url(:sixtyfour)
|
||||||
end
|
end
|
||||||
|
|
||||||
# rubocop:disable Style/PredicateName
|
|
||||||
def is_admin
|
def is_admin
|
||||||
object.admin
|
object.admin
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,21 +18,21 @@ class FollowService
|
||||||
|
|
||||||
def unfollow(entity, user)
|
def unfollow(entity, user)
|
||||||
follow = Follow.where(followed: entity, user: user).first
|
follow = Follow.where(followed: entity, user: user).first
|
||||||
if follow
|
return unless follow
|
||||||
|
|
||||||
unless follow.update(muted: true)
|
unless follow.update(muted: true)
|
||||||
raise follow.errors.full_messages.join("\n")
|
raise follow.errors.full_messages.join("\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def remove_reason(entity, user, reason)
|
def remove_reason(entity, user, reason)
|
||||||
return unless FollowReason::REASONS.include?(reason)
|
return unless FollowReason::REASONS.include?(reason)
|
||||||
follow = Follow.where(followed: entity, user: user).first
|
follow = Follow.where(followed: entity, user: user).first
|
||||||
if follow
|
return unless follow
|
||||||
|
|
||||||
follow.follow_reason.update_attribute(reason, false)
|
follow.follow_reason.update_attribute(reason, false)
|
||||||
follow.destroy unless follow.follow_reason.has_reason
|
follow.destroy unless follow.follow_reason.has_reason
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
@ -40,17 +40,11 @@ class FollowService
|
||||||
follow = Follow.where(followed: entity, user: user).first
|
follow = Follow.where(followed: entity, user: user).first
|
||||||
return false if follow && follow.muted
|
return false if follow && follow.muted
|
||||||
if entity.class == Topic
|
if entity.class == Topic
|
||||||
if reason == 'created'
|
return user.settings.follow_topic_on_created == '1' if reason == 'created'
|
||||||
return user.settings.follow_topic_on_created == '1'
|
return user.settings.follow_topic_on_contributed == '1' if reason == 'contributed'
|
||||||
elsif reason == 'contributed'
|
|
||||||
return user.settings.follow_topic_on_contributed == '1'
|
|
||||||
end
|
|
||||||
elsif entity.class == Map
|
elsif entity.class == Map
|
||||||
if reason == 'created'
|
return user.settings.follow_map_on_created == '1' if reason == 'created'
|
||||||
return user.settings.follow_map_on_created == '1'
|
return user.settings.follow_map_on_contributed == '1' if reason == 'contributed'
|
||||||
elsif reason == 'contributed'
|
|
||||||
return user.settings.follow_map_on_contributed == '1'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class MapActivityService
|
||||||
'Activity on map ' + map.name
|
'Activity on map ' + map.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.summarize_data(map, user, until_moment = DateTime.now)
|
def self.summarize_data(map, user, until_moment = DateTime.current)
|
||||||
results = {
|
results = {
|
||||||
stats: {}
|
stats: {}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ class MapActivityService
|
||||||
message_count = Message.where(resource: map)
|
message_count = Message.where(resource: map)
|
||||||
.where('created_at > ? AND created_at < ?', since, until_moment)
|
.where('created_at > ? AND created_at < ?', since, until_moment)
|
||||||
.where.not(user: user).count
|
.where.not(user: user).count
|
||||||
results[:stats][:messages_sent] = message_count if message_count > 0
|
results[:stats][:messages_sent] = message_count if message_count.positive?
|
||||||
|
|
||||||
moved_count = Event.where(kind: 'topic_moved_on_map', map: map)
|
moved_count = Event.where(kind: 'topic_moved_on_map', map: map)
|
||||||
.where('created_at > ? AND created_at < ?', since, until_moment)
|
.where('created_at > ? AND created_at < ?', since, until_moment)
|
||||||
|
@ -42,7 +42,9 @@ class MapActivityService
|
||||||
topics_added_events.each do |ta|
|
topics_added_events.each do |ta|
|
||||||
num_adds = topics_added_events.where(eventable_id: ta.eventable_id).count
|
num_adds = topics_added_events.where(eventable_id: ta.eventable_id).count
|
||||||
num_removes = topics_removed_events.where(eventable_id: ta.eventable_id).count
|
num_removes = topics_removed_events.where(eventable_id: ta.eventable_id).count
|
||||||
topics_added_to_include[ta.eventable_id] = ta if num_adds > num_removes && scoped_topic_ids.include?(ta.eventable.id)
|
if num_adds > num_removes && scoped_topic_ids.include?(ta.eventable.id)
|
||||||
|
topics_added_to_include[ta.eventable_id] = ta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
unless topics_added_to_include.keys.empty?
|
unless topics_added_to_include.keys.empty?
|
||||||
results[:stats][:topics_added] = topics_added_to_include.keys.length
|
results[:stats][:topics_added] = topics_added_to_include.keys.length
|
||||||
|
@ -53,7 +55,9 @@ class MapActivityService
|
||||||
topics_removed_events.each do |ta|
|
topics_removed_events.each do |ta|
|
||||||
num_adds = topics_added_events.where(eventable_id: ta.eventable_id).count
|
num_adds = topics_added_events.where(eventable_id: ta.eventable_id).count
|
||||||
num_removes = topics_removed_events.where(eventable_id: ta.eventable_id).count
|
num_removes = topics_removed_events.where(eventable_id: ta.eventable_id).count
|
||||||
topics_removed_to_include[ta.eventable_id] = ta if num_removes > num_adds && TopicPolicy.new(user, ta.eventable).show?
|
if num_removes > num_adds && TopicPolicy.new(user, ta.eventable).show?
|
||||||
|
topics_removed_to_include[ta.eventable_id] = ta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
unless topics_removed_to_include.keys.empty?
|
unless topics_removed_to_include.keys.empty?
|
||||||
results[:stats][:topics_removed] = topics_removed_to_include.keys.length
|
results[:stats][:topics_removed] = topics_removed_to_include.keys.length
|
||||||
|
@ -74,7 +78,9 @@ class MapActivityService
|
||||||
synapses_added_events.each do |ta|
|
synapses_added_events.each do |ta|
|
||||||
num_adds = synapses_added_events.where(eventable_id: ta.eventable_id).count
|
num_adds = synapses_added_events.where(eventable_id: ta.eventable_id).count
|
||||||
num_removes = synapses_removed_events.where(eventable_id: ta.eventable_id).count
|
num_removes = synapses_removed_events.where(eventable_id: ta.eventable_id).count
|
||||||
synapses_added_to_include[ta.eventable_id] = ta if num_adds > num_removes && scoped_synapse_ids.include?(ta.eventable.id)
|
if num_adds > num_removes && scoped_synapse_ids.include?(ta.eventable.id)
|
||||||
|
synapses_added_to_include[ta.eventable_id] = ta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
unless synapses_added_to_include.keys.empty?
|
unless synapses_added_to_include.keys.empty?
|
||||||
results[:stats][:synapses_added] = synapses_added_to_include.keys.length
|
results[:stats][:synapses_added] = synapses_added_to_include.keys.length
|
||||||
|
@ -85,7 +91,9 @@ class MapActivityService
|
||||||
synapses_removed_events.each do |ta|
|
synapses_removed_events.each do |ta|
|
||||||
num_adds = synapses_added_events.where(eventable_id: ta.eventable_id).count
|
num_adds = synapses_added_events.where(eventable_id: ta.eventable_id).count
|
||||||
num_removes = synapses_removed_events.where(eventable_id: ta.eventable_id).count
|
num_removes = synapses_removed_events.where(eventable_id: ta.eventable_id).count
|
||||||
synapses_removed_to_include[ta.eventable_id] = ta if num_removes > num_adds && SynapsePolicy.new(user, ta.eventable).show?
|
if num_removes > num_adds && SynapsePolicy.new(user, ta.eventable).show?
|
||||||
|
synapses_removed_to_include[ta.eventable_id] = ta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
unless synapses_removed_to_include.keys.empty?
|
unless synapses_removed_to_include.keys.empty?
|
||||||
results[:stats][:synapses_removed] = synapses_removed_to_include.keys.length
|
results[:stats][:synapses_removed] = synapses_removed_to_include.keys.length
|
||||||
|
|
|
@ -47,16 +47,16 @@ class MapExportService
|
||||||
private
|
private
|
||||||
|
|
||||||
def topic_headings
|
def topic_headings
|
||||||
%i(id name metacode x y description link user permission)
|
%i[id name metacode x y description link user permission]
|
||||||
end
|
end
|
||||||
|
|
||||||
def synapse_headings
|
def synapse_headings
|
||||||
%i(topic1 topic2 category description user permission)
|
%i[topic1 topic2 category description user permission]
|
||||||
end
|
end
|
||||||
|
|
||||||
def exportable_topics
|
def exportable_topics
|
||||||
visible_topics ||= Pundit.policy_scope!(user, map.topics)
|
visible_topics ||= Pundit.policy_scope!(user, map.topics)
|
||||||
topic_mappings = Mapping.includes(mappable: %i(metacode user))
|
topic_mappings = Mapping.includes(mappable: %i[metacode user])
|
||||||
.where(mappable: visible_topics, map: map)
|
.where(mappable: visible_topics, map: map)
|
||||||
topic_mappings.map do |mapping|
|
topic_mappings.map do |mapping|
|
||||||
topic = mapping.mappable
|
topic = mapping.mappable
|
||||||
|
|
|
@ -7,7 +7,7 @@ class NotificationService
|
||||||
include ActionView::Helpers::SanitizeHelper
|
include ActionView::Helpers::SanitizeHelper
|
||||||
|
|
||||||
def self.renderer
|
def self.renderer
|
||||||
renderer ||= ApplicationController.renderer.new(
|
@renderer ||= ApplicationController.renderer.new(
|
||||||
http_host: ENV['MAILER_DEFAULT_URL'],
|
http_host: ENV['MAILER_DEFAULT_URL'],
|
||||||
https: Rails.env.production? ? true : false
|
https: Rails.env.production? ? true : false
|
||||||
)
|
)
|
||||||
|
@ -70,19 +70,25 @@ class NotificationService
|
||||||
|
|
||||||
def self.access_request(request)
|
def self.access_request(request)
|
||||||
subject = access_request_subject(request.map)
|
subject = access_request_subject(request.map)
|
||||||
body = renderer.render(template: 'map_mailer/access_request', locals: { map: request.map, request: request }, layout: false)
|
body = renderer.render(template: 'map_mailer/access_request',
|
||||||
|
locals: { map: request.map, request: request },
|
||||||
|
layout: false)
|
||||||
request.map.user.notify(subject, body, request, false, MAP_ACCESS_REQUEST, true, request.user)
|
request.map.user.notify(subject, body, request, false, MAP_ACCESS_REQUEST, true, request.user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.access_approved(request)
|
def self.access_approved(request)
|
||||||
subject = access_approved_subject(request.map)
|
subject = access_approved_subject(request.map)
|
||||||
body = renderer.render(template: 'map_mailer/access_approved', locals: { map: request.map }, layout: false)
|
body = renderer.render(template: 'map_mailer/access_approved',
|
||||||
|
locals: { map: request.map },
|
||||||
|
layout: false)
|
||||||
request.user.notify(subject, body, request, false, MAP_ACCESS_APPROVED, true, request.map.user)
|
request.user.notify(subject, body, request, false, MAP_ACCESS_APPROVED, true, request.map.user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.invite_to_edit(user_map)
|
def self.invite_to_edit(user_map)
|
||||||
subject = invite_to_edit_subject(user_map.map)
|
subject = invite_to_edit_subject(user_map.map)
|
||||||
body = renderer.render(template: 'map_mailer/invite_to_edit', locals: { map: user_map.map, inviter: user_map.map.user }, layout: false)
|
body = renderer.render(template: 'map_mailer/invite_to_edit',
|
||||||
|
locals: { map: user_map.map, inviter: user_map.map.user },
|
||||||
|
layout: false)
|
||||||
user_map.user.notify(subject, body, user_map, false, MAP_INVITE_TO_EDIT, true, user_map.map.user)
|
user_map.user.notify(subject, body, user_map, false, MAP_INVITE_TO_EDIT, true, user_map.map.user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class Perm
|
class Perm
|
||||||
# e.g. Perm::ISSIONS
|
# e.g. Perm::ISSIONS
|
||||||
ISSIONS = %i(commons public private).freeze
|
ISSIONS = %i[commons public private].freeze
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def short(permission)
|
def short(permission)
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<% $i = 0 %>
|
<% $i = 0 %>
|
||||||
<% @m = Metacode.order("name").all %>
|
<% @m = Metacode.order("name").all %>
|
||||||
<% while $i < (Metacode.all.length / 4) do %>
|
<% while $i < (Metacode.all.length / 4) do %>
|
||||||
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
|
<li id="<%= @m[$i].id %>" <% if not @m[$i].in_metacode_set(@metacode_set) %>class="toggledOff"<% end %>
|
||||||
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
||||||
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
||||||
<p><%= @m[$i].name.downcase %></p>
|
<p><%= @m[$i].name.downcase %></p>
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="filters-two">
|
<ul id="filters-two">
|
||||||
<% while $i < (Metacode.all.length / 4 * 2) do %>
|
<% while $i < (Metacode.all.length / 4 * 2) do %>
|
||||||
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
|
<li id="<%= @m[$i].id %>" <% if not @m[$i].in_metacode_set(@metacode_set) %>class="toggledOff"<% end %>
|
||||||
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
||||||
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
||||||
<p><%= @m[$i].name.downcase %></p>
|
<p><%= @m[$i].name.downcase %></p>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="filters-three">
|
<ul id="filters-three">
|
||||||
<% while $i < (Metacode.all.length / 4 * 3) do %>
|
<% while $i < (Metacode.all.length / 4 * 3) do %>
|
||||||
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
|
<li id="<%= @m[$i].id %>" <% if not @m[$i].in_metacode_set(@metacode_set) %>class="toggledOff"<% end %>
|
||||||
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
||||||
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
||||||
<p><%= @m[$i].name.downcase %></p>
|
<p><%= @m[$i].name.downcase %></p>
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="filters-four">
|
<ul id="filters-four">
|
||||||
<% while $i < Metacode.all.length do %>
|
<% while $i < Metacode.all.length do %>
|
||||||
<li id="<%= @m[$i].id %>" <% if not @m[$i].inMetacodeSet(@metacode_set) %>class="toggledOff"<% end %>
|
<li id="<%= @m[$i].id %>" <% if not @m[$i].in_metacode_set(@metacode_set) %>class="toggledOff"<% end %>
|
||||||
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
onclick="Metamaps.Admin.liClickHandler.call(this);">
|
||||||
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
<img src="<%= asset_path @m[$i].icon %>" alt="<%= @m[$i].name %>" />
|
||||||
<p><%= @m[$i].name.downcase %></p>
|
<p><%= @m[$i].name.downcase %></p>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
<% Metacode.all.each do |m| %>
|
<% Metacode.all.each do |m| %>
|
||||||
<% if m.inMetacodeSet(@metacode_set) %>
|
<% if m.in_metacode_set(@metacode_set) %>
|
||||||
Metamaps.Admin.selectMetacodes.push("<%= m.id %>");
|
Metamaps.Admin.selectMetacodes.push("<%= m.id %>");
|
||||||
<% end %>
|
<% end %>
|
||||||
Metamaps.Admin.allMetacodes.push("<%= m.id %>");
|
Metamaps.Admin.allMetacodes.push("<%= m.id %>");
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
<% Metacode.all.each do |m| %>
|
<% Metacode.all.each do |m| %>
|
||||||
<% if m.inMetacodeSet(@metacode_set) %>
|
<% if m.in_metacode_set(@metacode_set) %>
|
||||||
Metamaps.Admin.selectMetacodes.push("<%= m.id %>");
|
Metamaps.Admin.selectMetacodes.push("<%= m.id %>");
|
||||||
<% end %>
|
<% end %>
|
||||||
Metamaps.Admin.allMetacodes.push("<%= m.id %>");
|
Metamaps.Admin.allMetacodes.push("<%= m.id %>");
|
||||||
|
|
|
@ -25,7 +25,7 @@ Rails.application.configure do
|
||||||
# Print deprecation notices to the Rails logger
|
# Print deprecation notices to the Rails logger
|
||||||
config.active_support.deprecation = :log
|
config.active_support.deprecation = :log
|
||||||
|
|
||||||
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"
|
config.action_mailer.preview_path = Rails.root.join('spec', 'mailers', 'previews')
|
||||||
|
|
||||||
# Expands the lines which load the assets
|
# Expands the lines which load the assets
|
||||||
config.assets.debug = false
|
config.assets.debug = false
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
Rails.application.configure do
|
Rails.application.configure do
|
||||||
# Settings specified here will take precedence over those in config/application.rb
|
# Settings specified here will take precedence over those in config/application.rb
|
||||||
|
|
||||||
config.action_cable.allowed_request_origins = ['https://metamaps.herokuapp.com', 'http://metamaps.herokuapp.com', 'https://metamaps.cc']
|
config.action_cable.allowed_request_origins = [
|
||||||
|
'https://metamaps.herokuapp.com', 'http://metamaps.herokuapp.com', 'https://metamaps.cc'
|
||||||
|
]
|
||||||
|
|
||||||
# log to stdout
|
# log to stdout
|
||||||
logger = Logger.new(STDOUT)
|
logger = Logger.new(STDOUT)
|
||||||
|
|
|
@ -10,5 +10,5 @@ Rails.application.configure do
|
||||||
|
|
||||||
# Precompile additional assets.
|
# Precompile additional assets.
|
||||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||||
config.assets.precompile += %w(application-secret.css application-secret.js webpacked/metamaps.bundle.js)
|
config.assets.precompile += %w[application-secret.css application-secret.js webpacked/metamaps.bundle.js]
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,6 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do
|
||||||
origins '*'
|
origins '*'
|
||||||
resource '/api/*',
|
resource '/api/*',
|
||||||
headers: :any,
|
headers: :any,
|
||||||
methods: %i(get post put delete options head)
|
methods: %i[get post put delete options head]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,4 +11,4 @@ Delayed::Worker.class_eval do
|
||||||
prepend ExceptionNotifierInDelayedJob
|
prepend ExceptionNotifierInDelayedJob
|
||||||
end
|
end
|
||||||
|
|
||||||
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
|
Delayed::Worker.logger = Logger.new(Rails.root.join('log', 'delayed_job.log'))
|
||||||
|
|
|
@ -51,11 +51,11 @@ ExceptionNotification.configure do |config|
|
||||||
# Ignore additional exception types.
|
# Ignore additional exception types.
|
||||||
# ActiveRecord::RecordNotFound, AbstractController::ActionNotFound and
|
# ActiveRecord::RecordNotFound, AbstractController::ActionNotFound and
|
||||||
# ActionController::RoutingError are already added.
|
# ActionController::RoutingError are already added.
|
||||||
config.ignored_exceptions += %w(
|
config.ignored_exceptions += %w[
|
||||||
ActionView::TemplateError CustomError UnauthorizedException
|
ActionView::TemplateError CustomError UnauthorizedException
|
||||||
InvalidArgumentException InvalidEntityException InvalidRequestException
|
InvalidArgumentException InvalidEntityException InvalidRequestException
|
||||||
NotFoundException ValidationException
|
NotFoundException ValidationException
|
||||||
)
|
]
|
||||||
|
|
||||||
# Adds a condition to decide when an exception must be ignored or not.
|
# Adds a condition to decide when an exception must be ignored or not.
|
||||||
# The ignore_if method can be invoked multiple times to add extra conditions.
|
# The ignore_if method can be invoked multiple times to add extra conditions.
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
def is_tester(user)
|
def is_tester(user)
|
||||||
user && %w(connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com ishanshapiro@gmail.com).include?(user.email)
|
user && %w[
|
||||||
|
connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com
|
||||||
|
ishanshapiro@gmail.com
|
||||||
|
].include?(user.email)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
METAMAPS_VERSION = '3.5'
|
METAMAPS_VERSION = '3..6.1'
|
||||||
METAMAPS_BUILD = `git log -1 --pretty=%H`.chomp[0..11].freeze
|
METAMAPS_BUILD = `git log -1 --pretty=%H`.chomp[0..11].freeze
|
||||||
METAMAPS_LAST_UPDATED = `git log -1 --pretty='%ad'`.split(' ').values_at(1, 2, 4).join(' ').freeze
|
METAMAPS_LAST_UPDATED = `git log -1 --pretty='%ad'`.split(' ').values_at(1, 2, 4).join(' ').freeze
|
||||||
|
|
|
@ -17,7 +17,7 @@ Metamaps::Application.routes.draw do
|
||||||
end
|
end
|
||||||
get :explore, to: redirect('/')
|
get :explore, to: redirect('/')
|
||||||
|
|
||||||
resources :maps, except: %i(index edit) do
|
resources :maps, except: %i[index edit] do
|
||||||
member do
|
member do
|
||||||
get :conversation
|
get :conversation
|
||||||
get :export
|
get :export
|
||||||
|
@ -55,10 +55,10 @@ Metamaps::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :mappings, except: %i(index new edit)
|
resources :mappings, except: %i[index new edit]
|
||||||
|
|
||||||
resources :messages, only: %i(show create update destroy)
|
resources :messages, only: %i[show create update destroy]
|
||||||
resources :notifications, only: %i(index show) do
|
resources :notifications, only: %i[index show] do
|
||||||
collection do
|
collection do
|
||||||
get :unsubscribe
|
get :unsubscribe
|
||||||
end
|
end
|
||||||
|
@ -80,9 +80,9 @@ Metamaps::Application.routes.draw do
|
||||||
get :synapses
|
get :synapses
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :synapses, except: %i(index new edit)
|
resources :synapses, except: %i[index new edit]
|
||||||
|
|
||||||
resources :topics, except: %i(index new edit) do
|
resources :topics, except: %i[index new edit] do
|
||||||
member do
|
member do
|
||||||
get :network
|
get :network
|
||||||
get :relative_numbers
|
get :relative_numbers
|
||||||
|
@ -111,7 +111,7 @@ Metamaps::Application.routes.draw do
|
||||||
get 'join' => 'users/registrations#new', :as => :sign_up
|
get 'join' => 'users/registrations#new', :as => :sign_up
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :users, except: %i(index destroy) do
|
resources :users, except: %i[index destroy] do
|
||||||
member do
|
member do
|
||||||
get :details
|
get :details
|
||||||
end
|
end
|
||||||
|
@ -121,16 +121,16 @@ Metamaps::Application.routes.draw do
|
||||||
|
|
||||||
namespace :api, path: '/api', default: { format: :json } do
|
namespace :api, path: '/api', default: { format: :json } do
|
||||||
namespace :v2, path: '/v2' do
|
namespace :v2, path: '/v2' do
|
||||||
resources :metacodes, only: %i(index show)
|
resources :metacodes, only: %i[index show]
|
||||||
resources :mappings, only: %i(index create show update destroy)
|
resources :mappings, only: %i[index create show update destroy]
|
||||||
resources :maps, only: %i(index create show update destroy) do
|
resources :maps, only: %i[index create show update destroy] do
|
||||||
post :stars, to: 'stars#create', on: :member
|
post :stars, to: 'stars#create', on: :member
|
||||||
delete :stars, to: 'stars#destroy', on: :member
|
delete :stars, to: 'stars#destroy', on: :member
|
||||||
end
|
end
|
||||||
resources :synapses, only: %i(index create show update destroy)
|
resources :synapses, only: %i[index create show update destroy]
|
||||||
resources :tokens, only: %i(index create destroy)
|
resources :tokens, only: %i[index create destroy]
|
||||||
resources :topics, only: %i(index create show update destroy)
|
resources :topics, only: %i[index create show update destroy]
|
||||||
resources :users, only: %i(index show) do
|
resources :users, only: %i[index show] do
|
||||||
get :current, on: :collection
|
get :current, on: :collection
|
||||||
end
|
end
|
||||||
match '*path', to: 'restful#catch_404', via: :all
|
match '*path', to: 'restful#catch_404', via: :all
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
%w(
|
%w[
|
||||||
.ruby-version
|
.ruby-version
|
||||||
.ruby-gemset
|
.ruby-gemset
|
||||||
.rbenv-vars
|
.rbenv-vars
|
||||||
tmp/restart.txt
|
tmp/restart.txt
|
||||||
tmp/caching-dev.txt
|
tmp/caching-dev.txt
|
||||||
).each { |path| Spring.watch(path) }
|
].each { |path| Spring.watch(path) }
|
||||||
|
|
|
@ -26,13 +26,13 @@ At the time of writing, there are four directories in the spec folder. One,
|
||||||
`support`, is for helper functions. `rails_helper.rb` and `spec_helper.rb` are
|
`support`, is for helper functions. `rails_helper.rb` and `spec_helper.rb` are
|
||||||
also for helper functions.
|
also for helper functions.
|
||||||
|
|
||||||
`factories` is for a gem called [factory-girl][factory-girl]. This gem lets you
|
`factories` is for a gem called [factory-bot][factory_bot]. This gem lets you
|
||||||
use the `create` and `build` functions to quickly create the simplest possible
|
use the `create` and `build` functions to quickly create the simplest possible
|
||||||
valid version of a given model. For instance:
|
valid version of a given model. For instance:
|
||||||
|
|
||||||
let(:map1) { create :map }
|
let(:map1) { create :map }
|
||||||
let(:ronald) { create :user, name: "Ronald" }
|
let(:alex) { create :user, name: "Alex" }
|
||||||
let(:map2) { create :map, user: ronald }
|
let(:map2) { create :map, user: alex }
|
||||||
|
|
||||||
As you can see, you can also customize the factories. You can read the full
|
As you can see, you can also customize the factories. You can read the full
|
||||||
documentation at the link above or check the existing specs to see how it works.
|
documentation at the link above or check the existing specs to see how it works.
|
||||||
|
@ -53,5 +53,5 @@ the added code works. This will help in a few ways:
|
||||||
|
|
||||||
Happy testing!
|
Happy testing!
|
||||||
|
|
||||||
[factory-girl]: https://github.com/thoughtbot/factory_girl
|
[factory-bot]: https://github.com/thoughtbot/factory_bot
|
||||||
[rspec-docs]: http://rspec.info
|
[rspec-docs]: http://rspec.info
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const Debug = function(arg = window.Metamaps) {
|
const Debug = function(arg = window.Metamaps) {
|
||||||
if (arg === undefined && typeof window !== 'undefined') arg = window.Metamaps
|
if (arg === undefined && typeof window !== 'undefined') arg = window.Metamaps
|
||||||
console.debug(arg)
|
console.log(arg)
|
||||||
console.debug(`Metamaps Version: ${arg.ServerData.VERSION}`)
|
console.log(`Metamaps Version: ${arg.ServerData.VERSION}`)
|
||||||
console.debug(`Build: ${arg.ServerData.BUILD}`)
|
console.log(`Build: ${arg.ServerData.BUILD}`)
|
||||||
console.debug(`Last Updated: ${arg.ServerData.LAST_UPDATED}`)
|
console.log(`Last Updated: ${arg.ServerData.LAST_UPDATED}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Debug
|
export default Debug
|
||||||
|
|
|
@ -15,10 +15,6 @@ class Permission extends Component {
|
||||||
this.setState({selectingPermission: !this.state.selectingPermission})
|
this.setState({selectingPermission: !this.state.selectingPermission})
|
||||||
}
|
}
|
||||||
|
|
||||||
openPermissionSelect = () => {
|
|
||||||
this.setState({selectingPermission: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
closePermissionSelect = () => {
|
closePermissionSelect = () => {
|
||||||
this.setState({selectingPermission: false})
|
this.setState({selectingPermission: false})
|
||||||
}
|
}
|
||||||
|
@ -67,4 +63,5 @@ Permission.propTypes = {
|
||||||
updateTopic: PropTypes.func
|
updateTopic: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { Permission } // for testing
|
||||||
export default onClickOutsideAddon(Permission)
|
export default onClickOutsideAddon(Permission)
|
||||||
|
|
99
frontend/test/components/TopicCard/Desc.spec.js
Normal file
99
frontend/test/components/TopicCard/Desc.spec.js
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import Desc from '../../../src/components/TopicCard/Desc.js'
|
||||||
|
|
||||||
|
function render(props) {
|
||||||
|
return shallow(<Desc {...props} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sharedAssertions(wrapper, desc, { descProp }) {
|
||||||
|
it('renders the correct wrapping html', function() {
|
||||||
|
expect(wrapper.find('.scroll').length).to.equal(1)
|
||||||
|
expect(wrapper.find('.scroll').find('.desc').length).to.equal(1)
|
||||||
|
})
|
||||||
|
it('renders the description', function() {
|
||||||
|
expect(wrapper
|
||||||
|
.find('.scroll')
|
||||||
|
.find('.desc')
|
||||||
|
.find('.riek_desc')
|
||||||
|
.prop(descProp)).to.equal(desc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TopicCard/Desc', function() {
|
||||||
|
const desc = 'sample description'
|
||||||
|
describe('not authorized to edit', function() {
|
||||||
|
const wrapper = render({ authorizedToEdit: false, desc })
|
||||||
|
sharedAssertions(wrapper, desc, { descProp: 'children' })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authorized to edit', function() {
|
||||||
|
const onChange = sinon.spy()
|
||||||
|
const wrapper = render({ authorizedToEdit: true, desc, onChange })
|
||||||
|
sharedAssertions(wrapper, desc, { descProp: 'value' })
|
||||||
|
|
||||||
|
it('renders mdSupport', function() {
|
||||||
|
const mdSupport = wrapper.find('.desc').childAt(1)
|
||||||
|
expect(mdSupport.prop('className')).to.equal('mdSupport')
|
||||||
|
expect(mdSupport.prop('href')).to.include('commonmark.org/help')
|
||||||
|
expect(mdSupport.prop('target')).to.equal('_blank')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders clearfloat', function() {
|
||||||
|
const clearfloat = wrapper.find('.desc').childAt(2)
|
||||||
|
expect(clearfloat.prop('className')).to.equal('clearfloat')
|
||||||
|
})
|
||||||
|
|
||||||
|
const textArea = wrapper.find('.riek_desc')
|
||||||
|
it('has the correct classEditing', function() {
|
||||||
|
expect(textArea.prop('classEditing')).to.equal('riek-editing')
|
||||||
|
})
|
||||||
|
it('has 6 rows', function() {
|
||||||
|
expect(textArea.prop('rows')).to.equal('6')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('defaultProps', function() {
|
||||||
|
describe('desc is present', function() {
|
||||||
|
const textArea = render({
|
||||||
|
authorizedToEdit: true, desc: '**sample description 2**'
|
||||||
|
}).find('.riek_desc')
|
||||||
|
|
||||||
|
// TODO I'd prefer to be mocking Util.mdToHTML
|
||||||
|
it('converts markdown to html', function() {
|
||||||
|
expect(textArea.prop('defaultProps').dangerouslySetInnerHTML.__html)
|
||||||
|
.to.equal('<p><strong>sample description 2</strong></p>\n')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('desc is not present', function() {
|
||||||
|
const textArea = render({ authorizedToEdit: true, desc: null })
|
||||||
|
.find('.riek_desc')
|
||||||
|
it('renders placeholder message', function() {
|
||||||
|
expect(textArea.prop('defaultProps').dangerouslySetInnerHTML.__html)
|
||||||
|
.to.equal('<p class="emptyDesc">Edit the description... (supports markdown)</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('editProps', function() {
|
||||||
|
const ENTER = 13
|
||||||
|
const target = { value: 'new value' }
|
||||||
|
it('does not call onChange on Shift+Enter', function() {
|
||||||
|
textArea.prop('editProps').onKeyPress({
|
||||||
|
shiftKey: true, which: ENTER
|
||||||
|
})
|
||||||
|
expect(onChange.notCalled).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls onChange on ENTER', function() {
|
||||||
|
textArea.prop('editProps').onKeyPress({
|
||||||
|
which: ENTER, preventDefault: () => {}, target
|
||||||
|
})
|
||||||
|
expect(onChange.calledWith({ desc: 'new value' })).to.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
95
frontend/test/components/TopicCard/Permission.spec.js
Normal file
95
frontend/test/components/TopicCard/Permission.spec.js
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import PermissionWrapper, { Permission } from '../../../src/components/TopicCard/Permission.js'
|
||||||
|
|
||||||
|
function render(props) {
|
||||||
|
return shallow(<Permission {...props} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sharedAssertions(permission) {
|
||||||
|
describe(permission, function() {
|
||||||
|
const shortname = permission === 'commons' ? 'co'
|
||||||
|
: permission === 'public' ? 'pu'
|
||||||
|
: permission === 'private' ? 'pr'
|
||||||
|
: new Error('invalid permission')
|
||||||
|
const wrapper = render({ permission })
|
||||||
|
|
||||||
|
it('has the correct css classes', function() {
|
||||||
|
expect(wrapper.find(`.${shortname}`).props().className).to.include('linkItem')
|
||||||
|
expect(wrapper.find(`.${shortname}`).props().className).to.include('mapPerm')
|
||||||
|
})
|
||||||
|
it('sets the title', function() {
|
||||||
|
expect(wrapper.find(`.${shortname}`).props().title).to.include(permission)
|
||||||
|
})
|
||||||
|
it('has correct permission select options', function() {
|
||||||
|
expect(wrapper.find('.permissionSelect').find('.commons').length)
|
||||||
|
.to.equal(permission === 'commons' ? 0 : 1)
|
||||||
|
expect(wrapper.find('.permissionSelect').find('.public').length)
|
||||||
|
.to.equal(permission === 'public' ? 0 : 1)
|
||||||
|
expect(wrapper.find('.permissionSelect').find('.private').length)
|
||||||
|
.to.equal(permission === 'private' ? 0 : 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TopicCard/Permission', function() {
|
||||||
|
sharedAssertions('commons')
|
||||||
|
sharedAssertions('public')
|
||||||
|
sharedAssertions('private')
|
||||||
|
|
||||||
|
describe('not authorizedToEdit', function() {
|
||||||
|
const togglePermissionSelect = sinon.spy()
|
||||||
|
const wrapper = render({
|
||||||
|
permission: 'commons', authorizedToEdit: false, togglePermissionSelect
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides the permissionSelect div', function() {
|
||||||
|
expect(wrapper.find('.permissionSelect').props().style.display)
|
||||||
|
.to.equal('none')
|
||||||
|
})
|
||||||
|
it("doesn't open the permissionSelect div", function() {
|
||||||
|
wrapper.find('.linkItem').simulate('click')
|
||||||
|
expect(togglePermissionSelect.notCalled).to.equal(true)
|
||||||
|
expect(wrapper.state().selectingPermission).to.equal(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authorizedToEdit', function() {
|
||||||
|
const updateTopic = sinon.spy()
|
||||||
|
const wrapper = render({
|
||||||
|
permission: 'commons', authorizedToEdit: true, updateTopic
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens the permissionSelect div', function() {
|
||||||
|
wrapper.setState({ selectingPermission: false })
|
||||||
|
|
||||||
|
wrapper.find('.linkItem').simulate('click')
|
||||||
|
|
||||||
|
expect(wrapper.state().selectingPermission).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updates the topic permissions', function() {
|
||||||
|
wrapper.setState({ selectingPermission: true })
|
||||||
|
|
||||||
|
wrapper.find('.permissionSelect').find('.public').simulate('click', {
|
||||||
|
preventDefault: () => {}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.state().selectingPermission).to.equal(false)
|
||||||
|
expect(updateTopic.calledWith({
|
||||||
|
permission: 'public', defer_to_map_id: null
|
||||||
|
})).to.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('PermissionWrapper', function() {
|
||||||
|
const wrapper = shallow(<PermissionWrapper />)
|
||||||
|
it('wraps Permission component in onclickoutside', function() {
|
||||||
|
expect(wrapper.type()).to.equal(Permission)
|
||||||
|
})
|
||||||
|
})
|
68
frontend/test/components/TopicCard/Title.spec.js
Normal file
68
frontend/test/components/TopicCard/Title.spec.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import { RIETextArea } from 'riek'
|
||||||
|
|
||||||
|
import Title from '../../../src/components/TopicCard/Title.js'
|
||||||
|
|
||||||
|
function render(props) {
|
||||||
|
return shallow(<Title {...props} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = 'name 1'
|
||||||
|
|
||||||
|
function assertParentTitleSpan(wrapper) {
|
||||||
|
it('wraps everything in span.title', function() {
|
||||||
|
expect(wrapper.props().className).to.equal('title')
|
||||||
|
expect(wrapper.type()).to.equal('span')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TopicCard/Title', function() {
|
||||||
|
describe('not authorized to edit', function() {
|
||||||
|
const wrapper = render({ authorizedToEdit: false, name })
|
||||||
|
|
||||||
|
assertParentTitleSpan(wrapper)
|
||||||
|
|
||||||
|
it('renders the name in span.titleWrapper', function() {
|
||||||
|
expect(wrapper.find('.titleWrapper').text()).to.have.string(name)
|
||||||
|
expect(wrapper.find('.titleWrapper').type()).to.equal('span')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authorized to edit', function() {
|
||||||
|
const onChange = sinon.spy()
|
||||||
|
const wrapper = render({ authorizedToEdit: true, onChange, name })
|
||||||
|
const textArea = wrapper.find('.titleWrapper')
|
||||||
|
|
||||||
|
assertParentTitleSpan(wrapper)
|
||||||
|
|
||||||
|
it('renders RIETextArea with correct value', function() {
|
||||||
|
expect(textArea.type()).to.equal(RIETextArea)
|
||||||
|
expect(textArea.props().value).to.equal(name)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('RIETextArea props are correct', function() {
|
||||||
|
expect(textArea.props().id).to.equal('titleActivator')
|
||||||
|
expect(textArea.props().classEditing).to.equal('riek-editing')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls onChange on Enter', function() {
|
||||||
|
// simulate pressing Enter
|
||||||
|
textArea.props().editProps.onKeyPress({
|
||||||
|
which: 13, preventDefault: () => {}, target: { value: 'new name' }
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(onChange.calledOnce).to.equal(true)
|
||||||
|
expect(onChange.calledWithExactly({ name: 'new name' }))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders a namecounter', function() {
|
||||||
|
expect(wrapper.find('.nameCounter').props().className).to.equal('nameCounter')
|
||||||
|
expect(wrapper.find('.nameCounter').text()).to.have.string(`${name.length}/140`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
108
frontend/test/components/TopicCard/index.spec.js
Normal file
108
frontend/test/components/TopicCard/index.spec.js
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import ReactTopicCard from '../../../src/components/TopicCard/index.js'
|
||||||
|
import Links from '../../../src/components/TopicCard/Links.js'
|
||||||
|
import Title from '../../../src/components/TopicCard/Title.js'
|
||||||
|
import Desc from '../../../src/components/TopicCard/Desc.js'
|
||||||
|
import Attachments from '../../../src/components/TopicCard/Attachments.js'
|
||||||
|
import Info from '../../../src/components/TopicCard/Info.js'
|
||||||
|
|
||||||
|
const currentUser = { current: 'user' }
|
||||||
|
|
||||||
|
function render(props) {
|
||||||
|
return shallow(<ReactTopicCard {...props} currentUser={currentUser} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockTopic({ hasAttachment, canEdit, isOwner }) {
|
||||||
|
const get = sinon.stub()
|
||||||
|
if (hasAttachment) {
|
||||||
|
get.withArgs('link').returns('https://www.google.ca')
|
||||||
|
} else {
|
||||||
|
get.withArgs('link').returns('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const authorizeToEdit = sinon.stub()
|
||||||
|
authorizeToEdit.withArgs(currentUser).returns(canEdit)
|
||||||
|
|
||||||
|
const authorizePermissionChange = sinon.stub()
|
||||||
|
authorizePermissionChange.withArgs(currentUser).returns(isOwner)
|
||||||
|
|
||||||
|
return {
|
||||||
|
get,
|
||||||
|
authorizeToEdit,
|
||||||
|
authorizePermissionChange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertCssClassPresent({ mockTopicParam, mockTopicValue, cssClass }) {
|
||||||
|
const topic = mockTopic({ [mockTopicParam]: mockTopicValue })
|
||||||
|
const wrapper = render({ openTopic: topic })
|
||||||
|
it(`correctly shows ${cssClass} css class`, function() {
|
||||||
|
expect(wrapper.find(`.${cssClass}`).length).to.equal(1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TopicCard', function() {
|
||||||
|
describe('topic is null', function() {
|
||||||
|
const wrapper = render({ openTopic: null })
|
||||||
|
it('returns null', function() {
|
||||||
|
expect(wrapper.type()).to.be.null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('has attachment', function() {
|
||||||
|
assertCssClassPresent({ mockTopicParam: 'hasAttachment', mockTopicValue: true, cssClass: 'hasAttachment' })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authorized to edit', function() {
|
||||||
|
assertCssClassPresent({ mockTopicParam: 'canEdit', mockTopicValue: true, cssClass: 'canEdit' })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('not authorized to edit', function() {
|
||||||
|
assertCssClassPresent({ mockTopicParam: 'canEdit', mockTopicValue: false, cssClass: 'cannotEdit' })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('topic is owned by current user', function() {
|
||||||
|
assertCssClassPresent({ mockTopicParam: 'isOwner', mockTopicValue: true, cssClass: 'yourTopic' })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Draggable wrapper', function() {
|
||||||
|
const wrapper = render({ openTopic: mockTopic({}) })
|
||||||
|
it('handle is metacodeImage', function() {
|
||||||
|
expect(wrapper.props().handle).to.equal('.metacodeImage')
|
||||||
|
})
|
||||||
|
it('default position is 100, 100', function() {
|
||||||
|
expect(wrapper.props().defaultPosition.x).to.equal(100)
|
||||||
|
expect(wrapper.props().defaultPosition.y).to.equal(100)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('content', function() {
|
||||||
|
const wrapper = render({ openTopic: mockTopic({}) })
|
||||||
|
const innerDiv = wrapper.find('.CardOnGraph')
|
||||||
|
it('renders a Links component', function() {
|
||||||
|
expect(innerDiv.childAt(0).type()).to.equal(Links)
|
||||||
|
})
|
||||||
|
it('renders a Title component', function() {
|
||||||
|
expect(innerDiv.childAt(1).type()).to.equal(Title)
|
||||||
|
})
|
||||||
|
it('renders a Desc component', function() {
|
||||||
|
expect(innerDiv.childAt(2).type()).to.equal(Desc)
|
||||||
|
})
|
||||||
|
it('renders a Attachments component', function() {
|
||||||
|
expect(innerDiv.childAt(3).type()).to.equal(Attachments)
|
||||||
|
})
|
||||||
|
it('renders a Info component', function() {
|
||||||
|
expect(innerDiv.childAt(4).type()).to.equal(Info)
|
||||||
|
})
|
||||||
|
it('renders a clearfloat div at the end', function() {
|
||||||
|
const div = innerDiv.childAt(5)
|
||||||
|
expect(div.type()).to.equal('div')
|
||||||
|
expect(div.props().className).to.have.string('clearfloat')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -15,7 +15,7 @@ RSpec.describe ExploreController, type: :controller do
|
||||||
expect(JSON.parse(response.body)).to eq []
|
expect(JSON.parse(response.body)).to eq []
|
||||||
end
|
end
|
||||||
it 'with 1 record' do
|
it 'with 1 record' do
|
||||||
map = create(:map)
|
create(:map)
|
||||||
get :active, format: :json
|
get :active, format: :json
|
||||||
expect(JSON.parse(response.body).class).to be Array
|
expect(JSON.parse(response.body).class).to be Array
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,7 +40,10 @@ RSpec.describe SynapsesController, type: :controller do
|
||||||
context 'with private topics' do
|
context 'with private topics' do
|
||||||
it 'redirects to /' do
|
it 'redirects to /' do
|
||||||
post :create, format: :json, params: {
|
post :create, format: :json, params: {
|
||||||
synapse: valid_attributes.merge(topic1_id: create(:topic, permission: 'private'), topic2_id: create(:topic, permission: 'private'))
|
synapse: valid_attributes.merge(
|
||||||
|
topic1_id: create(:topic, permission: 'private'),
|
||||||
|
topic2_id: create(:topic, permission: 'private')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
expect(response.status).to eq 302
|
expect(response.status).to eq 302
|
||||||
expect(response).to redirect_to('/')
|
expect(response).to redirect_to('/')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :access_request do
|
factory :access_request do
|
||||||
map
|
map
|
||||||
user
|
user
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :mapping do
|
factory :mapping do
|
||||||
xloc 0
|
xloc 0
|
||||||
yloc 0
|
yloc 0
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :map do
|
factory :map do
|
||||||
sequence(:name) { |n| "Cool Map ##{n}" }
|
sequence(:name) { |n| "Cool Map ##{n}" }
|
||||||
permission :commons
|
permission :commons
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :message do
|
factory :message do
|
||||||
association :resource, factory: :map
|
association :resource, factory: :map
|
||||||
user
|
user
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :metacode do
|
factory :metacode do
|
||||||
sequence(:name) { |n| "Cool Metacode ##{n}" }
|
sequence(:name) { |n| "Cool Metacode ##{n}" }
|
||||||
manual_icon 'https://images.com/image.png'
|
manual_icon 'https://images.com/image.png'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :star do
|
factory :star do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :synapse do
|
factory :synapse do
|
||||||
sequence(:desc) { |n| "Cool synapse ##{n}" }
|
sequence(:desc) { |n| "Cool synapse ##{n}" }
|
||||||
category :'from-to'
|
category :'from-to'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :token do
|
factory :token do
|
||||||
user
|
user
|
||||||
description ''
|
description ''
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :topic do
|
factory :topic do
|
||||||
user
|
user
|
||||||
association :updated_by, factory: :user
|
association :updated_by, factory: :user
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :user_map do
|
factory :user_map do
|
||||||
map
|
map
|
||||||
user
|
user
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
# have actual codes, you'll need to specify one simple_user and then you
|
# have actual codes, you'll need to specify one simple_user and then you
|
||||||
# can specify other :code_user users based on the pre-existing user's code.
|
# can specify other :code_user users based on the pre-existing user's code.
|
||||||
|
|
||||||
FactoryGirl.define do
|
FactoryBot.define do
|
||||||
factory :code_user, class: User do
|
factory :code_user, class: User do
|
||||||
sequence(:name) { |n| "Cool User ##{n}" }
|
sequence(:name) { |n| "Cool User ##{n}" }
|
||||||
sequence(:email) { |n| "cooluser#{n}@cooldomain.com" }
|
sequence(:email) { |n| "cooluser#{n}@cooldomain.com" }
|
||||||
|
|
|
@ -69,17 +69,20 @@ class MapActivityMailerPreview < ActionMailer::Preview
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_user
|
def generate_user
|
||||||
User.create(name: Faker::Name.name, email: Faker::Internet.email, password: 'password', password_confirmation: 'password', joinedwithcode: 'qwertyui')
|
User.create(name: Faker::Name.name, email: Faker::Internet.email,
|
||||||
|
password: 'password', password_confirmation: 'password',
|
||||||
|
joinedwithcode: 'qwertyui')
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_map
|
def generate_map
|
||||||
Map.create(name: Faker::HarryPotter.book, permission: 'commons', arranged: false, user: generate_user)
|
Map.create(name: Faker::HarryPotter.book, permission: 'commons',
|
||||||
|
arranged: false, user: generate_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_added_to_map(map)
|
def topic_added_to_map(map)
|
||||||
user = generate_user
|
user = generate_user
|
||||||
topic = Topic.create(name: Faker::Friends.quote, permission: 'commons', user: user)
|
topic = Topic.create(name: Faker::Friends.quote, permission: 'commons', user: user)
|
||||||
mapping = Mapping.create(map: map, mappable: topic, user: user)
|
Mapping.create(map: map, mappable: topic, user: user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_moved_on_map(mapping)
|
def topic_moved_on_map(mapping)
|
||||||
|
@ -95,8 +98,9 @@ class MapActivityMailerPreview < ActionMailer::Preview
|
||||||
|
|
||||||
def synapse_added_to_map(map, topic1, topic2)
|
def synapse_added_to_map(map, topic1, topic2)
|
||||||
user = generate_user
|
user = generate_user
|
||||||
topic = Synapse.create(desc: 'describes', permission: 'commons', user: user, topic1: topic1, topic2: topic2)
|
topic = Synapse.create(desc: 'describes', permission: 'commons',
|
||||||
mapping = Mapping.create(map: map, mappable: topic, user: user)
|
user: user, topic1: topic1, topic2: topic2)
|
||||||
|
Mapping.create(map: map, mappable: topic, user: user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def synapse_removed_from_map(mapping)
|
def synapse_removed_from_map(mapping)
|
||||||
|
|
|
@ -11,13 +11,13 @@ if Rails.env.production?
|
||||||
end
|
end
|
||||||
|
|
||||||
# require all support files
|
# require all support files
|
||||||
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
|
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
|
||||||
|
|
||||||
ActiveRecord::Migration.maintain_test_schema!
|
ActiveRecord::Migration.maintain_test_schema!
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
config.fixture_path = ::Rails.root.join('spec', 'fixtures')
|
||||||
|
|
||||||
config.use_transactional_fixtures = true
|
config.use_transactional_fixtures = true
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ RSpec.describe MapActivityService do
|
||||||
describe 'topics added to map' do
|
describe 'topics added to map' do
|
||||||
it 'includes a topic added within the last 24 hours' do
|
it 'includes a topic added within the last 24 hours' do
|
||||||
topic = create(:topic)
|
topic = create(:topic)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: topic, created_at: 6.hours.ago)
|
create(:mapping, user: other_user, map: map, mappable: topic, created_at: 6.hours.ago)
|
||||||
|
|
||||||
event = Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id)
|
event = Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id)
|
||||||
event.update_columns(created_at: 6.hours.ago)
|
event.update_columns(created_at: 6.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
|
@ -47,26 +48,33 @@ RSpec.describe MapActivityService do
|
||||||
mapping.destroy
|
mapping.destroy
|
||||||
Event.find_by(kind: 'topic_removed_from_map', eventable_id: topic.id).update_columns(created_at: 6.hours.ago)
|
Event.find_by(kind: 'topic_removed_from_map', eventable_id: topic.id).update_columns(created_at: 6.hours.ago)
|
||||||
mapping2 = create(:mapping, user: other_user, map: map, mappable: topic, created_at: 5.hours.ago)
|
mapping2 = create(:mapping, user: other_user, map: map, mappable: topic, created_at: 5.hours.ago)
|
||||||
Event.where(kind: 'topic_added_to_map').where("meta->>'mapping_id' = ?", mapping2.id.to_s).first.update_columns(created_at: 5.hours.ago)
|
Event.where(kind: 'topic_added_to_map').where("meta->>'mapping_id' = ?", mapping2.id.to_s)
|
||||||
|
.first
|
||||||
|
.update_columns(created_at: 5.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response).to eq empty_response
|
expect(response).to eq empty_response
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes a topic added outside the last 24 hours' do
|
it 'excludes a topic added outside the last 24 hours' do
|
||||||
topic = create(:topic)
|
topic = create(:topic)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: topic, created_at: 25.hours.ago)
|
create(:mapping, user: other_user, map: map, mappable: topic, created_at: 25.hours.ago)
|
||||||
|
|
||||||
Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id).update_columns(created_at: 25.hours.ago)
|
Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id).update_columns(created_at: 25.hours.ago)
|
||||||
|
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response).to eq empty_response
|
expect(response).to eq empty_response
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes topics added by the user who will receive the data' do
|
it 'excludes topics added by the user who will receive the data' do
|
||||||
topic = create(:topic)
|
topic = create(:topic)
|
||||||
topic2 = create(:topic)
|
create(:mapping, user: other_user, map: map, mappable: topic, created_at: 5.hours.ago)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: topic, created_at: 5.hours.ago)
|
|
||||||
event = Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id)
|
event = Event.find_by(kind: 'topic_added_to_map', eventable_id: topic.id)
|
||||||
event.update_columns(created_at: 5.hours.ago)
|
event.update_columns(created_at: 5.hours.ago)
|
||||||
mapping2 = create(:mapping, user: email_user, map: map, mappable: topic2, created_at: 5.hours.ago)
|
|
||||||
|
topic2 = create(:topic)
|
||||||
|
create(:mapping, user: email_user, map: map, mappable: topic2, created_at: 5.hours.ago)
|
||||||
|
|
||||||
Event.find_by(kind: 'topic_added_to_map', eventable_id: topic2.id).update_columns(created_at: 5.hours.ago)
|
Event.find_by(kind: 'topic_added_to_map', eventable_id: topic2.id).update_columns(created_at: 5.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response[:stats][:topics_added]).to eq(1)
|
expect(response[:stats][:topics_added]).to eq(1)
|
||||||
|
@ -166,7 +174,7 @@ RSpec.describe MapActivityService do
|
||||||
describe 'synapses added to map' do
|
describe 'synapses added to map' do
|
||||||
it 'includes a synapse added within the last 24 hours' do
|
it 'includes a synapse added within the last 24 hours' do
|
||||||
synapse = create(:synapse)
|
synapse = create(:synapse)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 6.hours.ago)
|
create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 6.hours.ago)
|
||||||
event = Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id)
|
event = Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id)
|
||||||
event.update_columns(created_at: 6.hours.ago)
|
event.update_columns(created_at: 6.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
|
@ -197,14 +205,16 @@ RSpec.describe MapActivityService do
|
||||||
mapping.destroy
|
mapping.destroy
|
||||||
Event.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse.id).update_columns(created_at: 6.hours.ago)
|
Event.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse.id).update_columns(created_at: 6.hours.ago)
|
||||||
mapping2 = create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 5.hours.ago)
|
mapping2 = create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 5.hours.ago)
|
||||||
Event.where(kind: 'synapse_added_to_map').where("meta->>'mapping_id' = ?", mapping2.id.to_s).first.update_columns(created_at: 5.hours.ago)
|
Event.where(kind: 'synapse_added_to_map').where("meta->>'mapping_id' = ?", mapping2.id.to_s)
|
||||||
|
.first
|
||||||
|
.update_columns(created_at: 5.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response).to eq empty_response
|
expect(response).to eq empty_response
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes a synapse added outside the last 24 hours' do
|
it 'excludes a synapse added outside the last 24 hours' do
|
||||||
synapse = create(:synapse)
|
synapse = create(:synapse)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 25.hours.ago)
|
create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 25.hours.ago)
|
||||||
Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id).update_columns(created_at: 25.hours.ago)
|
Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id).update_columns(created_at: 25.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response).to eq empty_response
|
expect(response).to eq empty_response
|
||||||
|
@ -212,11 +222,14 @@ RSpec.describe MapActivityService do
|
||||||
|
|
||||||
it 'excludes synapses added by the user who will receive the data' do
|
it 'excludes synapses added by the user who will receive the data' do
|
||||||
synapse = create(:synapse)
|
synapse = create(:synapse)
|
||||||
synapse2 = create(:synapse)
|
create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 5.hours.ago)
|
||||||
mapping = create(:mapping, user: other_user, map: map, mappable: synapse, created_at: 5.hours.ago)
|
|
||||||
event = Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id)
|
event = Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse.id)
|
||||||
event.update_columns(created_at: 5.hours.ago)
|
event.update_columns(created_at: 5.hours.ago)
|
||||||
mapping2 = create(:mapping, user: email_user, map: map, mappable: synapse2, created_at: 5.hours.ago)
|
|
||||||
|
synapse2 = create(:synapse)
|
||||||
|
create(:mapping, user: email_user, map: map, mappable: synapse2, created_at: 5.hours.ago)
|
||||||
|
|
||||||
Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse2.id).update_columns(created_at: 5.hours.ago)
|
Event.find_by(kind: 'synapse_added_to_map', eventable_id: synapse2.id).update_columns(created_at: 5.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response[:stats][:synapses_added]).to eq(1)
|
expect(response[:stats][:synapses_added]).to eq(1)
|
||||||
|
@ -262,7 +275,9 @@ RSpec.describe MapActivityService do
|
||||||
mapping2.destroy
|
mapping2.destroy
|
||||||
event = Event.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse.id)
|
event = Event.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse.id)
|
||||||
event.update_columns(created_at: 5.hours.ago)
|
event.update_columns(created_at: 5.hours.ago)
|
||||||
Event.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse2.id).update_columns(created_at: 5.hours.ago)
|
Event
|
||||||
|
.find_by(kind: 'synapse_removed_from_map', eventable_id: synapse2.id)
|
||||||
|
.update_columns(created_at: 5.hours.ago)
|
||||||
response = MapActivityService.summarize_data(map, email_user)
|
response = MapActivityService.summarize_data(map, email_user)
|
||||||
expect(response[:stats][:synapses_removed]).to eq(1)
|
expect(response[:stats][:synapses_removed]).to eq(1)
|
||||||
expect(response[:synapses_removed]).to eq([event])
|
expect(response[:synapses_removed]).to eq([event])
|
||||||
|
@ -297,7 +312,8 @@ RSpec.describe MapActivityService do
|
||||||
old_topic = create(:topic, permission: 'commons', user: other_user)
|
old_topic = create(:topic, permission: 'commons', user: other_user)
|
||||||
old_topic_mapping = create(:mapping, map: map, mappable: old_topic, user: other_user)
|
old_topic_mapping = create(:mapping, map: map, mappable: old_topic, user: other_user)
|
||||||
old_private_topic = create(:topic, permission: 'private', user: other_user)
|
old_private_topic = create(:topic, permission: 'private', user: other_user)
|
||||||
old_private_topic_mapping = create(:mapping, map: map, mappable: old_private_topic, user: other_user)
|
old_private_topic_mapping = create(:mapping, map: map, mappable: old_private_topic,
|
||||||
|
user: other_user)
|
||||||
end
|
end
|
||||||
Timecop.return
|
Timecop.return
|
||||||
|
|
||||||
|
@ -347,7 +363,8 @@ RSpec.describe MapActivityService do
|
||||||
old_synapse = create(:synapse, permission: 'commons', user: other_user)
|
old_synapse = create(:synapse, permission: 'commons', user: other_user)
|
||||||
old_synapse_mapping = create(:mapping, map: map, mappable: old_synapse, user: other_user)
|
old_synapse_mapping = create(:mapping, map: map, mappable: old_synapse, user: other_user)
|
||||||
old_private_synapse = create(:synapse, permission: 'private', user: other_user)
|
old_private_synapse = create(:synapse, permission: 'private', user: other_user)
|
||||||
old_private_synapse_mapping = create(:mapping, map: map, mappable: old_private_synapse, user: other_user)
|
old_private_synapse_mapping = create(:mapping, map: map, mappable: old_private_synapse,
|
||||||
|
user: other_user)
|
||||||
end
|
end
|
||||||
Timecop.return
|
Timecop.return
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# lets you type create(:user) instead of FactoryGirl.create(:user)
|
# lets you type create(:user) instead of FactoryBot.create(:user)
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.include FactoryGirl::Syntax::Methods
|
config.include FactoryBot::Syntax::Methods
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
RSpec::Matchers.define :match_json_schema do |schema_name|
|
RSpec::Matchers.define :match_json_schema do |schema_name|
|
||||||
match do |response|
|
match do |response|
|
||||||
schema_directory = Rails.root.join('doc', 'api', 'schemas').to_s
|
schema_path = Rails.root.join('doc', 'api', 'schemas', "#{schema_name}.json").to_s
|
||||||
schema = "#{schema_directory}/#{schema_name}.json"
|
|
||||||
|
|
||||||
# schema customizations
|
# schema customizations
|
||||||
schema = JSON.parse(File.read(schema))
|
schema = JSON.parse(File.read(schema_path))
|
||||||
schema = update_file_refs(schema)
|
schema = update_file_refs(schema)
|
||||||
|
|
||||||
data = JSON.parse(response.body)
|
data = JSON.parse(response.body)
|
||||||
|
@ -15,7 +14,7 @@ RSpec::Matchers.define :match_json_schema do |schema_name|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_json_example(resource)
|
def get_json_example(resource)
|
||||||
filepath = "#{Rails.root}/doc/api/examples/#{resource}.json"
|
filepath = Rails.root.join('doc', 'api', 'examples', "#{resource}.json")
|
||||||
OpenStruct.new(body: File.read(filepath))
|
OpenStruct.new(body: File.read(filepath))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ def update_file_refs(schema)
|
||||||
schema[key] = if value.is_a? Hash
|
schema[key] = if value.is_a? Hash
|
||||||
update_file_refs(value)
|
update_file_refs(value)
|
||||||
elsif key == '$ref'
|
elsif key == '$ref'
|
||||||
"#{Rails.root}/doc/api/schemas/#{value}"
|
Rails.root.join('doc', 'api', 'schemas', value).to_s
|
||||||
else
|
else
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue