decidim-debates 0.29.2 → 0.30.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/debates/content_blocks/highlighted_debates/content.erb +16 -0
  3. data/app/cells/decidim/debates/content_blocks/highlighted_debates_cell.rb +49 -0
  4. data/app/cells/decidim/debates/debate_card_metadata_cell.rb +2 -11
  5. data/app/cells/decidim/debates/debate_g/show.erb +12 -0
  6. data/app/cells/decidim/debates/debate_g_cell.rb +23 -0
  7. data/app/cells/decidim/debates/debate_metadata_g_cell.rb +14 -0
  8. data/app/commands/decidim/debates/admin/create_debate.rb +25 -2
  9. data/app/commands/decidim/debates/admin/update_debate.rb +34 -5
  10. data/app/commands/decidim/debates/create_debate.rb +22 -1
  11. data/app/commands/decidim/debates/update_debate.rb +26 -2
  12. data/app/controllers/decidim/debates/admin/debates_controller.rb +17 -14
  13. data/app/controllers/decidim/debates/debates_controller.rb +8 -4
  14. data/app/forms/decidim/debates/admin/debate_form.rb +34 -26
  15. data/app/forms/decidim/debates/debate_form.rb +12 -29
  16. data/app/helpers/decidim/debates/application_helper.rb +8 -8
  17. data/app/models/decidim/debates/debate.rb +23 -1
  18. data/app/permissions/decidim/debates/admin/permissions.rb +5 -5
  19. data/app/presenters/decidim/debates/admin_log/debate_presenter.rb +1 -1
  20. data/app/presenters/decidim/debates/debate_presenter.rb +1 -1
  21. data/app/queries/decidim/debates/metrics/debate_followers_metric_measure.rb +2 -2
  22. data/app/queries/decidim/debates/metrics/debate_participants_metric_measure.rb +2 -2
  23. data/app/queries/decidim/debates/metrics/debates_metric_manage.rb +6 -6
  24. data/app/serializers/decidim/debates/download_your_data_debate_serializer.rb +6 -13
  25. data/app/views/decidim/debates/admin/debates/_actions.html.erb +27 -0
  26. data/app/views/decidim/debates/admin/debates/_debate-tr.html.erb +25 -0
  27. data/app/views/decidim/debates/admin/debates/_debates-thead.html.erb +9 -0
  28. data/app/views/decidim/debates/admin/debates/_form.html.erb +27 -6
  29. data/app/views/decidim/debates/admin/debates/index.html.erb +17 -55
  30. data/app/views/decidim/debates/admin/debates/manage_trash.html.erb +19 -0
  31. data/app/views/decidim/debates/debates/_debate_actions.html.erb +33 -0
  32. data/app/views/decidim/debates/debates/_form.html.erb +19 -6
  33. data/app/views/decidim/debates/debates/index.html.erb +10 -1
  34. data/app/views/decidim/debates/debates/show.html.erb +31 -44
  35. data/config/locales/ar.yml +9 -12
  36. data/config/locales/bg.yml +1 -15
  37. data/config/locales/ca.yml +79 -16
  38. data/config/locales/cs.yml +79 -16
  39. data/config/locales/de.yml +79 -16
  40. data/config/locales/el.yml +1 -15
  41. data/config/locales/en.yml +78 -15
  42. data/config/locales/es-MX.yml +79 -16
  43. data/config/locales/es-PY.yml +79 -16
  44. data/config/locales/es.yml +79 -16
  45. data/config/locales/eu.yml +79 -16
  46. data/config/locales/fi-plain.yml +79 -16
  47. data/config/locales/fi.yml +79 -16
  48. data/config/locales/fr-CA.yml +41 -16
  49. data/config/locales/fr.yml +41 -16
  50. data/config/locales/ga-IE.yml +0 -10
  51. data/config/locales/gl.yml +1 -13
  52. data/config/locales/hu.yml +1 -15
  53. data/config/locales/id-ID.yml +1 -13
  54. data/config/locales/is-IS.yml +0 -10
  55. data/config/locales/it.yml +1 -15
  56. data/config/locales/ja.yml +59 -16
  57. data/config/locales/lb.yml +0 -6
  58. data/config/locales/lt.yml +1 -15
  59. data/config/locales/lv.yml +1 -11
  60. data/config/locales/nl.yml +1 -14
  61. data/config/locales/no.yml +1 -15
  62. data/config/locales/pl.yml +1 -15
  63. data/config/locales/pt-BR.yml +1 -15
  64. data/config/locales/pt.yml +1 -15
  65. data/config/locales/ro-RO.yml +1 -15
  66. data/config/locales/ru.yml +0 -12
  67. data/config/locales/sk.yml +1 -13
  68. data/config/locales/sl.yml +0 -2
  69. data/config/locales/sv.yml +1 -15
  70. data/config/locales/tr-TR.yml +1 -15
  71. data/config/locales/uk.yml +0 -12
  72. data/config/locales/zh-CN.yml +1 -13
  73. data/config/locales/zh-TW.yml +1 -15
  74. data/db/migrate/20200827154116_add_commentable_counter_cache_to_debates.rb +1 -1
  75. data/db/migrate/20200902133452_add_cached_comment_metadata_to_debates.rb +1 -1
  76. data/db/migrate/20210310120652_add_followable_counter_cache_to_debates.rb +1 -1
  77. data/db/migrate/20240828103648_add_deleted_at_to_decidim_debates_debates.rb +8 -0
  78. data/db/migrate/20241017153555_add_comments_layout_to_debates.rb +7 -0
  79. data/decidim-debates.gemspec +1 -1
  80. data/lib/decidim/api/debate_type.rb +6 -8
  81. data/lib/decidim/api/debates_type.rb +4 -5
  82. data/lib/decidim/debates/admin_engine.rb +7 -0
  83. data/lib/decidim/debates/component.rb +19 -4
  84. data/lib/decidim/debates/debate_serializer.rb +83 -0
  85. data/lib/decidim/debates/seeds.rb +1 -8
  86. data/lib/decidim/debates/test/factories.rb +2 -0
  87. data/lib/decidim/debates/version.rb +1 -1
  88. data/lib/decidim/debates.rb +1 -0
  89. metadata +27 -15
  90. data/app/helpers/decidim/debates/admin/application_helper.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6e33b33f45eb7ee4bb5a22738d16a2d228cb136ffb14de44eaf45b244e483c6
