effective_posts 2.6.2 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba2b29680fd67771e07107f6fc283581b317593e18bec35916ca2e99ff7f7a21
4
- data.tar.gz: 395b803b93e46491d74e9965702e2f50b019ce36410e57f5e0472ac5ed9524ca
3
+ metadata.gz: 3a1c81f231ae730f44dcbbfb64bead77d9a2530a3b6f4e2bdea6455f5ea78ca2
4
+ data.tar.gz: 0ef00c73d74471e23a06c322444f209ab58fd21fce475a9783ecc93e8dadc011
5
5
  SHA512:
6
- metadata.gz: a0908054fb05b30f5e45f4f0bfc9b58597c59dd2f3b9eddee0cac8a51fcfc2ef4a81bf83c1af487d228c648acca09734db53a5b3bde4a40b1fac943f9a7075de
7
- data.tar.gz: 21e8a107beba7055c689209ad068f9dfef739e8581eaf3be2b71c21cf252b42dfdf7d3f3fb63ae13661c0b69805718fe4fc1094158ff1a8f9e8f0766c43272cb
6
+ metadata.gz: 4eb6a0e3530b97ba6cd1679c4bb137dfe91937806ca6284a016a930509e416e49fed55ec489af4753aec4d0fcd783e5bcf88ca9bc62c6f629fddaa3c4f2fc442
7
+ data.tar.gz: 600dec645eb265e938d44315ecf2299755bbc678d8d0e8535fc690eff63867a0b884d3612b1b56c70403b6afeb844cf34c0b918be07020ae825458462598d8de
@@ -27,9 +27,15 @@ module Effective
27
27
  @posts = @posts.where(search) if search.present?
28
28
  end
29
29
 
30
+ if @category.present?
31
+ @page_title = @category.to_s
32
+ else
33
+ @page_title ||= view_context.posts_name_label
34
+ end
35
+
30
36
  EffectiveResources.authorize!(self, :index, Effective::Post)
31
37
 
32
- @page_title ||= [(@category || 'Blog').to_s.titleize, (" - Page #{params[:page]}" if params[:page])].compact.join
38
+ @page_title ||= [(@category || view_context.posts_name_label).to_s.titleize, (" - Page #{params[:page]}" if params[:page])].compact.join
33
39
  @canonical_url ||= helpers.effective_post_category_url(params[:category], page: params[:page])
34
40
  end
35
41
 
@@ -52,13 +58,12 @@ module Effective
52
58
  'Hi Admin!',
53
59
  ('You are viewing a hidden post.' unless @post.published?),
54
60
  ('You are viewing an archived post.' if @post.archived?),
55
- 'Click here to',
56
- ("<a href='#{effective_posts.edit_admin_post_path(@post)}' class='alert-link'>edit post settings</a>.")
61
+ ("<a href='#{effective_posts.edit_admin_post_path(@post)}' class='alert-link'>Edit this post</a>.")
57
62
  ].compact.join(' ')
58
63
  end
59
64
 
60
65
  @page_title ||= @post.title
61
- @meta_description ||= @post.description
66
+ @meta_description ||= (@post.description.presence || @post.title)
62
67
  @canonical_url ||= effective_posts.post_url(@post)
63
68
  end
64
69
 
@@ -26,12 +26,12 @@ class EffectivePostsDatatable < Effective::Datatable
26
26
 
27
27
  col :draft?, as: :boolean, visible: false
28
28
  col :published?, as: :boolean
29
- col :published_start_at
30
- col :published_end_at
29
+ col :published_start_at, label: "Published start"
30
+ col :published_end_at, label: "Published end"
31
31
 
32
32
  col :archived
33
33
 
34
- col :start_at
34
+ col :start_at, visible: EffectivePosts.categories.include?('Events')
35
35
  col :end_at, visible: false
36
36
  col :location, visible: false
37
37
  col :created_at, label: 'Submitted at', visible: false
