decidim-proposals 0.28.5 → 0.29.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -18
  3. data/app/cells/decidim/proposals/cost_report_cell.rb +0 -3
  4. data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +11 -11
  5. data/app/cells/decidim/proposals/highlighted_proposals_for_component_cell.rb +1 -1
  6. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +1 -1
  7. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +2 -3
  8. data/app/cells/decidim/proposals/proposal_cell.rb +2 -0
  9. data/app/cells/decidim/proposals/proposal_g/show.erb +23 -0
  10. data/app/cells/decidim/proposals/proposal_g_cell.rb +48 -0
  11. data/app/cells/decidim/proposals/proposal_l_cell.rb +18 -19
  12. data/app/cells/decidim/proposals/proposal_metadata_cell.rb +23 -15
  13. data/app/commands/decidim/proposals/admin/answer_proposal.rb +2 -1
  14. data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +7 -5
  15. data/app/commands/decidim/proposals/admin/create_proposal.rb +4 -6
  16. data/app/commands/decidim/proposals/admin/create_proposal_state.rb +15 -0
  17. data/app/commands/decidim/proposals/admin/destroy_proposal_state.rb +10 -0
  18. data/app/commands/decidim/proposals/admin/import_proposals.rb +10 -2
  19. data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +4 -21
  20. data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +6 -4
  21. data/app/commands/decidim/proposals/admin/update_proposal_state.rb +13 -0
  22. data/app/commands/decidim/proposals/create_proposal.rb +21 -2
  23. data/app/commands/decidim/proposals/update_proposal.rb +2 -2
  24. data/app/commands/decidim/proposals/vote_proposal.rb +1 -1
  25. data/app/commands/decidim/proposals/withdraw_proposal.rb +3 -7
  26. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +10 -22
  27. data/app/controllers/decidim/proposals/admin/proposal_states_controller.rb +86 -0
  28. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +4 -0
  29. data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +8 -11
  30. data/app/controllers/decidim/proposals/proposals_controller.rb +38 -39
  31. data/app/events/decidim/proposals/proposal_state_changed_event.rb +37 -0
  32. data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +8 -4
  33. data/app/forms/decidim/proposals/admin/proposal_form.rb +1 -1
  34. data/app/forms/decidim/proposals/admin/proposal_state_form.rb +22 -0
  35. data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -1
  36. data/app/forms/decidim/proposals/admin/proposals_import_form.rb +1 -1
  37. data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +12 -14
  38. data/app/forms/decidim/proposals/proposal_form.rb +25 -4
  39. data/app/forms/decidim/proposals/reject_access_to_collaborative_draft_form.rb +1 -1
  40. data/app/forms/decidim/proposals/request_access_to_collaborative_draft_form.rb +1 -1
  41. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +7 -17
  42. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +13 -89
  43. data/app/helpers/decidim/proposals/application_helper.rb +16 -10
  44. data/app/helpers/decidim/proposals/map_helper.rb +1 -1
  45. data/app/helpers/decidim/proposals/proposal_cells_helper.rb +6 -2
  46. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +3 -3
  47. data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +5 -8
  48. data/app/helpers/decidim/proposals/proposals_helper.rb +18 -24
  49. data/app/models/decidim/proposals/proposal.rb +83 -29
  50. data/app/models/decidim/proposals/proposal_state.rb +58 -0
  51. data/app/packs/documents/decidim/proposals/participatory_texts/participatory_text.md +1 -3
  52. data/app/packs/images/decidim/proposals/proposal-placeholder-card-g.svg +15 -0
  53. data/app/packs/src/decidim/proposals/add_proposal.js +2 -0
  54. data/app/packs/src/decidim/proposals/admin/proposals.js +43 -8
  55. data/app/packs/stylesheets/decidim/proposals/proposals.scss +39 -1
  56. data/app/permissions/decidim/proposals/admin/permissions.rb +16 -4
  57. data/app/permissions/decidim/proposals/permissions.rb +3 -4
  58. data/app/presenters/decidim/proposals/admin_log/proposal_state_presenter.rb +21 -0
  59. data/app/presenters/decidim/proposals/proposal_presenter.rb +12 -3
  60. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +1 -1
  61. data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +1 -1
  62. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +4 -4
  63. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +1 -1
  64. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +1 -1
  65. data/app/services/decidim/proposals/diff_renderer.rb +1 -3
  66. data/app/services/decidim/proposals/proposal_builder.rb +1 -1
  67. data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +1 -1
  68. data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +3 -2
  69. data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +2 -2
  70. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +3 -3
  71. data/app/views/decidim/proposals/admin/proposal_states/_form.html.erb +67 -0
  72. data/app/views/decidim/proposals/admin/proposal_states/edit.html.erb +18 -0
  73. data/app/views/decidim/proposals/admin/proposal_states/index.html.erb +50 -0
  74. data/app/views/decidim/proposals/admin/proposal_states/new.html.erb +18 -0
  75. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +6 -12
  76. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +6 -6
  77. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +2 -2
  78. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +11 -7
  79. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +7 -5
  80. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +2 -2
  81. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +2 -2
  82. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_recategorize.html.erb +2 -2
  83. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +2 -2
  84. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_split.html.erb +2 -2
  85. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +11 -7
  86. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_valuators_picker.html.erb +12 -0
  87. data/app/views/decidim/proposals/admin/proposals/index.html.erb +11 -7
  88. data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +1 -1
  89. data/app/views/decidim/proposals/admin/proposals/show.html.erb +3 -2
  90. data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +3 -3
  91. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +12 -5
  92. data/app/views/decidim/proposals/proposals/_proposal.html.erb +1 -1
  93. data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +1 -1
  94. data/app/views/decidim/proposals/proposals/_proposals.html.erb +9 -3
  95. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +1 -1
  96. data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +3 -3
  97. data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +0 -1
  98. data/app/views/decidim/proposals/proposals/index.html.erb +1 -1
  99. data/app/views/decidim/proposals/proposals/index.js.erb +0 -12
  100. data/app/views/decidim/proposals/proposals/new.html.erb +2 -7
  101. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +4 -4
  102. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_votes_count.html.erb +8 -8
  103. data/app/views/decidim/proposals/proposals/preview.html.erb +1 -1
  104. data/app/views/decidim/proposals/proposals/show.html.erb +3 -3
  105. data/config/locales/ar.yml +9 -115
  106. data/config/locales/bg.yml +117 -111
  107. data/config/locales/ca.yml +86 -83
  108. data/config/locales/cs.yml +65 -127
  109. data/config/locales/de.yml +128 -125
  110. data/config/locales/el.yml +8 -121
  111. data/config/locales/en.yml +110 -107
  112. data/config/locales/es-MX.yml +85 -82
  113. data/config/locales/es-PY.yml +88 -85
  114. data/config/locales/es.yml +83 -80
  115. data/config/locales/eu.yml +166 -170
  116. data/config/locales/fi-plain.yml +90 -87
  117. data/config/locales/fi.yml +139 -136
  118. data/config/locales/fr-CA.yml +92 -87
  119. data/config/locales/fr.yml +83 -78
  120. data/config/locales/ga-IE.yml +1 -27
  121. data/config/locales/gl.yml +11 -107
  122. data/config/locales/he-IL.yml +0 -17
  123. data/config/locales/hu.yml +18 -90
  124. data/config/locales/id-ID.yml +6 -106
  125. data/config/locales/is-IS.yml +8 -33
  126. data/config/locales/it.yml +14 -103
  127. data/config/locales/ja.yml +117 -112
  128. data/config/locales/lb.yml +1 -0
  129. data/config/locales/lt.yml +6 -123
  130. data/config/locales/lv.yml +4 -101
  131. data/config/locales/nl.yml +11 -102
  132. data/config/locales/no.yml +7 -108
  133. data/config/locales/pl.yml +110 -115
  134. data/config/locales/pt-BR.yml +10 -84
  135. data/config/locales/pt.yml +9 -109
  136. data/config/locales/ro-RO.yml +15 -117
  137. data/config/locales/ru.yml +9 -53
  138. data/config/locales/sk.yml +5 -109
  139. data/config/locales/sl.yml +4 -0
  140. data/config/locales/sv.yml +142 -337
  141. data/config/locales/tr-TR.yml +64 -108
  142. data/config/locales/uk.yml +11 -55
  143. data/config/locales/zh-CN.yml +5 -100
  144. data/config/locales/zh-TW.yml +8 -119
  145. data/db/migrate/20240110203500_add_withdrawn_at_field_to_proposals.rb +27 -0
  146. data/db/migrate/20240110203501_create_decidim_proposals_proposal_state.rb +14 -0
  147. data/db/migrate/20240110203502_add_state_id_to_decidim_proposals_proposals.rb +13 -0
  148. data/db/migrate/20240110203503_remove_state_from_decidim_proposals_proposals.rb +11 -0
  149. data/db/migrate/20240110203504_create_default_proposal_states.rb +31 -0
  150. data/db/migrate/20240209092404_change_color_fields_on_proposals_states.rb +54 -0
  151. data/decidim-proposals.gemspec +3 -3
  152. data/lib/decidim/api/proposal_type.rb +4 -13
  153. data/lib/decidim/api/proposals_type.rb +3 -1
  154. data/lib/decidim/proposals/admin_engine.rb +8 -0
  155. data/lib/decidim/proposals/admin_filter.rb +37 -0
  156. data/lib/decidim/proposals/component.rb +8 -5
  157. data/lib/decidim/proposals/engine.rb +1 -15
  158. data/lib/decidim/proposals/import/proposal_answer_creator.rb +6 -6
  159. data/lib/decidim/proposals/import/proposal_creator.rb +1 -1
  160. data/lib/decidim/proposals/markdown_to_proposals.rb +2 -8
  161. data/lib/decidim/proposals/proposal_serializer.rb +8 -9
  162. data/lib/decidim/proposals/seeds.rb +60 -51
  163. data/lib/decidim/proposals/test/factories.rb +69 -14
  164. data/lib/decidim/proposals/version.rb +1 -1
  165. data/lib/decidim/proposals.rb +84 -12
  166. data/lib/tasks/proposals/upgrade/{decdim_proposals_upgrade_tasks.rake → decidim_proposals_upgrade_tasks.rake} +0 -13
  167. metadata +51 -40
  168. data/app/events/decidim/proposals/accepted_proposal_event.rb +0 -17
  169. data/app/events/decidim/proposals/evaluating_proposal_event.rb +0 -11
  170. data/app/events/decidim/proposals/rejected_proposal_event.rb +0 -17
  171. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +0 -44
  172. data/app/queries/decidim/proposals/similar_proposals.rb +0 -67
  173. data/app/services/decidim/proposals/collaborative_draft_diff_renderer.rb +0 -22
  174. data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +0 -0
  175. data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +0 -3
  176. data/app/views/decidim/proposals/proposals/compare.html.erb +0 -24
  177. data/app/views/decidim/proposals/proposals/complete.html.erb +0 -31
  178. data/config/locales/bn-BD.yml +0 -1
  179. data/config/locales/bs-BA.yml +0 -100
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a1d75f047cf77a3873fed131cdefcd187c822c14f9fedb1b4d5c5d8a006454f
4
- data.tar.gz: 825829e1601b57bcb849fd9359190839dc2e8691d4c203377d0cb8d1865c43c2
3
+ metadata.gz: 22cc3e857b344169fadf51778fef41a0ea95d814e8855a90eb354d5b2bda88fe
4
+ data.tar.gz: 48d87bd26f7856a756da54a174edddc30c17a9330a7e5af07c808cdfac7adf36
5
5
  SHA512:
6
- metadata.gz: 56fd50c16ab2a410a880b20896c64c3faf5be9e295223d3a6a42aa5045719057e5ad9effb1511ed953e52c89c270c037dc57100167566cba67e2b04f952e52ef
7
- data.tar.gz: 46d01f111fab1ce7ba565990f435027a943dbb75f992f8873eb522739c9454a5a0c5ec3562daa20616ec03cf2ef4366d8ba82fd67dc51234464d262ff3cadbbf
6
+ metadata.gz: be95b2675428571df7ad89af801ad8a988c7f616272386c9cd213644cf285596379079da03c178ccf83d867d1ee70ebff706fc3ce35632c3ced1feeeaef3cd94
7
+ data.tar.gz: 940ea09bddab76eeacc28e581e3f02ccc79a85a230226aa34dcbbaf3e414f38361f35851557d0c86025a4ab9380230edf79e738fac02054d1c0a5fcc3f2782c2
data/README.md CHANGED
@@ -20,23 +20,6 @@ And then execute:
20
20
  bundle
21
21
  ```
22
22
 
23
- ### Configuring Similarity
24
-
25
- `pg_trgm` is a PostgreSQL extension providing simple fuzzy string matching used in the Proposal wizard to find similar published proposals (title and the body).
26
-
27
- Create config variables in your app's `/config/initializers/decidim-proposals.rb`:
28
-
29
- ```ruby
30
- Decidim::Proposals.configure do |config|
31
- config.similarity_threshold = 0.25 # default value
32
- config.similarity_limit = 10 # default value
33
- end
34
- ```
35
-
36
- `similarity_threshold`(real): Sets the current similarity threshold that is used by the % operator. The threshold must be between 0 and 1 (default is 0.3).
37
-
38
- `similarity_limit`: number of maximum results.
39
-
40
23
  ## Global Search
41
24
 
42
25
  This module includes the following models to Decidim's Global Search:
@@ -49,7 +32,7 @@ Participatory texts persist each section of the document in a Proposal.
49
32
 
50
33
  When importing participatory texts all formats are first transformed into Markdown and is the markdown that is parsed and processed to generate the corresponding Proposals.
51
34
 
52
- When processing participatory text documents three kinds of secions are taken into account.
35
+ When processing participatory text documents three kinds of sections are taken into account.
53
36
 
54
37
  - Section: each "Title 1" in the document becomes a section.
55
38
  - Subsection: the rest of the titles become subsections.
@@ -6,9 +6,6 @@ module Decidim
6
6
  module Proposals
7
7
  # This cell renders the cost report for a proposal.
8
8
  class CostReportCell < Decidim::ViewModel
9
- include ActionView::Helpers::NumberHelper
10
- include Decidim::SanitizeHelper
11
- include Decidim::LayoutHelper
12
9
  include ProposalCellsHelper
13
10
 
14
11
  private
@@ -11,21 +11,21 @@
11
11
  <% end %>
12
12
  </div>
13
13
 
14
- <div class="flex items-center justify-between space-x-6">
15
- <span class="content-block__span flex-shrink-0">
16
- <%= t("decidim.participatory_spaces.highlighted_proposals.last") %>
17
- </span>
18
- <% if single_component? %>
19
- <%= link_to decidim_proposals.new_proposal_path, class: "button button__xs md:button__lg button__secondary" do %>
20
- <span class="text-center"><%= t("decidim.proposals.actions.new") %></span>
21
- <%= icon "add-line" %>
22
- <% end %>
23
- <% end %>
24
- </div>
25
14
  <div class="flex items-start justify-between">
26
15
  <div class="grow space-y-6">
16
+ <span class="content-block__span">
17
+ <%= t("decidim.participatory_spaces.highlighted_proposals.last") %>
18
+ </span>
19
+
27
20
  <% proposals_to_render.each do |p| %>
28
21
  <%= card_for p, link_whole_card: true, title_tag: :h3, **options.slice(:show_space) %>
29
22
  <% end %>
30
23
  </div>
24
+
25
+ <% if single_component? %>
26
+ <%= link_to decidim_proposals.new_proposal_path, class: "button button__sm md:button__lg button__secondary" do %>
27
+ <span><%= t("decidim.proposals.actions.new") %></span>
28
+ <%= icon "add-line" %>
29
+ <% end %>
30
+ <% end %>
31
31
  </div>
@@ -35,7 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def base_relation
38
- Decidim::Proposals::Proposal.published.not_hidden.except_withdrawn.where(component: model)
38
+ Decidim::Proposals::Proposal.published.not_hidden.not_withdrawn.where(component: model)
39
39
  end
40
40
 
41
41
  def decidim_proposals
@@ -1,4 +1,4 @@
1
- <% if amendmendment_creation_enabled? || visible_emendations.any? %>
1
+ <% if amendment_creation_enabled? || visible_emendations.any? %>
2
2
  <%= action_authorized_link_to :amend, amend_resource_path, resource: model, disabled: amend_button_disabled?, class: "proposal-participatory__button" do %>
3
3
  <%= icon "chat-1-line" %>
4
4
  <span><%= t("amend", scope: "decidim.proposals.participatory_text_proposal.buttons") %></span>
@@ -10,7 +10,6 @@ module Decidim
10
10
  include ProposalCellsHelper
11
11
  include Cell::ViewModel::Partial
12
12
  include Messaging::ConversationHelper
13
- include Decidim::SanitizeHelper
14
13
 
15
14
  def show
16
15
  render
@@ -69,12 +68,12 @@ module Decidim
69
68
  @visible_emendations ||= model.visible_emendations_for(current_user)
70
69
  end
71
70
 
72
- def amendmendment_creation_enabled?
71
+ def amendment_creation_enabled?
73
72
  (current_component.settings.amendments_enabled? && current_settings.amendment_creation_enabled?)
74
73
  end
75
74
 
76
75
  def amend_button_disabled?
77
- !amendmendment_creation_enabled?
76
+ !amendment_creation_enabled?
78
77
  end
79
78
  end
80
79
  end
@@ -21,6 +21,8 @@ module Decidim
21
21
  case @options[:size]
22
22
  when :s
23
23
  "decidim/proposals/proposal_s"
24
+ when :g
25
+ "decidim/proposals/proposal_g"
24
26
  else
25
27
  "decidim/proposals/proposal_l"
26
28
  end
@@ -0,0 +1,23 @@
1
+ <%= link_to resource_path, class: classes[:default], id: resource_id do %>
2
+ <div class="<%= classes[:img] %>">
3
+ <% if has_image? %>
4
+ <%= image_tag resource_image_path, alt: alt_title %>
5
+ <% else %>
6
+ <%= external_icon "media/images/proposal-placeholder-card-g.svg", class: "card__proposal-placeholder-g" %>
7
+ <% end %>
8
+ </div>
9
+ <div class="<%= classes[:text] %>">
10
+ <div class="card__grid-text-title">
11
+ <%= content_tag title_tag, title, class: title_class %>
12
+ <%= proposal_state_item[:text] if proposal_state_item.present? %>
13
+ </div>
14
+
15
+ <%= description if show_description? %>
16
+
17
+ <% if metadata_cell.present? %>
18
+ <div class="<%= classes[:metadata] %>">
19
+ <%= cell metadata_cell, resource, links: false, skip_state: true, **options %>
20
+ </div>
21
+ <% end %>
22
+ </div>
23
+ <% end %>
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cell/partial"
4
+
5
+ module Decidim
6
+ module Proposals
7
+ # This cell renders the proposal card for an instance of a Proposal
8
+ # the default size is the Grid Card (:g)
9
+ class ProposalGCell < Decidim::CardGCell
10
+ include Decidim::Proposals::ApplicationHelper
11
+ include Decidim::LayoutHelper
12
+
13
+ delegate :state_class, to: :metadata_cell_instance
14
+
15
+ def show
16
+ render
17
+ end
18
+
19
+ def title
20
+ present(model).title(html_escape: true)
21
+ end
22
+
23
+ def metadata_cell
24
+ "decidim/proposals/proposal_metadata"
25
+ end
26
+
27
+ def metadata_cell_instance
28
+ @metadata_cell_instance ||= cell("decidim/proposals/proposal_metadata", model)
29
+ end
30
+
31
+ def resource_image_path
32
+ model.attachments.first&.url
33
+ end
34
+
35
+ def proposal_state_item
36
+ return if model.state.blank?
37
+
38
+ @proposal_state_item ||= { text: content_tag(:span, humanize_proposal_state(model.state), class: "label #{state_class}") }
39
+ end
40
+
41
+ private
42
+
43
+ def classes
44
+ super.merge(metadata: "card__list-metadata")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -7,8 +7,6 @@ module Decidim
7
7
  # This cell renders the List (:l) proposal card
8
8
  # for an instance of a Proposal
9
9
  class ProposalLCell < Decidim::CardLCell
10
- delegate :component_settings, to: :controller
11
-
12
10
  alias proposal model
13
11
 
14
12
  def title
@@ -22,24 +20,25 @@ module Decidim
22
20
  end
23
21
 
24
22
  def cache_hash
25
- @cache_hash ||= begin
26
- hash = []
27
- hash << I18n.locale.to_s
28
- hash << self.class.name.demodulize.underscore
29
- hash << model.cache_key_with_version
30
- hash << model.proposal_votes_count
31
- hash << model.endorsements_count
32
- hash << model.comments_count
33
- hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
34
- hash << Digest::MD5.hexdigest(resource_image_url) if resource_image_url
35
- hash << render_space? ? 1 : 0
36
- hash << model.follows_count
37
- hash << Digest::MD5.hexdigest(model.authors.map(&:cache_key_with_version).to_s)
38
- hash << (model.must_render_translation?(model.organization) ? 1 : 0) if model.respond_to?(:must_render_translation?)
39
- hash << model.component.participatory_space.active_step.id if model.component.participatory_space.try(:active_step)
40
-
41
- hash.join(Decidim.cache_key_separator)
23
+ hash = []
24
+ hash << I18n.locale.to_s
25
+ hash << model.cache_key_with_version
26
+ hash << model.proposal_votes_count
27
+ hash << model.endorsements_count
28
+ hash << model.comments_count
29
+ hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
30
+ hash << Digest::MD5.hexdigest(resource_image_path) if resource_image_path
31
+ hash << render_space? ? 1 : 0
32
+ if current_user
33
+ hash << current_user.cache_key_with_version
34
+ hash << current_user.follows?(model) ? 1 : 0
42
35
  end
36
+ hash << model.follows_count
37
+ hash << Digest::MD5.hexdigest(model.authors.map(&:cache_key_with_version).to_s)
38
+ hash << (model.must_render_translation?(model.organization) ? 1 : 0) if model.respond_to?(:must_render_translation?)
39
+ hash << model.component.participatory_space.active_step.id if model.component.participatory_space.try(:active_step)
40
+
41
+ hash.join(Decidim.cache_key_separator)
43
42
  end
44
43
  end
45
44
  end
@@ -15,9 +15,30 @@ module Decidim
15
15
  end
16
16
 
17
17
  def state_item
18
- return if state.blank?
18
+ return if state.blank? || @options.fetch(:skip_state, false)
19
19
 
20
- { text: content_tag(:span, humanize_proposal_state(state), class: "label #{state_class}") }
20
+ if model.withdrawn?
21
+ { text: content_tag(:span, humanize_proposal_state(:withdrawn), class: "label alert") }
22
+ elsif model.emendation?
23
+ { text: content_tag(:span, humanize_proposal_state(state), class: "label #{state_class}") }
24
+ else
25
+ { text: content_tag(:span, translated_attribute(model.proposal_state&.title), class: "label", style: model.proposal_state.css_style) }
26
+ end
27
+ end
28
+
29
+ def state_class
30
+ return "alert" if model.withdrawn?
31
+
32
+ case state
33
+ when "accepted"
34
+ "success"
35
+ when "rejected"
36
+ "alert"
37
+ when "evaluating"
38
+ "warning"
39
+ else
40
+ "muted"
41
+ end
21
42
  end
22
43
 
23
44
  private
@@ -43,19 +64,6 @@ module Decidim
43
64
  icon: "account-circle-line"
44
65
  }
45
66
  end
46
-
47
- def state_class
48
- case state
49
- when "accepted"
50
- "success"
51
- when "rejected", "withdrawn"
52
- "alert"
53
- when "evaluating"
54
- "warning"
55
- else
56
- "muted"
57
- end
58
- end
59
67
  end
60
68
  end
61
69
  end
@@ -44,7 +44,6 @@ module Decidim
44
44
  form.current_user
45
45
  ) do
46
46
  attributes = {
47
- state: form.state,
48
47
  answer: form.answer,
49
48
  cost: form.cost,
50
49
  cost_report: form.cost_report,
@@ -54,7 +53,9 @@ module Decidim
54
53
  if form.state == "not_answered"
55
54
  attributes[:answered_at] = nil
56
55
  attributes[:state_published_at] = nil
56
+ proposal.proposal_state = nil
57
57
  else
58
+ proposal.assign_state(form.state)
58
59
  attributes[:answered_at] = Time.current
59
60
  attributes[:state_published_at] = Time.current if !initial_has_state_published && form.publish_answer?
60
61
  end
@@ -35,24 +35,26 @@ module Decidim
35
35
  def assign_proposals
36
36
  transaction do
37
37
  form.proposals.flat_map do |proposal|
38
- find_assignment(proposal) || assign_proposal(proposal)
38
+ form.valuator_roles.each do |valuator_role|
39
+ find_assignment(proposal, valuator_role) || assign_proposal(proposal, valuator_role)
40
+ end
39
41
  end
40
42
  end
41
43
  end
42
44
 
43
- def find_assignment(proposal)
45
+ def find_assignment(proposal, valuator_role)
44
46
  Decidim::Proposals::ValuationAssignment.find_by(
45
47
  proposal:,
46
- valuator_role: form.valuator_role
48
+ valuator_role:
47
49
  )
48
50
  end
49
51
 
50
- def assign_proposal(proposal)
52
+ def assign_proposal(proposal, valuator_role)
51
53
  Decidim.traceability.create!(
52
54
  Decidim::Proposals::ValuationAssignment,
53
55
  form.current_user,
54
56
  proposal:,
55
- valuator_role: form.valuator_role
57
+ valuator_role:
56
58
  )
57
59
  end
58
60
  end
@@ -39,7 +39,7 @@ module Decidim
39
39
  create_proposal
40
40
  create_gallery if process_gallery?
41
41
  create_attachment(weight: first_attachment_weight) if process_attachments?
42
- link_author_meeeting if form.created_in_meeting?
42
+ link_author_meeting if form.created_in_meeting?
43
43
  end
44
44
 
45
45
  send_notification
@@ -58,9 +58,6 @@ module Decidim
58
58
  action_user: form.current_user
59
59
  )
60
60
  @attached_to = @proposal
61
- Decidim.traceability.perform_action!(:publish, @proposal, form.current_user, visibility: "all") do
62
- @proposal.update!(published_at: Time.current)
63
- end
64
61
  end
65
62
 
66
63
  def attributes
@@ -75,11 +72,12 @@ module Decidim
75
72
  address: form.address,
76
73
  latitude: form.latitude,
77
74
  longitude: form.longitude,
78
- created_in_meeting: form.created_in_meeting
75
+ created_in_meeting: form.created_in_meeting,
76
+ published_at: Time.current
79
77
  }
80
78
  end
81
79
 
82
- def link_author_meeeting
80
+ def link_author_meeting
83
81
  proposal.link_resources(form.author, "proposals_from_meeting")
84
82
  end
85
83
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ class CreateProposalState < Decidim::Commands::CreateResource
7
+ fetch_form_attributes :title, :text_color, :bg_color, :announcement_title, :component
8
+
9
+ def resource_class
10
+ Decidim::Proposals::ProposalState
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ class DestroyProposalState < Decidim::Commands::DestroyResource
7
+ end
8
+ end
9
+ end
10
+ end
@@ -47,8 +47,14 @@ module Decidim
47
47
  def proposals
48
48
  @proposals = Decidim::Proposals::Proposal
49
49
  .where(component: origin_component)
50
- .where(state: @form.states)
51
50
  @proposals = @proposals.where(scope: proposal_scopes) unless proposal_scopes.empty?
51
+
52
+ @proposals = if @form.states.include?("not_answered")
53
+ @proposals.not_answered.or(@proposals.where(id: @proposals.only_status(@form.states).pluck(:id)))
54
+ else
55
+ @proposals.only_status(@form.states)
56
+ end
57
+
52
58
  @proposals
53
59
  end
54
60
 
@@ -80,10 +86,12 @@ module Decidim
80
86
  def proposal_answer_attributes(original_proposal)
81
87
  return {} unless form.keep_answers
82
88
 
89
+ state = Decidim::Proposals::ProposalState.where(component: target_component, token: original_proposal.state).first
90
+
83
91
  {
84
92
  answer: original_proposal.answer,
85
93
  answered_at: original_proposal.answered_at,
86
- state: original_proposal.state,
94
+ proposal_state: state,
87
95
  state_published_at: original_proposal.state_published_at
88
96
  }
89
97
  end
@@ -11,7 +11,7 @@ module Decidim
11
11
  # initial_state - The proposal state before the current process.
12
12
  def initialize(proposal, initial_state)
13
13
  @proposal = proposal
14
- @initial_state = initial_state.to_s
14
+ @initial_state = initial_state
15
15
  end
16
16
 
17
17
  # Executes the command. Broadcasts these events:
@@ -42,28 +42,11 @@ module Decidim
42
42
  end
43
43
 
44
44
  def notify_followers
45
- if proposal.accepted?
46
- publish_event(
47
- "decidim.events.proposals.proposal_accepted",
48
- Decidim::Proposals::AcceptedProposalEvent
49
- )
50
- elsif proposal.rejected?
51
- publish_event(
52
- "decidim.events.proposals.proposal_rejected",
53
- Decidim::Proposals::RejectedProposalEvent
54
- )
55
- elsif proposal.evaluating?
56
- publish_event(
57
- "decidim.events.proposals.proposal_evaluating",
58
- Decidim::Proposals::EvaluatingProposalEvent
59
- )
60
- end
61
- end
45
+ return if proposal.state == "not_answered"
62
46
 
63
- def publish_event(event, event_class)
64
47
  Decidim::EventsManager.publish(
65
- event:,
66
- event_class:,
48
+ event: "decidim.events.proposals.proposal_state_changed",
49
+ event_class: Decidim::Proposals::ProposalStateChangedEvent,
67
50
  resource: proposal,
68
51
  affected_users: proposal.notifiable_identities,
69
52
  followers: proposal.followers - proposal.notifiable_identities
@@ -33,16 +33,18 @@ module Decidim
33
33
  def unassign_proposals
34
34
  transaction do
35
35
  form.proposals.flat_map do |proposal|
36
- assignment = find_assignment(proposal)
37
- unassign(assignment) if assignment
36
+ form.valuator_roles.each do |valuator_role|
37
+ assignment = find_assignment(proposal, valuator_role)
38
+ unassign(assignment) if assignment
39
+ end
38
40
  end
39
41
  end
40
42
  end
41
43
 
42
- def find_assignment(proposal)
44
+ def find_assignment(proposal, valuator_role)
43
45
  Decidim::Proposals::ValuationAssignment.find_by(
44
46
  proposal:,
45
- valuator_role: form.valuator_role
47
+ valuator_role:
46
48
  )
47
49
  end
48
50
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ class UpdateProposalState < Decidim::Commands::UpdateResource
7
+ include TranslatableAttributes
8
+
9
+ fetch_form_attributes :title, :text_color, :bg_color, :announcement_title, :component
10
+ end
11
+ end
12
+ end
13
+ end
@@ -4,6 +4,7 @@ module Decidim
4
4
  module Proposals
5
5
  # A command with all the business logic when a user creates a new proposal.
6
6
  class CreateProposal < Decidim::Command
7
+ include ::Decidim::MultipleAttachmentsMethods
7
8
  include HashtagsMethods
8
9
 
9
10
  # Public: Initializes the command.
@@ -31,8 +32,14 @@ module Decidim
31
32
  return broadcast(:invalid)
32
33
  end
33
34
 
35
+ if process_attachments?
36
+ build_attachments
37
+ return broadcast(:invalid) if attachments_invalid?
38
+ end
39
+
34
40
  with_events(with_transaction: true) do
35
41
  create_proposal
42
+ create_attachments(first_weight: first_attachment_weight) if process_attachments?
36
43
  end
37
44
 
38
45
  broadcast(:ok, proposal)
@@ -74,8 +81,14 @@ module Decidim
74
81
  },
75
82
  component: form.component
76
83
  )
84
+
85
+ proposal.category = form.category if form.category_id.present?
86
+ proposal.scope = form.scope if form.scope_id.present?
87
+ proposal.documents = form.documents if form.documents.present?
88
+ proposal.address = form.address if form.has_address? && !form.geocoded?
77
89
  proposal.add_coauthor(@current_user, user_group:)
78
90
  proposal.save!
91
+ @attached_to = proposal
79
92
  proposal
80
93
  end
81
94
  end
@@ -104,11 +117,17 @@ module Decidim
104
117
  end
105
118
 
106
119
  def current_user_proposals
107
- Proposal.from_author(@current_user).where(component: form.current_component).except_withdrawn
120
+ Proposal.not_withdrawn.from_author(@current_user).where(component: form.current_component)
108
121
  end
109
122
 
110
123
  def user_group_proposals
111
- Proposal.from_user_group(@user_group).where(component: form.current_component).except_withdrawn
124
+ Proposal.not_withdrawn.from_user_group(@user_group).where(component: form.current_component)
125
+ end
126
+
127
+ def first_attachment_weight
128
+ return 1 if proposal.photos.count.zero?
129
+
130
+ proposal.photos.count
112
131
  end
113
132
  end
114
133
  end
@@ -133,11 +133,11 @@ module Decidim
133
133
  end
134
134
 
135
135
  def current_user_proposals
136
- Proposal.from_author(current_user).where(component: form.current_component).published.where.not(id: proposal.id).except_withdrawn
136
+ Proposal.from_author(current_user).where(component: form.current_component).published.where.not(id: proposal.id).not_withdrawn
137
137
  end
138
138
 
139
139
  def user_group_proposals
140
- Proposal.from_user_group(user_group).where(component: form.current_component).published.where.not(id: proposal.id).except_withdrawn
140
+ Proposal.from_user_group(user_group).where(component: form.current_component).published.where.not(id: proposal.id).not_withdrawn
141
141
  end
142
142
  end
143
143
  end
@@ -20,7 +20,7 @@ module Decidim
20
20
  #
21
21
  # Returns nothing.
22
22
  def call
23
- return broadcast(:invalid) if @proposal.maximum_votes_reached? && !@proposal.can_accumulate_supports_beyond_threshold
23
+ return broadcast(:invalid) if @proposal.maximum_votes_reached? && !@proposal.can_accumulate_votes_beyond_threshold
24
24
 
25
25
  build_proposal_vote
26
26
  return broadcast(:invalid) unless vote.valid?
@@ -16,14 +16,14 @@ module Decidim
16
16
  # Executes the command. Broadcasts these events:
17
17
  #
18
18
  # - :ok when everything is valid, together with the proposal.
19
- # - :has_supports if the proposal already has supports or does not belong to current user.
19
+ # - :has_votes if the proposal already has votes or does not belong to current user.
20
20
  #
21
21
  # Returns nothing.
22
22
  def call
23
- return broadcast(:has_supports) if @proposal.votes.any?
23
+ return broadcast(:has_votes) if @proposal.votes.any?
24
24
 
25
25
  transaction do
26
- change_proposal_state_to_withdrawn
26
+ @proposal.withdraw!
27
27
  reject_emendations_if_any
28
28
  end
29
29
 
@@ -32,10 +32,6 @@ module Decidim
32
32
 
33
33
  private
34
34
 
35
- def change_proposal_state_to_withdrawn
36
- @proposal.update state: "withdrawn"
37
- end
38
-
39
35
  def reject_emendations_if_any
40
36
  return if @proposal.emendations.empty?
41
37