biovision-post 0.21.190513.0 → 0.26.191013.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/biovision_post_manifest.js +1 -0
  3. data/app/assets/images/biovision/post/icons/comment.svg +9 -0
  4. data/app/assets/javascripts/biovision/post/biovision-posts.js +21 -28
  5. data/app/assets/stylesheets/biovision/post/posts.scss +6 -0
  6. data/app/controllers/admin/editorial_members_controller.rb +9 -4
  7. data/app/controllers/admin/featured_posts_controller.rb +9 -4
  8. data/app/controllers/admin/post_categories_controller.rb +12 -6
  9. data/app/controllers/admin/post_group_categories_controller.rb +9 -4
  10. data/app/controllers/admin/post_group_tags_controller.rb +9 -4
  11. data/app/controllers/admin/post_groups_controller.rb +9 -4
  12. data/app/controllers/admin/post_illustrations_controller.rb +9 -4
  13. data/app/controllers/admin/post_images_controller.rb +9 -4
  14. data/app/controllers/admin/post_links_controller.rb +9 -4
  15. data/app/controllers/admin/post_tags_controller.rb +9 -4
  16. data/app/controllers/admin/post_types_controller.rb +13 -4
  17. data/app/controllers/admin/posts_controller.rb +6 -8
  18. data/app/controllers/articles_controller.rb +16 -6
  19. data/app/controllers/authors_controller.rb +9 -4
  20. data/app/controllers/blog_posts_controller.rb +16 -6
  21. data/app/controllers/editorial_members_controller.rb +9 -4
  22. data/app/controllers/featured_posts_controller.rb +6 -1
  23. data/app/controllers/my/posts_controller.rb +35 -38
  24. data/app/controllers/news_controller.rb +16 -6
  25. data/app/controllers/post_attachments_controller.rb +36 -0
  26. data/app/controllers/post_categories_controller.rb +6 -1
  27. data/app/controllers/post_groups_controller.rb +9 -4
  28. data/app/controllers/post_illustrations_controller.rb +6 -1
  29. data/app/controllers/post_images_controller.rb +9 -8
  30. data/app/controllers/post_links_controller.rb +5 -2
  31. data/app/controllers/post_tags_controller.rb +9 -4
  32. data/app/controllers/posts_controller.rb +39 -17
  33. data/app/helpers/biovision_posts_helper.rb +28 -27
  34. data/app/jobs/post_body_parser_job.rb +1 -1
  35. data/app/models/concerns/post_child_with_priority.rb +2 -1
  36. data/app/models/editorial_member.rb +10 -1
  37. data/app/models/post.rb +39 -11
  38. data/app/models/post_attachment.rb +49 -0
  39. data/app/models/post_category.rb +6 -0
  40. data/app/models/post_group_category.rb +1 -1
  41. data/app/models/post_illustration.rb +2 -1
  42. data/app/models/post_image.rb +2 -1
  43. data/app/models/post_type.rb +15 -0
  44. data/app/services/biovision/components/posts_component.rb +65 -0
  45. data/app/views/admin/components/links/_posts.html.erb +33 -0
  46. data/app/views/admin/editorial_members/index.html.erb +2 -1
  47. data/app/views/admin/editorial_members/show.html.erb +1 -0
  48. data/app/views/admin/featured_posts/index.html.erb +1 -0
  49. data/app/views/admin/post_categories/entity/_in_list.html.erb +10 -0
  50. data/app/views/admin/post_categories/show.html.erb +11 -0
  51. data/app/views/admin/post_groups/index.html.erb +2 -1
  52. data/app/views/admin/post_groups/show.html.erb +1 -0
  53. data/app/views/admin/post_illustrations/index.html.erb +1 -0
  54. data/app/views/admin/post_illustrations/show.html.erb +1 -0
  55. data/app/views/admin/post_images/index.html.erb +2 -1
  56. data/app/views/admin/post_images/show.html.erb +1 -0
  57. data/app/views/admin/post_tags/index.html.erb +2 -1
  58. data/app/views/admin/post_tags/posts.html.erb +4 -3
  59. data/app/views/admin/post_tags/show.html.erb +3 -2
  60. data/app/views/admin/post_types/authors.html.erb +1 -0
  61. data/app/views/admin/post_types/index.html.erb +2 -1
  62. data/app/views/admin/post_types/new_post.html.erb +13 -4
  63. data/app/views/admin/post_types/post_categories.html.erb +1 -0
  64. data/app/views/admin/post_types/post_tags.html.erb +4 -3
  65. data/app/views/admin/post_types/show.html.erb +3 -2
  66. data/app/views/admin/posts/entity/_in_list.html.erb +3 -3
  67. data/app/views/admin/posts/images.html.erb +1 -0
  68. data/app/views/admin/posts/index.html.erb +2 -1
  69. data/app/views/admin/posts/search.html.erb +10 -1
  70. data/app/views/admin/posts/show.html.erb +6 -7
  71. data/app/views/authors/show.html.erb +1 -1
  72. data/app/views/blog_posts/index.html.erb +4 -2
  73. data/app/views/editorial_members/edit.html.erb +1 -0
  74. data/app/views/editorial_members/new.html.erb +3 -2
  75. data/app/views/my/index/dashboard/_biovision_post.html.erb +5 -4
  76. data/app/views/my/posts/_form.html.erb +40 -194
  77. data/app/views/my/posts/_post.html.erb +2 -3
  78. data/app/views/my/posts/articles.html.erb +1 -1
  79. data/app/views/my/posts/blog_posts.html.erb +1 -1
  80. data/app/views/my/posts/index/_navigation.html.erb +3 -3
  81. data/app/views/my/posts/new.html.erb +9 -1
  82. data/app/views/my/posts/news_index.html.erb +1 -1
  83. data/app/views/posts/_breadcrumbs.html.erb +1 -6
  84. data/app/views/posts/_form.html.erb +9 -2
  85. data/app/views/posts/_post.html.erb +7 -11
  86. data/app/views/posts/_preview.html.erb +7 -1
  87. data/app/views/posts/edit.html.erb +9 -1
  88. data/app/views/posts/post_type/_category.html.erb +4 -2
  89. data/app/views/posts/post_type/_post_page.html.erb +7 -1
  90. data/app/views/posts/post_type/_posts.html.erb +11 -2
  91. data/app/views/posts/post_type/_tagged.html.erb +4 -4
  92. data/app/views/posts/rss.xml.erb +1 -1
  93. data/app/views/posts/show.html.erb +0 -5
  94. data/app/views/posts/zen.xml.erb +3 -3
  95. data/config/locales/posts-ru.yml +11 -1
  96. data/config/routes.rb +3 -0
  97. data/db/{migrate → amends}/20190202232323_add_spam_to_posts.rb +0 -0
  98. data/db/{migrate → amends}/20190224212121_add_data_to_posts.rb +0 -0
  99. data/db/{migrate → amends}/20190224212122_rename_post_image_source.rb +0 -0
  100. data/db/{migrate → amends}/20190224212123_add_uuid_to_post_images.rb +0 -0
  101. data/db/{migrate → amends}/20190313141414_convert_json_post_columns.rb +0 -0
  102. data/db/amends/20190925181818_add_search_index_to_posts.rb +24 -0
  103. data/db/migrate/20170930000001_create_post_types.rb +4 -13
  104. data/db/migrate/20170930000010_create_posts.rb +26 -3
  105. data/db/migrate/20190715141414_add_data_to_post_categories.rb +14 -0
  106. data/db/migrate/20190801161616_add_posts_component.rb +14 -0
  107. data/db/migrate/20190822121212_create_post_attachments.rb +20 -0
  108. data/db/migrate/20190914212121_convert_post_privileges.rb +56 -0
  109. data/lib/biovision/post/version.rb +1 -1
  110. metadata +18 -13
  111. data/app/services/post_manager.rb +0 -71
  112. data/app/views/admin/index/dashboard/_biovision_post.html.erb +0 -36
  113. data/app/views/articles/show.html.erb +0 -6
  114. data/app/views/blog_posts/show.html.erb +0 -6
  115. data/app/views/news/show.html.erb +0 -6
