decidim-proposals 0.28.3 → 0.29.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) 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_cell.rb +1 -1
  5. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +1 -1
  6. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +2 -3
  7. data/app/cells/decidim/proposals/proposal_cell.rb +2 -0
  8. data/app/cells/decidim/proposals/proposal_g/show.erb +23 -0
  9. data/app/cells/decidim/proposals/proposal_g_cell.rb +48 -0
  10. data/app/cells/decidim/proposals/proposal_l_cell.rb +1 -3
  11. data/app/cells/decidim/proposals/proposal_metadata_cell.rb +23 -15
  12. data/app/commands/decidim/proposals/admin/answer_proposal.rb +2 -1
  13. data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +7 -5
  14. data/app/commands/decidim/proposals/admin/create_proposal.rb +2 -2
  15. data/app/commands/decidim/proposals/admin/create_proposal_state.rb +15 -0
  16. data/app/commands/decidim/proposals/admin/destroy_proposal_state.rb +10 -0
  17. data/app/commands/decidim/proposals/admin/import_proposals.rb +10 -2
  18. data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +4 -21
  19. data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +6 -4
  20. data/app/commands/decidim/proposals/admin/update_proposal_state.rb +13 -0
  21. data/app/commands/decidim/proposals/create_proposal.rb +21 -2
  22. data/app/commands/decidim/proposals/update_proposal.rb +2 -2
  23. data/app/commands/decidim/proposals/vote_proposal.rb +1 -1
  24. data/app/commands/decidim/proposals/withdraw_proposal.rb +3 -7
  25. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +10 -22
  26. data/app/controllers/decidim/proposals/admin/proposal_states_controller.rb +86 -0
  27. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +4 -0
  28. data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +8 -11
  29. data/app/controllers/decidim/proposals/proposals_controller.rb +30 -35
  30. data/app/events/decidim/proposals/proposal_state_changed_event.rb +37 -0
  31. data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +5 -1
  32. data/app/forms/decidim/proposals/admin/proposal_state_form.rb +22 -0
  33. data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -1
  34. data/app/forms/decidim/proposals/admin/proposals_import_form.rb +1 -1
  35. data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +12 -14
  36. data/app/forms/decidim/proposals/proposal_form.rb +25 -4
  37. data/app/forms/decidim/proposals/reject_access_to_collaborative_draft_form.rb +1 -1
  38. data/app/forms/decidim/proposals/request_access_to_collaborative_draft_form.rb +1 -1
  39. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +7 -17
  40. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +13 -89
  41. data/app/helpers/decidim/proposals/application_helper.rb +16 -10
  42. data/app/helpers/decidim/proposals/proposal_cells_helper.rb +6 -2
  43. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +3 -3
  44. data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +5 -8
  45. data/app/helpers/decidim/proposals/proposals_helper.rb +18 -24
  46. data/app/models/decidim/proposals/proposal.rb +78 -28
  47. data/app/models/decidim/proposals/proposal_state.rb +58 -0
  48. data/app/packs/documents/decidim/proposals/participatory_texts/participatory_text.md +1 -3
  49. data/app/packs/images/decidim/proposals/proposal-placeholder-card-g.svg +15 -0
  50. data/app/packs/src/decidim/proposals/add_proposal.js +2 -0
  51. data/app/packs/src/decidim/proposals/admin/proposals.js +43 -8
  52. data/app/packs/stylesheets/decidim/proposals/proposals.scss +39 -1
  53. data/app/permissions/decidim/proposals/admin/permissions.rb +16 -4
  54. data/app/presenters/decidim/proposals/admin_log/proposal_state_presenter.rb +21 -0
  55. data/app/presenters/decidim/proposals/proposal_presenter.rb +12 -3
  56. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +1 -1
  57. data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +1 -1
  58. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +4 -4
  59. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +1 -1
  60. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +1 -1
  61. data/app/services/decidim/proposals/diff_renderer.rb +1 -1
  62. data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +1 -1
  63. data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +3 -2
  64. data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +2 -2
  65. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +3 -3
  66. data/app/views/decidim/proposals/admin/proposal_states/_form.html.erb +67 -0
  67. data/app/views/decidim/proposals/admin/proposal_states/edit.html.erb +18 -0
  68. data/app/views/decidim/proposals/admin/proposal_states/index.html.erb +50 -0
  69. data/app/views/decidim/proposals/admin/proposal_states/new.html.erb +18 -0
  70. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +6 -12
  71. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +6 -6
  72. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +2 -2
  73. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +11 -7
  74. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +7 -5
  75. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +2 -2
  76. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +2 -2
  77. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_recategorize.html.erb +2 -2
  78. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +2 -2
  79. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_split.html.erb +2 -2
  80. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +11 -7
  81. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_valuators_picker.html.erb +12 -0
  82. data/app/views/decidim/proposals/admin/proposals/index.html.erb +9 -5
  83. data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +1 -1
  84. data/app/views/decidim/proposals/admin/proposals/show.html.erb +3 -2
  85. data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +3 -3
  86. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +12 -5
  87. data/app/views/decidim/proposals/proposals/_proposal.html.erb +1 -1
  88. data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +1 -1
  89. data/app/views/decidim/proposals/proposals/_proposals.html.erb +9 -3
  90. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +1 -1
  91. data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +3 -3
  92. data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +0 -1
  93. data/app/views/decidim/proposals/proposals/new.html.erb +2 -7
  94. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +4 -4
  95. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_votes_count.html.erb +8 -8
  96. data/app/views/decidim/proposals/proposals/preview.html.erb +1 -1
  97. data/app/views/decidim/proposals/proposals/show.html.erb +1 -1
  98. data/config/locales/ar.yml +6 -114
  99. data/config/locales/bg.yml +110 -106
  100. data/config/locales/ca.yml +81 -78
  101. data/config/locales/cs.yml +60 -122
  102. data/config/locales/de.yml +122 -119
  103. data/config/locales/el.yml +3 -118
  104. data/config/locales/en.yml +110 -107
  105. data/config/locales/es-MX.yml +82 -79
  106. data/config/locales/es-PY.yml +85 -82
  107. data/config/locales/es.yml +81 -78
  108. data/config/locales/eu.yml +103 -107
  109. data/config/locales/fi-plain.yml +87 -84
  110. data/config/locales/fi.yml +118 -115
  111. data/config/locales/fr-CA.yml +86 -83
  112. data/config/locales/fr.yml +78 -75
  113. data/config/locales/ga-IE.yml +1 -27
  114. data/config/locales/gl.yml +5 -104
  115. data/config/locales/he-IL.yml +0 -13
  116. data/config/locales/hu.yml +15 -88
  117. data/config/locales/id-ID.yml +2 -97
  118. data/config/locales/is-IS.yml +1 -33
  119. data/config/locales/it.yml +6 -96
  120. data/config/locales/ja.yml +110 -107
  121. data/config/locales/lb.yml +1 -0
  122. data/config/locales/lt.yml +3 -122
  123. data/config/locales/lv.yml +2 -96
  124. data/config/locales/nl.yml +6 -95
  125. data/config/locales/no.yml +3 -107
  126. data/config/locales/pl.yml +106 -113
  127. data/config/locales/pt-BR.yml +5 -81
  128. data/config/locales/pt.yml +5 -107
  129. data/config/locales/ro-RO.yml +6 -110
  130. data/config/locales/ru.yml +2 -53
  131. data/config/locales/sk.yml +2 -103
  132. data/config/locales/sv.yml +66 -206
  133. data/config/locales/tr-TR.yml +57 -103
  134. data/config/locales/uk.yml +3 -54
  135. data/config/locales/zh-CN.yml +2 -99
  136. data/config/locales/zh-TW.yml +3 -116
  137. data/db/migrate/20240110203500_add_withdrawn_at_field_to_proposals.rb +27 -0
  138. data/db/migrate/20240110203501_create_decidim_proposals_proposal_state.rb +14 -0
  139. data/db/migrate/20240110203502_add_state_id_to_decidim_proposals_proposals.rb +13 -0
  140. data/db/migrate/20240110203503_remove_state_from_decidim_proposals_proposals.rb +11 -0
  141. data/db/migrate/20240110203504_create_default_proposal_states.rb +31 -0
  142. data/db/migrate/20240209092404_change_color_fields_on_proposals_states.rb +54 -0
  143. data/decidim-proposals.gemspec +2 -2
  144. data/lib/decidim/api/proposal_type.rb +4 -0
  145. data/lib/decidim/proposals/admin_engine.rb +8 -0
  146. data/lib/decidim/proposals/admin_filter.rb +37 -0
  147. data/lib/decidim/proposals/component.rb +8 -5
  148. data/lib/decidim/proposals/engine.rb +1 -15
  149. data/lib/decidim/proposals/import/proposal_answer_creator.rb +6 -6
  150. data/lib/decidim/proposals/import/proposal_creator.rb +1 -1
  151. data/lib/decidim/proposals/markdown_to_proposals.rb +2 -8
  152. data/lib/decidim/proposals/proposal_serializer.rb +5 -3
  153. data/lib/decidim/proposals/seeds.rb +60 -51
  154. data/lib/decidim/proposals/test/factories.rb +64 -8
  155. data/lib/decidim/proposals/version.rb +1 -1
  156. data/lib/decidim/proposals.rb +84 -12
  157. data/lib/tasks/proposals/upgrade/decidim_proposals_upgrade_tasks.rake +32 -0
  158. metadata +50 -36
  159. data/app/events/decidim/proposals/accepted_proposal_event.rb +0 -17
  160. data/app/events/decidim/proposals/evaluating_proposal_event.rb +0 -11
  161. data/app/events/decidim/proposals/rejected_proposal_event.rb +0 -17
  162. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +0 -44
  163. data/app/queries/decidim/proposals/similar_proposals.rb +0 -67
  164. data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +0 -0
  165. data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +0 -3
  166. data/app/views/decidim/proposals/proposals/compare.html.erb +0 -24
  167. data/app/views/decidim/proposals/proposals/complete.html.erb +0 -31
  168. data/lib/tasks/proposals/upgrade/decdim_proposal_upgrade_tasks.rake +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e4bd14ec5e23a0ba39c81c825c919ceaadbba6c9a2f47498a8f1a2d0bf59dd6