@@ -2,6 +2,21 @@ require 'cgi'
2
2
 
3
3
  module EffectivePostsHelper
4
4
 
5
+ # Posts
6
+ def posts_name_label
7
+ et('effective_posts.name')
8
+ end
9
+
10
+ # Post
11
+ def post_label
12
+ et(Effective::Post)
13
+ end
14
+
15
+ # Posts
16
+ def posts_label
17
+ ets(Effective::Post)
18
+ end
19
+
5
20
  def effective_posts_header_tags
6
21
  return unless @post && @post.kind_of?(Effective::Post) && @post.persisted? && @post.published?
7
22
 
@@ -54,17 +69,20 @@ module EffectivePostsHelper
54
69
  link_to(category.to_s.titleize, effective_post_category_path(category), title: category.to_s.titleize)
55
70
  end
56
71
 
72
+ def badge_to_post_category(category, options = {})
73
+ category = category.to_s.downcase
74
+ link_to(category.to_s.titleize, effective_post_category_path(category), title: category.to_s.titleize, class: "badge badge-primary badge-post mb-2 effective-posts-#{category.parameterize}")
75
+ end
76
+
57
77
  def render_post(post)
58
78
  render(partial: 'effective/posts/post', locals: { post: post })
59
79
  end
60
80
 
61
81
  def post_meta(post, date: true, datetime: false, category: true, author: true)
62
82
  [
63
- 'Published',
64
- ("on #{post.published_start_at.strftime('%B %d, %Y')}" if date && post.published_start_at),
65
- ("on #{post.published_start_at.strftime('%B %d, %Y at %l:%M %p')}" if datetime && post.published_start_at),
66
- ("to #{link_to_post_category(post.category)}" if category && Array(EffectivePosts.categories).length > 1),
67
- ("by #{post.user.to_s.presence || 'Unknown'}" if author && EffectivePosts.post_meta_author && post.user.present?)
83
+ ("#{post.published_start_at.strftime('%A, %B %d, %Y')}" if date && post.published_start_at),
84
+ ("#{post.published_start_at.strftime('%A, %B %d, %Y · %l:%M%P')}" if datetime && post.published_start_at),
85
+ ("#{post.user.to_s.presence || 'Unknown'}" if author && EffectivePosts.post_meta_author && post.user.present?)
68
86
  ].compact.join(' ').html_safe
69
87
  end
70
88
 
@@ -82,7 +100,8 @@ module EffectivePostsHelper
82
100
 
83
101
  # All other options are passed to the link_to 'Read more'
84
102
  def post_excerpt(post, label: 'Continue reading')
85
- (post.excerpt.to_s + readmore_link(post, label: label)).html_safe
103
+ content = post.excerpt.presence || post.body.presence
104
+ (content.to_s + readmore_link(post, label: label)).html_safe
86
105
  end
87
106
 
88
107
  def read_more_link(post, options = {})
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Effective
2
4
  class Post < ActiveRecord::Base
3
5
  self.table_name = (EffectivePosts.posts_table_name || :posts).to_s
4
6
 
5
7
  if defined?(PgSearch)
6
8
  include PgSearch::Model
7
-
8
9
  multisearchable against: [:body]
9
10
  end
10
11
 
@@ -55,8 +56,8 @@ module Effective
55
56
  self.user ||= current_user
56
57
  end
57
58
 
58
- validates :title, presence: true, length: { maximum: 255 }
59
- validates :description, presence: true, length: { maximum: 150 }
59
+ validates :title, presence: true
60
+ validates :description, length: { maximum: 150 }
60
61
  validates :category, presence: true
61
62
  validates :start_at, presence: true, if: -> { category == 'events' }
62
63
 
@@ -1,51 +1,48 @@
1
1
  = effective_form_with(model: [:admin, post], engine: true) do |f|
2
2
  = f.text_field :title, hint: 'The title of your post.'
3
3
 