@@ -26,13 +26,18 @@ class PostTagsController < AdminController
26
26
 
27
27
  private
28
28
 
29
- def set_entity
30
- @entity = PostTag.find_by(id: params[:id])
31
- handle_http_404('Cannot find post_tag') if @entity.nil?
29
+ def component_slug
30
+ Biovision::Components::PostsComponent::SLUG
32
31
  end
33
32
 
34
33
  def restrict_access
35
- require_privilege_group :editors
34
+ error = 'Managing post tags is not allowed'
35
+ handle_http_401(error) unless component_handler.allow?('chief_editor')
36
+ end
37
+
38
+ def set_entity
39
+ @entity = PostTag.find_by(id: params[:id])
40
+ handle_http_404('Cannot find post_tag') if @entity.nil?
36
41
  end
37
42
 
38
43
  def entity_parameters
@@ -20,8 +20,9 @@ class PostsController < ApplicationController
20
20
  if @entity.save
21
21
  apply_post_tags
22
22
  apply_post_categories
23
- PostBodyParserJob.perform_later(@entity.id)
24
- form_processed_ok(PostManager.new(@entity).post_path)
23
+ add_attachments if params.key?(:post_attachment)
24
+ mark_as_featured if params[:featured]
25
+ form_processed_ok(@entity.url)
25
26
  else
