effective_posts 2.2.4 → 2.3.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: 747172ede1bd476cba7fc584e38368332d6b6d762b201a1a654f93da03a42a5e
4
- data.tar.gz: c3ec95126b30ea18c2c3f70ebbd13d4551185c548385f95c799f4733a43cf71b
3
+ metadata.gz: f9d8e5570b02bb73d75d54a4b910001b9c1762c6fabe432169647c87b27e8192
4
+ data.tar.gz: 41e7bb371e0e9e35199cbc4f756861c38bb06a73c737839a31d84a33429a1215
5
5
  SHA512:
6
- metadata.gz: 277cb171ce914d5000d489cb755ba767143529966c1044f86489ca8a790a4b24530162edec364c04c76a893566bc9384fe788a1ac64e7f84034a15100c2b8fc4
7
- data.tar.gz: f442aca9a9727ca2a6bced567b3cd9b8770c10deb4da0838801d689e4712315956e35ad37c3cbc9d5bd029996cb145b97939200f2f534187fc909e06dab5779c
6
+ metadata.gz: 29142f4e9ba9cf43ccef2f15b4dc555c54c7962a89df168d058a09a1ac8e3cd52e4e0010ddfacd902ae426c41d11a967a067a4ffd0acea9e2064ffac2b2ec7e4
7
+ data.tar.gz: 80480ad18d597104970d8356afb629067a2dd459a9344234e128e5ab406c858e1291916f2b4f13cb07229709c24af9faf67c7cd50ab84d6c42b27049f2d2add4
@@ -1 +0,0 @@
1
- //= require effective_posts/additional_fields
@@ -8,15 +8,17 @@ module Effective
8
8
  include Effective::CrudController
9
9
 
10
10
  def index
11
+ @category = EffectivePosts.category(params[:category])
12
+
11
13
  @posts ||= Effective::Post.posts(
12
14
  user: current_user,
13
- category: params[:category],
15
+ category: @category,
14
16
  unpublished: EffectiveResources.authorized?(self, :admin, :effective_posts)
15
17
  )
16
18
 
17
19
  @posts = @posts.paginate(page: params[:page])
18
20
 
19
- if params[:category] == 'events'
21
+ if EffectivePosts.event_categories.include?(@category)
20
22
  @posts = @posts.reorder(:start_at).where('start_at > ?', Time.zone.now)
21
23
  end
22
24
 
@@ -27,12 +29,14 @@ module Effective
27
29
 
28
30
  EffectiveResources.authorize!(self, :index, Effective::Post)
29
31
 
30
- @page_title ||= [(params[:category] || 'Blog').to_s.titleize, (" - Page #{params[:page]}" if params[:page])].compact.join
32
+ @page_title ||= [(@category || 'Blog').to_s.titleize, (" - Page #{params[:page]}" if params[:page])].compact.join
31
33
  @canonical_url ||= helpers.effective_post_category_url(params[:category], page: params[:page])
32
34
  end
33
35
 
34
36
  def show
35
- @posts ||= Effective::Post.posts(user: current_user, category: params[:category], unpublished: EffectiveResources.authorized?(self, :admin, :effective_posts))
37
+ @category = EffectivePosts.category(params[:category])
38
+
39
+ @posts ||= Effective::Post.posts(user: current_user, unpublished: EffectiveResources.authorized?(self, :admin, :effective_posts))
36
40
  @post = @posts.find(params[:id])
37
41
 
38
42
  if @post.respond_to?(:roles_permit?)
@@ -1,4 +1,12 @@
1
1
  class EffectivePostsDatatable < Effective::Datatable
2
+ filters do
3
+ scope :all
4
+ scope :published
5
+ scope :unpublished
6
+ scope :news
7
+ scope :events
8
+ end
9
+
2
10
  datatable do
3
11
  order :published_at, :desc
4
12
 
@@ -22,7 +30,6 @@ class EffectivePostsDatatable < Effective::Datatable
22
30
  col :start_at
23
31
  col :end_at, visible: false
24
32
  col :location, visible: false
25
-
26
33
  col :created_at, label: 'Submitted at', visible: false
27
34
 
28
35
  actions_col do |post|
@@ -16,7 +16,7 @@ module EffectivePostsHelper
16
16
  end
17
17
 
18
18
  def effective_post_path(post, opts = nil)
19
- category = post.category.to_s.downcase
19
+ category = post.category.to_s.downcase.parameterize
20
20
  opts ||= {}
21
21
 
22
22
  if EffectivePosts.use_blog_routes
@@ -9,7 +9,6 @@ module Effective
9
9
  attr_accessor :current_user
10
10
 
11
11
  acts_as_slugged
12
-
13
12
  log_changes if respond_to?(:log_changes)
14
13
  acts_as_tagged if respond_to?(:acts_as_tagged)
