biovision-base 0.17.180619 → 0.19.180703.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/biovision/base/icons/back.svg +18 -27
- data/app/assets/images/biovision/base/icons/create.svg +19 -1
- data/app/assets/images/biovision/base/icons/destroy.svg +8 -2
- data/app/assets/images/biovision/base/icons/gear.svg +9 -2
- data/app/assets/images/biovision/base/icons/lock-closed.svg +12 -1
- data/app/assets/images/biovision/base/icons/lock-open.svg +12 -1
- data/app/assets/images/biovision/base/icons/notice.svg +9 -1
- data/app/assets/images/biovision/base/icons/return.svg +25 -1
- data/app/assets/images/biovision/base/icons/warning.svg +31 -42
- data/app/assets/images/biovision/base/icons/world.svg +9 -2
- data/app/assets/images/biovision/base/placeholders/16x9.svg +5 -0
- data/app/assets/images/biovision/base/placeholders/3x2.svg +5 -0
- data/app/assets/javascripts/biovision/base/biovision.js +75 -17
- data/app/assets/stylesheets/biovision/base/admin.scss +1 -0
- data/app/assets/stylesheets/biovision/base/biovision.scss +10 -0
- data/app/controllers/admin/editable_blocks_controller.rb +27 -0
- data/app/controllers/admin/editable_pages_controller.rb +1 -1
- data/app/controllers/admin/link_block_items_controller.rb +23 -0
- data/app/controllers/admin/link_blocks_controller.rb +27 -0
- data/app/controllers/admin/privileges_controller.rb +0 -1
- data/app/controllers/concerns/removable_image.rb +33 -0
- data/app/controllers/editable_blocks_controller.rb +64 -0
- data/app/controllers/editable_pages_controller.rb +1 -1
- data/app/controllers/feedback_requests_controller.rb +1 -0
- data/app/controllers/link_block_items_controller.rb +68 -0
- data/app/controllers/link_blocks_controller.rb +64 -0
- data/app/helpers/editable_pages_helper.rb +19 -0
- data/app/helpers/link_blocks_helper.rb +18 -0
- data/app/models/editable_block.rb +49 -0
- data/app/models/link_block.rb +43 -0
- data/app/models/link_block_item.rb +81 -0
- data/app/models/privilege.rb +10 -2
- data/app/models/privilege_group.rb +5 -0
- data/app/models/user.rb +4 -0
- data/app/models/user_privilege.rb +8 -3
- data/app/services/user_profile_handler.rb +2 -2
- data/app/uploaders/editable_page_image_uploader.rb +5 -1
- data/app/uploaders/link_block_image_uploader.rb +17 -0
- data/app/views/admin/editable_blocks/_nav_item.html.erb +6 -0
- data/app/views/admin/editable_blocks/entity/_in_list.html.erb +29 -0
- data/app/views/admin/editable_blocks/index.html.erb +14 -0
- data/app/views/admin/editable_blocks/show.html.erb +72 -0
- data/app/views/admin/index/_biovision_base.html.erb +2 -1
- data/app/views/admin/index/dashboard/_biovision_links.html.erb +11 -0
- data/app/views/admin/index/dashboard/_editorial.html.erb +5 -6
- data/app/views/admin/link_block_items/entity/_in_list.html.erb +39 -0
- data/app/views/admin/link_block_items/show.html.erb +74 -0
- data/app/views/admin/link_blocks/_nav_item.html.erb +6 -0
- data/app/views/admin/link_blocks/entity/_in_list.html.erb +26 -0
- data/app/views/admin/link_blocks/entity/_items.html.erb +23 -0
- data/app/views/admin/link_blocks/index.html.erb +14 -0
- data/app/views/admin/link_blocks/show.html.erb +57 -0
- data/app/views/admin/metrics/show.html.erb +1 -1
- data/app/views/admin/privileges/entity/_groups.html.erb +1 -1
- data/app/views/admin/privileges/entity/_in_list.html.erb +8 -1
- data/app/views/admin/users/entity/_in_list.html.erb +3 -0
- data/app/views/admin/users/privileges.html.erb +3 -3
- data/app/views/editable_blocks/_entity.html.erb +36 -0
- data/app/views/editable_blocks/_form.html.erb +171 -0
- data/app/views/editable_blocks/edit.html.erb +17 -0
- data/app/views/editable_blocks/new.html.erb +15 -0
- data/app/views/link_block_items/_form.html.erb +158 -0
- data/app/views/link_block_items/_list.html.erb +32 -0
- data/app/views/link_block_items/edit.html.erb +18 -0
- data/app/views/link_block_items/new.html.erb +18 -0
- data/app/views/link_blocks/_entity.html.erb +34 -0
- data/app/views/link_blocks/_form.html.erb +97 -0
- data/app/views/link_blocks/edit.html.erb +17 -0
- data/app/views/link_blocks/new.html.erb +15 -0
- data/app/views/my/index/index/_dashboard.html.erb +1 -3
- data/app/views/privileges/_form.html.erb +2 -7
- data/app/views/shared/_counters.html.erb +3 -0
- data/app/views/shared/forms/_entity_flags.html.erb +5 -1
- data/app/views/shared/forms/_image_remover.html.erb +13 -0
- data/config/locales/common-en.yml +1 -0
- data/config/locales/common-ru.yml +1 -0
- data/config/locales/editable-pages-ru.yml +50 -0
- data/config/locales/links-ru.yml +95 -0
- data/config/locales/users-en.yml +1 -0
- data/config/locales/users-ru.yml +1 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20170302000101_create_privileges.rb +1 -0
- data/db/migrate/20180622140000_create_link_blocks.rb +29 -0
- data/db/migrate/20180622140001_create_link_block_items.rb +23 -0
- data/db/migrate/20180627190000_create_editable_blocks.rb +39 -0
- data/db/migrate/20180703111111_add_fields_to_editable_blocks.rb +14 -0
- data/lib/biovision/base/version.rb +1 -1
- metadata +46 -2
@@ -0,0 +1,23 @@
|
|
1
|
+
class Admin::LinkBlockItemsController < AdminController
|
2
|
+
include ToggleableEntity
|
3
|
+
include EntityPriority
|
4
|
+
|
5
|
+
before_action :set_entity
|
6
|
+
|
7
|
+
# get /admin/link_block_items/:id
|
8
|
+
def show
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def restrict_access
|
14
|
+
require_privilege :content_manager
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_entity
|
18
|
+
@entity = LinkBlockItem.find_by(id: params[:id])
|
19
|
+
if @entity.nil?
|
20
|
+
handle_http_404("Cannot find link_block_item #{params[:id]}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Admin::LinkBlocksController < AdminController
|
2
|
+
include ToggleableEntity
|
3
|
+
|
4
|
+
before_action :set_entity, except: [:index]
|
5
|
+
|
6
|
+
# get /admin/link_blocks
|
7
|
+
def index
|
8
|
+
@collection = LinkBlock.list_for_administration
|
9
|
+
end
|
10
|
+
|
11
|
+
# get /admin/link_blocks/:id
|
12
|
+
def show
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def restrict_access
|
18
|
+
require_privilege :content_manager
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_entity
|
22
|
+
@entity = LinkBlock.find_by(id: params[:id])
|
23
|
+
if @entity.nil?
|
24
|
+
handle_http_404("Cannot find link_block #{params[:id]}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RemovableImage
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
# Remove entity image when allowed
|
5
|
+
def destroy_image
|
6
|
+
if entity_image_is_locked?
|
7
|
+
render json: { errors: { locked: true } }, status: :forbidden
|
8
|
+
elsif entity_image_is_editable?
|
9
|
+
@entity.remove_image!
|
10
|
+
render json: { meta: { result: @entity.save } }
|
11
|
+
else
|
12
|
+
head :unauthorized
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def entity_image_is_editable?
|
19
|
+
if @entity.respond_to?(:editable_by?)
|
20
|
+
@entity.editable_by?(current_user)
|
21
|
+
else
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def entity_image_is_locked?
|
27
|
+
if @entity.respond_to?(:locked?)
|
28
|
+
@entity.locked?
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class EditableBlocksController < AdminController
|
2
|
+
before_action :set_entity, only: [:edit, :update, :destroy]
|
3
|
+
|
4
|
+
# post /editable_blocks/check
|
5
|
+
def check
|
6
|
+
@entity = EditableBlock.instance_for_check(params[:entity_id], entity_parameters)
|
7
|
+
|
8
|
+
render 'shared/forms/check'
|
9
|
+
end
|
10
|
+
|
11
|
+
# get /editable_blocks/new
|
12
|
+
def new
|
13
|
+
@entity = EditableBlock.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# post /editable_blocks
|
17
|
+
def create
|
18
|
+
@entity = EditableBlock.new(entity_parameters)
|
19
|
+
if @entity.save
|
20
|
+
form_processed_ok(admin_editable_block_path(id: @entity.id))
|
21
|
+
else
|
22
|
+
form_processed_with_error(:new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# get /editable_blocks/:id/edit
|
27
|
+
def edit
|
28
|
+
end
|
29
|
+
|
30
|
+
# patch /editable_blocks/:id
|
31
|
+
def update
|
32
|
+
if @entity.update(entity_parameters)
|
33
|
+
flash[:notice] = t('editable_blocks.update.success')
|
34
|
+
form_processed_ok(admin_editable_block_path(id: @entity.id))
|
35
|
+
else
|
36
|
+
form_processed_with_error(:edit)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# delete /editable_blocks/:id
|
41
|
+
def destroy
|
42
|
+
if @entity.destroy
|
43
|
+
flash[:notice] = t('editable_blocks.destroy.success')
|
44
|
+
end
|
45
|
+
redirect_to(admin_editable_blocks_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def restrict_access
|
51
|
+
require_privilege :content_manager
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_entity
|
55
|
+
@entity = EditableBlock.find_by(id: params[:id])
|
56
|
+
if @entity.nil?
|
57
|
+
handle_http_404('Cannot find editable_block')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def entity_parameters
|
62
|
+
params.require(:editable_block).permit(EditableBlock.entity_parameters)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class LinkBlockItemsController < AdminController
|
2
|
+
before_action :set_entity, only: [:edit, :update, :destroy]
|
3
|
+
|
4
|
+
# post /admin/link_blocks/check
|
5
|
+
def check
|
6
|
+
@entity = LinkBlockItem.instance_for_check(params[:entity_id], entity_parameters)
|
7
|
+
|
8
|
+
render 'shared/forms/check'
|
9
|
+
end
|
10
|
+
|
11
|
+
# get /link_block_items/new
|
12
|
+
def new
|
13
|
+
@entity = LinkBlockItem.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# post /link_block_items
|
17
|
+
def create
|
18
|
+
@entity = LinkBlockItem.new(creation_parameters)
|
19
|
+
if @entity.save
|
20
|
+
form_processed_ok(admin_link_block_item_path(id: @entity.id))
|
21
|
+
else
|
22
|
+
form_processed_with_error(:new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# get /link_block_items/:id/edit
|
27
|
+
def edit
|
28
|
+
end
|
29
|
+
|
30
|
+
# patch /link_block_items/:id
|
31
|
+
def update
|
32
|
+
if @entity.update(entity_parameters)
|
33
|
+
flash[:notice] = t('link_block_items.update.success')
|
34
|
+
form_processed_ok(admin_link_block_item_path(id: @entity.id))
|
35
|
+
else
|
36
|
+
form_processed_with_error(:edit)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# delete /link_block_items/:id
|
41
|
+
def destroy
|
42
|
+
if @entity.destroy
|
43
|
+
flash[:notice] = t('link_block_items.destroy.success')
|
44
|
+
end
|
45
|
+
redirect_to(admin_link_block_items_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def restrict_access
|
51
|
+
require_privilege :content_manager
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_entity
|
55
|
+
@entity = LinkBlockItem.find_by(id: params[:id])
|
56
|
+
if @entity.nil?
|
57
|
+
handle_http_404('Cannot find link_block_item')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def entity_parameters
|
62
|
+
params.require(:link_block_item).permit(LinkBlockItem.entity_parameters)
|
63
|
+
end
|
64
|
+
|
65
|
+
def creation_parameters
|
66
|
+
params.require(:link_block_item).permit(LinkBlockItem.creation_parameters)
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class LinkBlocksController < AdminController
|
2
|
+
before_action :set_entity, only: [:edit, :update, :destroy]
|
3
|
+
|
4
|
+
# post /link_blocks/check
|
5
|
+
def check
|
6
|
+
@entity = LinkBlock.instance_for_check(params[:entity_id], entity_parameters)
|
7
|
+
|
8
|
+
render 'shared/forms/check'
|
9
|
+
end
|
10
|
+
|
11
|
+
# get /link_blocks/new
|
12
|
+
def new
|
13
|
+
@entity = LinkBlock.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# post /link_blocks
|
17
|
+
def create
|
18
|
+
@entity = LinkBlock.new(entity_parameters)
|
19
|
+
if @entity.save
|
20
|
+
form_processed_ok(admin_link_block_path(id: @entity.id))
|
21
|
+
else
|
22
|
+
form_processed_with_error(:new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# get /link_blocks/:id/edit
|
27
|
+
def edit
|
28
|
+
end
|
29
|
+
|
30
|
+
# patch /link_blocks/:id
|
31
|
+
def update
|
32
|
+
if @entity.update(entity_parameters)
|
33
|
+
flash[:notice] = t('link_blocks.update.success')
|
34
|
+
form_processed_ok(admin_link_block_path(id: @entity.id))
|
35
|
+
else
|
36
|
+
form_processed_with_error(:edit)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# delete /link_blocks/:id
|
41
|
+
def destroy
|
42
|
+
if @entity.destroy
|
43
|
+
flash[:notice] = t('link_blocks.destroy.success')
|
44
|
+
end
|
45
|
+
redirect_to(admin_link_blocks_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def restrict_access
|
51
|
+
require_privilege :content_manager
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_entity
|
55
|
+
@entity = LinkBlock.find_by(id: params[:id])
|
56
|
+
if @entity.nil?
|
57
|
+
handle_http_404('Cannot find link_block')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def entity_parameters
|
62
|
+
params.require(:link_block).permit(LinkBlock.entity_parameters)
|
63
|
+
end
|
64
|
+
end
|
@@ -4,6 +4,11 @@ module EditablePagesHelper
|
|
4
4
|
link_to(entity.name, admin_editable_page_path(id: entity.id))
|
5
5
|
end
|
6
6
|
|
7
|
+
# @param [EditableBlock] entity
|
8
|
+
def admin_editable_block_link(entity)
|
9
|
+
link_to(entity.name, admin_editable_block_path(id: entity.id))
|
10
|
+
end
|
11
|
+
|
7
12
|
# @param [EditablePage] entity
|
8
13
|
def editable_page_image_preview(entity)
|
9
14
|
return '' if entity.image.blank?
|
@@ -17,4 +22,18 @@ module EditablePagesHelper
|
|
17
22
|
versions = "#{entity.image.medium_2x.url} 2x"
|
18
23
|
image_tag(entity.image.medium.url, alt: entity.name, srcset: versions)
|
19
24
|
end
|
25
|
+
|
26
|
+
# @param [EditableBlock] entity
|
27
|
+
def editable_block_image_preview(entity)
|
28
|
+
return '' if entity.image.blank?
|
29
|
+
versions = "#{entity.image.preview_2x.url} 2x"
|
30
|
+
image_tag(entity.image.preview.url, alt: entity.name, srcset: versions)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [EditableBlock] entity
|
34
|
+
def editable_block_image_medium(entity)
|
35
|
+
return '' if entity.image.blank?
|
36
|
+
versions = "#{entity.image.medium_2x.url} 2x"
|
37
|
+
image_tag(entity.image.medium.url, alt: entity.name, srcset: versions)
|
38
|
+
end
|
20
39
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module LinkBlocksHelper
|
2
|
+
# @param [LinkBlock] entity
|
3
|
+
def admin_link_block_link(entity)
|
4
|
+
text = entity.title.blank? ? entity.slug : entity.title
|
5
|
+
link_to(text, admin_link_block_path(id: entity.id))
|
6
|
+
end
|
7
|
+
|
8
|
+
# @param [LinkBlockItem] entity
|
9
|
+
def admin_link_block_item_link(entity)
|
10
|
+
link_to(entity.text_for_link, admin_link_block_item_path(id: entity.id))
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param [LinkBlock] entity
|
14
|
+
def link_block_image(entity)
|
15
|
+
return '' if entity.image.blank?
|
16
|
+
image_tag(entity.image.url, alt: entity.image_alt_text)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class EditableBlock < ApplicationRecord
|
2
|
+
include Checkable
|
3
|
+
include Toggleable
|
4
|
+
|
5
|
+
DESCRIPTION_LIMIT = 250
|
6
|
+
NAME_LIMIT = 50
|
7
|
+
SLUG_LIMIT = 50
|
8
|
+
SLUG_PATTERN = /\A[a-z][-_a-z0-9]*[a-z]\z/i
|
9
|
+
SLUG_PATTERN_HTML = '^[a-zA-Z][-_a-zA_Z0-9]*[a-zA-Z]$'
|
10
|
+
TITLE_LIMIT = 255
|
11
|
+
TEXT_LIMIT = 5000
|
12
|
+
|
13
|
+
toggleable :visible, :raw_output
|
14
|
+
|
15
|
+
mount_uploader :image, EditablePageImageUploader
|
16
|
+
|
17
|
+
belongs_to :language, optional: true
|
18
|
+
|
19
|
+
validates_presence_of :name
|
20
|
+
validates_uniqueness_of :slug, scope: [:language_id]
|
21
|
+
validates_format_of :slug, with: SLUG_PATTERN
|
22
|
+
validates_length_of :slug, maximum: SLUG_LIMIT
|
23
|
+
validates_length_of :name, maximum: NAME_LIMIT
|
24
|
+
validates_length_of :title, maximum: TITLE_LIMIT
|
25
|
+
validates_length_of :lead, maximum: TEXT_LIMIT
|
26
|
+
validates_length_of :body, maximum: TEXT_LIMIT
|
27
|
+
validates_length_of :footer, maximum: TEXT_LIMIT
|
28
|
+
|
29
|
+
scope :ordered_by_slug, -> { order('slug asc, language_id asc nulls first') }
|
30
|
+
scope :visible, -> { where(visible: true) }
|
31
|
+
scope :list_for_administration, -> { ordered_by_slug }
|
32
|
+
|
33
|
+
# @param [String] slug
|
34
|
+
# @param [String] language_code
|
35
|
+
def self.localized_block(slug, language_code)
|
36
|
+
language = Language.find_by(code: language_code)
|
37
|
+
criteria = { visible: true, slug: slug }
|
38
|
+
find_by(criteria.merge(language: language)) || find_by(criteria)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.entity_parameters
|
42
|
+
%i[body description footer image language_id lead name raw_output slug title visible]
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param [User] user
|
46
|
+
def editable_by?(user)
|
47
|
+
UserPrivilege.user_has_privilege?(user, :content_manager)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class LinkBlock < ApplicationRecord
|
2
|
+
include Checkable
|
3
|
+
include Toggleable
|
4
|
+
|
5
|
+
toggleable :visible
|
6
|
+
|
7
|
+
SLUG_LIMIT = 50
|
8
|
+
SLUG_PATTERN = /\A[a-z][-_a-z0-9]*[a-z]\z/i
|
9
|
+
SLUG_PATTERN_HTML = '^[a-zA-Z][-_a-zA_Z0-9]*[a-zA-Z]$'
|
10
|
+
TITLE_LIMIT = 255
|
11
|
+
TEXT_LIMIT = 5000
|
12
|
+
|
13
|
+
belongs_to :language, optional: true
|
14
|
+
has_many :link_block_items, dependent: :destroy
|
15
|
+
|
16
|
+
validates_uniqueness_of :slug, scope: [:language_id]
|
17
|
+
validates_format_of :slug, with: SLUG_PATTERN
|
18
|
+
validates_length_of :slug, maximum: SLUG_LIMIT
|
19
|
+
validates_length_of :title, maximum: TITLE_LIMIT
|
20
|
+
validates_length_of :lead, maximum: TEXT_LIMIT
|
21
|
+
validates_length_of :footer_text, maximum: TEXT_LIMIT
|
22
|
+
|
23
|
+
scope :ordered_by_slug, -> { order('slug asc, language_id asc nulls first') }
|
24
|
+
scope :visible, -> { where(visible: true) }
|
25
|
+
scope :list_for_administration, -> { ordered_by_slug }
|
26
|
+
|
27
|
+
# @param [String] slug
|
28
|
+
# @param [String] language_code
|
29
|
+
def self.localized_block(slug, language_code)
|
30
|
+
language = Language.find_by(code: language_code)
|
31
|
+
criteria = { visible: true, slug: slug }
|
32
|
+
find_by(criteria.merge(language: language)) || find_by(criteria)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.entity_parameters
|
36
|
+
%i(footer_text language_id lead slug title visible)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [User] user
|
40
|
+
def editable_by?(user)
|
41
|
+
UserPrivilege.user_has_privilege?(user, :content_manager)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class LinkBlockItem < ApplicationRecord
|
2
|
+
include Checkable
|
3
|
+
include Toggleable
|
4
|
+
|
5
|
+
BUTTON_TEXT_LIMIT = 50
|
6
|
+
META_LIMIT = 255
|
7
|
+
PRIORITY_RANGE = (1..32767)
|
8
|
+
SLUG_LIMIT = 50
|
9
|
+
SLUG_PATTERN = /\A[a-z][-_a-z0-9]*[a-z]\z/i
|
10
|
+
SLUG_PATTERN_HTML = '^[a-zA-Z][-_a-zA_Z0-9]*[a-zA-Z]$'
|
11
|
+
TITLE_LIMIT = 255
|
12
|
+
TEXT_LIMIT = 5000
|
13
|
+
URL_LIMIT = 255
|
14
|
+
|
15
|
+
toggleable :visible
|
16
|
+
|
17
|
+
mount_uploader :image, LinkBlockImageUploader
|
18
|
+
|
19
|
+
belongs_to :link_block
|
20
|
+
|
21
|
+
after_initialize :set_next_priority
|
22
|
+
before_validation { self.slug = nil if slug.blank? }
|
23
|
+
before_validation { self.slug = slug.strip unless slug.nil? }
|
24
|
+
before_validation :normalize_priority
|
25
|
+
|
26
|
+
validates_format_of :slug, with: SLUG_PATTERN, allow_nil: true
|
27
|
+
validates_length_of :body, maximum: TEXT_LIMIT
|
28
|
+
validates_length_of :button_text, maximum: BUTTON_TEXT_LIMIT
|
29
|
+
validates_length_of :button_url, maximum: URL_LIMIT
|
30
|
+
validates_length_of :image_alt_text, maximum: META_LIMIT
|
31
|
+
validates_length_of :slug, maximum: SLUG_LIMIT
|
32
|
+
validates_length_of :title, maximum: TITLE_LIMIT
|
33
|
+
|
34
|
+
scope :ordered_by_priority, -> { order('priority asc, slug asc') }
|
35
|
+
scope :siblings, -> (link_block_id) { where(link_block_id: link_block_id) }
|
36
|
+
scope :visible, -> { where(visible: true) }
|
37
|
+
scope :list_for_administration, -> { ordered_by_priority }
|
38
|
+
scope :list_for_visitors, -> { visible.ordered_by_priority }
|
39
|
+
|
40
|
+
def self.entity_parameters
|
41
|
+
%i(body button_text button_url image image_alt_text priority slug title visible)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.creation_parameters
|
45
|
+
entity_parameters + %i(link_block_id)
|
46
|
+
end
|
47
|
+
|
48
|
+
def text_for_link
|
49
|
+
if title.blank?
|
50
|
+
slug.blank? ? "#{link_block.slug}-#{priority}" : slug
|
51
|
+
else
|
52
|
+
title
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [Integer] delta
|
57
|
+
def change_priority(delta)
|
58
|
+
new_priority = priority + delta
|
59
|
+
criteria = { priority: new_priority }
|
60
|
+
adjacent = self.class.siblings(link_block_id).find_by(criteria)
|
61
|
+
if adjacent.is_a?(self.class) && (adjacent.id != id)
|
62
|
+
adjacent.update!(priority: priority)
|
63
|
+
end
|
64
|
+
update(priority: new_priority)
|
65
|
+
|
66
|
+
self.class.siblings(link_block_id).ordered_by_priority.map { |e| [e.id, e.priority] }.to_h
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def set_next_priority
|
72
|
+
if id.nil? && priority == 1
|
73
|
+
self.priority = self.class.siblings(link_block_id).maximum(:priority).to_i + 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def normalize_priority
|
78
|
+
self.priority = PRIORITY_RANGE.first if priority < PRIORITY_RANGE.first
|
79
|
+
self.priority = PRIORITY_RANGE.last if priority > PRIORITY_RANGE.last
|
80
|
+
end
|
81
|
+
end
|
data/app/models/privilege.rb
CHANGED
@@ -34,8 +34,10 @@ class Privilege < ApplicationRecord
|
|
34
34
|
scope :ordered_by_priority, -> { order('priority asc, name asc') }
|
35
35
|
scope :ordered_by_name, -> { order('name asc, slug asc') }
|
36
36
|
scope :visible, -> { where(visible: true, deleted: false) }
|
37
|
+
scope :administrative, -> { where(administrative: true) }
|
37
38
|
scope :for_tree, ->(parent_id = nil) { where(parent_id: parent_id).ordered_by_priority }
|
38
39
|
scope :siblings, ->(item) { where(parent_id: item.parent_id) }
|
40
|
+
scope :list_for_administration, -> { ordered_by_name }
|
39
41
|
|
40
42
|
def self.page_for_administration
|
41
43
|
ordered_by_name
|
@@ -54,11 +56,16 @@ class Privilege < ApplicationRecord
|
|
54
56
|
(parents.map(&:name) + [name]).join ' / '
|
55
57
|
end
|
56
58
|
|
57
|
-
# @
|
59
|
+
# @deprecated use #subbranch_ids
|
58
60
|
def ids
|
59
61
|
[id] + children_cache
|
60
62
|
end
|
61
63
|
|
64
|
+
# @return [Array<Integer>]
|
65
|
+
def subbranch_ids
|
66
|
+
[id] + children_cache
|
67
|
+
end
|
68
|
+
|
62
69
|
# @return [Array<Integer>]
|
63
70
|
def branch_ids
|
64
71
|
parents_cache.split(',').map(&:to_i).reject { |i| i < 1 }.uniq + [id]
|
@@ -124,7 +131,8 @@ class Privilege < ApplicationRecord
|
|
124
131
|
# @param [Integer] delta
|
125
132
|
def change_priority(delta)
|
126
133
|
new_priority = priority + delta
|
127
|
-
|
134
|
+
criteria = { priority: new_priority }
|
135
|
+
adjacent = self.class.siblings(self).find_by(criteria)
|
128
136
|
if adjacent.is_a?(self.class) && (adjacent.id != id)
|
129
137
|
adjacent.update!(priority: priority)
|
130
138
|
end
|
@@ -30,6 +30,11 @@ class PrivilegeGroup < ApplicationRecord
|
|
30
30
|
%i(name slug description)
|
31
31
|
end
|
32
32
|
|
33
|
+
# @param [String] slug
|
34
|
+
def self.users(slug)
|
35
|
+
User.with_privilege_ids(ids(slug)).ordered_by_screen_name
|
36
|
+
end
|
37
|
+
|
33
38
|
# @param [Privilege] privilege
|
34
39
|
def has_privilege?(privilege)
|
35
40
|
privilege_group_privileges.exists?(privilege: privilege)
|
data/app/models/user.rb
CHANGED
@@ -39,6 +39,8 @@ class User < ApplicationRecord
|
|
39
39
|
before_save :normalize_slug
|
40
40
|
before_save :prepare_search_string
|
41
41
|
|
42
|
+
before_validation { self.email = nil if email.blank? }
|
43
|
+
|
42
44
|
validates_acceptance_of :consent
|
43
45
|
validates_presence_of :screen_name
|
44
46
|
validates_format_of :screen_name, with: SCREEN_NAME_PATTERN, if: :native_slug?
|
@@ -52,6 +54,8 @@ class User < ApplicationRecord
|
|
52
54
|
validates_length_of :notice, maximum: NOTICE_LIMIT
|
53
55
|
|
54
56
|
scope :with_privilege, ->(privilege) { joins(:user_privileges).where(user_privileges: { privilege_id: privilege.branch_ids }) }
|
57
|
+
scope :with_privilege_ids, -> (privilege_ids) { joins(:user_privileges).where(user_privileges: { privilege_id: privilege_ids }) }
|
58
|
+
scope :ordered_by_screen_name, -> { order('screen_name asc') }
|
55
59
|
scope :bots, ->(flag) { where(bot: flag.to_i > 0) unless flag.blank? }
|
56
60
|
scope :email_like, ->(val) { where('email ilike ?', "%#{val}%") unless val.blank? }
|
57
61
|
scope :with_email, ->(email) { where('lower(email) = lower(?)', email) }
|
@@ -11,7 +11,7 @@ class UserPrivilege < ApplicationRecord
|
|
11
11
|
def self.ids(user)
|
12
12
|
privileges = user&.privileges
|
13
13
|
return [] if privileges.blank?
|
14
|
-
privileges.map(&:
|
14
|
+
privileges.map(&:subbranch_ids).flatten.uniq
|
15
15
|
end
|
16
16
|
|
17
17
|
# @param [User] user
|
@@ -25,10 +25,15 @@ class UserPrivilege < ApplicationRecord
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# @param [User] user
|
28
|
-
|
28
|
+
# @param [TrueClass|FalseClass] administrative
|
29
|
+
def self.user_has_any_privilege?(user, administrative = true)
|
29
30
|
return false if user.nil?
|
30
31
|
return true if user.super_user?
|
31
|
-
|
32
|
+
criteria = { user: user }
|
33
|
+
if administrative
|
34
|
+
criteria[:privilege_id] = Privilege.administrative.pluck(:id)
|
35
|
+
end
|
36
|
+
exists?(criteria)
|
32
37
|
end
|
33
38
|
|
34
39
|
# @param [User] user
|
@@ -2,13 +2,13 @@ class UserProfileHandler
|
|
2
2
|
GENDERS = { 0 => 'female', 1 => 'male' }
|
3
3
|
|
4
4
|
def self.allowed_parameters
|
5
|
-
%w(gender name patronymic surname)
|
5
|
+
%w(gender name patronymic surname about)
|
6
6
|
end
|
7
7
|
|
8
8
|
# @param [Hash] input
|
9
9
|
def self.clean_parameters(input)
|
10
10
|
if input.key?('gender')
|
11
|
-
gender_key = input['gender'].to_i
|
11
|
+
gender_key = input['gender'].blank? ? nil : input['gender'].to_i
|
12
12
|
gender = GENDERS.key?(gender_key) ? gender_key : nil
|
13
13
|
else
|
14
14
|
gender = nil
|
@@ -14,7 +14,11 @@ class EditablePageImageUploader < CarrierWave::Uploader::Base
|
|
14
14
|
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
15
15
|
end
|
16
16
|
|
17
|
-
version :
|
17
|
+
version :large do
|
18
|
+
resize_to_fit 1920, 1920
|
19
|
+
end
|
20
|
+
|
21
|
+
version :medium_2x, from_version: :large do
|
18
22
|
resize_to_fit 1280, 1280
|
19
23
|
end
|
20
24
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class LinkBlockImageUploader < CarrierWave::Uploader::Base
|
2
|
+
# Choose what kind of storage to use for this uploader:
|
3
|
+
storage :file
|
4
|
+
# storage :fog
|
5
|
+
|
6
|
+
# Override the directory where uploaded files will be stored.
|
7
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
8
|
+
def store_dir
|
9
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add a white list of extensions which are allowed to be uploaded.
|
13
|
+
# For images you might use something like this:
|
14
|
+
def extension_whitelist
|
15
|
+
%w(jpg jpeg png svg)
|
16
|
+
end
|
17
|
+
end
|