26
27
  form_processed_with_error(:new)
27
28
  end
@@ -48,8 +49,8 @@ class PostsController < ApplicationController
48
49
  if @entity.update(entity_parameters)
49
50
  apply_post_tags
50
51
  apply_post_categories
51
- PostBodyParserJob.perform_later(@entity.id)
52
- form_processed_ok(PostManager.new(@entity).post_path)
52
+ add_attachments if params.key?(:post_attachment)
53
+ form_processed_ok(@entity.url)
53
54
  else
54
55
  form_processed_with_error(:edit)
55
56
  end
@@ -57,9 +58,8 @@ class PostsController < ApplicationController
57
58
 
58
59
  # delete /posts/:id
59
60
  def destroy
60
- if @entity.destroy #@entity.update(deleted: true)
61
- flash[:notice] = t('posts.destroy.success')
62
- end
61
+ flash[:notice] = t('posts.destroy.success') if @entity.destroy #@entity.update(deleted: true)
62
+
63
63
  redirect_to admin_posts_path
64
64
  end
65
65
 
@@ -70,7 +70,8 @@ class PostsController < ApplicationController
70
70
 
71
71
  # get /posts/:category_slug
72
72
  def category
73
- @collection = Post.in_category(params[:category_slug]).page_for_visitors(current_page)
73
+ posts = Post.in_category(params[:category_slug])
74
+ @collection = posts.page_for_visitors(current_page)
74
75
  @category = @collection.first&.post_category
75
76
 
76
77
  handle_http_404('Cannot find post category in collection') if @category.nil?
@@ -88,12 +89,14 @@ class PostsController < ApplicationController
88
89
 
89
90
  # get /posts/rss/zen.xml
90
91
  def zen
91
- @collection = Post.for_language(current_language).list_for_visitors.posted_after(3.days.ago)
92
+ posts = Post.for_language(current_language).list_for_visitors
93
+ @collection = posts.posted_after(3.days.ago)
92
94
  end
93
95
 
94
96
  # get /posts/rss.xml
95
97
  def rss
96
- @collection = Post.for_language(current_language).list_for_visitors.first(20)
98
+ posts = Post.for_language(current_language).list_for_visitors
99
+ @collection = posts.first(20)
97
100
  end
98
101
 
99
102
  # get /posts/archive/(:year)(-:month)(-:day)
@@ -108,17 +111,22 @@ class PostsController < ApplicationController
108
111
 
109
112
  private
110
113
 
111
- def set_entity
112
- @entity = Post.find_by(id: params[:id])
113
- handle_http_404('Cannot find post') if @entity.nil?
114
+ def component_slug
115
+ Biovision::Components::PostsComponent::SLUG
114
116
  end
115
117
 
116
118
  def restrict_access
