decidim-blogs 0.11.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +30 -0
  3. data/Rakefile +3 -0
  4. data/app/assets/images/decidim/blogs/icon.svg +3 -0
  5. data/app/commands/decidim/blogs/admin/create_post.rb +50 -0
  6. data/app/commands/decidim/blogs/admin/update_post.rb +44 -0
  7. data/app/controllers/decidim/blogs/admin/application_controller.rb +22 -0
  8. data/app/controllers/decidim/blogs/admin/posts_controller.rb +64 -0
  9. data/app/controllers/decidim/blogs/application_controller.rb +14 -0
  10. data/app/controllers/decidim/blogs/posts_controller.rb +35 -0
  11. data/app/events/decidim/blogs/create_post_event.rb +8 -0
  12. data/app/forms/decidim/blogs/admin/post_form.rb +18 -0
  13. data/app/helpers/decidim/blogs/admin/posts_helper.rb +25 -0
  14. data/app/helpers/decidim/blogs/application_helper.rb +13 -0
  15. data/app/helpers/decidim/blogs/posts_helper.rb +25 -0
  16. data/app/models/decidim/blogs/application_record.rb +10 -0
  17. data/app/models/decidim/blogs/post.rb +44 -0
  18. data/app/presenters/decidim/module/blogs/post_presenter.rb +14 -0
  19. data/app/views/decidim/blogs/admin/posts/_form.html.erb +13 -0
  20. data/app/views/decidim/blogs/admin/posts/edit.html.erb +7 -0
  21. data/app/views/decidim/blogs/admin/posts/index.html.erb +53 -0
  22. data/app/views/decidim/blogs/admin/posts/new.html.erb +7 -0
  23. data/app/views/decidim/blogs/posts/_author_data.html.erb +7 -0
  24. data/app/views/decidim/blogs/posts/_datetime.html.erb +1 -0
  25. data/app/views/decidim/blogs/posts/_posts.html.erb +20 -0
  26. data/app/views/decidim/blogs/posts/_sidebar_blog.html.erb +21 -0
  27. data/app/views/decidim/blogs/posts/index.html.erb +10 -0
  28. data/app/views/decidim/blogs/posts/show.html.erb +23 -0
  29. data/config/locales/ca.yml +69 -0
  30. data/config/locales/en.yml +70 -0
  31. data/config/locales/es.yml +69 -0
  32. data/config/locales/eu.yml +69 -0
  33. data/config/locales/fi.yml +69 -0
  34. data/config/locales/fr.yml +69 -0
  35. data/config/locales/gl.yml +69 -0
  36. data/config/locales/it.yml +69 -0
  37. data/config/locales/nl.yml +69 -0
  38. data/config/locales/pl.yml +69 -0
  39. data/config/locales/pt-BR.yml +69 -0
  40. data/config/locales/pt.yml +69 -0
  41. data/config/locales/ru.yml +5 -0
  42. data/config/locales/sv.yml +69 -0
  43. data/config/locales/uk.yml +6 -0
  44. data/db/migrate/20171129131353_create_decidim_blogs_posts.rb +12 -0
  45. data/db/migrate/20171211084630_add_author_to_decidim_blogs_posts.rb +7 -0
  46. data/lib/decidim/blogs.rb +13 -0
  47. data/lib/decidim/blogs/admin.rb +10 -0
  48. data/lib/decidim/blogs/admin_engine.rb +22 -0
  49. data/lib/decidim/blogs/component.rb +65 -0
  50. data/lib/decidim/blogs/engine.rb +24 -0
  51. data/lib/decidim/blogs/test/factories.rb +20 -0
  52. data/lib/decidim/blogs/version.rb +10 -0
  53. metadata +235 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 77d681860119dee520f12322bc3f82962b485e3710348cf0f95d3c2a3ac8fa2e