15
14
  acts_as_role_restricted if respond_to?(:acts_as_role_restricted)
@@ -19,7 +18,7 @@ module Effective
19
18
  has_rich_text :excerpt
20
19
  has_rich_text :body
21
20
 
22
- self.table_name = EffectivePosts.posts_table_name.to_s
21
+ self.table_name = (EffectivePosts.posts_table_name || :posts).to_s
23
22
 
24
23
  belongs_to :user, polymorphic: true, optional: true
25
24
 
@@ -55,13 +54,16 @@ module Effective
55
54
  validates :description, presence: true, length: { maximum: 150 }
56
55
  validates :category, presence: true
57
56
  validates :published_at, presence: true, unless: -> { draft? }
58
-
59
57
  validates :start_at, presence: true, if: -> { category == 'events' }
60
58
 
61
59
  scope :drafts, -> { where(draft: true) }
62
60
  scope :published, -> { where(draft: false).where("#{EffectivePosts.posts_table_name}.published_at < ?", Time.zone.now) }
63
61
  scope :unpublished, -> { where(draft: true).or(where("#{EffectivePosts.posts_table_name}.published_at > ?", Time.zone.now)) }
64
- scope :with_category, -> (category) { where(category: category.to_s.downcase) }
62
+ scope :with_category, -> (category) { where(category: category) }
63
+
64
+ # Kind of a meta category
65
+ scope :news, -> { where(category: EffectivePosts.news_categories) }
66
+ scope :events, -> { where(category: EffectivePosts.event_categories) }
65
67
 
66
68
  scope :deep, -> { with_rich_text_excerpt_and_embeds.with_rich_text_body_and_embeds }
67
69
 
@@ -105,7 +107,7 @@ module Effective
105
107
  end
106
108
 
107
109
  def event?
108
- category == 'events'
110
+ EffectivePosts.event_categories.include?(EffectivePosts.category(category))
109
111
  end
110
112
 
111
113
  def start_time
@@ -123,14 +125,17 @@ module Effective
123
125
 
124
126
  # Returns a duplicated post object, or throws an exception
125
127
  def duplicate
126
- Post.new(attributes.except('id', 'updated_at', 'created_at')).tap do |post|
127
- post.title = post.title + ' (Copy)'
128
- post.slug = post.slug + '-copy'
129
- post.draft = true
128
+ post = Post.new(attributes.except('id', 'updated_at', 'created_at', 'tags'))
130
129
 
131
- post.body = body
132
- post.excerpt = excerpt
133
- end
130
+ post.assign_attributes(
131
+ title: post.title + ' (Copy)',
132
+ slug: post.slug + '-copy',
133
+ draft: true,
134
+ body: body,
135
+ excerpt: excerpt
136
+ )
137
+
138
+ post
134
139
  end
135
140
 
136
141
  def duplicate!
@@ -1,49 +1,7 @@
1
- = effective_form_with(model: [:admin, post], engine: true) do |f|
2
- = tabs do
3
- = tab "Post" do
4
- = f.text_field :title, hint: 'The title of your post.'
1
+ = tabs do
2
+ = tab "Post" do
3
+ = render 'admin/posts/form_post', post: post
5
4
 