4
+ - if Array(EffectivePosts.categories).length > 1
5
+ = f.select :category, EffectivePosts.categories
6
+ - else
7
+ = f.hidden_field :category, value: (EffectivePosts.categories.first || 'posts')
8
+
4
9
  -# acts_as_published
5
10
  = f.hide_if(:save_as_draft, true) do
6
11
  .row
7
12
  .col-md-6
8
- = f.datetime_field :published_start_at, hint: 'The page will be available starting on this date and time.'
13
+ = f.datetime_field :published_start_at, label: 'Published start', hint: 'The page will appear on the website after this date and time. Leave blank to publish immediately'
9
14
  .col-md-6
10
- = f.datetime_field :published_end_at, hint: 'The page will no longer be available after this date and time. Leave blank for no end date.', date_linked: false
15
+ = f.datetime_field :published_end_at, label: 'Published end', hint: 'The page will not appear on the website after this date and time. Leave blank for no end date.', date_linked: false
11
16
 
12
17
  = f.check_box :save_as_draft, label: "Save as a draft. It will not appear on the website and can only be accessed by admin users."
13
18
 
14
- = f.text_field :description,
15
- hint: "150 character summary. Appears on Google search results underneath the post title. ",
16
- input_html: { maxlength: 150 }
17
-
19
+ - # acts_as_slugged
18
20
  - if f.object.persisted? || f.object.errors.include?(:slug)
19
21
  - current_url = effective_posts.post_path(f.object)
20
22
 
21
23
  = f.text_field :slug, required: f.object.persisted?,
22
24
  hint: "The slug controls this post's internet address. Be careful, changing the slug will break links that other websites may have to the old address.<br>#{('This post is currently reachable via ' + link_to(current_url.gsub(f.object.slug, '<strong>' + f.object.slug + '</strong>').html_safe, current_url)) if current_url && f.object.slug.present? }".html_safe
23
25
 
24
- - if defined?(EffectiveArticleEditor)
25
- = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages.'
26
- - else
27
- = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages.'
28
-
29
- - if Array(EffectivePosts.categories).length > 1
30
- = f.select :category, EffectivePosts.categories
31
- - else
32
- = f.hidden_field :category, value: (EffectivePosts.categories.first || 'posts')
33
-
34
- - if f.object.class.respond_to?(:acts_as_tagged?)
35
- = render 'effective/tags/fields', f: f
26
+ - if EffectivePosts.use_description
27
+ = f.text_field :description, label: "Meta description", input_html: { maxlength: 150 },
28
+ hint: "150 character summary that appears on Google search result pages."
36
29
 
37
30
  - if EffectivePosts.use_active_storage
38
- = f.file_field :image, hint: 'An image for your post'
31
+ = f.file_field :image, label: "Image preview", hint: "Optional. Shown on the posts index and post pages. Dimensions are 220px tall and 350px wide."
32
+
33
+ - if EffectivePosts.use_excerpt
34
+ - if defined?(EffectiveArticleEditor)
35
+ = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages. Leave blank to use the body instead.'
36
+ - else
37
+ = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages. Leave blank to use the body instead.'
39
38
 
40
39
  - if defined?(EffectiveArticleEditor)
41
- = f.article_editor :body, hint: 'The main body of your post'
40
+ = f.article_editor :body
42
41
  - else
43
- = f.rich_text_area :body, hint: 'The main body of your post'
42
+ = f.rich_text_area :body
44
43
 
45
44
  = render partial: '/effective/posts/additional_fields', locals: { post: post, form: f, f: f }
46
45
 
47
- = f.check_box :archived, label: 'Yes, this post is archived. It will not be displayed.'
48
-
49
46
  - if EffectivePosts.use_effective_roles
50
47
  = render partial: '/admin/posts/roles', locals: { post: post, form: f, f: f }
51
48
 
@@ -1,30 +1,35 @@
1
1
  = effective_form_with(model: post, engine: true) do |f|
2
2
  = f.text_field :title, hint: 'The title of your post.'