4
- data.tar.gz: 10812d25f44712fad5a7f69082dab94e7ef68b49c1f3e18353c5d6189cc04807
3
+ metadata.gz: 78f039d689f600da716551b3f5a55d9fb87aa7ef3573b06211bc82f2159b8589
4
+ data.tar.gz: f8b66668b01fc1d2bf5e4d8eaff1e201bff109446db7cb50b0700e893ab49e4f
5
5
  SHA512:
6
- metadata.gz: 40dfcf61dd255eb0a0d76357eb397c0b224ddfe045755d2f9a55dcd9916a355a111445624c734bb7e613bd8e9a7a3229e58cd34b4366630837ca9c18e8cfa777
7
- data.tar.gz: 7522cc0b99b73b541ce8e7d10328d74fb4c211a72efda7f62fb42354ab25057941b8bde1c3d4e4bc59e7cab1b07fdafbaafcc603cd00704fffb774e6db245a65
6
+ metadata.gz: 6b6f2b8a26fb981104022b0b259e5b5156fe0872a332fe8c5a7f80642cadbef149fd4194276f146793e54e63b6f777a00c4ede0127238fdeb0c545be82095f26
7
+ data.tar.gz: 66e3af8576c881255c92ba9958891ff938450c86677a2663fefbe3e24aff3b7f551ce36f64884457403e2bad67db322ede84f131d1f76157d1879590566ecbb2
@@ -0,0 +1,16 @@
1
+ <div class="content-block__title">
2
+ <h2 class="h2 decorator"><%= single_component ? translated_attribute(single_component.name) : t("name", scope: "decidim.components.debates") %></h2>
3
+ <div class="label text-lg"><%= items_count %></div>
4
+ <% if single_component %>
5
+ <%= link_to decidim_debates.root_path, class: "button button__sm button__text-secondary" do %>
6
+ <span><%= t("decidim.debates.content_blocks.highlighted_debates.see_all") %></span>
7
+ <%= icon "arrow-right-line" %>
8
+ <% end %>
9
+ <% end %>
10
+ </div>
11
+
12
+ <div class="participatory-space__block-grid">
13
+ <% debates_to_render.each do |debate| %>
14
+ <%= cell "decidim/debates/debate_g", debate %>
15
+ <% end %>
16
+ </div>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ module ContentBlocks
6
+ class HighlightedDebatesCell < Decidim::ContentBlocks::HighlightedElementsCell
7
+ def show
8
+ render unless items_count.zero?
9
+ end
10
+
11
+ private
12
+
13
+ def debates
14
+ @debates ||= Decidim::Debates::Debate.open.where(component: published_components).updated_at_desc
15
+ end
16
+
17
+ def decidim_debates
18
+ return unless single_component
19
+
20
+ Decidim::EngineRouter.main_proxy(single_component)
21
+ end
22
+
23
+ def single_component
24
+ @single_component ||= published_components.one? ? published_components.first : nil
25
+ end
26
+
27
+ def debates_to_render
28
+ @debates_to_render ||= debates.includes([:author, :component]).limit(limit)
29
+ end
30
+
31
+ def items_count
32
+ debates_to_render.size
33
+ end
34
+
35
+ def cache_hash
36
+ hash = []
37
+ hash << "decidim/debates/content_blocks/highlighted_debates"
38
+ hash << debates.cache_key_with_version
39
+ hash << I18n.locale.to_s
40
+ hash.join(Decidim.cache_key_separator)
41
+ end
42
+
43
+ def limit
44
+ 3
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -9,7 +9,7 @@ module Decidim
9
9
 