4
- data.tar.gz: 757238cf1ff370f483d05ce6a569f4cd41aa5f06191342b374a583babc10d570
3
+ metadata.gz: 22cc3e857b344169fadf51778fef41a0ea95d814e8855a90eb354d5b2bda88fe
4
+ data.tar.gz: 48d87bd26f7856a756da54a174edddc30c17a9330a7e5af07c808cdfac7adf36
5
5
  SHA512:
6
- metadata.gz: a08f20046706481335121d31d830f25e2255b76cec1b93aa4bc38e63145498aa8111995505a8f4ac007cbf245d252466b90f744d5bd51b80fc9e74bc2db82af3
7
- data.tar.gz: 3ae92e1d44a2c9bdbce252029947d91dca471f9a00d3f932980ce55f2b796e4ecd7abf83c394f746dd4651dcb736f7c2bc88abc566cd72127b4fa4ca7dfc4066
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
@@ -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
@@ -29,7 +27,7 @@ module Decidim
29
27
  hash << model.endorsements_count
30
28
  hash << model.comments_count
31
29
  hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
32
- hash << Digest::MD5.hexdigest(resource_image_url) if resource_image_url
30
+ hash << Digest::MD5.hexdigest(resource_image_path) if resource_image_path
33
31
  hash << render_space? ? 1 : 0