6
- - if f.object.persisted? || f.object.errors.include?(:slug)
7
- - current_url = effective_posts.post_path(f.object)
8
-
9
- = f.text_field :slug, required: f.object.persisted?,
10
- 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
11
-
12
- - if defined?(EffectiveArticleEditor)
13
- = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages.'
14
- - else
15
- = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages.'
16
-
17
- = f.text_field :description, hint: 'The content of the post meta tags.', maxlength: 150
18
-
19
- - if Array(EffectivePosts.categories).length > 1
20
- = f.select :category, EffectivePosts.categories
21
- - else
22
- = f.hidden_field :category, value: (EffectivePosts.categories.first || 'posts')
23
-
24
- - if EffectivePosts.use_active_storage
25
- = f.file_field :image, hint: 'An image for your post'
26
-
27
- - if defined?(EffectiveArticleEditor)
28
- = f.article_editor :body, hint: 'The main body of your post'
29
- - else
30
- = f.rich_text_area :body, hint: 'The main body of your post'
31
-
32
- = render partial: '/effective/posts/additional_fields', locals: { post: post, form: f, f: f }
33
-
34
- = f.datetime_field :published_at, label: 'Publish date', hint: 'When should this be displayed on the website.'
35
-
36
- = f.check_box :draft, hint: 'Save this post as a draft. It will not be accessible on the website.'
37
-
38
- - if defined?(EffectiveRoles) && f.object.respond_to?(:roles) && EffectivePosts.use_effective_roles
39
- = render partial: '/admin/posts/roles', locals: { post: post, form: f, f: f }
40
-
41
- - if f.object.class.respond_to?(:acts_as_tagged?)
42
- = tab "Tags" do
43
- = render 'effective/tags/fields', f: f
44
-
45
- = f.submit do
46
- = f.save 'Save'
47
- = f.save 'Save and View', class: 'btn btn-secondary'
48
- - if f.object.persisted?
49
- = f.save 'Duplicate', class: 'btn btn-info'
5
+ - if post.persisted? && post.respond_to?(:log_changes_datatable)
6
+ = tab "Logs" do
7
+ = render_inline_datatable(post.log_changes_datatable)
@@ -0,0 +1,46 @@
1
+ = effective_form_with(model: [:admin, post], engine: true) do |f|
2
+ = f.text_field :title, hint: 'The title of your post.'
3
+
4
+ - if f.object.persisted? || f.object.errors.include?(:slug)
5
+ - current_url = effective_posts.post_path(f.object)
6
+
7
+ = f.text_field :slug, required: f.object.persisted?,
8
+ 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
9
+
10
+ - if defined?(EffectiveArticleEditor)
11
+ = f.article_editor :excerpt, hint: 'Will be used for the post excerpt on index pages.'
12
+ - else
13
+ = f.rich_text_area :excerpt, hint: 'Will be used for the post excerpt on index pages.'
14
+
15
+ = f.text_field :description, hint: 'The content of the post meta tags.', maxlength: 150
16
+
17
+ - if Array(EffectivePosts.categories).length > 1
18
+ = f.select :category, EffectivePosts.categories
19
+ - else
20
+ = f.hidden_field :category, value: (EffectivePosts.categories.first || 'posts')
21
+
22
+ - if f.object.class.respond_to?(:acts_as_tagged?)
23
+ = render 'effective/tags/fields', f: f
24
+
25
+ - if EffectivePosts.use_active_storage
26
+ = f.file_field :image, hint: 'An image for your post'
27
+
28
+ - if defined?(EffectiveArticleEditor)
29
+ = f.article_editor :body, hint: 'The main body of your post'
30
+ - else
31
+ = f.rich_text_area :body, hint: 'The main body of your post'
32
+
33
+ = render partial: '/effective/posts/additional_fields', locals: { post: post, form: f, f: f }
34
+
35
+ = f.datetime_field :published_at, label: 'Publish date', hint: 'When should this be displayed on the website.'
36
+
37
+ = f.check_box :draft, hint: 'Save this post as a draft. It will not be accessible on the website.'
38
+
39
+ - if EffectivePosts.use_effective_roles
40
+ = render partial: '/admin/posts/roles', locals: { post: post, form: f, f: f }
41
+
42
+ = f.submit do
43
+ = f.save 'Save'
44
+ = f.save 'Save and View', class: 'btn btn-secondary'
45
+ - if f.object.persisted?
46
+ = f.save 'Duplicate', class: 'btn btn-info'
@@ -1,17 +1,14 @@
1
- -# Adding additional .effective-posts-category-#{category} will correctly show/hide on Posts#new forms
2
-
3
1
  - # Event specific fields
4
- .effective-post-category-events.card.mb-4{style: ('display: none' unless f.object.category == 'events')}
5
- .card-body
6
- %h5.card-title Event Info
7
- = form.datetime_field :start_at, required: false, hint: 'Display a start time for this event.'
2
+ = f.show_if_any(:category, EffectivePosts.event_categories) do
3
+ = card('Event Info') do
4
+ = f.datetime_field :start_at, required: false, hint: 'Display a start time for this event.'
8
5
 
9
- = form.datetime_field :end_at, required: false, hint: 'Display an end time of this event.'
6
+ = f.datetime_field :end_at, required: false, hint: 'Display an end time of this event.'
10
7
 
11
- = form.text_field :location, required: false, hint: 'Display a location where this event is taking place.'
8
+ = f.text_field :location, required: false, hint: 'Display a location where this event is taking place.'
12
9
 
13
- = form.text_field :website_name, label: 'External website',
10
+ = f.text_field :website_name, label: 'External website',
14
11
  placeholder: 'Buy Tickets', hint: 'The label of an external website.'
15
12
 
16
- = form.url_field :website_href, label: 'External website address',
13
+ = f.url_field :website_href, label: 'External website address',
17
14
  placeholder: 'http://', hint: 'The address of an external website (start with http:// or https://).'
@@ -1,9 +1,14 @@
1
1
  EffectivePosts.setup do |config|
2
2
  config.posts_table_name = :posts
3
3
 
4
- # Every post must belong to one or more category.
5
- # Don't use the category :posts
6
- config.categories = [:news]
4
+ # Every post must have a category
5
+ # Each of these categories parameterized value will be a top level route
6
+ config.categories = ['News', 'Events']
7
+
8
+ # Which of the above categories will be considered post.event?
9
+ # Used to select the fields on the Admin form
10
+ # Can't be unique. Must be subset of config.categories
11
+ config.event_categories = ['Events']
7
12
 
