biovision-post 0.0.171104 → 0.1.171229

Sign up to get free protection for your applications and to get access to all the features.
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 %>