34
32
  if current_user
35
33
  hash << current_user.cache_key_with_version
@@ -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
@@ -77,7 +77,7 @@ module Decidim
77
77
  }
78
78
  end
79
79
 
80
- def link_author_meeeting
80
+ def link_author_meeting
81
81
  proposal.link_resources(form.author, "proposals_from_meeting")
82
82
  end
83
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
 
@@ -13,6 +13,8 @@ module Decidim
13
13
 
14
14
  private
15
15
 
16
+ delegate :filters, :dynamically_translated_filters, :filters_with_values, to: :filter_config
17
+
16
18
  # Comment about participatory_texts_enabled.
17
19
  def base_query
18
20
  return collection.order(:position) if current_component.settings.participatory_texts_enabled?
@@ -30,32 +32,18 @@ module Decidim
30
32
  :id_string_or_title_cont
31
33
  end
32
34
 
33
- def filters
34
- [
35
- :is_emendation_true,
36
- :with_any_state,
37
- :state_eq,
38
- :scope_id_eq,
39
- :category_id_eq,
40
- :valuator_role_ids_has
41
- ]
35
+ def filter_config
36
+ @filter_config ||= Decidim::AdminFilter.new(:proposals).build_for(self)
42
37
  end
43
38
 
44
- def filters_with_values
45
- {
46
- is_emendation_true: %w(true false),
47
- state_eq: Proposal::STATES,
48
- with_any_state: %w(state_published state_not_published),
49
- scope_id_eq: scope_ids_hash(scopes.top_level),
50
- category_id_eq: category_ids_hash(categories.first_class),
51
- valuator_role_ids_has: valuator_role_ids
52
- }
39
+ def translated_state_eq(state)
40
+ return t("decidim.admin.filters.proposals.state_eq.values.withdrawn") if state == "withdrawn"
41
+
42
+ translated_attribute(ProposalState.where(component: current_component, token: state).first&.title)
53
43
  end
54
44
 
55
- # Cannot user `super` here, because it does not belong to a superclass
56
- # but to a concern.
57
- def dynamically_translated_filters
58
- [:scope_id_eq, :category_id_eq, :valuator_role_ids_has]
45
+ def state_eq_values
46
+ ProposalState.where(component: current_component).pluck(:token) + ["withdrawn"]
59
47
  end
60
48
 
61
49
  def valuator_role_ids