biovision-post 0.0.171104 → 0.1.171229

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 (54) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/images/biovision/post/icons/view.svg +1 -0
  3. data/app/assets/stylesheets/biovision/post/posts.scss +150 -0
  4. data/app/controllers/admin/post_types_controller.rb +1 -1
  5. data/app/controllers/admin/posts_controller.rb +26 -1
  6. data/app/controllers/articles_controller.rb +35 -0
  7. data/app/controllers/blog_posts_controller.rb +37 -0
  8. data/app/controllers/news_controller.rb +37 -0
  9. data/app/controllers/posts_controller.rb +11 -32
  10. data/app/helpers/biovision_posts_helper.rb +21 -4
  11. data/app/models/post.rb +21 -9
  12. data/app/models/post_type.rb +1 -1
  13. data/app/services/post_manager/article_handler.rb +10 -0
  14. data/app/services/post_manager/blog_post_handler.rb +10 -0
  15. data/app/services/post_manager/news_handler.rb +10 -0
  16. data/app/services/post_manager.rb +9 -0
  17. data/app/views/admin/index/_biovision_post.html.erb +29 -0
  18. data/app/views/admin/index/biovision_post/_additional_items.html.erb +0 -0
  19. data/app/views/admin/post_categories/show.html.erb +22 -21
  20. data/app/views/admin/post_types/show.html.erb +8 -5
  21. data/app/views/admin/posts/entity/_in_list.html.erb +38 -0
  22. data/app/views/admin/posts/index.html.erb +14 -0
  23. data/app/views/admin/posts/show.html.erb +99 -0
  24. data/app/views/articles/category.html.erb +18 -0
  25. data/app/views/articles/index.html.erb +14 -0
  26. data/app/views/articles/index.jbuilder +11 -0
  27. data/app/views/articles/show.html.erb +8 -0
  28. data/app/views/blog_posts/category.html.erb +18 -0
  29. data/app/views/blog_posts/index.html.erb +14 -0
  30. data/app/views/blog_posts/index.jbuilder +11 -0
  31. data/app/views/blog_posts/show.html.erb +8 -0
  32. data/app/views/index/index/_recent_posts.html.erb +5 -0
  33. data/app/views/news/category.html.erb +18 -0
  34. data/app/views/news/index.html.erb +14 -0
  35. data/app/views/news/index.jbuilder +11 -0
  36. data/app/views/news/show.html.erb +8 -0
  37. data/app/views/posts/_breadcrumbs.html.erb +11 -0
  38. data/app/views/posts/_form.html.erb +151 -122
  39. data/app/views/posts/_list.html.erb +9 -0
  40. data/app/views/posts/_post.html.erb +73 -67
  41. data/app/views/posts/_preview.html.erb +35 -0
  42. data/app/views/posts/edit.html.erb +12 -0
  43. data/app/views/posts/entity/_metadata.html.erb +4 -2
  44. data/app/views/posts/form/_wysiwyg.html.erb +1 -1
  45. data/config/locales/posts-en.yml +175 -0
  46. data/config/locales/posts-ru.yml +52 -3
  47. data/config/routes.rb +28 -2
  48. data/db/migrate/20170930000001_create_post_types.rb +1 -0
  49. data/db/migrate/20170930000002_create_post_categories.rb +1 -1
  50. data/db/migrate/20170930000003_create_posts.rb +11 -7
  51. data/db/migrate/20171218111111_add_meta_fields_to_posts.rb +15 -0
  52. data/db/migrate/20171219111112_add_author_fields_to_posts.rb +11 -0
  53. data/lib/biovision/post/version.rb +1 -1
  54. metadata +34 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 871f4df57bc36185ad704b40973eac86de0dc805
4
- data.tar.gz: 5a6597244a86d50a0d22f6a831bfd6642f62d5d3
2
+ SHA256:
3
+ metadata.gz: be80d9c2f7d4d049810beb5d10445ad941141a6984fedefc72afc66f5d8aa26c
4
+ data.tar.gz: 18afaf4b8bd45ccce8ed430f44ebb2ba29782b81ea0ed835fb7a1f77ae1e83a7
5
5
  SHA512:
6
- metadata.gz: 6764d17960b4ec4761885b21b9731e0d2d268a3d79a0ee69af5a9bb556397cfab5b8635b070d1be8674acc670be483452d5cf4a5032f3b31e97b6b3e58cf6f0d
7
- data.tar.gz: 5aed65b3c46a6f6b2b75bb7b95a204be0471cadb76e25483145d2796ce07c02793e46ea8659ea2541796911013aa73fd902acfa44481b40be69c6cb74101ee7e
6
+ metadata.gz: b7e5489d2ca7af603433b61f51fa4b9c15871b4e0c146eb2fd19840bc52e73788f894386859b85700fd7fc5c09e0f60634bc9bda5e9e6ef942a6c90817ba1c01
7
+ data.tar.gz: 1b5a1c2fad734dea9eb2c582a4f95fbc3bdb5eab16e2f5458fe42d9709ad8506e1708685b3e54d68be2850199d77771730f11bb0616c0a94fb5dacc87f6b80e4
@@ -0,0 +1 @@
1
+ <?xml version="1.0" ?><svg style="enable-background:new 0 0 93.388 75.594;" version="1.1" viewBox="0 0 93.388 75.594" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="search"><g><path d="M57.158,42.7l-2.041,1.076l-6.061-4.054l-0.669,0.762l5.607,3.994l-0.503,0.572c-0.836,0.953-1.522,2.376-2.059,4.268 c-0.615,2.047-0.683,3.534-0.204,4.461l-9.422-5.318c-3.705,3.835-8.748,5.736-15.131,5.702 c-6.593-0.05-12.336-2.224-17.228-6.518C4.747,43.517,1.864,39.496,0.8,35.581c-0.656-2.264-0.909-7.07-0.758-14.419 c0.685,6.845,3.648,12.568,8.89,17.17c5.591,4.909,11.841,7.752,18.752,8.531c7.753,0.845,13.986-1.419,18.699-6.788 c0.697-0.794,1.534-1.747,2.51-2.859L57.158,42.7z"/><path d="M51.853,21.927c-0.862-5.425-3.85-10.383-8.965-14.873c-5.147-4.518-11.186-6.866-18.116-7.044 C17.392-0.17,11.498,2.25,7.092,7.269c-8.952,10.197-7.9,20.149,3.154,29.854c5.401,4.742,11.505,7.4,18.311,7.975 c7.472,0.653,13.507-1.642,18.109-6.884C51.073,33.196,52.801,27.767,51.853,21.927z M44.868,36.804 c-4.156,4.734-9.637,6.812-16.444,6.236c-6.202-0.495-11.765-2.904-16.69-7.227C1.727,27.029,0.767,18.03,8.855,8.817 c4.016-4.574,9.369-6.794,16.057-6.66c6.326,0.098,11.825,2.197,16.495,6.296c4.67,4.1,7.405,8.61,8.204,13.53 C50.465,27.289,48.884,32.23,44.868,36.804z"/><path d="M38.683,13.453c6.735,5.913,8.805,13.102,6.21,21.568c-0.974-7.605-3.875-13.527-8.704-17.766 c-4.701-4.127-9.898-6.074-15.589-5.838c-5.692,0.235-10.666,2.619-14.924,7.149c0.623-1.927,1.66-3.717,3.11-5.369 c3.625-4.129,8.548-6.051,14.767-5.768C29.383,7.708,34.426,9.716,38.683,13.453z"/><path d="M31.133,32.963c-1.589,0.913-3.873,0.791-6.854-0.363c-2.456-0.918-4.541-2.131-6.257-3.637 c-2.097-1.84-3.291-3.845-3.581-6.012C19.638,25.488,25.202,28.826,31.133,32.963z"/><path d="M91.741,65.298c1.08,0.948,1.628,2.245,1.646,3.892c0.016,1.646-0.491,3.057-1.522,4.232 c-1.088,1.239-2.525,1.947-4.311,2.123c-1.547,0.16-2.776-0.075-3.685-0.704L53.183,54.82c-1.156-0.733-1.474-2.165-0.953-4.296 c0.468-2.007,1.442-3.853,2.92-5.537c1.004-1.144,2.281-1.541,3.832-1.192L87.85,62.81L91.741,65.298z"/></g></g><g id="Слой_1"/></svg>
@@ -0,0 +1,150 @@
1
+ $block-shadow: .2rem .2rem .4rem .2rem rgba(0, 0, 0, .125) !default;
2
+ $border-primary: .1rem solid rgb(192, 192, 192) !default;
3
+ $border-secondary: .1rem solid rgb(230, 230, 230) !default;
4
+ $text-color-secondary: #777 !default;
5
+ $font-size-large: 2rem !default;
6
+ $font-size-decreased: 1.2rem !default;
7
+ $font-family-heading: serif !default;
8
+
9
+ $background-post-footer: rgb(248, 248, 248) !default;
10
+ $background-post-preview-image: linear-gradient(to top, #f0f0f0, #fff) !default;
11
+
12
+ .recent-posts {
13
+ .list {
14
+ align-items: stretch;
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ justify-content: space-around;
18
+ }
19
+ }
20
+
21
+ .post-preview {
22
+ border-radius: .2rem;
23
+ box-shadow: $block-shadow;
24
+ display: flex;
25
+ flex: 1;
26
+ flex-direction: column;
27
+ margin: 1rem;
28
+ position: relative;
29
+ max-width: 30rem;
30
+ min-width: 28rem;
31
+
32
+ .image {
33
+ background: $background-post-preview-image;
34
+ border-radius: .2rem .2rem 0 0;
35
+ height: 20rem;
36
+ overflow: hidden;
37
+ width: 100%;
38
+ }
39
+
40
+ img {
41
+ height: 100%;
42
+ object-fit: cover;
43
+ width: 100%;
44
+ }
45
+
46
+ .title {
47
+ font: 500 $font-size-large $font-family-heading;
48
+ min-height: 6.4rem;
49
+ padding: .4rem;
50
+ }
51
+
52
+ .lead {
53
+ color: $text-color-secondary;
54
+ padding: .4rem;
55
+ }
56
+
57
+ .counters {
58
+ margin-top: auto;
59
+ padding: .4rem;
60
+ text-align: right;
61
+ }
62
+
63
+ .category {
64
+ padding: .4rem;
65
+ }
66
+
67
+ .info {
68
+ align-items: center;
69
+ -webkit-backdrop-filter: blur(.2rem);
70
+ background: rgba(255, 255, 255, .75);
71
+ border-radius: .2rem .2rem 0 0;
72
+ display: flex;
73
+ flex-wrap: wrap;
74
+ left: 0;
75
+ padding: .2rem .4rem;
76
+ position: absolute;
77
+ right: 0;
78
+
79
+ time {
80
+ font-size: $font-size-decreased;
81
+ font-style: italic;
82
+ line-height: 2rem;
83
+ margin-left: auto;
84
+ }
85
+ }
86
+ }
87
+
88
+ .view_count {
89
+ background: image_url('biovision/post/icons/view.svg') no-repeat center left / 1.6rem auto;
90
+ margin: 0 .4rem;
91
+ padding-left: 1.8rem;
92
+ }
93
+
94
+ article.post {
95
+ figure {
96
+ border-bottom: $border-secondary;
97
+ margin: 0 auto;
98
+ max-width: 64rem;
99
+ padding: 0 0 .8rem 0;
100
+ }
101
+
102
+ figcaption {
103
+ align-items: flex-end;
104
+ display: flex;
105
+ flex-wrap: wrap;
106
+ }
107
+
108
+ .image_author {
109
+ color: $text-color-secondary;
110
+ font-size: $font-size-decreased;
111
+ margin-left: auto;
112
+ }
113
+
114
+ .body {
115
+ padding: .4rem;
116
+ }
117
+
118
+ footer {
119
+ align-items: center;
120
+ background: $background-post-footer;
121
+ display: flex;
122
+ flex-wrap: wrap;
123
+ font-size: $font-size-decreased;
124
+ padding: .8rem;
125
+
126
+ .author {
127
+ margin: 0 1.6rem 0 0;
128
+ }
129
+
130
+ .author-title {
131
+ &::before {
132
+ content: '(';
133
+ }
134
+
135
+ &::after {
136
+ content: ')';
137
+ }
138
+ }
139
+
140
+ .source {
141
+ color: $text-color-secondary;
142
+ margin-left: auto;
143
+ }
144
+
145
+ .time {
146
+ margin: .8rem 0 0 0;
147
+ width: 100%;
148
+ }
149
+ }
150
+ }
@@ -25,6 +25,6 @@ class Admin::PostTypesController < AdminController
25
25
  end
26
26
 
27
27
  def restrict_access
28
- require_privilege :chief_editor
28
+ require_privilege_group :editors
29
29
  end
30
30
  end
@@ -1,2 +1,27 @@
1
- class Admin::PostsController < ApplicationController
1
+ class Admin::PostsController < AdminController
2
+ include ToggleableEntity
3
+
4
+ before_action :set_entity, except: [:index]
5
+
6
+ # get /admin/posts
7
+ def index
8
+ @collection = Post.page_for_administration(current_page)
9
+ end
10
+
11
+ # get /admin/posts/:id
12
+ def show
13
+ end
14
+
15
+ private
16
+
17
+ def set_entity
18
+ @entity = Post.find_by(id: params[:id])
19
+ if @entity.nil?
20
+ handle_http_404('Cannot find post')
21
+ end
22
+ end
23
+
24
+ def restrict_access
25
+ require_privilege_group :editors
26
+ end
2
27
  end
@@ -1,2 +1,37 @@
1
1
  class ArticlesController < ApplicationController
2
+ before_action :set_category, only: [:category]
3
+ before_action :set_entity, only: [:show]
4
+
5
+ # get /articles
6
+ def index
7
+ post_type = PostType.find_by(slug: 'article')
8
+ @collection = post_type.posts.page_for_visitors(current_page)
9
+ end
10
+
11
+ # get /articles/:category_slug
12
+ def category
13
+ @collection = @category.posts.page_for_visitors(current_page)
14
+ end
15
+
16
+ # get /articles/:post_id-:post_slug
17
+ def show
18
+ @entity.increment!(:view_count)
19
+ end
20
+
21
+ private
22
+
23
+ def set_category
24
+ type = PostType.find_by(slug: 'article')
25
+ @category = type.post_categories.find_by(long_slug: params[:category_slug])
26
+ if @category.nil?
27
+ handle_http_404('Cannot find post category (article)')
28
+ end
29
+ end
30
+
31
+ def set_entity
32
+ @entity = Post.visible.find_by(id: params[:post_id])
33
+ if @entity.nil?
34
+ handle_http_404('Cannot find article')
35
+ end
36
+ end
2
37
  end
@@ -0,0 +1,37 @@
1
+ class BlogPostsController < ApplicationController
2
+ before_action :set_category, only: [:category]
3
+ before_action :set_entity, only: [:show]
4
+
5
+ # get /blog_posts
6
+ def index
7
+ post_type = PostType.find_by(slug: 'blog_post')
8
+ @collection = post_type.posts.page_for_visitors(current_page)
9
+ end
10
+
11
+ # get /blog_posts/:category_slug
12
+ def category
13
+ @collection = @category.posts.page_for_visitors(current_page)
14
+ end
15
+
16
+ # get /blog_posts/:post_id-:post_slug
17
+ def show
18
+ @entity.increment!(:view_count)
19
+ end
20
+
21
+ private
22
+
23
+ def set_category
24
+ type = PostType.find_by(slug: 'blog_post')
25
+ @category = type.post_categories.find_by(long_slug: params[:category_slug])
26
+ if @category.nil?
27
+ handle_http_404('Cannot find post category (blog_post)')
28
+ end
29
+ end
30
+
31
+ def set_entity
32
+ @entity = Post.visible.find_by(id: params[:post_id])
33
+ if @entity.nil?
34
+ handle_http_404('Cannot find blog_post')
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ class NewsController < ApplicationController
2
+ before_action :set_category, only: [:category]
3
+ before_action :set_entity, only: [:show]
4
+
5
+ # get /news
6
+ def index
7
+ post_type = PostType.find_by(slug: 'news')
8
+ @collection = post_type.posts.page_for_visitors(current_page)
9
+ end
10
+
11
+ # get /news/:category_slug
12
+ def category
13
+ @collection = @category.posts.page_for_visitors(current_page)
14
+ end
15
+
16
+ # get /news/:post_id-:post_slug
17
+ def show
18
+ @entity.increment!(:view_count)
19
+ end
20
+
21
+ private
22
+
23
+ def set_category
24
+ type = PostType.find_by(slug: 'news')
25
+ @category = type.post_categories.find_by(long_slug: params[:category_slug])
26
+ if @category.nil?
27
+ handle_http_404('Cannot find post category (news)')
28
+ end
29
+ end
30
+
31
+ def set_entity
32
+ @entity = Post.visible.find_by(id: params[:post_id])
33
+ if @entity.nil?
34
+ handle_http_404('Cannot find news')
35
+ end
36
+ end
37
+ end
@@ -10,12 +10,6 @@ class PostsController < ApplicationController
10
10
  @collection = Post.page_for_visitors(current_page)
11
11
  end
12
12
 
13
- # get /posts/:category_slug
14
- def category
15
- @category = PostCategory.find_by! long_slug: params[:category_slug]
16
- @collection = @category.posts.page_for_visitors(current_page)
17
- end
18
-
19
13
  # post /posts
20
14
  def create
21
15
  @entity = Post.new(creation_parameters)
@@ -33,26 +27,12 @@ class PostsController < ApplicationController
33
27
 
34
28
  # get /posts/:id
35
29
  def show
36
- @entity = Post.find_by(id: params[:id], deleted: false)
30
+ @entity = Post.find_by(id: params[:id], visible: true, deleted: false)
37
31
  if @entity.nil?
38
32
  handle_http_404("Cannot find non-deleted post #{params[:id]}")
39
33
  end
40
34
  end
41
35
 
42
- # get /posts/:category_slug/:slug
43
- def show_in_category
44
- @category = PostCategory.find_by(slug: params[:category_slug])
45
- @entity = Post.find_by(slug: params[:slug], deleted: false)
46
- if @entity.nil? || !@entity.visible_to?(current_user)
47
- handle_http_404("Cannot show posts #{params[:slug]} to user #{current_user&.id}")
48
- elsif @entity.posts_category == @category
49
- @entity.increment! :view_count
50
- else
51
- parameters = { category_slug: @entity.posts_category.slug, slug: @entity.slug }
52
- redirect_to posts_in_category_posts_index_path(parameters)
53
- end
54
- end
55
-
56
36
  # get /posts/:id/edit
57
37
  def edit
58
38
  end
@@ -73,24 +53,29 @@ class PostsController < ApplicationController
73
53
 
74
54
  # delete /posts/:id
75
55
  def destroy
76
- if @entity.update(deleted: true)
56
+ if @entity.destroy #@entity.update(deleted: true)
77
57
  flash[:notice] = t('posts.destroy.success')
78
58
  end
79
- redirect_to admin_posts_index_path
59
+ redirect_to admin_posts_path
80
60
  end
81
61
 
82
62
  private
83
63
 
84
64
  def set_entity
85
- @entity = Post.find params[:id]
65
+ @entity = Post.find_by(id: params[:id])
66
+ if @entity.nil?
67
+ handle_http_404('Cannot find post')
68
+ end
86
69
  end
87
70
 
88
71
  def restrict_access
89
- require_privilege_group :reporters
72
+ require_privilege_group :editors
90
73
  end
91
74
 
92
75
  def restrict_editing
93
- raise record_not_found unless @entity.editable_by? current_user
76
+ if @entity.locked? || !@entity.editable_by?(current_user)
77
+ handle_http_403('Post is locked or not editable by current user')
78
+ end
94
79
  end
95
80
 
96
81
  def entity_parameters
@@ -101,10 +86,4 @@ class PostsController < ApplicationController
101
86
  parameters = params.require(:post).permit(Post.creation_parameters)
102
87
  parameters.merge(owner_for_entity(true))
103
88
  end
104
-
105
- def add_figures
106
- params[:figures].values.reject { |f| f[:slug].blank? || f[:image].blank? }.each do |data|
107
- @entity.figures.create!(data.select { |key, _| Figure.creation_parameters.include? key.to_sym })
108
- end
109
- end
110
89
  end
@@ -37,8 +37,23 @@ module BiovisionPostsHelper
37
37
  end
38
38
 
39
39
  # @param [Post] entity
40
- def post_link(entity, text = entity.title)
41
- link_to(text, PostManager.handler(entity).post_path)
40
+ # @param [String] text
41
+ # @param [Hash] options
42
+ def post_link(entity, text = entity.title, options = {})
43
+ link_to(text, PostManager.handler(entity).post_path, options)
44
+ end
45
+
46
+ # @param [Post] entity
47
+ # @param [Hash] options
48
+ def post_author_link(entity, options = {})
49
+ if entity.author_url.blank?
50
+ entity.author_name
51
+ else
52
+ link_options = {
53
+ rel: 'external nofollow noopener noreferrer'
54
+ }
55
+ link_to(entity.author_name, entity.author_url, link_options.merge(options))
56
+ end
42
57
  end
43
58
 
44
59
  # Post image preview for displaying in "administrative" lists
@@ -58,8 +73,9 @@ module BiovisionPostsHelper
58
73
  def post_image_small(entity, add_options = {})
59
74
  return '' if entity.image.blank?
60
75
 
76
+ alt_text = entity.image_alt_text.to_s
61
77
  versions = "#{entity.image.medium.url} 2x"
62
- options = { alt: entity.title, srcset: versions }.merge(add_options)
78
+ options = { alt: alt_text, srcset: versions }.merge(add_options)
63
79
  image_tag(entity.image.small.url, options)
64
80
  end
65
81
 
@@ -70,8 +86,9 @@ module BiovisionPostsHelper
70
86
  def post_image_medium(entity, add_options = {})
71
87
  return '' if entity.image.blank?
72
88
 
89
+ alt_text = entity.image_alt_text.to_s
73
90
  versions = "#{entity.image.big.url} 2x"
74
- options = { alt: entity.title, srcset: versions }.merge(add_options)
91
+ options = { alt: alt_text, srcset: versions }.merge(add_options)
75
92
  image_tag(entity.image.medium.url, options)
76
93
  end
77
94
  end
data/app/models/post.rb CHANGED
@@ -2,15 +2,19 @@ class Post < ApplicationRecord
2
2
  include HasOwner
3
3
  include CommentableItem if 'CommentableItem'.safe_constantize
4
4
  include VotableItem if 'VotableItem'.safe_constantize
5
+ include Toggleable
5
6
 
6
7
  TITLE_LIMIT = 140
7
8
  SLUG_LIMIT = 200
8
9
  SLUG_PATTERN = /\A[a-z0-9]+[-_.a-z0-9]*[a-z0-9]+\z/
9
10
  LEAD_LIMIT = 350
10
11
  BODY_LIMIT = 50000
11
- META_LIMIT = 100
12
+ META_LIMIT = 250
13
+ ALT_LIMIT = 200
12
14
  PER_PAGE = 10
13
15
 
16
+ toggleable :visible, :show_owner, :allow_comments
17
+
14
18
  mount_uploader :image, PostImageUploader
15
19
 
16
20
  belongs_to :user
@@ -22,7 +26,6 @@ class Post < ApplicationRecord
22
26
  after_initialize { self.uuid = SecureRandom.uuid if uuid.nil? }
23
27
  before_validation { self.slug = Canonizer.transliterate(title.to_s) if slug.blank? }
24
28
  before_validation { self.slug = slug.downcase }
25
- before_validation { self.publication_time = Time.now if publication_time.nil? }
26
29
  before_validation :prepare_source_names
27
30
  before_save { self.parsed_body = PostManager.handler(self).parsed_body }
28
31
 
@@ -32,15 +35,23 @@ class Post < ApplicationRecord
32
35
  validates_length_of :lead, maximum: LEAD_LIMIT
33
36
  validates_length_of :body, maximum: BODY_LIMIT
34
37
  validates_length_of :image_name, maximum: META_LIMIT
38
+ validates_length_of :image_alt_text, maximum: ALT_LIMIT
35
39
  validates_length_of :image_author_name, maximum: META_LIMIT
36
40
  validates_length_of :image_author_link, maximum: META_LIMIT
37
41
  validates_length_of :source_link, maximum: META_LIMIT
38
42
  validates_length_of :source_name, maximum: META_LIMIT
43
+ validates_length_of :meta_title, maximum: TITLE_LIMIT
44
+ validates_length_of :meta_description, maximum: META_LIMIT
45
+ validates_length_of :meta_keywords, maximum: META_LIMIT
46
+ validates_length_of :author_name, maximum: META_LIMIT
47
+ validates_length_of :author_title, maximum: META_LIMIT
48
+ validates_length_of :author_url, maximum: META_LIMIT
39
49
  validates_format_of :slug, with: SLUG_PATTERN
40
50
  validate :category_consistency
41
51
 
42
- scope :recent, -> { order('publication_time desc') }
52
+ scope :recent, -> { order('id desc') }
43
53
  scope :visible, -> { where(visible: true, deleted: false, approved: true) }
54
+ scope :list_for_visitors, -> { visible.recent }
44
55
 
45
56
  # @param [Integer] page
46
57
  def self.page_for_administration(page = 1)
@@ -49,16 +60,17 @@ class Post < ApplicationRecord
49
60
 
50
61
  # @param [Integer] page
51
62
  def self.page_for_visitors(page = 1)
52
- visible.recent.page(page).per(PER_PAGE)
63
+ list_for_visitors.page(page).per(PER_PAGE)
53
64
  end
54
65
 
55
66
  def self.entity_parameters
56
- main_data = %i(post_category_id title slug lead body visible region_id)
57
- image_data = %i(image image_name image_author_name image_author_link)
58
- meta_data = %i(source_name source_link publication_time)
59
- flags_data = %i(show_owner allow_comments)
67
+ main_data = %i(post_category_id title slug lead body visible translation region_id)
68
+ image_data = %i(image image_alt_text image_name image_author_name image_author_link)
69
+ meta_data = %i(source_name source_link meta_title meta_description meta_keywords)
70
+ flags_data = %i(show_owner allow_comments)
71
+ author_data = %i(author_name author_title author_url)
60
72
 
61
- main_data + image_data + meta_data + flags_data
73
+ main_data + image_data + meta_data + author_data + flags_data
62
74
  end
63
75
 
64
76
  def self.creation_parameters
@@ -8,7 +8,7 @@ class PostType < ApplicationRecord
8
8
  DEPTH_RANGE = (0..10)
9
9
 
10
10
  has_many :post_categories, dependent: :destroy
11
- has_many :posts, through: :post_categories
11
+ has_many :posts
12
12
 
13
13
  validates_length_of :name, maximum: NAME_LIMIT
14
14
  validates_length_of :slug, maximum: SLUG_LIMIT
@@ -0,0 +1,10 @@
1
+ class PostManager::ArticleHandler < PostManager
2
+ def post_path
3
+ "/articles/#{@entity.id}-#{@entity.slug}"
4
+ end
5
+
6
+ # @param [PostCategory] category
7
+ def category_path(category)
8
+ "/articles/#{category.long_slug}"
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class PostManager::BlogPostHandler < PostManager
2
+ def post_path
3
+ "/blog_posts/#{@entity.id}-#{@entity.slug}"
4
+ end
5
+
6
+ # @param [PostCategory] category
7
+ def category_path(category)
8
+ "/blog_posts/#{category.long_slug}"
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class PostManager::NewsHandler < PostManager
2
+ def post_path
3
+ "/news/#{@entity.id}-#{@entity.slug}"
4
+ end
5
+
6
+ # @param [PostCategory] category
7
+ def category_path(category)
8
+ "/news/#{category.long_slug}"
9
+ end
10
+ end
@@ -19,4 +19,13 @@ class PostManager
19
19
  def post_path
20
20
  "/posts/#{@entity.id}"
21
21
  end
22
+
23
+ def edit_path
24
+ "/posts/#{@entity.id}/edit"
25
+ end
26
+
27
+ # @param [PostCategory] category
28
+ def category_path(category)
29
+ "posts/#{category.long_slug}"
30
+ end
22
31
  end
@@ -0,0 +1,29 @@
1
+ <% if current_user_in_group?(:editors) %>
2
+ <nav>
3
+ <div class="heading" id="biovision-post-nav-heading">
4
+ <%= t('.heading') %>
5
+ </div>
6
+ <ul aria-labelledby="biovision-post-nav-heading">
7
+ <li>
8
+ <%= render 'admin/post_types/nav_item' %>
9
+ <ul>
10
+ <% PostType.page_for_administration.each do |post_type| %>
11
+ <li>
12
+ <div><%= admin_post_type_link(post_type) %></div>
13
+ <div class="description">
14
+ <%= t(:post_count, count: post_type.posts_count) %>
15
+ </div>
16
+ <ul class="actions">
17
+ <li>
18
+ <%= create_icon(new_post_admin_post_type_path(post_type.id)) %>
19
+ </li>
20
+ </ul>
21
+ </li>
22
+ <% end %>
23
+ </ul>
24
+ </li>
25
+ <li><%= render 'admin/posts/nav_item' %></li>
26
+ <%= render 'admin/index/biovision_post/additional_items' %>
27
+ </ul>
28
+ </nav>
29
+ <% end %>