10
10
  alias debate model
11
11
 
12
- delegate :type_of_meeting, :start_time, :end_time, :category, :withdrawn?, to: :debate
12
+ delegate :type_of_meeting, :start_time, :end_time, :withdrawn?, to: :debate
13
13
 
14
14
  def initialize(*)
15
15
  super
@@ -17,17 +17,8 @@ module Decidim
17
17
  @items.prepend(*debate_items)
18
18
  end
19
19
 
20
- def category_item
21
- return if category.blank?
22
-
23
- {
24
- text: category.translated_name,
25
- icon: resource_type_icon_key("Decidim::Category")
26
- }
27
- end
28
-
29
20
  def debate_items
30
- [duration, comments_count_item, endorsements_count_item, category_item, coauthors_item]
21
+ [duration, comments_count_item, endorsements_count_item] + taxonomy_items + [coauthors_item]
31
22
  end
32
23
 
33
24
  def duration
@@ -0,0 +1,12 @@
1
+ <%= link_to resource_path, class: classes[:default], id: resource_id do %>
2
+ <div class="<%= classes[:text] %>">
3
+ <%= content_tag title_tag, title, class: title_class %>
4
+ <%= description if show_description? %>
5
+
6
+ <% if metadata_cell.present? %>
7
+ <div class="<%= classes[:metadata] %>">
8
+ <%= cell metadata_cell, resource, links: false, **options %>
9
+ </div>
10
+ <% end %>
11
+ </div>
12
+ <% end %>
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ # This cell renders the Grid (:g) debate card
6
+ # for a given instance of a Debate
7
+ class DebateGCell < Decidim::CardGCell
8
+ def show
9
+ render
10
+ end
11
+
12
+ private
13
+
14
+ def show_description?
15
+ true
16
+ end
17
+
18
+ def metadata_cell
19
+ "decidim/debates/debate_metadata_g"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ # This cell renders metadata for an instance of a Debate
6
+ class DebateMetadataGCell < Decidim::Debates::DebateCardMetadataCell
7
+ private
8
+
9
+ def debate_items
10
+ [author_item, comments_count_item]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -6,7 +6,26 @@ module Decidim
6
6
  # This command is executed when the user creates a Debate from the admin