117
- require_privilege_group :editors
119
+ error = 'Managing posts is not allowed'
120
+ handle_http_401(error) unless component_handler.allow?
121
+ end
122
+
123
+ def set_entity
124
+ @entity = Post.find_by(id: params[:id])
125
+ handle_http_404('Cannot find post') if @entity.nil?
118
126
  end
119
127
 
120
128
  def restrict_editing
121
- if @entity.locked? || !@entity.editable_by?(current_user)
129
+ if @entity.locked? || !component_handler.editable?(@entity)
122
130
  handle_http_403('Post is locked or not editable by current user')
123
131
  end
124
132
  end
@@ -147,7 +155,7 @@ class PostsController < ApplicationController
147
155
  def owner_for_post
148
156
  key = :user_for_entity
149
157
  result = {}
150
- if current_user_has_privilege?(:chief_editor) && params.key?(key)
158
+ if component_handler.group?(:chief) && params.key?(key)
151
159
  result[:user_id] = param_from_request(key)
152
160
  end
153
161
  result
@@ -178,7 +186,21 @@ class PostsController < ApplicationController
178
186
  if Post.respond_to?(:search)
179
187
  Post.search(q).records.first(50).select(&:visible_to_visitors?)
180
188
  else
181
- Post.where('title ilike ?', "%#{q}%").list_for_visitors.first(50)
189
+ Post.pg_search(q).list_for_visitors.first(50)
182
190
  end
183
191
  end
192
+
193
+ def add_attachments
194
+ permitted = PostAttachment.entity_parameters
195
+ parameters = params.require(:post_attachment).permit(permitted)
196
+
197
+ @entity.post_attachments.create(parameters)
198
+ end
199
+
200
+ def mark_as_featured
201
+ FeaturedPost.where(language: @entity.language).update_all('priority = priority + 1')
202
+ link = FeaturedPost.new(language: @entity.language, post: @entity)
203
+ link.priority = 1
204
+ link.save
205
+ end
184
206
  end
@@ -70,26 +70,6 @@ module BiovisionPostsHelper
70
70
  end
71
71
  end
72
72
 
73
- # @param [Integer] post_type_id
74
- # @param [String] first_item
75
- def post_categories_for_select(post_type_id, first_item = t(:not_set))
76
- options = [[first_item, '']]
77
- PostCategory.for_tree(post_type_id).each do |category|
78
- options << [category.name, category.id]
79
- if category.child_categories.any?
80
- PostCategory.for_tree(post_type_id, category.id).each do |subcategory|
81
- options << ["-#{subcategory.name}", subcategory.id]
82
- if subcategory.child_categories.any?
83
- PostCategory.for_tree(post_type_id, subcategory.id).each do |deep_category|
84
- options << ["--#{deep_category.name}", deep_category.id]
85
- end
86
- end
87
- end
88
- end
89
- end
90
- options
91
- end
92
-
93
73
  def post_layouts_for_select
94
74
  options = PostLayout.ordered_by_name.map { |i| [i.name, i.id] }
95
75
  options + [[t(:not_set), '']]
@@ -99,13 +79,22 @@ module BiovisionPostsHelper
99
79
  # @param [String] text
100
80
  # @param [Hash] options
101
81
  def post_link(entity, text = entity.title, options = {})
102
- link_to(text, PostManager.new(entity).post_path, options)
82
+ link_to(text, entity.url, options)
103
83
  end
104
84
 
105
- # @param [Post|PostCategory] entity
106
- def post_category_link(entity)
107
- handler = PostManager.new(entity)
108
- link_to(handler.category_name, handler.category_path)
85
+ # @param [PostCategory] entity
86
+ # @param [String] text
87
+ # @param [Hash] options
88
+ def post_category_link(entity, text = nil, options = {})
89
+ text ||= entity.respond_to?(:name) ? entity.name : entity.title
90
+ link_to(text, entity.url, options)
91
+ end
92
+
93
+ # @param [PostType] entity
94
+ # @param [String] text
95
+ # @param [Hash] options
96
+ def post_type_link(entity, text = entity.category_name!, options = {})
97
+ link_to(text, entity.url, options)
109
98
  end