4
+ data.tar.gz: b48ac462f570f74867ff27af60100619bac5a9324654ac916696e8266fd90f43
5
+ SHA512:
6
+ metadata.gz: 46b48ee482df01acd8c07a2e24dd98efd75a5550eee2a33d96bf4d3ffae82718f269c5fdcb3f1bf01b5d7e7bc0b46fbdf3e4f502904bf2d7fd0407962b21fce8
7
+ data.tar.gz: 401e1475f4107a3b265ea7f3bbf1e72ec2dc6188ce213da3f229f8bea989eec290708ce3008fa5d6aaf1c1022381634b09edef1c16e1e81c78d44958f7ccd6cb
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # decidim-blogs
2
+
3
+ The BLOG module adds posts to any participatory process. It adds a CRUD engine
4
+ to the admin and public view scoped inside the participatory process.
5
+
6
+ ## Usage
7
+
8
+ BLOG will be available as a Component for a Participatory Process.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'decidim-blogs'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```bash
21
+ bundle
22
+ ```
23
+
24
+ ## Contributing
25
+
26
+ See [Decidim](https://github.com/decidim/decidim).
27
+
28
+ ## License
29
+
30
+ See [Decidim](https://github.com/decidim/decidim).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
2
+ <path d="M18 0C8.07 0 0 8.07 0 18s8.07 18 18 18 18-8.071 18-18S27.93 0 18 0zm0 2c8.85 0 16 7.152 16 16 0 8.848-7.15 16-16 16-8.848 0-16-7.152-16-16C2 9.152 9.152 2 18 2zm-7 9a1 1 0 1 0 0 2h14a1 1 0 1 0 0-2H11zm0 4a1 1 0 1 0 0 2h10a1 1 0 1 0 0-2H11zm0 4a1 1 0 1 0 0 2h14a1 1 0 1 0 0-2H11zm0 4a1 1 0 1 0 0 2h10a1 1 0 1 0 0-2H11z"/>
3
+ </svg>
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # This command is executed when the user creates a Post from the admin
7
+ # panel.
8
+ class CreatePost < Rectify::Command
9
+ def initialize(form, current_user)
10
+ @form = form
11
+ @current_user = current_user
12
+ end
13
+
14
+ # Creates the post if valid.
15
+ #
16
+ # Broadcasts :ok if successful, :invalid otherwise.
17
+ def call
18
+ return broadcast(:invalid) if @form.invalid?
19
+
20
+ transaction do
21
+ create_post!
22
+ send_notification
23
+ end
24
+
25
+ broadcast(:ok, @post)
26
+ end
27
+
28
+ private
29
+
30
+ def create_post!
31
+ @post = Post.create!(
32
+ title: @form.title,
33
+ body: @form.body,
34
+ component: @form.current_component,
35
+ decidim_author_id: @current_user.id
36
+ )
37
+ end
38
+
39
+ def send_notification
40
+ Decidim::EventsManager.publish(
41
+ event: "decidim.events.blogs.post_created",
42
+ event_class: Decidim::Blogs::CreatePostEvent,
43
+ resource: @post,
44
+ recipient_ids: @post.participatory_space.followers.pluck(:id)
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # This command is executed when the user changes a Blog from the admin
7
+ # panel.
8
+ class UpdatePost < Rectify::Command
9
+ # Initializes a UpdateBlog Command.
10
+ #
11
+ # form - The form from which to get the data.
12
+ # blog - The current instance of the page to be updated.
13
+ def initialize(form, post)
14
+ @form = form
15
+ @post = post
16
+ end
17
+
18
+ # Updates the blog if valid.
19
+ #
20
+ # Broadcasts :ok if successful, :invalid otherwise.
21
+ def call
22
+ return broadcast(:invalid) if form.invalid?
23
+
24
+ transaction do
25
+ update_post!
26
+ end
27
+
28
+ broadcast(:ok, post)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :form, :post
34
+
35
+ def update_post!
36
+ post.update!(
37
+ title: form.title,
38
+ body: form.body
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # Base controller for the administration of this module. It inherits from
7
+ # Decidim's admin base controller in order to inherit the layout and other
8
+ # convenience methods relevant to a this component.
9
+ class ApplicationController < Decidim::Admin::Components::BaseController
10
+ helper_method :posts, :post
11
+
12
+ def posts
13
+ @posts ||= Post.where(component: current_component).page(params[:page]).per(15)
14
+ end
15
+
16
+ def post
17
+ @post ||= posts.find(params[:id])
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # This controller allows the create or update a blog.
7
+ class PostsController < Admin::ApplicationController
8
+ def new
9
+ @form = form(PostForm).instance
10
+ end
11
+
12
+ def create
13
+ @form = form(PostForm).from_params(params, current_component: current_component)
14
+
15
+ CreatePost.call(@form, current_user) do
16
+ on(:ok) do
17
+ flash[:notice] = I18n.t("posts.create.success", scope: "decidim.blogs.admin")
18
+ redirect_to posts_path
19
+ end
20
+
21
+ on(:invalid) do
22
+ flash.now[:alert] = I18n.t("posts.create.invalid", scope: "decidim.blogs.admin")
23
+ render action: "new"
24
+ end
25
+ end
26
+ end
27
+
28
+ def edit
29
+ @form = form(PostForm).from_model(post)
30
+ end
31
+
32
+ def update
33
+ @form = form(PostForm).from_params(params, current_component: current_component)
34
+
35
+ UpdatePost.call(@form, post) do
36
+ on(:ok) do
37
+ flash[:notice] = I18n.t("posts.update.success", scope: "decidim.blogs.admin")
38
+ redirect_to posts_path
39
+ end
40
+
41
+ on(:invalid) do
42
+ flash.now[:alert] = I18n.t("posts.update.invalid", scope: "decidim.blogs.admin")
43
+ render action: "edit"
44
+ end
45
+ end
46
+ end
47
+
48
+ def destroy
49
+ post.destroy!
50
+
51
+ flash[:notice] = I18n.t("posts.destroy.success", scope: "decidim.blogs.admin")
52
+
53
+ redirect_to posts_path
54
+ end
55
+
56
+ private
57
+
58
+ def post
59
+ @post ||= Blogs::Post.find_by(component: current_component)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # This controller is the abstract class from which all other controllers of
6
+ # this engine inherit.
7
+ #
8
+ # Note that it inherits from `Decidim::Components::Basecontroller`, which
9
+ # override its layout and provide all kinds of useful methods.
10
+ class ApplicationController < Decidim::Components::BaseController
11
+ helper Decidim::Blogs::ApplicationHelper
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # Exposes the blog resource so users can view them
6
+ class PostsController < Decidim::Blogs::ApplicationController
7
+ helper_method :posts, :post, :paginate_posts, :posts_most_commented
8
+
9
+ def index; end
10
+
11
+ def show; end
12
+
13
+ private
14
+
15
+ def paginate_posts
16
+ @paginate_posts ||= posts.created_at_desc.page(params[:page]).per(4)
17
+ end
18
+
19
+ def post
20
+ @post ||= posts.find(params[:id])
21
+ end
22
+
23
+ def posts
24
+ @posts ||= Post.where(component: current_component)
25
+ end
26
+
27
+ # PROVISIONAL if we implement counter cache
28
+ def posts_most_commented
29
+ @posts_most_commented ||= posts.joins(:comments).group(:id)
30
+ .select("count(decidim_comments_comments.id) as counter")
31
+ .select("decidim_blogs_posts.*").order("counter DESC").created_at_desc.limit(7)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ class CreatePostEvent < Decidim::Events::SimpleEvent
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # This class holds a Form to update pages from Decidim's admin panel.
7
+ class PostForm < Decidim::Form
8
+ include TranslatableAttributes
9
+
10
+ translatable_attribute :title, String
11
+ translatable_attribute :body, String
12
+
13
+ validates :title, translatable_presence: true
14
+ validates :body, translatable_presence: true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ module Admin
6
+ # Custom helpers used in posts views
7
+ module PostsHelper
8
+ include Decidim::ApplicationHelper
9
+ # include Decidim::TranslationsHelper
10
+ # include Decidim::ResourceHelper
11
+
12
+ # Public: truncates the post body
13
+ #
14
+ # post - a Decidim::Blog instance
15
+ # max_length - a number to limit the length of the body
16
+ #
17
+ # Returns the post's body truncated.
18
+ def post_description_admin(post, max_length = 100)
19
+ body = translated_attribute(post.body)
20
+ CGI.unescapeHTML html_truncate(body, max_length: max_length)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # Custom helpers, scoped to the blogs engine.
6
+ #
7
+ module ApplicationHelper
8
+ include PaginateHelper
9
+ include Decidim::Blogs::PostsHelper
10
+ include Decidim::Comments::CommentsHelper
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # Custom helpers used in posts views
6
+ module PostsHelper
7
+ include Decidim::ApplicationHelper
8
+ include Decidim::TranslationsHelper
9
+ include Decidim::ResourceHelper
10
+
11
+ # Public: truncates the post body
12
+ #
13
+ # post - a Decidim::Blog instance
14
+ # max_length - a number to limit the length of the body
15
+ #
16
+ # Returns the post's body truncated.
17
+ def post_description(post, max_length = 600)
18
+ link = post_path(post)
19
+ body = translated_attribute(post.body)
20
+ tail = "... <br/> #{link_to(t("read_more", scope: "decidim.blogs"), link)}".html_safe
21
+ CGI.unescapeHTML html_truncate(body, max_length: max_length, tail: tail)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # Abstract class from which all models in this engine inherit.
6
+ class ApplicationRecord < ActiveRecord::Base
7
+ self.abstract_class = true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Blogs
5
+ # The data store for a Blog in the Decidim::Blogs component. It stores a
6
+ # title, description and any other useful information to render a blog.
7
+ class Post < Blogs::ApplicationRecord
8
+ include Decidim::Resourceable
9
+ include Decidim::HasComponent
10
+ include Decidim::Authorable
11
+ include Decidim::Comments::Commentable
12
+
13
+ component_manifest_name "blogs"
14
+
15
+ validates :title, presence: true
16
+
17
+ scope :created_at_desc, -> { order(arel_table[:created_at].desc) }
18
+
19
+ # Public: Overrides the `commentable?` Commentable concern method.
20
+ def commentable?
21
+ component.settings.comments_enabled?
22
+ end
23
+
24
+ # Public: Overrides the `accepts_new_comments?` Commentable concern method.
25
+ def accepts_new_comments?
26
+ commentable? && !component.current_settings.comments_blocked
27
+ end
28
+
29
+ # Public: Overrides the `comments_have_alignment?` Commentable concern method.
30
+ def comments_have_alignment?
31
+ true
32
+ end
33
+
34
+ # Public: Overrides the `comments_have_votes?` Commentable concern method.
35
+ def comments_have_votes?
36
+ true
37
+ end
38
+
39
+ def official?
40
+ author.nil?
41
+ end
42
+ end
43
+ end
44
+ end