biovision 0.0.200518.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +214 -0
- data/Rakefile +22 -0
- data/app/assets/config/biovision_manifest.js +1 -0
- data/app/assets/images/biovision/components/carousel/arrow-left.svg +4 -0
- data/app/assets/images/biovision/components/carousel/arrow-right.svg +4 -0
- data/app/assets/images/biovision/icons/breadcrumb-hover.svg +1 -0
- data/app/assets/images/biovision/icons/breadcrumb.svg +1 -0
- data/app/assets/images/biovision/icons/components/contact.svg +26 -0
- data/app/assets/images/biovision/icons/components/content.svg +20 -0
- data/app/assets/images/biovision/icons/components/users.svg +21 -0
- data/app/assets/images/biovision/icons/key.svg +16 -0
- data/app/assets/images/biovision/icons/log_in.svg +15 -0
- data/app/assets/images/biovision/icons/log_out.svg +15 -0
- data/app/assets/images/biovision/icons/messages/error.svg +14 -0
- data/app/assets/images/biovision/icons/messages/info.svg +8 -0
- data/app/assets/images/biovision/icons/messages/success.svg +12 -0
- data/app/assets/images/biovision/icons/messages/warning.svg +13 -0
- data/app/assets/images/biovision/icons/settings.svg +41 -0
- data/app/assets/images/biovision/placeholders/16x9.svg +11 -0
- data/app/assets/images/biovision/placeholders/1x1.svg +11 -0
- data/app/assets/images/biovision/placeholders/3x2.svg +11 -0
- data/app/assets/images/biovision/placeholders/user.svg +15 -0
- data/app/assets/stylesheets/biovision/admin.scss +6 -0
- data/app/assets/stylesheets/biovision/admin/components.scss +59 -0
- data/app/assets/stylesheets/biovision/admin/default.scss +57 -0
- data/app/assets/stylesheets/biovision/admin/layout.scss +95 -0
- data/app/assets/stylesheets/biovision/admin/vars.scss +56 -0
- data/app/assets/stylesheets/biovision/biovision.scss +134 -0
- data/app/assets/stylesheets/biovision/biovision/messages.scss +41 -0
- data/app/assets/stylesheets/biovision/components/carousel.scss +53 -0
- data/app/assets/stylesheets/biovision/components/forms.scss +85 -0
- data/app/assets/stylesheets/biovision/components/hamburger.scss +56 -0
- data/app/assets/stylesheets/biovision/components/lists.scss +91 -0
- data/app/assets/stylesheets/biovision/default.scss +57 -0
- data/app/assets/stylesheets/biovision/themes/default_theme.scss +2 -0
- data/app/assets/stylesheets/biovision/themes/default_theme/components.scss +3 -0
- data/app/assets/stylesheets/biovision/themes/default_theme/layout.scss +44 -0
- data/app/assets/stylesheets/biovision/themes/default_theme/layout/footer.scss +0 -0
- data/app/assets/stylesheets/biovision/themes/default_theme/layout/header.scss +39 -0
- data/app/assets/stylesheets/biovision/vars.scss +53 -0
- data/app/controllers/admin/agents_controller.rb +15 -0
- data/app/controllers/admin/components_controller.rb +174 -0
- data/app/controllers/admin/index_controller.rb +11 -0
- data/app/controllers/admin/ip_addresses_controller.rb +15 -0
- data/app/controllers/admin_controller.rb +14 -0
- data/app/controllers/authentication_controller.rb +79 -0
- data/app/controllers/concerns/authentication.rb +45 -0
- data/app/controllers/index_controller.rb +8 -0
- data/app/controllers/my/confirmations_controller.rb +2 -0
- data/app/controllers/my/index_controller.rb +8 -0
- data/app/controllers/my/profiles_controller.rb +128 -0
- data/app/controllers/my/recoveries_controller.rb +2 -0
- data/app/helpers/biovision_components_helper.rb +14 -0
- data/app/helpers/users_helper.rb +11 -0
- data/app/lib/biovision/components/base_component.rb +177 -0
- data/app/lib/biovision/components/component_settings.rb +30 -0
- data/app/lib/biovision/components/privilege_handler.rb +77 -0
- data/app/lib/biovision/components/track_component.rb +9 -0
- data/app/lib/biovision/components/users/authentication.rb +47 -0
- data/app/lib/biovision/components/users/code_handler.rb +23 -0
- data/app/lib/biovision/components/users/profile_handler.rb +12 -0
- data/app/lib/biovision/components/users/registration_handler.rb +99 -0
- data/app/lib/biovision/components/users_component.rb +47 -0
- data/app/lib/biovision/notifiers/base_notifier.rb +69 -0
- data/app/lib/biovision/notifiers/socialization_notifier.rb +31 -0
- data/app/lib/biovision/notifiers/users_notifier.rb +15 -0
- data/app/models/agent.rb +35 -0
- data/app/models/biovision_component.rb +45 -0
- data/app/models/biovision_component_user.rb +21 -0
- data/app/models/browser.rb +34 -0
- data/app/models/code.rb +71 -0
- data/app/models/concerns/checkable.rb +22 -0
- data/app/models/concerns/flat_priority.rb +50 -0
- data/app/models/concerns/has_language.rb +10 -0
- data/app/models/concerns/has_owner.rb +22 -0
- data/app/models/concerns/has_simple_image.rb +18 -0
- data/app/models/concerns/has_track.rb +10 -0
- data/app/models/concerns/has_uuid.rb +12 -0
- data/app/models/concerns/meta_texts.rb +16 -0
- data/app/models/concerns/nested_priority.rb +58 -0
- data/app/models/concerns/required_unique_name.rb +16 -0
- data/app/models/concerns/required_unique_slug.rb +15 -0
- data/app/models/concerns/toggleable.rb +33 -0
- data/app/models/foreign_site.rb +34 -0
- data/app/models/foreign_user.rb +21 -0
- data/app/models/ip_address.rb +31 -0
- data/app/models/language.rb +31 -0
- data/app/models/login_attempt.rb +35 -0
- data/app/models/metric.rb +48 -0
- data/app/models/metric_value.rb +11 -0
- data/app/models/notification.rb +37 -0
- data/app/models/simple_image.rb +47 -0
- data/app/models/simple_image_tag.rb +30 -0
- data/app/models/simple_image_tag_image.rb +13 -0
- data/app/models/token.rb +96 -0
- data/app/models/user.rb +136 -0
- data/app/models/user_language.rb +15 -0
- data/app/uploaders/simple_image_uploader.rb +96 -0
- data/app/uploaders/user_image_uploader.rb +58 -0
- data/app/views/admin/agents/_nav_item.html.erb +6 -0
- data/app/views/admin/agents/entity/_in_list.html.erb +6 -0
- data/app/views/admin/agents/index.html.erb +13 -0
- data/app/views/admin/components/_list.html.erb +12 -0
- data/app/views/admin/components/entity/_links.html.erb +35 -0
- data/app/views/admin/components/entity/_section.html.erb +12 -0
- data/app/views/admin/components/index.html.erb +12 -0
- data/app/views/admin/components/links/_track.html.erb +2 -0
- data/app/views/admin/components/links/_users.html.erb +11 -0
- data/app/views/admin/components/privileges.html.erb +20 -0
- data/app/views/admin/components/privileges/_component_user.html.erb +17 -0
- data/app/views/admin/components/privileges/_links.html.erb +35 -0
- data/app/views/admin/components/privileges/_privilege_flag.html.erb +28 -0
- data/app/views/admin/components/privileges/_users.html.erb +23 -0
- data/app/views/admin/components/settings.html.erb +39 -0
- data/app/views/admin/components/settings/_new_parameter.html.erb +46 -0
- data/app/views/admin/components/settings/_parameters.html.erb +20 -0
- data/app/views/admin/components/settings/_setting.html.erb +18 -0
- data/app/views/admin/components/settings/_settings.html.erb +31 -0
- data/app/views/admin/components/show.html.erb +14 -0
- data/app/views/admin/index/index.html.erb +14 -0
- data/app/views/admin/ip_addresses/_nav_item.html.erb +6 -0
- data/app/views/admin/ip_addresses/entity/_in_list.html.erb +6 -0
- data/app/views/admin/ip_addresses/index.html.erb +13 -0
- data/app/views/admin/unauthorized.html.erb +19 -0
- data/app/views/authentication/_form.html.erb +40 -0
- data/app/views/authentication/failed.js.erb +3 -0
- data/app/views/authentication/new.html.erb +21 -0
- data/app/views/index/index.html.erb +0 -0
- data/app/views/layouts/admin.html.erb +23 -0
- data/app/views/layouts/admin/_breadcrumbs.html.erb +8 -0
- data/app/views/layouts/admin/_footer.html.erb +10 -0
- data/app/views/layouts/admin/_header.html.erb +18 -0
- data/app/views/layouts/admin/header/_logo.html.erb +3 -0
- data/app/views/layouts/application/_footer.html.erb +8 -0
- data/app/views/layouts/application/_header.html.erb +9 -0
- data/app/views/layouts/application/header/_authentication.html.erb +13 -0
- data/app/views/my/index/index.html.erb +0 -0
- data/app/views/my/profiles/closed.html.erb +12 -0
- data/app/views/my/profiles/new.html.erb +17 -0
- data/app/views/my/profiles/new/_form.html.erb +147 -0
- data/app/views/shared/_breadcrumbs.html.erb +8 -0
- data/app/views/shared/_cookie_notification.html.erb +4 -0
- data/app/views/shared/_flash_messages.html.erb +7 -0
- data/app/views/shared/_meta_texts.html.erb +31 -0
- data/app/views/shared/_nothing_found.html.erb +1 -0
- data/app/views/shared/_pagination.jbuilder +15 -0
- data/app/views/shared/admin/_list.html.erb +19 -0
- data/app/views/shared/admin/_list_with_priority.html.erb +19 -0
- data/app/views/shared/admin/_toggleable.html.erb +8 -0
- data/app/views/shared/entity/_list_of_errors.html.erb +7 -0
- data/app/views/shared/forms/errors.js.erb +5 -0
- data/config/initializers/carrierwave.rb +27 -0
- data/config/initializers/pluralization.rb +2 -0
- data/config/locales/biovision-ru.yml +90 -0
- data/config/locales/components-ru.yml +81 -0
- data/config/locales/track-ru.yml +40 -0
- data/config/locales/users-ru.yml +130 -0
- data/config/routes.rb +75 -0
- data/db/migrate/20191228000000_create_biovision_components.rb +72 -0
- data/db/migrate/20200224000000_create_track_component.rb +59 -0
- data/db/migrate/20200224000010_create_users_component.rb +189 -0
- data/db/migrate/20200404000000_create_simple_images.rb +54 -0
- data/lib/biovision.rb +9 -0
- data/lib/biovision/base_methods.rb +167 -0
- data/lib/biovision/engine.rb +40 -0
- data/lib/biovision/version.rb +5 -0
- data/lib/tasks/biovision_tasks.rake +4 -0
- metadata +392 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Biovision
|
4
|
+
module Components
|
5
|
+
# Handling users
|
6
|
+
class UsersComponent < BaseComponent
|
7
|
+
include Users::Authentication
|
8
|
+
|
9
|
+
METRIC_NEW_USER = 'users.new_user.hit'
|
10
|
+
|
11
|
+
def self.settings_flags
|
12
|
+
%w[
|
13
|
+
registration_open email_as_login confirm_email require_email
|
14
|
+
invite_only use_invites
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.settings_numbers
|
19
|
+
%w[invite_count bounce_count bounce_timeout]
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Hash] parameters
|
23
|
+
# @param [Code] code
|
24
|
+
def register_user(parameters, code)
|
25
|
+
handler = Users::RegistrationHandler.new(self)
|
26
|
+
handler.handle(parameters, code)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [User] entity
|
30
|
+
def valid?(entity)
|
31
|
+
entity.valid? && valid_slug?(entity)
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_slug?(entity)
|
35
|
+
if settings['email_as_login']
|
36
|
+
entity.slug =~ /\A[-_a-z0-9.]+@[-a-z0-9.]+\.[a-z]{2,24}\z/
|
37
|
+
elsif entity.slug =~ /\A[_a-z0-9]{1,30}\z/
|
38
|
+
true
|
39
|
+
else
|
40
|
+
key = 'activerecord.errors.models.user.attributes.slug.invalid'
|
41
|
+
entity.errors[:slug] = t(key)
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Biovision
|
4
|
+
module Notifiers
|
5
|
+
# Base notifier class for dispatching component notifications
|
6
|
+
class BaseNotifier
|
7
|
+
attr_accessor :notification, :user
|
8
|
+
|
9
|
+
# @param [User] user
|
10
|
+
def initialize(user)
|
11
|
+
@user = user
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Notification] notification
|
15
|
+
def self.[](notification)
|
16
|
+
slug = notification.component_slug
|
17
|
+
instance = handler_class(slug).new(notification.user)
|
18
|
+
instance.notification = notification
|
19
|
+
instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.slug
|
23
|
+
to_s.demodulize.underscore.gsub('_notifier', '')
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [String] slug
|
27
|
+
def self.handler_class(slug)
|
28
|
+
handler_name = "biovision/notifiers/#{slug}_notifier".classify
|
29
|
+
handler_name.safe_constantize || BaseNotifier
|
30
|
+
end
|
31
|
+
|
32
|
+
def component
|
33
|
+
@component ||= BiovisionComponent[self.class.slug]
|
34
|
+
end
|
35
|
+
|
36
|
+
def entity
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def view
|
41
|
+
return if notification.nil?
|
42
|
+
|
43
|
+
"my/notifications/#{self.class.slug}/#{notification.data['type']}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Hash] data
|
47
|
+
def notify(data)
|
48
|
+
attributes = { user: user, biovision_component: component, data: data }
|
49
|
+
Notification.create(attributes)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
# @param [Integer] id
|
55
|
+
# @param [String] type
|
56
|
+
def check_and_notify(id, type)
|
57
|
+
return if check_chain(id, type).exists?
|
58
|
+
|
59
|
+
notify({id: id, type: type})
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [Integer] id
|
63
|
+
# @param [String] type
|
64
|
+
def check_chain(id, type)
|
65
|
+
Notification.owned_by(user).unread.data_id(id).data_type(type)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Biovision
|
4
|
+
module Notifiers
|
5
|
+
# Notification mapper for socialization component
|
6
|
+
class SocializationNotifier < BaseNotifier
|
7
|
+
TYPE_FOLLOWER = 'follower'
|
8
|
+
TYPE_MESSAGE = 'message'
|
9
|
+
|
10
|
+
def entity
|
11
|
+
data = notification&.data.to_h
|
12
|
+
case data['type']
|
13
|
+
when TYPE_MESSAGE, TYPE_FOLLOWER
|
14
|
+
User.find_by(id: data['id'])
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Integer] sender_id
|
21
|
+
def new_message(sender_id)
|
22
|
+
check_and_notify(sender_id, TYPE_MESSAGE)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Integer] follower_id
|
26
|
+
def new_follower(follower_id)
|
27
|
+
check_and_notify(follower_id, TYPE_FOLLOWER)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Biovision
|
4
|
+
module Notifiers
|
5
|
+
# Notification mapper for socialization component
|
6
|
+
class UsersNotifier < BaseNotifier
|
7
|
+
TYPE_LOGIN_ATTEMPT = 'login_attempt'
|
8
|
+
|
9
|
+
# @param [Hash] track
|
10
|
+
def new_login_attempt(track)
|
11
|
+
check_and_notify(track[:ip_address]&.id, TYPE_LOGIN_ATTEMPT)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/app/models/agent.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# User agent
|
4
|
+
#
|
5
|
+
# Attributes:
|
6
|
+
# banned [boolean]
|
7
|
+
# browser_id [Browser], optional
|
8
|
+
# created_at [DateTime]
|
9
|
+
# object_count [integer]
|
10
|
+
# name [string]
|
11
|
+
# updated_at [DateTime]
|
12
|
+
class Agent < ApplicationRecord
|
13
|
+
include RequiredUniqueName
|
14
|
+
include Toggleable
|
15
|
+
|
16
|
+
toggleable :banned
|
17
|
+
|
18
|
+
belongs_to :browser, optional: true, counter_cache: true
|
19
|
+
|
20
|
+
before_validation { self.name = name.to_s[0..254] }
|
21
|
+
|
22
|
+
scope :list_for_administration, -> { ordered_by_name }
|
23
|
+
|
24
|
+
# @param [Integer] page
|
25
|
+
def self.page_for_administration(page = 1)
|
26
|
+
list_for_administration.page(page)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [String] name
|
30
|
+
def self.[](name)
|
31
|
+
return if name.blank?
|
32
|
+
|
33
|
+
find_or_create_by(name: name[0..254])
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Biovision component entity, settings and parameters
|
4
|
+
#
|
5
|
+
# Attributes:
|
6
|
+
# active [Boolean]
|
7
|
+
# created_at [DateTime]
|
8
|
+
# parameters [JSON]
|
9
|
+
# priority [Integer]
|
10
|
+
# settings [JSON]
|
11
|
+
# slug [String]
|
12
|
+
# updated_at [DateTime]
|
13
|
+
class BiovisionComponent < ApplicationRecord
|
14
|
+
include FlatPriority
|
15
|
+
include RequiredUniqueSlug
|
16
|
+
|
17
|
+
has_many :biovision_component_users, dependent: :delete_all
|
18
|
+
has_many :simple_images, dependent: :destroy
|
19
|
+
|
20
|
+
scope :list_for_administration, -> { ordered_by_priority }
|
21
|
+
|
22
|
+
# Find component by slug
|
23
|
+
#
|
24
|
+
# @param [String] slug
|
25
|
+
def self.[](slug)
|
26
|
+
find_by(slug: slug)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [String] slug
|
30
|
+
# @param [String] default_value
|
31
|
+
def get(slug, default_value = '')
|
32
|
+
parameters.fetch(slug.to_s) { default_value }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param [String] slug
|
36
|
+
# @param value
|
37
|
+
def []=(slug, value)
|
38
|
+
parameters[slug.to_s] = value
|
39
|
+
save!
|
40
|
+
end
|
41
|
+
|
42
|
+
def privileges
|
43
|
+
biovision_component_users.recent
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# User data in biovision component
|
4
|
+
#
|
5
|
+
# Attributes:
|
6
|
+
# administrator [boolean]
|
7
|
+
# biovision_component_id [BiovisionComponent]
|
8
|
+
# created_at [DateTime]
|
9
|
+
# data [jsonb]
|
10
|
+
# updated_at [DateTime]
|
11
|
+
# user_id [User]
|
12
|
+
class BiovisionComponentUser < ApplicationRecord
|
13
|
+
include HasOwner
|
14
|
+
|
15
|
+
belongs_to :biovision_component
|
16
|
+
belongs_to :user
|
17
|
+
|
18
|
+
validates_uniqueness_of :user_id, scope: :biovision_component_id
|
19
|
+
|
20
|
+
scope :recent, -> { order('updated_at desc') }
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Browser
|
4
|
+
#
|
5
|
+
# Attributes:
|
6
|
+
# agents_count [integer]
|
7
|
+
# banned [boolean]
|
8
|
+
# created_at [DateTime]
|
9
|
+
# mobile [boolean]
|
10
|
+
# name [string]
|
11
|
+
# updated_at [DateTime]
|
12
|
+
# version [string]
|
13
|
+
class Browser < ApplicationRecord
|
14
|
+
include Checkable
|
15
|
+
include Toggleable
|
16
|
+
|
17
|
+
NAME_LIMIT = 50
|
18
|
+
VERSION_LIMIT = 10
|
19
|
+
|
20
|
+
toggleable :banned
|
21
|
+
|
22
|
+
has_many :agents, dependent: :nullify
|
23
|
+
|
24
|
+
validates_presence_of :name, :version
|
25
|
+
validates_uniqueness_of :version, scope: :name
|
26
|
+
validates_length_of :name, maximum: NAME_LIMIT
|
27
|
+
validates_length_of :version, maximum: VERSION_LIMIT
|
28
|
+
|
29
|
+
scope :list_for_administration, -> { order('name asc, version asc') }
|
30
|
+
|
31
|
+
def self.entity_parameters
|
32
|
+
%i[banned mobile name version]
|
33
|
+
end
|
34
|
+
end
|
data/app/models/code.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Code for users
|
4
|
+
#
|
5
|
+
# Attributes:
|
6
|
+
# agent_id [Agent], optional
|
7
|
+
# biovision_component_id [BiovisionComponent]
|
8
|
+
# body [string]
|
9
|
+
# created_at [DateTime]
|
10
|
+
# data [jsonb]
|
11
|
+
# ip_address_id [IpAddress], optional
|
12
|
+
# quantity [integer]
|
13
|
+
# updated_at [DateTime]
|
14
|
+
# user_id [User]
|
15
|
+
class Code < ApplicationRecord
|
16
|
+
include HasOwner
|
17
|
+
include HasTrack
|
18
|
+
|
19
|
+
BODY_LIMIT = 50
|
20
|
+
QUANTITY_RANGE = (0..32_767).freeze
|
21
|
+
|
22
|
+
belongs_to :biovision_component
|
23
|
+
belongs_to :user
|
24
|
+
|
25
|
+
after_initialize :generate_body
|
26
|
+
|
27
|
+
before_validation :sanitize_quantity
|
28
|
+
|
29
|
+
validates_presence_of :body
|
30
|
+
validates_uniqueness_of :body
|
31
|
+
validates_length_of :body, maximum: BODY_LIMIT
|
32
|
+
|
33
|
+
scope :recent, -> { order('id desc') }
|
34
|
+
scope :active, -> { where('quantity > 0') }
|
35
|
+
scope :list_for_administration, -> { recent }
|
36
|
+
|
37
|
+
# @param [Integer] page
|
38
|
+
def self.page_for_administration(page = 1)
|
39
|
+
list_for_administration.page(page)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.entity_parameters
|
43
|
+
%i[body payload quantity]
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.creation_parameters
|
47
|
+
entity_parameters + %i[user_id code_type_id]
|
48
|
+
end
|
49
|
+
|
50
|
+
def activated?
|
51
|
+
quantity < 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def active?
|
55
|
+
quantity.positive?
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def generate_body
|
61
|
+
return unless body.nil?
|
62
|
+
|
63
|
+
number = SecureRandom.random_number(0xffff_ffff_ffff_ffff)
|
64
|
+
self.body = number.to_s(36).scan(/.{4}/).join('-').upcase
|
65
|
+
end
|
66
|
+
|
67
|
+
def sanitize_quantity
|
68
|
+
self.quantity = QUANTITY_RANGE.first if quantity < QUANTITY_RANGE.first
|
69
|
+
self.quantity = QUANTITY_RANGE.last if quantity > QUANTITY_RANGE.last
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Adds method for validating model in controllers
|
4
|
+
#
|
5
|
+
# @author Maxim Khan-Magomedov <maxim.km@gmail.com>
|
6
|
+
module Checkable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# @param id
|
11
|
+
# @param [Hash] parameters
|
12
|
+
def self.instance_for_check(id, parameters)
|
13
|
+
if id.blank?
|
14
|
+
entity = new(parameters)
|
15
|
+
else
|
16
|
+
entity = find_by(id: id)
|
17
|
+
entity.assign_attributes(parameters)
|
18
|
+
end
|
19
|
+
entity
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Model has flat priority field
|
4
|
+
#
|
5
|
+
# Adds sorting items by priority
|
6
|
+
# @author Maxim Khan-Magomedov <maxim.km@gmail.com>
|
7
|
+
module FlatPriority
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
after_initialize :set_next_priority
|
12
|
+
before_validation :normalize_priority
|
13
|
+
|
14
|
+
scope :ordered_by_priority, -> { order('priority asc, id asc') }
|
15
|
+
|
16
|
+
def self.priority_range
|
17
|
+
(1..32_767)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [Integer] delta
|
22
|
+
def change_priority(delta)
|
23
|
+
swap_priority_with_adjacent(priority + delta)
|
24
|
+
|
25
|
+
self.class.ordered_by_priority.map { |e| [e.id, e.priority] }.to_h
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
# @param [Integer] new_priority
|
31
|
+
def swap_priority_with_adjacent(new_priority)
|
32
|
+
adjacent = self.class.find_by(priority: new_priority)
|
33
|
+
if adjacent.is_a?(self.class) && (adjacent.id != id)
|
34
|
+
adjacent.update!(priority: priority)
|
35
|
+
end
|
36
|
+
update!(priority: new_priority)
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_next_priority
|
40
|
+
return unless id.nil? && priority == 1
|
41
|
+
|
42
|
+
self.priority = self.class.maximum(:priority).to_i + 1
|
43
|
+
end
|
44
|
+
|
45
|
+
def normalize_priority
|
46
|
+
range = self.class.priority_range
|
47
|
+
self.priority = range.first if priority < range.first
|
48
|
+
self.priority = range.last if priority > range.last
|
49
|
+
end
|
50
|
+
end
|