110
99
 
111
100
  # @param [PostGroup] entity
@@ -134,11 +123,23 @@ module BiovisionPostsHelper
134
123
  if entity.nil?
135
124
  link_to(tag_name, tagged_posts_path(tag_name: tag_name), rel: 'tag')
136
125
  else
137
- handler = PostManager.new(entity)
138
- link_to(tag_name, handler.tagged_path(tag_name), rel: 'tag')
126
+ link_to(tag_name, entity.tagged_path(tag_name), rel: 'tag')
139
127
  end
140
128
  end
141
129
 
130
+ # @param [PostAttachment] entity
131
+ # @param [String] text
132
+ # @param [Hash] options
133
+ def post_attachment_link(entity, text = entity.name!, options = {})
134
+ return '' if entity.file.blank?
135
+
136
+ default_options = {
137
+ target: '_blank'
138
+ }
139
+
140
+ link_to(text, entity.file.url, default_options.merge(options))
141
+ end
142
+
142
143
  # Post image preview for displaying in "administrative" lists
143
144
  #
144
145
  # @param [Post] entity
@@ -10,6 +10,6 @@ class PostBodyParserJob < ApplicationJob
10
10
 
11
11
  return if post.nil?
12
12
 
13
- post.update(parsed_body: PostManager.new(post).parsed_body)
13
+ post.update(parsed_body: PostParser.new(post).parsed_body)
14
14
  end
15
15
  end
@@ -15,8 +15,9 @@ module PostChildWithPriority
15
15
  end
16
16
 
17
17
  # @param [User] user
18
+ # @deprecated use component handler
18
19
  def editable_by?(user)
19
- post.editable_by?(user)
20
+ Biovision::Components::BaseComponent.handler('posts', user).editable?(post)
20
21
  end
21
22
 
22
23
  # @param [Integer] delta
@@ -50,6 +50,14 @@ class EditorialMember < ApplicationRecord
50
50
  user.is_a?(self) || owned_by(user).visible.exists?
51
51
  end
52
52
 
53
+ # @param [String|User] user
54
+ def self.[](user)
55
+ criteria = {
56
+ user: user.is_a?(User) ? user : User.find_by(slug: user)
57
+ }
58
+ find_by(criteria)
59
+ end
60
+
53
61
  def name
54
62
  user.profile_name
55
63
  end
@@ -71,8 +79,9 @@ class EditorialMember < ApplicationRecord
71
79
  end
72
80
 
73
81
  # @param [User] user
82
+ # @deprecated use component handler
74
83
  def editable_by?(user)
75
- UserPrivilege.user_has_privilege?(user, :chief_editor)
84
+ Biovision::Components::BaseComponent.handler('posts', user).editable?(self)
76
85
  end
77
86
 
78
87
  # @param [PostType] post_type
@@ -45,21 +45,19 @@ class Post < ApplicationRecord
45
45
  has_many :post_post_tags, dependent: :destroy
46
46
  has_many :post_tags, through: :post_post_tags
47
47
  has_many :post_images, dependent: :destroy
48
+ has_many :post_attachments, dependent: :destroy
48
49
  has_many :post_translations, dependent: :delete_all
49
50
  has_many :post_zen_categories, dependent: :destroy
50
51
  has_many :zen_categories, through: :post_zen_categories
51
52
 
52
53
  after_initialize { self.uuid = SecureRandom.uuid if uuid.nil? }
53
54
  after_initialize { self.publication_time = Time.now if publication_time.nil? }
54
- before_validation { self.slug = Canonizer.transliterate(title.to_s) if slug.blank? }
55
- before_validation { self.slug = slug.downcase }
55
+ before_validation :prepare_slug
56
56
  before_validation :prepare_source_names
57
57
 
58
58
  validates_presence_of :uuid, :title, :slug, :body
59
59
  validates_length_of :title, maximum: TITLE_LIMIT
60
- validates_length_of :slug, maximum: SLUG_LIMIT
61
60
  validates_length_of :lead, maximum: LEAD_LIMIT