7
7
  # panel.
8
8
  class CreateDebate < Decidim::Commands::CreateResource
9
- fetch_form_attributes :category, :component, :information_updates, :instructions, :scope, :start_time, :end_time, :comments_enabled
9
+ include ::Decidim::MultipleAttachmentsMethods
10
+
11
+ fetch_form_attributes :taxonomizations, :component, :information_updates, :instructions, :start_time, :end_time, :comments_enabled
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
+ perform!
22
+ broadcast(:ok, resource)
23
+ rescue ActiveRecord::RecordInvalid
24
+ add_file_attribute_errors!
25
+ broadcast(:invalid)
26
+ rescue Decidim::Commands::HookError
27
+ broadcast(:invalid)
28
+ end
10
29
 
11
30
  protected
12
31
 
@@ -22,11 +41,15 @@ module Decidim
22
41
  title: parsed_title,
23
42
  description: parsed_description,
24
43
  end_time: (form.end_time if form.finite),
25
- start_time: (form.start_time if form.finite)
44
+ start_time: (form.start_time if form.finite),
45
+ comments_layout: form.comments_layout
26
46
  })
27
47
  end
28
48
 
29
49
  def run_after_hooks
50
+ @attached_to = resource
51
+ create_attachments(first_weight: 1) if process_attachments?
52
+
30
53
  Decidim::EventsManager.publish(
31
54
  event: "decidim.events.debates.debate_created",
32
55
  event_class: Decidim::Debates::CreateDebateEvent,
@@ -6,7 +6,26 @@ module Decidim
6
6
  # This command is executed when the user changes a Debate from the admin
7
7
  # panel.
8
8
  class UpdateDebate < Decidim::Commands::UpdateResource
9
- fetch_form_attributes :category, :information_updates, :instructions, :scope, :start_time, :end_time, :comments_enabled
9
+ include Decidim::MultipleAttachmentsMethods
10
+
11
+ fetch_form_attributes :taxonomizations, :information_updates, :instructions, :start_time, :end_time, :comments_enabled
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
+ perform!
22
+ broadcast(:ok, resource)
23
+ rescue ActiveRecord::RecordInvalid
24
+ add_file_attribute_errors!
25
+ broadcast(:invalid)
26
+ rescue Decidim::Commands::HookError
27
+ broadcast(:invalid)
28
+ end
10
29
 
11
30
  private
12
31
 
@@ -14,10 +33,20 @@ module Decidim
14
33
  parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
15
34
  parsed_description = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.description, current_organization: form.current_organization).rewrite
16
35
 
17
- super.merge({
18
- title: parsed_title,
19
- description: parsed_description
20
- })
36
+ attrs = {
37
+ title: parsed_title,
38
+ description: parsed_description
39
+ }
40
+
41
+ attrs[:comments_layout] = form.comments_layout if resource.comments_count.zero?
42
+
43
+ super.merge(attrs)
44
+ end
45
+
46
+ def run_after_hooks
47
+ @attached_to = resource
48
+ document_cleanup!(include_all_attachments: true)
49
+ create_attachments(first_weight: 1) if process_attachments?
21
50
  end
22
51
  end
23
52
  end
@@ -5,7 +5,26 @@ module Decidim
5
5
  # This command is executed when the user creates a Debate from the public
6
6
  # views.
7
7
  class CreateDebate < Decidim::Commands::CreateResource