3
3
 
4
- - if f.object.persisted? || f.object.errors.include?(:slug)
5
- - current_url = effective_posts.post_path(f.object)
6
- = f.text_field :slug, hint: "The slug controls this post's internet address. Be careful, changing the slug will break links that other websites may have to the old address.<br>#{('This post is currently reachable via ' + link_to(current_url.gsub(f.object.slug, '<strong>' + f.object.slug + '</strong>').html_safe, current_url)) if current_url && f.object.slug.present? }".html_safe
7
-
8
4
  - if Array(EffectivePosts.categories).length > 1
9
5
  = f.select :category, EffectivePosts.categories
10
6
  - else
11
7
  = f.hidden_field :category, value: (EffectivePosts.categories.first || 'posts')
12
8
 
13
- - if EffectivePosts.use_active_storage
14
- = f.file_field :image, hint: 'An image for your post'
9
+ - # acts_as_slugged
10
+ - if f.object.persisted? || f.object.errors.include?(:slug)
11
+ - current_url = effective_posts.post_path(f.object)
15
12
 
16
- - if defined?(EffectiveArticleEditor)
17
- = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages.'
18
- - else
19
- = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages.'
13
+ = f.text_field :slug, required: f.object.persisted?,
14
+ hint: "The slug controls this post's internet address. Be careful, changing the slug will break links that other websites may have to the old address.<br>#{('This post is currently reachable via ' + link_to(current_url.gsub(f.object.slug, '<strong>' + f.object.slug + '</strong>').html_safe, current_url)) if current_url && f.object.slug.present? }".html_safe
20
15
 
21
- = f.text_field :description, hint: 'The content of the post meta tags.', maxlength: 150
16
+ - if EffectivePosts.use_description
17
+ = f.text_field :description, hint: 'The content of the post meta tags.', maxlength: 150
22
18
 
23
- = render partial: '/effective/posts/additional_fields', locals: { post: post, form: f, f: f }
19
+ - if EffectivePosts.use_active_storage
20
+ = f.file_field :image, hint: 'An image for your post'
21
+
22
+ - if EffectivePosts.use_excerpt
23
+ - if defined?(EffectiveArticleEditor)
24
+ = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages.'
25
+ - else
26
+ = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages.'
24
27
 
25
28
  - if defined?(EffectiveArticleEditor)
26
29
  = f.article_editor :body, hint: 'The main body of your post'
27
30
  - else
28
31
  = f.rich_text_area :body, hint: 'The main body of your post'
29
32
 
33
+ = render partial: '/effective/posts/additional_fields', locals: { post: post, form: f, f: f }
34
+
30
35
  = f.submit 'Save'
@@ -1,3 +1,2 @@
1
- .row
2
- .col-sm-8= yield
3
- .col-sm-4= render 'sidebar'
1
+ .effective-posts.mb-3
2
+ = yield
@@ -1,9 +1,18 @@
1
- .effective-post
2
- %h2.post-title= link_to post, effective_post_path(post)
1
+ .col.effective-post.mb-5
2
+ - if EffectivePosts.categories.length > 1 && post.category.present?
3
+ = badge_to_post_category(post.category)
3
4
 
4
- %p.post-meta.text-muted
5
+ - if EffectivePosts.use_active_storage && post.image && post.image.attached?
6
+ = link_to effective_posts.post_path(post) do
7
+ = image_tag url_for(post.image), class: "effective-posts-image d-none d-lg-flex align-self-start mb-2", alt: post.title, width: "350", height: "220"
8
+
9
+ .effective-posts-meta.mb-2
5
10
  = post_meta(post, author: false)
6
11
  = admin_post_status_badge(post)
7
12
 
8
- .post-content.post-excerpt
9
- = post.excerpt
13
+ %h2.effective-posts-title= link_to post, effective_post_path(post)
14
+
15
+ - if EffectivePosts.use_excerpt && post.excerpt.present?
16
+ .effective-posts-excerpt
17
+ = post.excerpt
18
+
@@ -1,8 +1,8 @@
1
- %h1= @page_title
2
-
3
1
  = render 'layout' do