8
13
  # Create top level routes for each category
9
14
  # Should each of the above categories have a top level route created for it
data/config/routes.rb CHANGED
@@ -11,7 +11,7 @@ EffectivePosts::Engine.routes.draw do
11
11
 
12
12
  # Blog Routes
13
13
  match 'blog/category/:category', to: 'posts#index', via: :get, constraints: lambda { |req|
14
- EffectivePosts.use_blog_routes && EffectivePosts.categories.include?(req.params['category'].to_sym)
14
+ EffectivePosts.use_blog_routes && EffectivePosts.category(req.params['category']).present?
15
15
  }
16
16
 
17
17
  resources :posts, only: [:index, :show], path: 'blog', constraints: lambda { |req|
@@ -20,11 +20,11 @@ EffectivePosts::Engine.routes.draw do
20
20
 
21
21
  # Category routes
22
22
  match ':category', to: 'posts#index', via: :get, constraints: lambda { |req|
23
- EffectivePosts.use_category_routes && EffectivePosts.categories.include?(req.params['category'].to_sym)
23
+ EffectivePosts.use_category_routes && EffectivePosts.category(req.params['category']).present?
24
24
  }
25
25
 
26
26
  match ":category/:id", to: 'posts#show', via: :get, constraints: lambda { |req|
27
- EffectivePosts.use_category_routes && EffectivePosts.categories.include?(req.params['category'].to_sym)
27
+ EffectivePosts.use_category_routes && EffectivePosts.category(req.params['category']).present?
28
28
  }
29
29
  end
30
30
 
@@ -1,3 +1,3 @@
1
1
  module EffectivePosts
2
- VERSION = '2.2.4'.freeze
2
+ VERSION = '2.3.1'.freeze
3
3
  end
@@ -6,7 +6,8 @@ module EffectivePosts
6
6
 
7
7
  def self.config_keys
8
8
  [
9
- :posts_table_name, :layout, :categories,
9
+ :posts_table_name, :layout,
10
+ :categories, :event_categories,
10
11
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject,
11
12
  :use_category_routes, :use_blog_routes,
12
13
  :use_effective_roles, :use_active_storage,
@@ -29,4 +30,33 @@ module EffectivePosts
29
30
  ]
30
31
  end
31
32
 
33
+ # Normalize and return the category that matches this value
34
+ def self.category(value, safe: true)
35
+ values = [value, value.to_s, value.to_s.downcase, value.to_s.downcase.parameterize, value.to_s.parameterize]
36
+
37
+ category = categories.find do |cat|
38
+ (values & [cat, cat.to_s, cat.to_s.downcase, cat.to_s.downcase.parameterize, cat.to_s.parameterize]).present?
39
+ end
40
+
41
+ raise("Unable to find EffectivePosts.category for value '#{value.presence || 'nil'}'") unless safe
42
+
43
+ category
44
+ end
45
+
46
+ def self.categories
47
+ Array(config[:categories])
48
+ end
49
+
50
+ def self.event_categories
51
+ Array(config[:event_categories])
52
+ end
53
+
54
+ def self.not_event_categories
55
+ categories - event_categories
56
+ end
57
+
58
+ def self.news_categories
59
+ categories - event_categories
60
+ end
61
+
32
62
  end
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.2.4
4
+ version: 2.3.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: 2023-06-26 00:00:00.000000000 Z
11
+ date: 2023-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -92,7 +92,6 @@ files:
92
92
  - README.md
93
93
  - app/assets/config/effective_posts_manifest.js
94
94
  - app/assets/javascripts/effective_posts.js
95
- - app/assets/javascripts/effective_posts/additional_fields.js.coffee
96
95
  - app/assets/stylesheets/effective_posts.scss
97
96
  - app/controllers/admin/posts_controller.rb
98
97
  - app/controllers/effective/posts_controller.rb
@@ -101,6 +100,7 @@ files:
101
100
  - app/mailers/effective/posts_mailer.rb
102
101
  - app/models/effective/post.rb
103
102
  - app/views/admin/posts/_form.html.haml
103
+ - app/views/admin/posts/_form_post.html.haml
104
104
  - app/views/admin/posts/_roles.html.haml
105
105
  - app/views/admin/posts/excerpts.html.haml
106
106
  - app/views/admin/posts/index.html.haml
@@ -1,8 +0,0 @@
1
- # Show/hide the Event fields on admin/posts form
2
-
3
- $(document).on 'change', "select[name='effective_post[category]']", (event) ->
4
- obj = $(event.currentTarget)
5
-
6
- obj.closest('form').find("[class^='effective-post-category-']").hide()
7
- obj.closest('form').find(".effective-post-category-#{obj.val()}").show()
8
-