8
- fetch_form_attributes :category, :scope
8
+ include ::Decidim::MultipleAttachmentsMethods
9
+
10
+ fetch_form_attributes :taxonomizations
11
+
12
+ def call
13
+ return broadcast(:invalid) if invalid?
14
+
15
+ if process_attachments?
16
+ build_attachments
17
+ return broadcast(:invalid) if attachments_invalid?
18
+ end
19
+
20
+ perform!
21
+ broadcast(:ok, resource)
22
+ rescue ActiveRecord::RecordInvalid
23
+ add_file_attribute_errors!
24
+ broadcast(:invalid)
25
+ rescue Decidim::Commands::HookError
26
+ broadcast(:invalid)
27
+ end
9
28
 
10
29
  private
11
30
 
@@ -20,6 +39,8 @@ module Decidim
20
39
  end
21
40
 
22
41
  def run_after_hooks
42
+ @attached_to = resource
43
+ create_attachments(first_weight: 1) if process_attachments?
23
44
  send_notification_to_author_followers
24
45
  send_notification_to_space_followers
25
46
  follow_debate
@@ -4,7 +4,26 @@ module Decidim
4
4
  module Debates
5
5
  # A command with all the business logic when a user updates a debate.
6
6
  class UpdateDebate < Decidim::Commands::UpdateResource
7
- fetch_form_attributes :category, :scope
7
+ include Decidim::MultipleAttachmentsMethods
8
+
9
+ fetch_form_attributes :taxonomizations
10
+
11
+ def call
12
+ return broadcast(:invalid) if invalid?
13
+
14
+ if process_attachments?
15
+ build_attachments
16
+ return broadcast(:invalid) if attachments_invalid?
17
+ end
18
+
19
+ perform!
20
+ broadcast(:ok, resource)
21
+ rescue ActiveRecord::RecordInvalid
22
+ add_file_attribute_errors!
23
+ broadcast(:invalid)
24
+ rescue Decidim::Commands::HookError
25
+ broadcast(:invalid)
26
+ end
8
27
 
9
28
  private
10
29
 
@@ -29,12 +48,17 @@ module Decidim
29
48
  def attributes
30
49
  parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
31
50
  parsed_description = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.description, current_organization: form.current_organization).rewrite
32
-
33
51
  super.merge({
34
52
  title: { I18n.locale => parsed_title },
35
53
  description: { I18n.locale => parsed_description }
36
54
  })
37
55
  end
56
+
57
+ def run_after_hooks
58
+ @attached_to = resource
59
+ document_cleanup!(include_all_attachments: true)
60
+ create_attachments(first_weight: 1) if process_attachments?
61
+ end
38
62
  end
39
63
  end
40
64
  end
@@ -5,6 +5,7 @@ module Decidim
5
5
  module Admin
6
6
  # This controller allows an admin to manage debates from a Participatory Space
7
7
  class DebatesController < Decidim::Debates::Admin::ApplicationController
8
+ include Decidim::Admin::HasTrashableResources
8
9
  helper Decidim::ApplicationHelper
9
10
 
10
11
  helper_method :debates
@@ -15,8 +16,9 @@ module Decidim
15
16
 
16
17
  def new
17
18
  enforce_permission_to :create, :debate
18
-
19
- @form = form(Decidim::Debates::Admin::DebateForm).instance
19
+ @form = form(Decidim::Debates::Admin::DebateForm).from_params(
20
+ attachment: form(AttachmentForm).from_params({})
21
+ )
20
22
  end
21
23
 
22
24
  def create
@@ -39,14 +41,13 @@ module Decidim
39
41
 
40
42
  def edit
41
43
  enforce_permission_to(:update, :debate, debate:)
42
-
43
44
  @form = form(Decidim::Debates::Admin::DebateForm).from_model(debate)
44
45
  end
45
46
 
46
47
  def update
47
48
  enforce_permission_to(:update, :debate, debate:)
48
49
 