4
- .effective-posts
5
- = render partial: @posts, spacer_template: 'spacer'
2
+ %h1.effective-title.mb-4= @page_title
3
+
4
+ .row.row-cols-1.row-cols-lg-3.effective-posts
5
+ = render @posts
6
6
 
7
7
  %nav.d-flex.justify-content-center
8
8
  = bootstrap_paginate(@posts, per_page: EffectivePosts.per_page)
@@ -1,12 +1,14 @@
1
1
  = render 'layout' do
2
2
  .effective-post
3
- %h1.post-title= link_to @post, effective_post_path(@post)
4
-
5
- %p.post-meta.text-muted
3
+ .effective-posts-meta.mb-2
6
4
  = post_meta(@post, author: false)
7
5
  = admin_post_status_badge(@post)
8
6
 
7
+ %h1.effective-post-title.mb-4= @page_title
8
+
9
9
  = render 'effective/posts/event', post: @post
10
10
 
11
- .post-body.post-content
11
+ .effective-posts-body.mb-5
12
12
  = @post.body
13
+
14
+ = link_to("&larr; #{posts_name_label}" .html_safe, effective_posts.posts_path, class: "btn btn-secondary my-4")
@@ -41,6 +41,12 @@ EffectivePosts.setup do |config|
41
41
  # Display a file upload field when the admin creates a new post to collect a post.image
42
42
  config.use_active_storage = true
43
43
 
44
+ # Display the google search results description field on admin form
45
+ config.use_description = true
46
+
47
+ # Display the excerpt field on admin form
48
+ config.use_excerpt = true
49
+
44
50
  # Submissions
45
51
  # Allow users to submit posts (optionally for approval) to display on the website
46
52
  config.submissions_enabled = true
@@ -0,0 +1,7 @@
1
+ en:
2
+ effective_posts:
3
+ name: 'Blog'
4
+
5
+ activerecord:
6
+ models:
7
+ effective/post: 'Post'
@@ -1,3 +1,3 @@
1
1
  module EffectivePosts
2
- VERSION = '2.6.2'.freeze
2
+ VERSION = '2.7.1'.freeze
3
3
  end
@@ -10,7 +10,7 @@ module EffectivePosts
10
10
  :categories, :event_categories,
11
11
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject,
12
12
  :use_category_routes, :use_blog_routes,
13
- :use_effective_roles, :use_active_storage,
13
+ :use_effective_roles, :use_active_storage, :use_description, :use_excerpt,
14
14
  :per_page, :post_meta_author,
15
15
  :submissions_enabled, :submissions_require_current_user,
16
16
  :submissions_require_approval, :submissions_note
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_posts
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.2
4
+ version: 2.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-09 00:00:00.000000000 Z
11
+ date: 2024-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -196,7 +196,6 @@ files:
196
196
  - app/views/effective/posts/_post.html.haml
197
197
  - app/views/effective/posts/_recent_posts.html.haml
198
198
  - app/views/effective/posts/_sidebar.html.haml
199
- - app/views/effective/posts/_spacer.html.haml
200
199
  - app/views/effective/posts/_upcoming_events.html.haml
201
200
  - app/views/effective/posts/edit.html.haml
202
201
  - app/views/effective/posts/index.html.haml
@@ -205,6 +204,7 @@ files:
205
204
  - app/views/effective/posts/submitted.html.haml
206
205
  - app/views/effective/posts_mailer/post_submitted.html.haml
207
206
  - config/effective_posts.rb
207
+ - config/locales/effective_posts.en.yml
208
208
  - config/routes.rb
209
209
  - db/migrate/101_create_effective_posts.rb
210
210
  - lib/effective_posts.rb
@@ -1 +0,0 @@
1
- %hr