decidim-posts 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +40 -0
  4. data/Rakefile +9 -0
  5. data/app/cells/decidim/posts/comments/add_comment.erb +15 -0
  6. data/app/cells/decidim/posts/comments/comments_loading.erb +1 -0
  7. data/app/cells/decidim/posts/comments/order_control.erb +13 -0
  8. data/app/cells/decidim/posts/comments/show.erb +31 -0
  9. data/app/cells/decidim/posts/comments_cell.rb +158 -0
  10. data/app/cells/decidim/posts/content_blocks/posts/show.erb +3 -0
  11. data/app/cells/decidim/posts/content_blocks/posts_cell.rb +50 -0
  12. data/app/cells/decidim/posts/content_blocks/posts_settings_form/show.erb +3 -0
  13. data/app/cells/decidim/posts/content_blocks/posts_settings_form_cell.rb +23 -0
  14. data/app/cells/decidim/posts/feed_dropdown_metadata_cell.rb +19 -0
  15. data/app/cells/decidim/posts/meeting/show.erb +65 -0
  16. data/app/cells/decidim/posts/meeting_cell.rb +44 -0
  17. data/app/cells/decidim/posts/post/show.erb +30 -0
  18. data/app/cells/decidim/posts/post/survey.erb +68 -0
  19. data/app/cells/decidim/posts/post_attachments/show.erb +40 -0
  20. data/app/cells/decidim/posts/post_attachments_cell.rb +17 -0
  21. data/app/cells/decidim/posts/post_cell.rb +44 -0
  22. data/app/cells/decidim/posts/post_comment/show.erb +17 -0
  23. data/app/cells/decidim/posts/post_comment_cell.rb +49 -0
  24. data/app/cells/decidim/posts/post_header/show.erb +53 -0
  25. data/app/cells/decidim/posts/post_header_cell.rb +79 -0
  26. data/app/cells/decidim/posts/post_host/show.erb +74 -0
  27. data/app/cells/decidim/posts/post_host_cell.rb +73 -0
  28. data/app/cells/decidim/posts/post_metadata/show.erb +9 -0
  29. data/app/cells/decidim/posts/post_metadata_cell.rb +67 -0
  30. data/app/cells/decidim/posts/reaction_menu/show.erb +18 -0
  31. data/app/cells/decidim/posts/reaction_menu/styles.erb +7 -0
  32. data/app/cells/decidim/posts/reaction_menu_cell.rb +26 -0
  33. data/app/cells/decidim/posts/reactions/show.erb +8 -0
  34. data/app/cells/decidim/posts/reactions_cell.rb +22 -0
  35. data/app/commands/decidim/posts/add_reaction_to_resource.rb +90 -0
  36. data/app/commands/decidim/posts/create_post.rb +112 -0
  37. data/app/commands/decidim/posts/destroy_post.rb +20 -0
  38. data/app/commands/decidim/posts/remove_reaction_from_resource.rb +41 -0
  39. data/app/commands/decidim/posts/update_post.rb +72 -0
  40. data/app/controllers/concerns/decidim/posts/admin/filterable.rb +46 -0
  41. data/app/controllers/concerns/decidim/posts/reactionable.rb +31 -0
  42. data/app/controllers/decidim/posts/admin/application_controller.rb +26 -0
  43. data/app/controllers/decidim/posts/admin/posts_controller.rb +93 -0
  44. data/app/controllers/decidim/posts/application_controller.rb +18 -0
  45. data/app/controllers/decidim/posts/meetings_controller.rb +176 -0
  46. data/app/controllers/decidim/posts/posts_controller.rb +202 -0
  47. data/app/controllers/decidim/posts/reactions_controller.rb +54 -0
  48. data/app/controllers/decidim/posts/user_answers_controller.rb +36 -0
  49. data/app/events/decidim/posts/resource_reacted_event.rb +38 -0
  50. data/app/forms/decidim/posts/answer_form.rb +13 -0
  51. data/app/forms/decidim/posts/post_form.rb +121 -0
  52. data/app/forms/decidim/posts/question_form.rb +20 -0
  53. data/app/helpers/decidim/posts/admin/posts_helper.rb +8 -0
  54. data/app/helpers/decidim/posts/application_helper.rb +20 -0
  55. data/app/helpers/decidim/posts/post_cells_helper.rb +35 -0
  56. data/app/helpers/decidim/posts/posts_helper.rb +34 -0
  57. data/app/helpers/decidim/posts/reaction_helper.rb +22 -0
  58. data/app/models/decidim/posts/answer.rb +13 -0
  59. data/app/models/decidim/posts/application_record.rb +10 -0
  60. data/app/models/decidim/posts/post.rb +116 -0
  61. data/app/models/decidim/posts/question.rb +17 -0
  62. data/app/models/decidim/posts/reaction.rb +22 -0
  63. data/app/models/decidim/posts/reaction_type.rb +13 -0
  64. data/app/models/decidim/posts/user_answer.rb +11 -0
  65. data/app/packs/entrypoints/decidim_posts.js +5 -0
  66. data/app/packs/entrypoints/decidim_posts.scss +1 -0
  67. data/app/packs/images/decidim/posts/icon.svg +1 -0
  68. data/app/packs/src/decidim/posts/carousel.js +112 -0
  69. data/app/packs/src/decidim/posts/host_status.js +75 -0
  70. data/app/packs/src/decidim/posts/newFeeds.js +98 -0
  71. data/app/packs/src/decidim/posts/posts.js +272 -0
  72. data/app/packs/src/decidim/posts/submenu.js +46 -0
  73. data/app/packs/src/decidim/posts/survey.js +94 -0
  74. data/app/packs/stylesheets/decidim/posts/_variables.scss +10 -0
  75. data/app/packs/stylesheets/decidim/posts/posts.scss +415 -0
  76. data/app/permissions/decidim/posts/admin/permissions.rb +23 -0
  77. data/app/permissions/decidim/posts/permissions.rb +101 -0
  78. data/app/presenters/decidim/posts/post_presenter.rb +45 -0
  79. data/app/views/decidim/posts/admin/posts/_post-tr.html.erb +45 -0
  80. data/app/views/decidim/posts/admin/posts/index.html.erb +54 -0
  81. data/app/views/decidim/posts/meetings/edit.html.erb +24 -0
  82. data/app/views/decidim/posts/posts/_admin_options.html.erb +30 -0
  83. data/app/views/decidim/posts/posts/_attachment.html.erb +24 -0
  84. data/app/views/decidim/posts/posts/_edit_form.html.erb +16 -0
  85. data/app/views/decidim/posts/posts/_feed.html.erb +8 -0
  86. data/app/views/decidim/posts/posts/_form.html.erb +104 -0
  87. data/app/views/decidim/posts/posts/_index.html.erb +49 -0
  88. data/app/views/decidim/posts/posts/_meeting_form.erb +18 -0
  89. data/app/views/decidim/posts/posts/_new.html.erb +33 -0
  90. data/app/views/decidim/posts/posts/_new_survey.html.erb +20 -0
  91. data/app/views/decidim/posts/posts/_new_survey_answer.html.erb +11 -0
  92. data/app/views/decidim/posts/posts/_new_survey_question.html.erb +17 -0
  93. data/app/views/decidim/posts/posts/_post.html.erb +11 -0
  94. data/app/views/decidim/posts/posts/_post_form.html.erb +5 -0
  95. data/app/views/decidim/posts/posts/_sidebar.html.erb +36 -0
  96. data/app/views/decidim/posts/posts/edit.html.erb +34 -0
  97. data/app/views/decidim/posts/posts/index.html.erb +1 -0
  98. data/app/views/decidim/posts/posts/show.html.erb +12 -0
  99. data/app/views/decidim/posts/reactions/_update_buttons_and_counters.html.erb +1 -0
  100. data/config/assets.rb +9 -0
  101. data/config/i18n-tasks.yml +10 -0
  102. data/config/locales/bs.yml +215 -0
  103. data/config/locales/de.yml +217 -0
  104. data/config/locales/en.yml +216 -0
  105. data/config/locales/hr.yml +219 -0
  106. data/config/locales/it.yml +215 -0
  107. data/config/locales/sr.yml +220 -0
  108. data/config/locales/tr.yml +219 -0
  109. data/lib/decidim/posts/admin.rb +10 -0
  110. data/lib/decidim/posts/admin_engine.rb +25 -0
  111. data/lib/decidim/posts/component.rb +59 -0
  112. data/lib/decidim/posts/content_blocks/content_blocks_homepage.rb +19 -0
  113. data/lib/decidim/posts/engine.rb +84 -0
  114. data/lib/decidim/posts/test/factories.rb +14 -0
  115. data/lib/decidim/posts/version.rb +9 -0
  116. data/lib/decidim/posts.rb +13 -0
  117. metadata +183 -0
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ # This command is executed when a participant or user group creates a Meeting from the public
6
+ # views.
7
+ class CreatePost < Decidim::Command
8
+ # include CurrentLocale
9
+ include ::Decidim::MultipleAttachmentsMethods
10
+
11
+ def initialize(form)
12
+ @form = form
13
+ end
14
+
15
+ def call
16
+ return broadcast(:invalid) if form.invalid?
17
+
18
+ if process_attachments?
19
+ build_attachments
20
+ return broadcast(:invalid) if attachments_invalid?
21
+ end
22
+
23
+ with_events(with_transaction: true) do
24
+ Decidim.traceability.perform_action!("create_feeds_post", Post, form.current_user) do
25
+ create_post
26
+ end
27
+
28
+ # create_attachments(weight: first_attachment_weight) if process_attachments?
29
+ create_attachments if process_attachments?
30
+ end
31
+
32
+ # create_follow_form_resource(form.current_user)
33
+ #send_notification
34
+
35
+ broadcast(:ok, post)
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :post, :form, :attachment
41
+
42
+ def event_arguments
43
+ {
44
+ resource: post,
45
+ extra: {
46
+ event_author: form.current_user,
47
+ locale:
48
+ }
49
+ }
50
+ end
51
+
52
+ def create_post
53
+ # parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
54
+ # parsed_description = Decidim::ContentProcessor.parse(form.description, current_organization: form.current_organization).rewrite
55
+
56
+ @post = Decidim::Posts::Post.new(
57
+ category: form.category,
58
+ enable_comments: form.enable_comments,
59
+ body: { I18n.locale => form.body },
60
+ author: form.current_user,
61
+ component: form.current_component,
62
+ highlighted: form.highlighted,
63
+ fixed: form.fixed
64
+ )
65
+
66
+ form.questions.each do |question_form|
67
+ @post.questions.build(
68
+ title: { I18n.locale => question_form.title },
69
+ question_type: question_form.question_type,
70
+ post: @post
71
+ )
72
+ # build answers for each question
73
+ question_form.answers.each do |answer_form|
74
+ @post.questions.last.answers.build(
75
+ title: { I18n.locale => answer_form.title },
76
+ question: @post.questions.last
77
+ )
78
+ end
79
+ end
80
+ @post.save!
81
+
82
+ @attached_to = @post
83
+
84
+ @post
85
+ end
86
+
87
+ # TODO: Finish this method
88
+ # def send_notification
89
+ # Decidim::EventsManager.publish(
90
+ # event: "decidim.events.feeds.post_created",
91
+ # event_class: Decidim::Posts::CreatePostEvent,
92
+ # resource: post,
93
+ # followers: post.participatory_space.followers,
94
+ # extra: {
95
+ # participatory_space: true,
96
+ # }
97
+ # )
98
+ # end
99
+
100
+ # def create_follow_form_resource(user)
101
+ # follow_form = Decidim::FollowForm.from_params(followable_gid: post.to_signed_global_id.to_s).with_context(current_user: user)
102
+ # Decidim::CreateFollow.call(follow_form, user)
103
+ # end
104
+
105
+ def first_attachment_weight
106
+ return 1 if post.documents.count.zero?
107
+
108
+ post.documents.count
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ class DestroyPost < Decidim::Command
6
+ def initialize(post, current_user)
7
+ @post = post
8
+ @current_user = current_user
9
+ end
10
+
11
+ def call
12
+ return broadcast(:invalid) unless @post.authored_by?(@current_user) || @current_user.admin?
13
+
14
+ @post.destroy!
15
+
16
+ broadcast(:ok, @post)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ # A command with all the business logic to remove a reaction from a resource, both as a user or as a user_group.
6
+ class RemoveReactionFromResource < Decidim::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # resource - A Decidim::Posts::Reactionable object.
10
+ # current_user - The current user.
11
+ # current_group- (optional) The current_group that is unendorsing the Resource.
12
+ def initialize(resource, current_user, current_group = nil)
13
+ @resource = resource
14
+ @current_user = current_user
15
+ @current_group = current_group
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid, together with the resource.
21
+ # - :invalid if the form was not valid and we could not proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ destroy_resource_reaction
26
+ broadcast(:ok, @resource)
27
+ end
28
+
29
+ private
30
+
31
+ def destroy_resource_reaction
32
+ query = if @current_group.present?
33
+ @resource.reactions.where(decidim_user_group_id: @current_group&.id)
34
+ else
35
+ @resource.reactions.where(author: @current_user, decidim_user_group_id: 0)
36
+ end
37
+ query.destroy_all
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,72 @@
1
+ module Decidim
2
+ module Posts
3
+ class UpdatePost < Decidim::Command
4
+ include ::Decidim::MultipleAttachmentsMethods
5
+
6
+ def initialize(form, current_user, post)
7
+ @form = form
8
+ @current_user = current_user
9
+ @post = post
10
+ @attached_to = post
11
+ end
12
+
13
+ def call
14
+ return broadcast(:invalid) if invalid?
15
+
16
+ if process_attachments?
17
+ build_attachments
18
+ return broadcast(:invalid) if attachments_invalid?
19
+ end
20
+
21
+ with_events(with_transaction: true) do
22
+ #Decidim.traceability.perform_action!("update_feeds_post", Post, form.current_user) do
23
+ update_post
24
+ #end
25
+ document_cleanup!(include_all_attachments: true)
26
+ create_attachments if process_attachments?
27
+ end
28
+
29
+
30
+ broadcast(:ok, @post)
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :post, :form, :current_user, :attachment
36
+
37
+ def event_arguments
38
+ {
39
+ resource: @post,
40
+ extra: {
41
+ event_author: form.current_user,
42
+ locale:
43
+ }
44
+ }
45
+ end
46
+
47
+ def invalid?
48
+ form.invalid? || !@post.editable_by?(current_user)
49
+ end
50
+
51
+ def update_post
52
+ @post = Decidim.traceability.update!(
53
+ @post,
54
+ current_user,
55
+ attributes,
56
+ visibility: "public-only"
57
+ )
58
+ end
59
+
60
+ def attributes
61
+ {
62
+ category: form.category,
63
+ body: { I18n.locale => form.body },
64
+ enable_comments: form.enable_comments,
65
+ highlighted: form.highlighted,
66
+ fixed: form.fixed
67
+ }
68
+ end
69
+ end
70
+ end
71
+ end
72
+
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Posts
7
+ module Admin
8
+ module Filterable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Decidim::Admin::Filterable
13
+
14
+ private
15
+
16
+ # Comment about participatory_texts_enabled.
17
+ def base_query
18
+ return collection
19
+ end
20
+
21
+ def search_field_predicate
22
+ :id_string_or_title_cont
23
+ end
24
+
25
+ def filters
26
+ [
27
+ # :category_eq
28
+ ]
29
+ end
30
+
31
+ def filters_with_values
32
+ {
33
+ # category_eq: category_ids_hash(categories.first_class)
34
+ }
35
+ end
36
+
37
+ # Cannot user `super` here, because it does not belong to a superclass
38
+ # but to a concern.
39
+ # def dynamically_translated_filters
40
+ # [:scope_id_eq, :category_id_eq, :valuator_role_ids_has]
41
+ # end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This concern contains the logic related with resources that can be reacted to.
5
+ # Thus, it is expected to be included into a resource that is wanted to be reactionable.
6
+ # This resource will have many `Decidim::Posts::Reactions.
7
+ module Posts
8
+ module Reactionable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ has_many :reactions,
13
+ as: :resource,
14
+ dependent: :destroy,
15
+ counter_cache: "reactions_count"
16
+
17
+ # Public: Check if the user has reacted to the resource.
18
+ # - user_group: may be nil if user is not representing any user_group.
19
+ #
20
+ # Returns Boolean.
21
+ def reacted_by?(user, user_group = nil)
22
+ if user_group
23
+ reactions.where(user_group:).any?
24
+ else
25
+ reactions.where(author: user, user_group: 0).any?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ module Admin
6
+ # This controller is the abstract class from which all other controllers of
7
+ # this engine inherit.
8
+ #
9
+ # Note that it inherits from `Decidim::Admin::Components::BaseController`, which
10
+ # override its layout and provide all kinds of useful methods.
11
+ class ApplicationController < Decidim::Admin::Components::BaseController
12
+ def permission_class_chain
13
+ [::Decidim::Posts::Admin::Permissions] + super
14
+ end
15
+
16
+ def user_not_authorized_path
17
+ decidim.root_path
18
+ end
19
+
20
+ def user_has_no_permission_path
21
+ decidim.root_path
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ module Admin
6
+ # This controller allows admins to manage posts in a participatory space.
7
+ class PostsController < Admin::ApplicationController
8
+ include Decidim::ApplicationHelper
9
+ include Decidim::Posts::Admin::Filterable
10
+
11
+ helper Feeds::ApplicationHelper
12
+ # helper Decidim::Messaging::ConversationHelper
13
+ helper_method :posts, :query, :form_presenter, :post, :post_ids, :present
14
+
15
+ def index
16
+ end
17
+
18
+ def show
19
+ end
20
+
21
+ def new
22
+ enforce_permission_to :create, :post
23
+ # @form = form(Decidim::Posts::Admin::PostForm).from_params(
24
+ # attachment: form(AttachmentForm).from_params({})
25
+ # )
26
+ end
27
+
28
+ def create
29
+ enforce_permission_to :create, :post
30
+ @form = form(Decidim::Posts::Admin::PostForm).from_params(params)
31
+
32
+ Admin::CreatePost.call(@form) do
33
+ on(:ok) do
34
+ flash[:notice] = I18n.t("posts.create.success", scope: "decidim.posts.admin")
35
+ redirect_to posts_path
36
+ end
37
+
38
+ on(:invalid) do
39
+ flash.now[:alert] = I18n.t("posts.create.invalid", scope: "decidim.posts.admin")
40
+ render action: "new"
41
+ end
42
+ end
43
+ end
44
+
45
+ def edit
46
+ enforce_permission_to(:edit, :post, post:)
47
+ @form = form(Admin::PostForm).from_model(post)
48
+ end
49
+
50
+ def update
51
+ enforce_permission_to(:edit, :post, post:)
52
+
53
+ @form = form(Admin::PostForm).from_params(params)
54
+
55
+ Admin::UpdatePost.call(@form, @post) do
56
+ on(:ok) do |_post|
57
+ flash[:notice] = t("feeds.update.success", scope: "decidim")
58
+ redirect_to posts_path
59
+ end
60
+
61
+ on(:invalid) do
62
+ flash.now[:alert] = t("feeds.update.error", scope: "decidim")
63
+ render :edit
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def collection
71
+ @collection ||= Post.where(component: current_component)#.not_hidden
72
+ end
73
+
74
+ def posts
75
+ # @posts ||= filtered_collection
76
+ @posts ||= collection
77
+ end
78
+
79
+ def post
80
+ @post ||= collection.find(params[:id])
81
+ end
82
+
83
+ def post_ids
84
+ @post_ids ||= params[:post_ids]
85
+ end
86
+
87
+ def form_presenter
88
+ @form_presenter ||= present(@form, presenter_class: Decidim::Posts::PostPresenter)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
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::Posts::ApplicationHelper
12
+
13
+ def user_has_no_permission_path
14
+ decidim.new_user_session_path
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Posts
5
+ # Exposes the meeting resource so users can view them
6
+ class MeetingsController < Decidim::Posts::ApplicationController
7
+ # include FilterResource
8
+ # include ComponentFilterable
9
+ include Flaggable
10
+ include Withdrawable
11
+ include FormFactory
12
+ # include Paginable
13
+
14
+ helper Decidim::ResourceVersionsHelper
15
+ helper Decidim::ShortLinkHelper
16
+ include Decidim::AttachmentsHelper
17
+
18
+ helper_method :meetings, :meeting, :registration, :search, :nav_paths, :tab_panel_items
19
+
20
+ before_action :add_addtional_csp_directives, only: [:show]
21
+
22
+ def new
23
+ enforce_permission_to :create, :meeting
24
+
25
+ @form = meeting_form.instance
26
+ end
27
+
28
+ def create
29
+ enforce_permission_to :create, :meeting
30
+
31
+ # Duplicate location to address field
32
+ params[:meeting][:address] = params[:meeting][:location] if params[:meeting][:address].blank?
33
+
34
+ @form = meeting_form.from_params(params, current_component: meetings_component)
35
+
36
+ Decidim::Meetings::CreateMeeting.call(@form) do
37
+ on(:ok) do |meeting|
38
+ flash[:notice] = I18n.t("meetings.create.success", scope: "decidim.meetings")
39
+ redirect_to posts_path
40
+ end
41
+
42
+ on(:invalid) do
43
+ flash.now[:alert] = I18n.t("meetings.create.invalid", scope: "decidim.meetings")
44
+ redirect_to posts_path
45
+ end
46
+ end
47
+ end
48
+
49
+ def edit
50
+ enforce_permission_to(:update, :meeting, meeting:)
51
+
52
+ @context = {
53
+ current_organization: @controller.try(:current_organization),
54
+ current_component: @controller.try(:current_component),
55
+ current_user: @controller.try(:current_user),
56
+ current_participatory_space: @controller.try(:current_participatory_space)
57
+ }
58
+ @feeds_component = current_component.participatory_space.components.find_by(manifest_name: "posts")
59
+ @target_participatory_space = @feeds_component.participatory_space
60
+ @form = meeting_form.from_model(meeting).with_context(@context)
61
+ end
62
+
63
+ def update
64
+ enforce_permission_to(:update, :meeting, meeting:)
65
+
66
+ @form = meeting_form.from_params(params)
67
+
68
+ Decidim::Meetings::UpdateMeeting.call(@form, current_user, meeting) do
69
+ on(:ok) do |meeting|
70
+ flash[:notice] = I18n.t("meetings.update.success", scope: "decidim.meetings")
71
+ redirect_to posts_path
72
+ end
73
+
74
+ on(:invalid) do
75
+ flash.now[:alert] = I18n.t("meetings.update.invalid", scope: "decidim.meetings")
76
+ render :edit
77
+ end
78
+ end
79
+ end
80
+
81
+ def withdraw
82
+ enforce_permission_to(:withdraw, :meeting, meeting:)
83
+
84
+ Decidim::Meetings::WithdrawMeeting.call(@meeting, current_user) do
85
+ on(:ok) do
86
+ flash[:notice] = I18n.t("meetings.withdraw.success", scope: "decidim")
87
+ redirect_to posts_path
88
+ end
89
+ on(:invalid) do
90
+ flash[:alert] = I18n.t("meetings.withdraw.error", scope: "decidim")
91
+ redirect_to posts_path
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def meeting
99
+ @meeting ||= Decidim::Meetings::Meeting.not_hidden.where(component: current_component.participatory_space.components.find_by(manifest_name: "meetings")).find_by(id: params[:id])
100
+ end
101
+
102
+ def nav_paths
103
+ return {} if meeting.blank?
104
+
105
+ { prev_path: prev_meeting, next_path: next_meeting }.compact_blank.transform_values { |meeting| meeting_path(meeting) }
106
+ end
107
+
108
+ def meetings
109
+ is_past_meetings = params.dig("filter", "with_any_date")&.include?("past")
110
+ @meetings ||= paginate(search.result.order(start_time: is_past_meetings ? :desc : :asc))
111
+ end
112
+
113
+ def registration
114
+ @registration ||= meeting.registrations.find_by(user: current_user)
115
+ end
116
+
117
+ def search_collection
118
+ Decidim::Meetings::Meeting.where(component: current_component).published.not_hidden.visible_for(current_user).with_availability(
119
+ filter_params[:with_availability]
120
+ ).includes(
121
+ :component,
122
+ attachments: :file_attachment
123
+ )
124
+ end
125
+
126
+ def participatory_space
127
+ @participatory_space ||= current_component.participatory_space
128
+ end
129
+
130
+ def meetings_component
131
+ @meetings_component ||= participatory_space.components.find_by(manifest_name: "meetings")
132
+ end
133
+
134
+ def meeting_form
135
+ form(Decidim::Meetings::MeetingForm)
136
+ end
137
+
138
+ def tab_panel_items
139
+ @tab_panel_items ||= [
140
+ {
141
+ enabled: meeting.public_participants.any?,
142
+ id: "participants",
143
+ text: t("attending_participants", scope: "decidim.meetings.public_participants_list"),
144
+ icon: "group-line",
145
+ method: :cell,
146
+ args: ["decidim/meetings/public_participants_list", meeting]
147
+ },
148
+ {
149
+ enabled: !meeting.closed? && meeting.user_group_registrations.any?,
150
+ id: "organizations",
151
+ text: t("attending_organizations", scope: "decidim.meetings.public_participants_list"),
152
+ icon: "community-line",
153
+ method: :cell,
154
+ args: ["decidim/meetings/attending_organizations_list", meeting]
155
+ },
156
+ {
157
+ enabled: meeting.linked_resources(:proposals, "proposals_from_meeting").present?,
158
+ id: "included_proposals",
159
+ text: t("decidim/proposals/proposal", scope: "activerecord.models", count: 2),
160
+ icon: resource_type_icon_key("Decidim::Proposals::Proposal"),
161
+ method: :cell,
162
+ args: ["decidim/linked_resources_for", meeting, { type: :proposals, link_name: "proposals_from_meeting" }]
163
+ },
164
+ {
165
+ enabled: meeting.linked_resources(:results, "meetings_through_proposals").present?,
166
+ id: "included_meetings",
167
+ text: t("decidim/accountability/result", scope: "activerecord.models", count: 2),
168
+ icon: resource_type_icon_key("Decidim::Accountability::Result"),
169
+ method: :cell,
170
+ args: ["decidim/linked_resources_for", meeting, { type: :results, link_name: "meetings_through_proposals" }]
171
+ }
172
+ ] + attachments_tab_panel_items(@meeting)
173
+ end
174
+ end
175
+ end
176
+ end