62
- validates_length_of :body, maximum: BODY_LIMIT
63
61
  validates_length_of :image_name, maximum: IMAGE_NAME_LIMIT
64
62
  validates_length_of :image_alt_text, maximum: ALT_LIMIT
65
63
  validates_length_of :image_source_name, maximum: META_LIMIT
@@ -74,14 +72,15 @@ class Post < ApplicationRecord
74
72
  validates_length_of :author_title, maximum: META_LIMIT
75
73
  validates_length_of :author_url, maximum: META_LIMIT
76
74
  validates_length_of :translator_name, maximum: META_LIMIT
77
- validates_format_of :slug, with: SLUG_PATTERN
75
+ # validates_format_of :slug, with: SLUG_PATTERN
78
76
  validates_numericality_of :time_required, in: TIME_RANGE, allow_nil: true
79
77
 
80
78
  scope :recent, -> { order('publication_time desc') }
81
79
  scope :popular, -> { order('rating desc') }
82
80
  scope :visible, -> { where(visible: true, deleted: false, approved: true) }
83
81
  scope :published, -> { where('publication_time <= current_timestamp') }
84
- scope :for_language, ->(language) { where(language: language) }
82
+ scope :for_language, ->(language) { where(language: language).or(where(language: nil)) }
83
+ scope :pg_search, ->(v) { where("posts_tsvector(title, lead, body) @@ phraseto_tsquery('russian', ?)", v) }
85
84
  scope :exclude_ids, ->(v) { where('posts.id not in (?)', Array(v)) unless v.blank? }
86
85
  scope :list_for_visitors, -> { visible.published.recent }
87
86
  scope :list_for_administration, -> { order('id desc') }
@@ -89,6 +88,7 @@ class Post < ApplicationRecord
89
88
  scope :tagged, ->(tag) { joins(:post_post_tags).where(post_post_tags: { post_tag_id: PostTag.ids_for_name(tag) }).distinct unless tag.blank? }
90
89
  scope :in_category, ->(slug) { joins(:post_post_categories).where(post_post_categories: { post_category_id: PostCategory.ids_for_slug(slug) }).distinct unless slug.blank? }
91
90
  scope :in_category_branch, ->(category) { joins(:post_post_categories).where(post_post_categories: { post_category_id: category.subbranch_ids }).distinct }
91
+ scope :with_category_ids, ->(v) { joins(:post_post_categories).where(post_post_categories: { post_category_id: Array(v) }) }
92
92
  scope :authors, -> { User.where(id: Post.author_ids).order('screen_name asc') }
93
93
  scope :of_type, ->(slug) { where(post_type: PostType.find_by(slug: slug)) unless slug.blank? }
94
94
  scope :archive, -> { f = Arel.sql('date(publication_time)'); distinct.order(f).pluck(f) }
@@ -116,7 +116,7 @@ class Post < ApplicationRecord
116
116
  end
117
117
 
118
118
  def self.entity_parameters
119
- main_data = %i[body language_id lead original_title post_layout_id publication_time slug title]
119
+ main_data = %i[body language_id lead original_title post_layout_id publication_time region_id slug title]
120
120
  image_data = %i[image image_alt_text image_source_link image_source_name image_name]
121
121
  meta_data = %i[rating source_name source_link meta_title meta_description meta_keywords time_required]
122
122
  flags_data = %i[allow_comments allow_votes explicit show_owner visible translation]
@@ -148,9 +148,8 @@ class Post < ApplicationRecord
148
148
  def lead!
149
149
  if lead.blank?
150
150
  pattern = %r{<p>(.+?)</p>}
151
- chunk = parsed_body.blank? ? body : parsed_body
152
- passage = chunk.match(pattern)
153
- (passage.nil? ? chunk.gsub(/<[^>]+>/, '') : passage[1]).to_s[0..499]
151
+ passage = body.match(pattern)
152
+ (passage.nil? ? body.gsub(/<[^>]+>/, '') : passage[1]).to_s[0..499]
154
153
  else
155
154
  lead
156
155
  end
@@ -167,6 +166,25 @@ class Post < ApplicationRecord
167
166
  end
168
167
  end