49
- @form = form(Decidim::Debates::Admin::DebateForm).from_params(params, current_component:)
50
+ @form = form(Decidim::Debates::Admin::DebateForm).from_params(params, current_component:, debate:)
50
51
 
51
52
  UpdateDebate.call(@form, debate) do
52
53
  on(:ok) do
@@ -61,24 +62,26 @@ module Decidim
61
62
  end
62
63
  end
63
64
 
64
- def destroy
65
- enforce_permission_to(:delete, :debate, debate:)
66
-
67
- debate.destroy!
68
-
69
- flash[:notice] = I18n.t("debates.destroy.success", scope: "decidim.debates.admin")
65
+ private
70
66
 
71
- redirect_to debates_path
67
+ def trashable_deleted_resource_type
68
+ :debate
72
69
  end
73
70
 
74
- private
75
-
76
71
  def debates
77
72
  @debates ||= Debate.where(component: current_component).not_hidden
78
73
  end
79
74
 
75
+ def trashable_deleted_collection
76
+ @trashable_deleted_collection ||= Debate.where(component: current_component).only_deleted.deleted_at_desc
77
+ end
78
+
79
+ def trashable_deleted_resource
80
+ @trashable_deleted_resource ||= Debate.with_deleted.find_by(component: current_component, id: params[:id])
81
+ end
82
+
80
83
  def debate
81
- @debate ||= debates.find(params[:id])
84
+ @debate ||= Debate.find_by(component: current_component, id: params[:id])
82
85
  end
83
86
  end
84
87
  end
@@ -11,8 +11,9 @@ module Decidim
11
11
  include Paginable
12
12
  include Flaggable
13
13
  include Decidim::Debates::Orderable
14
+ include Decidim::AttachmentsHelper
14
15
 
15
- helper_method :debates, :debate, :form_presenter, :paginated_debates, :close_debate_form
16
+ helper_method :debates, :debate, :form_presenter, :paginated_debates, :close_debate_form, :tab_panel_items
16
17
  before_action :authenticate_user!, only: [:new, :create]
17
18
 
18
19
  def new
@@ -92,7 +93,7 @@ module Decidim
92
93
  end
93
94
 
94
95
  def paginated_debates
95
- @paginated_debates ||= paginate(debates).includes(:category)
96
+ @paginated_debates ||= paginate(debates).includes(:taxonomies)
96
97
  end
97
98
 
98
99
  def debates
@@ -116,11 +117,14 @@ module Decidim
116
117
  search_text_cont: "",
117
118
  with_any_origin: nil,
118
119
  activity: %w(all),
119
- with_any_category: nil,
120
- with_any_scope: nil,
120
+ with_any_taxonomies: nil,
121
121
  with_any_state: %w(open closed)
122
122
  }
123
123
  end
124
+
125
+ def tab_panel_items
126
+ @tab_panel_items ||= attachments_tab_panel_items(debate)
127
+ end
124
128
  end
125
129
  end
126
130
  end
@@ -5,7 +5,12 @@ module Decidim
5
5
  module Admin
6
6
  # This class holds a Form to create/update debates from Decidim's admin panel.
7
7
  class DebateForm < Decidim::Form
8
- include TranslatableAttributes
8
+ mimic :debate
9
+
10
+ include Decidim::HasUploadValidations
11
+ include Decidim::AttachmentAttributes
12
+ include Decidim::TranslatableAttributes
13
+ include Decidim::HasTaxonomyFormAttributes
9
14
 
10
15
  translatable_attribute :title, String
11
16
  translatable_attribute :description, Decidim::Attributes::RichText
@@ -13,52 +18,43 @@ module Decidim
13
18
  translatable_attribute :information_updates, Decidim::Attributes::RichText
14
19
  attribute :start_time, Decidim::Attributes::TimeWithZone
15
20
  attribute :end_time, Decidim::Attributes::TimeWithZone
16
- attribute :decidim_category_id, Integer
17
21
  attribute :finite, Boolean, default: true
18
- attribute :scope_id, Integer
22
+ attribute :comments_layout, String, default: "single_column"
19
23
  attribute :comments_enabled, Boolean, default: true
24
+ attribute :attachment, AttachmentForm
25
+
26
+ attachments_attribute :documents
20
27
 
21
- validates :title, translatable_presence: true
22
- validates :description, translatable_presence: true
28
+ validates :title, :description, translatable_presence: true
29
+ validates :title, :description, translated_etiquette: true
23
30
  validates :instructions, translatable_presence: true
24
31
  validates :start_time, presence: { if: :validate_start_time? }, date: { before: :end_time, allow_blank: true, if: :validate_start_time? }
25
32
  validates :end_time, presence: { if: :validate_end_time? }, date: { after: :start_time, allow_blank: true, if: :validate_end_time? }
33
+ validates :comments_layout, presence: true, inclusion: { in: %w(single_column two_columns) }
34
+ validate :comments_layout_change, if: -> { debate&.comments_count&.positive? }
26
35
 
27
- validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
28
- validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
29
- validates :scope_id, scope_belongs_to_component: true, if: ->(form) { form.scope_id.present? }
36
+ validate :notify_missing_attachment_if_errored
30
37
 
31
38
  def map_model(model)
32
39
  self.finite = model.start_time.present? && model.end_time.present?
33
- self.decidim_category_id = model.categorization.decidim_category_id if model.categorization
34
40
  presenter = DebatePresenter.new(model)
35
41
 
36
42
  self.title = presenter.title(all_locales: title.is_a?(Hash))
37
43
  self.description = presenter.description(all_locales: description.is_a?(Hash))
44
+ self.comments_layout = model.comments_layout || "single_column"
45
+ self.documents = model.attachments
38
46
  end
39
47
 
40
- def category
41
- return unless current_component
42
-
43
- @category ||= current_component.categories.find_by(id: decidim_category_id)
48
+ def participatory_space_manifest
49
+ @participatory_space_manifest ||= current_component.participatory_space.manifest.name
44
50
  end
45
51
 
46
- # Finds the Scope from the given decidim_scope_id, uses the component scope if missing.
47
- #
48
- # Returns a Decidim::Scope
49
- def scope
50
- @scope ||= @attributes["scope_id"].value ? current_component.scopes.find_by(id: @attributes["scope_id"].value) : current_component.scope
51
- end
52
+ private
52
53
 
53
- # Scope identifier
54
- #
55
- # Returns the scope identifier related to the meeting
56
- def scope_id
57
- super || scope&.id
54
+ def debate
55
+ @debate ||= context[:debate]
58
56
  end
59
57
 
60
- private
61
-
62
58
  def validate_end_time?
63
59
  finite && start_time.present?
64
60
  end
@@ -66,6 +62,18 @@ module Decidim
66
62
  def validate_start_time?
67
63
  end_time.present?
68
64
  end
65
+
66
+ def comments_layout_change
67
+ errors.add(:comments_layout, I18n.t("form.errors.comments_layout_locked", scope: "decidim.debates.admin.debates")) if debate.comments_layout != comments_layout
68
+ end
69
+
70
+ # This method will add an error to the `add_documents` field only if there is
71
+ # any error in any other field. This is needed because when the form has
72
+ # an error, the attachment is lost, so we need a way to inform the user of
73
+ # this problem.
74
+ def notify_missing_attachment_if_errored
75
+ errors.add(:add_documents, :needs_to_be_reattached) if errors.any? && add_documents.present?
76
+ end
69
77
  end
70
78
  end
71
79
  end
@@ -4,20 +4,21 @@ module Decidim
4
4
  module Debates
5
5
  # This class holds a Form to create/update debates from Decidim's public views.
6
6
  class DebateForm < Decidim::Form
7
- include TranslatableAttributes
7
+ include Decidim::HasUploadValidations
8
+ include Decidim::AttachmentAttributes
9
+ include Decidim::TranslatableAttributes
10
+ include Decidim::HasTaxonomyFormAttributes
8
11
 