169
168
 
169
+ # @param [Symbol] locale
170
+ def url(locale = I18n.default_locale)
171
+ prefix = locale.nil? || locale == I18n.default_locale ? '' : "/#{locale}"
172
+ "#{prefix}/#{post_type.url_part}/#{id}-#{slug}"
173
+ end
174
+
175
+ # @param [String] tag_name
176
+ # @param [Symbol] locale
177
+ def tagged_path(tag_name, locale = I18n.default_locale)
178
+ prefix = locale.nil? || locale == I18n.default_locale ? '' : "/#{locale}"
179
+ "#{prefix}/#{post_type.url_part}/tagged/#{CGI.escape(tag_name)}"
180
+ end
181
+
182
+ def enclosures
183
+ body.scan(/<img[^>]+>/).map do |image|
184
+ image.scan(/src="([^"]+)"/)[0][0]
185
+ end
186
+ end
187
+
170
188
  # Get editorial member instance for this post
171
189
  #
172
190
  # If user can be shown and is member of editorial, this method returns
@@ -223,8 +241,9 @@ class Post < ApplicationRecord
223
241
  end
224
242
 
225
243
  # @param [User] user
244
+ # @deprecated use component handler
226
245
  def editable_by?(user)
227
- owned_by?(user) || UserPrivilege.user_has_privilege?(user, :chief_editor)
246
+ Biovision::Components::BaseComponent.handler('posts', user).editable?(self)
228
247
  end
229
248
 
230
249
  def has_image_data?
@@ -253,8 +272,17 @@ class Post < ApplicationRecord
253
272
  update! tags_cache: post_tags.order('slug asc').map(&:name)
254
273
  end
255
274
 
275
+ def commentable_by?(user)
276
+ allow_comments? && !user.nil?
277
+ end
278
+
256
279
  private
257
280
 
281
+ def prepare_slug
282
+ self.slug = Canonizer.transliterate(title.to_s) if slug.blank?
283
+ self.slug = slug.downcase
284
+ end
285
+
258
286
  def prepare_source_names
259
287
  prepare_image_source
260
288
  prepare_source
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Model for post attachment
4
+ #
5
+ # Attributes
6
+ # created_at [DateTime]
7
+ # file [SimpleFileUploader]
8
+ # name [String]
9
+ # post_id [Post]
10
+ # updated_at [DateTime]
11
+ # uuid [UUID]
12
+ class PostAttachment < ApplicationRecord
13
+ include Checkable
14
+
15
+ NAME_LIMIT = 120
16
+
17
+ mount_uploader :file, SimpleFileUploader
18
+
19
+ belongs_to :post
20
+
21
+ after_initialize { self.uuid = SecureRandom.uuid if uuid.nil? }
22
+
23
+ validates_length_of :name, maximum: NAME_LIMIT
24
+ validates_presence_of :file
25
+
26
+ scope :ordered_for_list, -> { order('name asc, file asc') }
27
+
28
+ def self.entity_parameters
29
+ %i[file name]
30
+ end
31
+
32
+ def name!
33
+ return '' if file.blank?
34
+
35
+ name.blank? ? CGI.unescape(File.basename(file.path)) : name
36
+ end
37
+
38
+ def size
39
+ return 0 if file.blank?
40
+
41
+ File.size(file.path)
42
+ end
43
+
44
+ # @param [User] user
45
+ # @deprecated use component handler
46
+ def editable_by?(user)
47
+ Biovision::Components::BaseComponent.handler('posts', user).editable?(post)
48
+ end
49
+ end
@@ -141,6 +141,12 @@ class PostCategory < ApplicationRecord
141
141
  post_post_categories.where(post: post).delete_all
142
142
  end
143
143
 
144
+ # @param [Symbol] locale
145
+ def url(locale = I18n.default_locale)
146
+ prefix = locale.nil? || locale == I18n.default_locale ? '' : "/#{locale}"
147
+ "#{prefix}/#{post_type.url_part}/#{long_slug}"
148
+ end
149
+
144
150
  def text_for_link
145
151
  nav_text.blank? ? name : nav_text
146
152
  end