9
12
  attribute :title, String
10
13
  attribute :description, String
11
- attribute :category_id, Integer
12
- attribute :scope_id, Integer
13
14
  attribute :user_group_id, Integer
15
+ attribute :attachment, AttachmentForm
14
16
 
15
- validates :title, presence: true
16
- validates :description, presence: true
17
- validates :category, presence: true, if: ->(form) { form.category_id.present? }
18
- validate :editable_by_user
17
+ attachments_attribute :documents
19
18
 
20
- validates :scope_id, scope_belongs_to_component: true, if: ->(form) { form.scope_id.present? }
19
+ validates :title, :description, presence: true
20
+ validates :title, :description, etiquette: true
21
+ validate :editable_by_user
21
22
 
22
23
  def map_model(debate)
23
24
  super
@@ -27,29 +28,11 @@ module Decidim
27
28
  self.title = debate.title.values.first
28
29
  self.description = debate.description.values.first
29
30
  self.user_group_id = debate.decidim_user_group_id
30
-
31
- if debate.category.present?
32
- self.category_id = debate.category.id
33
- @category = debate.category
34
- end
35
- end
36
-
37
- def category
38
- @category ||= current_component.categories.find_by(id: category_id)
39
- end
40
-
41
- # Finds the Scope from the given scope_id, uses component scope if missing.
42
- #
43
- # Returns a Decidim::Scope
44
- def scope
45
- @scope ||= @attributes["scope_id"].value ? current_component.scopes.find_by(id: @attributes["scope_id"].value) : current_component.scope
31
+ self.documents = debate.attachments
46
32
  end
47
33
 
48
- # Scope identifier
49
- #
50
- # Returns the scope identifier related to the debate
51
- def scope_id
52
- super || scope&.id
34
+ def participatory_space_manifest
35
+ @participatory_space_manifest ||= current_component.participatory_space.manifest.name
53
36
  end
54
37
 
55
38
  def debate
@@ -74,18 +74,18 @@ module Decidim
74
74
  items = [{
75
75
  method: :with_any_state,
76
76
  collection: filter_debates_state_values,
77
- label_scope: "decidim.meetings.meetings.filters",
77
+ label: t("decidim.meetings.meetings.filters.date"),
78
78
  id: "date",
79
79
  type: :radio_buttons
80
80
  }]
81
- if current_component.has_subscopes?
82
- items.append(method: :with_any_scope, collection: filter_scopes_values, label_scope: "decidim.shared.participatory_space_filters.filters", id: "scope")
81
+ current_component.available_taxonomy_filters.each do |taxonomy_filter|
82
+ items.append(method: "with_any_taxonomies[#{taxonomy_filter.root_taxonomy_id}]",
83
+ collection: filter_taxonomy_values_for(taxonomy_filter),
84
+ label: decidim_sanitize_translated(taxonomy_filter.name),
85
+ id: "taxonomy-#{taxonomy_filter.root_taxonomy_id}")
83
86
  end
84
- if current_participatory_space.categories.any?
85
- items.append(method: :with_any_category, collection: filter_categories_values, label_scope: "decidim.debates.debates.filters", id: "category")
86
- end
87
- items.append(method: :with_any_origin, collection: filter_origin_values, label_scope: "decidim.debates.debates.filters", id: "origin")
88
- items.append(method: :activity, collection: activity_filter_values, label_scope: "decidim.debates.debates.filters", id: "activity") if current_user
87
+ items.append(method: :with_any_origin, collection: filter_origin_values, label: t("decidim.debates.debates.filters.origin"), id: "origin")
88
+ items.append(method: :activity, collection: activity_filter_values, label: t("decidim.debates.debates.filters.activity"), id: "activity") if current_user
89
89
 
90
90
  items.reject { |item| item[:collection].blank? }
91
91
  end