decidim-proposals 0.30.2 → 0.31.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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/proposals/collaborative_draft_metadata_cell.rb +1 -1
  3. data/app/cells/decidim/proposals/proposal_g_cell.rb +4 -4
  4. data/app/cells/decidim/proposals/proposal_l_cell.rb +4 -4
  5. data/app/cells/decidim/proposals/proposal_metadata_cell.rb +2 -2
  6. data/app/commands/decidim/proposals/admin/{assign_proposals_to_valuator.rb → assign_proposals_to_evaluator.rb} +16 -16
  7. data/app/commands/decidim/proposals/admin/create_proposal.rb +1 -2
  8. data/app/commands/decidim/proposals/admin/create_proposal_note.rb +4 -4
  9. data/app/commands/decidim/proposals/admin/merge_proposals.rb +60 -13
  10. data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +2 -2
  11. data/app/commands/decidim/proposals/admin/proposal_notes_methods.rb +5 -5
  12. data/app/commands/decidim/proposals/admin/reply_proposal_note.rb +1 -1
  13. data/app/commands/decidim/proposals/admin/{unassign_proposals_from_valuator.rb → unassign_proposals_from_evaluator.rb} +7 -7
  14. data/app/commands/decidim/proposals/admin/update_proposal.rb +1 -2
  15. data/app/commands/decidim/proposals/create_collaborative_draft.rb +3 -8
  16. data/app/commands/decidim/proposals/create_proposal.rb +4 -17
  17. data/app/commands/decidim/proposals/publish_collaborative_draft.rb +2 -2
  18. data/app/commands/decidim/proposals/publish_proposal.rb +1 -5
  19. data/app/commands/decidim/proposals/update_collaborative_draft.rb +2 -4
  20. data/app/commands/decidim/proposals/update_proposal.rb +5 -18
  21. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +6 -6
  22. data/app/controllers/concerns/decidim/proposals/orderable.rb +3 -3
  23. data/app/controllers/decidim/proposals/admin/evaluation_assignments_controller.rb +55 -0
  24. data/app/controllers/decidim/proposals/admin/participatory_texts_controller.rb +6 -6
  25. data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +1 -1
  26. data/app/controllers/decidim/proposals/admin/proposal_states_controller.rb +2 -2
  27. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +2 -2
  28. data/app/controllers/decidim/proposals/admin/proposals_imports_controller.rb +1 -1
  29. data/app/controllers/decidim/proposals/admin/proposals_merges_controller.rb +12 -3
  30. data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +2 -3
  31. data/app/controllers/decidim/proposals/proposals_controller.rb +5 -6
  32. data/app/events/decidim/proposals/admin/{proposal_assigned_to_valuator_event.rb → proposal_assigned_to_evaluator_event.rb} +1 -1
  33. data/app/events/decidim/proposals/{endorsing_enabled_event.rb → liking_enabled_event.rb} +1 -1
  34. data/app/events/decidim/proposals/merged_proposal_event.rb +9 -0
  35. data/app/events/decidim/proposals/proposal_liked_event.rb +33 -0
  36. data/app/forms/decidim/proposals/admin/evaluation_assignment_form.rb +38 -0
  37. data/app/forms/decidim/proposals/admin/proposal_base_form.rb +1 -27
  38. data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -1
  39. data/app/forms/decidim/proposals/admin/proposals_merge_form.rb +58 -2
  40. data/app/forms/decidim/proposals/collaborative_draft_form.rb +1 -5
  41. data/app/forms/decidim/proposals/proposal_form.rb +0 -29
  42. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +8 -8
  43. data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +6 -6
  44. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +2 -17
  45. data/app/helpers/decidim/proposals/application_helper.rb +3 -6
  46. data/app/jobs/decidim/proposals/settings_change_job.rb +6 -6
  47. data/app/models/decidim/proposals/collaborative_draft.rb +1 -1
  48. data/app/models/decidim/proposals/{valuation_assignment.rb → evaluation_assignment.rb} +7 -7
  49. data/app/models/decidim/proposals/proposal.rb +22 -32
  50. data/app/packs/entrypoints/decidim_proposals_admin.js +1 -0
  51. data/app/packs/src/decidim/proposals/add_proposal.js +1 -1
  52. data/app/packs/src/decidim/proposals/admin/proposals.js +22 -11
  53. data/app/packs/src/decidim/proposals/admin/proposals_form.js +1 -1
  54. data/app/packs/src/decidim/proposals/admin/proposals_merge.js +92 -0
  55. data/app/packs/src/decidim/proposals/choose_proposals.js +1 -1
  56. data/app/packs/src/decidim/proposals/exit_handler.js +1 -1
  57. data/app/packs/src/decidim/proposals/utils.js +1 -1
  58. data/app/packs/stylesheets/decidim/proposals/proposals.scss +29 -1
  59. data/app/permissions/decidim/proposals/admin/permissions.rb +20 -20
  60. data/app/presenters/decidim/proposals/admin_log/{valuation_assignment_presenter.rb → evaluation_assignment_presenter.rb} +7 -7
  61. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +15 -0
  62. data/app/presenters/decidim/proposals/admin_log/value_types/{valuator_role_user_presenter.rb → evaluator_role_user_presenter.rb} +2 -2
  63. data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +1 -1
  64. data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +1 -6
  65. data/app/presenters/decidim/proposals/log/{valuation_assignment_presenter.rb → evaluation_assignment_presenter.rb} +1 -1
  66. data/app/presenters/decidim/proposals/proposal_presenter.rb +9 -13
  67. data/app/services/decidim/proposals/diff_renderer.rb +0 -1
  68. data/app/services/decidim/proposals/proposal_builder.rb +5 -10
  69. data/app/views/decidim/proposals/admin/participatory_texts/_article-preview.html.erb +1 -1
  70. data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +1 -2
  71. data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +1 -1
  72. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +1 -1
  73. data/app/views/decidim/proposals/admin/proposal_states/index.html.erb +42 -12
  74. data/app/views/decidim/proposals/admin/proposals/_actions.html.erb +87 -21
  75. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +9 -13
  76. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +2 -24
  77. data/app/views/decidim/proposals/admin/proposals/_likes.html.erb +25 -0
  78. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +13 -12
  79. data/app/views/decidim/proposals/admin/proposals/_proposals-thead.html.erb +1 -1
  80. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_evaluator.html.erb +19 -0
  81. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +45 -49
  82. data/app/views/decidim/proposals/admin/proposals/bulk_actions/{_valuators_picker.html.erb → _evaluators_picker.html.erb} +4 -4
  83. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +7 -14
  84. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_evaluator.html.erb +19 -0
  85. data/app/views/decidim/proposals/admin/proposals/index.html.erb +9 -5
  86. data/app/views/decidim/proposals/admin/proposals/manage_trash.html.erb +2 -1
  87. data/app/views/decidim/proposals/admin/proposals/show.html.erb +17 -17
  88. data/app/views/decidim/proposals/admin/proposals_merges/_form.html.erb +49 -0
  89. data/app/views/decidim/proposals/admin/proposals_merges/new.html.erb +14 -0
  90. data/app/views/decidim/proposals/collaborative_drafts/_collaborative_actions.html.erb +2 -2
  91. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +1 -21
  92. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -1
  93. data/app/views/decidim/proposals/proposals/_actions.html.erb +2 -2
  94. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +1 -21
  95. data/app/views/decidim/proposals/proposals/_proposal_actions.html.erb +4 -4
  96. data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +2 -2
  97. data/app/views/decidim/proposals/proposals/_proposal_voting_rules.html.erb +1 -1
  98. data/app/views/decidim/proposals/proposals/participatory_texts/_view_index.html.erb +1 -1
  99. data/app/views/decidim/proposals/proposals/preview.html.erb +1 -1
  100. data/app/views/decidim/proposals/proposals/show.html.erb +2 -2
  101. data/config/assets.rb +2 -2
  102. data/config/locales/ar.yml +0 -65
  103. data/config/locales/bg.yml +0 -71
  104. data/config/locales/bs-BA.yml +0 -25
  105. data/config/locales/ca-IT.yml +64 -72
  106. data/config/locales/ca.yml +64 -72
  107. data/config/locales/cs.yml +52 -81
  108. data/config/locales/de.yml +66 -73
  109. data/config/locales/el.yml +0 -66
  110. data/config/locales/en.yml +69 -77
  111. data/config/locales/es-MX.yml +68 -76
  112. data/config/locales/es-PY.yml +68 -76
  113. data/config/locales/es.yml +68 -76
  114. data/config/locales/eu.yml +66 -74
  115. data/config/locales/fi-plain.yml +67 -75
  116. data/config/locales/fi.yml +67 -75
  117. data/config/locales/fr-CA.yml +49 -74
  118. data/config/locales/fr.yml +49 -74
  119. data/config/locales/ga-IE.yml +0 -22
  120. data/config/locales/gl.yml +0 -47
  121. data/config/locales/hu.yml +0 -64
  122. data/config/locales/id-ID.yml +0 -34
  123. data/config/locales/is-IS.yml +0 -14
  124. data/config/locales/it.yml +0 -58
  125. data/config/locales/ja.yml +68 -76
  126. data/config/locales/lb.yml +0 -3
  127. data/config/locales/lt.yml +0 -68
  128. data/config/locales/lv.yml +0 -62
  129. data/config/locales/nl.yml +0 -63
  130. data/config/locales/no.yml +0 -42
  131. data/config/locales/pl.yml +0 -73
  132. data/config/locales/pt-BR.yml +0 -59
  133. data/config/locales/pt.yml +0 -60
  134. data/config/locales/ro-RO.yml +45 -64
  135. data/config/locales/ru.yml +0 -15
  136. data/config/locales/sk.yml +0 -60
  137. data/config/locales/sr-CS.yml +0 -25
  138. data/config/locales/sv.yml +58 -76
  139. data/config/locales/tr-TR.yml +0 -58
  140. data/config/locales/uk.yml +0 -15
  141. data/config/locales/zh-CN.yml +0 -57
  142. data/config/locales/zh-TW.yml +0 -65
  143. data/db/migrate/20240110203500_add_withdrawn_at_field_to_proposals.rb +1 -1
  144. data/db/migrate/20240110203504_create_default_proposal_states.rb +1 -1
  145. data/db/migrate/20250121110014_rename_proposal_valuation_assignments_to_evaluation_assignments.rb +15 -0
  146. data/db/migrate/20250121110904_rename_valuation_assignments_count_to_evaluation_assignments_count.rb +16 -0
  147. data/db/migrate/20250211141313_rename_valuator_columns.rb +8 -0
  148. data/db/migrate/20250515132351_rename_proposals_endorsements_count_to_likes.rb +7 -0
  149. data/decidim-proposals.gemspec +1 -1
  150. data/lib/decidim/api/mutations/answer_proposal_attributes.rb +17 -0
  151. data/lib/decidim/api/mutations/proposal_answer_type.rb +57 -0
  152. data/lib/decidim/api/mutations/proposal_mutation_type.rb +14 -0
  153. data/lib/decidim/api/mutations/proposals_mutation_type.rb +23 -0
  154. data/lib/decidim/api/proposal_input_sort.rb +1 -1
  155. data/lib/decidim/api/proposal_state_type.rb +16 -0
  156. data/lib/decidim/api/proposal_type.rb +59 -9
  157. data/lib/decidim/proposals/admin_engine.rb +3 -3
  158. data/lib/decidim/proposals/admin_filter.rb +3 -3
  159. data/lib/decidim/proposals/api.rb +5 -0
  160. data/lib/decidim/proposals/component.rb +44 -24
  161. data/lib/decidim/proposals/engine.rb +18 -83
  162. data/lib/decidim/proposals/evaluable.rb +22 -0
  163. data/lib/decidim/proposals/import/proposal_creator.rb +1 -1
  164. data/lib/decidim/proposals/proposal_serializer.rb +9 -11
  165. data/lib/decidim/proposals/seeds.rb +16 -27
  166. data/lib/decidim/proposals/test/factories.rb +21 -53
  167. data/lib/decidim/proposals/version.rb +1 -1
  168. data/lib/decidim/proposals.rb +3 -3
  169. data/lib/tasks/proposals/upgrade/decidim_proposals_upgrade_tasks.rake +11 -11
  170. metadata +57 -47
  171. data/app/commands/decidim/proposals/hashtags_methods.rb +0 -36
  172. data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +0 -55
  173. data/app/events/decidim/proposals/proposal_endorsed_event.rb +0 -33
  174. data/app/forms/decidim/proposals/admin/proposals_file_import_form.rb +0 -31
  175. data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +0 -38
  176. data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +0 -32
  177. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +0 -58
  178. data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +0 -58
  179. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +0 -74
  180. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +0 -48
  181. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +0 -52
  182. data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +0 -11
  183. data/app/views/decidim/proposals/admin/proposals/_endorsers.html.erb +0 -25
  184. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +0 -19
  185. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +0 -19
  186. data/lib/decidim/proposals/valuatable.rb +0 -22
@@ -3,6 +3,8 @@
3
3
  module Decidim
4
4
  module Proposals
5
5
  class ProposalType < Decidim::Api::Types::BaseObject
6
+ include ActiveSupport::NumberHelper
7
+
6
8
  description "A proposal"
7
9
 
8
10
  implements Decidim::Comments::CommentableInterface
@@ -13,39 +15,77 @@ module Decidim
13
15
  implements Decidim::Core::AmendableInterface
14
16
  implements Decidim::Core::AmendableEntityInterface
15
17
  implements Decidim::Core::TraceableInterface
16
- implements Decidim::Core::EndorsableInterface
18
+ implements Decidim::Core::LikeableInterface
17
19
  implements Decidim::Core::TimestampsInterface
20
+ implements Decidim::Core::ReferableInterface
21
+ implements Decidim::Core::LocalizableInterface
22
+ implements Decidim::Core::FollowableInterface
18
23
 
19
- field :address, GraphQL::Types::String, "The physical address (location) of this proposal", null: true
20
24
  field :answer, Decidim::Core::TranslatedFieldType, "The answer feedback for the status for this proposal", null: true
21
25
  field :answered_at, Decidim::Core::DateTimeType, description: "The date and time this proposal was answered", null: true
22
26
  field :body, Decidim::Core::TranslatedFieldType, "The description for this body", null: true
23
- field :coordinates, Decidim::Core::CoordinatesType, "Physical coordinates for this proposal", null: true
27
+ field :cost, GraphQL::Types::String, "The proposal cost", null: true
28
+ field :cost_report, Decidim::Core::TranslatedFieldType, "The cost report for this proposal", null: true
24
29
  field :created_in_meeting, GraphQL::Types::Boolean, "Whether this proposal comes from a meeting or not", method: :official_meeting?, null: true
30
+ field :execution_period, Decidim::Core::TranslatedFieldType, "The execution period for this proposal", null: true
25
31
  field :id, GraphQL::Types::ID, "The id of the Proposal", null: false
26
32
  field :meeting, Decidim::Meetings::MeetingType, description: "If the proposal comes from a meeting, the related meeting", null: true
27
33
  field :official, GraphQL::Types::Boolean, "Whether this proposal is official or not", method: :official?, null: true
28
34
  field :participatory_text_level, GraphQL::Types::String, description: "If it is a participatory text, the level indicates the type of paragraph", null: true
29
35
  field :position, GraphQL::Types::Int, "Position of this proposal in the participatory text", null: true
36
+ field :proposal_state, Decidim::Proposals::ProposalStateType, "The proposal state for this proposal", null: true
30
37
  field :published_at, Decidim::Core::DateTimeType, description: "The date and time this proposal was published", null: true
31
- field :reference, GraphQL::Types::String, "This proposal's unique reference", null: true
32
38
  field :state, GraphQL::Types::String, "The answer status in which proposal is in", null: true
33
- field :title, Decidim::Core::TranslatedFieldType, "The title for this title", null: true
39
+ field :title, Decidim::Core::TranslatedFieldType, "The title for this proposal", null: true
34
40
  field :vote_count, GraphQL::Types::Int, description: "The total amount of votes the proposal has received", null: true
35
41
  field :withdrawn, GraphQL::Types::Boolean, "Whether this proposal has been withdrawn or not", method: :withdrawn?, null: true
36
42
  field :withdrawn_at, Decidim::Core::DateTimeType, description: "The date and time this proposal was withdrawn", null: true
37
43
 
38
- def coordinates
39
- [object.latitude, object.longitude]
44
+ field :url, GraphQL::Types::String, "The URL for this proposal", null: false
45
+
46
+ def url
47
+ Decidim::ResourceLocatorPresenter.new(object).url
48
+ end
49
+
50
+ def answered_at
51
+ return unless object.published_state?
52
+
53
+ object.answered_at
54
+ end
55
+
56
+ def answer
57
+ return unless object.published_state?
58
+
59
+ object.answer
40
60
  end
41
61
 
42
62
  def meeting
43
63
  object.authors.first if object.official_meeting?
44
64
  end
45
65
 
66
+ def cost_report
67
+ return unless object.published_state?
68
+ return unless proposal_has_costs? && current_settings.answers_with_costs?
69
+
70
+ object.cost_report
71
+ end
72
+
73
+ def execution_period
74
+ return unless object.published_state?
75
+ return unless proposal_has_costs? && current_settings.answers_with_costs?
76
+
77
+ object.execution_period
78
+ end
79
+
80
+ def cost
81
+ return unless object.published_state?
82
+ return unless proposal_has_costs? && current_settings.answers_with_costs?
83
+
84
+ number_to_currency(object.cost, unit: Decidim.currency_unit)
85
+ end
86
+
46
87
  def vote_count
47
- current_component = object.component
48
- object.proposal_votes_count unless current_component.current_settings.votes_hidden?
88
+ object.proposal_votes_count unless current_settings.votes_hidden?
49
89
  end
50
90
 
51
91
  def self.authorized?(object, context)
@@ -60,6 +100,16 @@ module Decidim
60
100
  rescue Decidim::PermissionAction::PermissionNotSetError
61
101
  false
62
102
  end
103
+
104
+ private
105
+
106
+ def current_settings
107
+ object.component.current_settings
108
+ end
109
+
110
+ def proposal_has_costs?
111
+ object.cost.present?
112
+ end
63
113
  end
64
114
  end
65
115
  end
@@ -13,7 +13,7 @@ module Decidim
13
13
 
14
14
  routes do
15
15
  resources :proposals, only: [:show, :index, :new, :create, :edit, :update] do
16
- resources :valuation_assignments, only: [:destroy]
16
+ resources :evaluation_assignments, only: [:destroy]
17
17
  member do
18
18
  patch :soft_delete
19
19
  patch :restore
@@ -24,9 +24,9 @@ module Decidim
24
24
  post :update_multiple_answers, controller: "proposal_answers"
25
25
  get :manage_trash, controller: "proposals"
26
26
  resource :proposals_import, only: [:new, :create]
27
- resource :proposals_merge, only: [:create]
27
+ resource :proposals_merge, only: [:new, :create]
28
28
  resource :proposals_split, only: [:create]
29
- resource :valuation_assignment, only: [:create, :destroy]
29
+ resource :evaluation_assignment, only: [:create, :destroy]
30
30
  end
31
31
  resources :proposal_answers, only: [:edit, :update]
32
32
  resources :proposal_notes, only: [:create] do
@@ -10,7 +10,7 @@ module Decidim
10
10
  :state_eq,
11
11
  :with_any_state,
12
12
  :taxonomies_part_of_contains,
13
- :valuator_role_ids_has
13
+ :evaluator_role_ids_has
14
14
  )
15
15
 
16
16
  configuration.add_filters_with_values(
@@ -18,11 +18,11 @@ module Decidim
18
18
  state_eq: state_eq_values,
19
19
  with_any_state: %w(state_published state_not_published),
20
20
  taxonomies_part_of_contains: taxonomy_ids_hash(available_root_taxonomies),
21
- valuator_role_ids_has: valuator_role_ids
21
+ evaluator_role_ids_has: evaluator_role_ids
22
22
  )
23
23
 
24
24
  configuration.add_dynamically_translated_filters(
25
- :valuator_role_ids_has,
25
+ :evaluator_role_ids_has,
26
26
  :proposal_state_id_eq,
27
27
  :taxonomies_part_of_contains,
28
28
  :state_eq
@@ -6,5 +6,10 @@ module Decidim
6
6
  autoload :ProposalInputSort, "decidim/api/proposal_input_sort"
7
7
  autoload :ProposalType, "decidim/api/proposal_type"
8
8
  autoload :ProposalsType, "decidim/api/proposals_type"
9
+ autoload :ProposalStateType, "decidim/api/proposal_state_type"
10
+ autoload :ProposalsMutationType, "decidim/api/mutations/proposals_mutation_type"
11
+ autoload :ProposalMutationType, "decidim/api/mutations/proposal_mutation_type"
12
+ autoload :ProposalAnswerType, "decidim/api/mutations/proposal_answer_type"
13
+ autoload :AnswerProposalAttributes, "decidim/api/mutations/answer_proposal_attributes"
9
14
  end
10
15
  end
@@ -20,13 +20,13 @@ Decidim.register_component(:proposals) do |component|
20
20
 
21
21
  component.newsletter_participant_entities = ["Decidim::Proposals::Proposal"]
22
22
 
23
- component.actions = %w(endorse vote create withdraw amend comment vote_comment)
23
+ component.actions = %w(like vote create withdraw amend comment vote_comment)
24
24
 
25
25
  component.query_type = "Decidim::Proposals::ProposalsType"
26
26
 
27
27
  component.permissions_class_name = "Decidim::Proposals::Permissions"
28
28
 
29
- POSSIBLE_SORT_ORDERS = %w(automatic random recent most_endorsed most_voted most_commented most_followed with_more_authors).freeze
29
+ POSSIBLE_SORT_ORDERS = %w(automatic random recent most_liked most_voted most_commented most_followed with_more_authors).freeze
30
30
 
31
31
  component.settings(:global) do |settings|
32
32
  settings.attribute :taxonomy_filters, type: :taxonomy_filters
@@ -34,12 +34,12 @@ Decidim.register_component(:proposals) do |component|
34
34
  settings.attribute :minimum_votes_per_user, type: :integer, default: 0, required: true
35
35
  settings.attribute :proposal_limit, type: :integer, default: 0, required: true
36
36
  settings.attribute :proposal_length, type: :integer, default: 500
37
- settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: -> { %w(infinite limited) }
37
+ settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: ->(_context) { %w(infinite limited) }
38
38
  settings.attribute :edit_time, type: :integer_with_units, default: [5, "minutes"], required: true, units: %w(minutes hours days)
39
39
  settings.attribute :threshold_per_proposal, type: :integer, default: 0, required: true
40
40
  settings.attribute :can_accumulate_votes_beyond_threshold, type: :boolean, default: false
41
41
  settings.attribute :proposal_answering_enabled, type: :boolean, default: true
42
- settings.attribute :default_sort_order, type: :select, default: "automatic", choices: -> { POSSIBLE_SORT_ORDERS }
42
+ settings.attribute :default_sort_order, type: :select, default: "automatic", choices: ->(_context) { POSSIBLE_SORT_ORDERS }
43
43
  settings.attribute :official_proposals_enabled, type: :boolean, default: true
44
44
  settings.attribute :comments_enabled, type: :boolean, default: true
45
45
  settings.attribute :comments_max_length, type: :integer, required: true
@@ -63,8 +63,8 @@ Decidim.register_component(:proposals) do |component|
63
63
  end
64
64
 
65
65
  component.settings(:step) do |settings|
66
- settings.attribute :endorsements_enabled, type: :boolean, default: true
67
- settings.attribute :endorsements_blocked, type: :boolean
66
+ settings.attribute :likes_enabled, type: :boolean, default: true
67
+ settings.attribute :likes_blocked, type: :boolean
68
68
  settings.attribute :votes_enabled, type: :boolean
69
69
  settings.attribute :votes_blocked, type: :boolean
70
70
  settings.attribute :votes_hidden, type: :boolean, default: false
@@ -73,16 +73,14 @@ Decidim.register_component(:proposals) do |component|
73
73
  settings.attribute :proposal_answering_enabled, type: :boolean, default: true
74
74
  settings.attribute :publish_answers_immediately, type: :boolean, default: true
75
75
  settings.attribute :answers_with_costs, type: :boolean, default: false
76
- settings.attribute :default_sort_order, type: :select, include_blank: true, choices: -> { POSSIBLE_SORT_ORDERS }
76
+ settings.attribute :default_sort_order, type: :select, include_blank: true, choices: ->(_context) { POSSIBLE_SORT_ORDERS }
77
77
  settings.attribute :amendment_creation_enabled, type: :boolean, default: true
78
78
  settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
79
79
  settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
80
80
  settings.attribute :amendments_visibility,
81
81
  type: :enum, default: "all",
82
- choices: -> { Decidim.config.amendments_visibility_options }
82
+ choices: ->(_context) { Decidim.config.amendments_visibility_options }
83
83
  settings.attribute :announcement, type: :text, translated: true, editor: true
84
- settings.attribute :automatic_hashtags, type: :text, editor: false, required: false
85
- settings.attribute :suggested_hashtags, type: :text, editor: false, required: false
86
84
  end
87
85
 
88
86
  component.register_resource(:proposal) do |resource|
@@ -90,7 +88,7 @@ Decidim.register_component(:proposals) do |component|
90
88
  resource.template = "decidim/proposals/proposals/linked_proposals"
91
89
  resource.card = "decidim/proposals/proposal"
92
90
  resource.reported_content_cell = "decidim/proposals/reported_content"
93
- resource.actions = %w(endorse vote amend comment vote_comment)
91
+ resource.actions = %w(like vote amend comment vote_comment)
94
92
  resource.searchable = true
95
93
  end
96
94
 
@@ -100,30 +98,55 @@ Decidim.register_component(:proposals) do |component|
100
98
  resource.reported_content_cell = "decidim/proposals/collaborative_drafts/reported_content"
101
99
  end
102
100
 
103
- component.register_stat :proposals_count, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
101
+ component.register_stat :proposals_count,
102
+ primary: true,
103
+ admin: false,
104
+ priority: Decidim::StatsRegistry::HIGH_PRIORITY,
105
+ icon_name: "chat-new-line",
106
+ tooltip_key: "proposals_count_tooltip" do |components, start_at, end_at|
104
107
  Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_withdrawn.not_hidden.count
105
108
  end
106
109
 
107
- component.register_stat :proposals_accepted, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
110
+ component.register_stat :participatory_space_proposals_count,
111
+ priority: Decidim::StatsRegistry::MEDIUM_PRIORITY,
112
+ sub_title: "votes",
113
+ icon_name: "chat-new-line",
114
+ tooltip_key: "proposals_count_tooltip" do |components, start_at, end_at|
115
+ proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_withdrawn.not_hidden
116
+ [
117
+ proposals.count,
118
+ Decidim::Proposals::ProposalVote.where(proposal: proposals).count
119
+ ]
120
+ end
121
+
122
+ component.register_stat :proposals_accepted, primary: true, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
108
123
  Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).accepted.not_hidden.count
109
124
  end
110
125
 
111
- component.register_stat :votes_count, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
126
+ component.register_stat :votes_count, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
112
127
  proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
113
128
  Decidim::Proposals::ProposalVote.where(proposal: proposals).count
114
129
  end
115
130
 
116
- component.register_stat :endorsements_count, priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, start_at, end_at|
131
+ component.register_stat :likes_count, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
117
132
  proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).not_hidden
118
- proposals.sum(:endorsements_count)
133
+ proposals.sum(:likes_count)
119
134
  end
120
135
 
121
- component.register_stat :comments_count, tag: :comments do |components, start_at, end_at|
136
+ component.register_stat :comments_count,
137
+ priority: Decidim::StatsRegistry::HIGH_PRIORITY,
138
+ icon_name: "chat-1-line",
139
+ tooltip_key: "comments_count",
140
+ tag: :comments do |components, start_at, end_at|
122
141
  proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
123
142
  proposals.sum(:comments_count)
124
143
  end
125
144
 
126
- component.register_stat :followers_count, tag: :followers, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
145
+ component.register_stat :followers_count,
146
+ tag: :followers,
147
+ icon_name: "user-follow-line",
148
+ tooltip_key: "followers_count_tooltip",
149
+ priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, start_at, end_at|
127
150
  proposals_ids = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden.pluck(:id)
128
151
  Decidim::Follow.where(decidim_followable_type: "Decidim::Proposals::Proposal", decidim_followable_id: proposals_ids).count
129
152
  end
@@ -138,8 +161,8 @@ Decidim.register_component(:proposals) do |component|
138
161
  .where(component: component_instance)
139
162
  .includes(:taxonomies, :component)
140
163
 
141
- if space.user_roles(:valuator).where(user:).any?
142
- collection.with_valuation_assigned_to(user, space)
164
+ if space.user_roles(:evaluator).where(user:).any?
165
+ collection.with_evaluation_assigned_to(user, space)
143
166
  else
144
167
  collection
145
168
  end
@@ -154,7 +177,7 @@ Decidim.register_component(:proposals) do |component|
154
177
  exports.collection do |component_instance|
155
178
  Decidim::Comments::Export.comments_for_resource(
156
179
  Decidim::Proposals::Proposal, component_instance
157
- ).includes(:author, :user_group, root_commentable: { component: { participatory_space: :organization } })
180
+ ).includes(:author, root_commentable: { component: { participatory_space: :organization } })
158
181
  end
159
182
 
160
183
  exports.include_in_open_data = true
@@ -163,9 +186,6 @@ Decidim.register_component(:proposals) do |component|
163
186
  end
164
187
 
165
188
  component.imports :proposals do |imports|
166
- imports.form_view = "decidim/proposals/admin/imports/proposals_fields"
167
- imports.form_class_name = "Decidim::Proposals::Admin::ProposalsFileImportForm"
168
-
169
189
  imports.messages do |msg|
170
190
  msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.proposals", count:) }
171
191
  msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.proposals") }
@@ -103,7 +103,7 @@ module Decidim
103
103
 
104
104
  initializer "decidim_proposals.remove_space_admins" do
105
105
  ActiveSupport::Notifications.subscribe("decidim.admin.participatory_space.destroy_admin:after") do |_event_name, data|
106
- Decidim::Proposals::ValuationAssignment.where(valuator_role_type: data.fetch(:class_name), valuator_role_id: data.fetch(:role)).destroy_all
106
+ Decidim::Proposals::EvaluationAssignment.where(evaluator_role_type: data.fetch(:class_name), evaluator_role_id: data.fetch(:role)).destroy_all
107
107
  end
108
108
  end
109
109
 
@@ -111,44 +111,26 @@ module Decidim
111
111
  Decidim::Gamification.register_badge(:proposals) do |badge|
112
112
  badge.levels = [1, 5, 10, 30, 60]
113
113
 
114
- badge.valid_for = [:user, :user_group]
114
+ badge.valid_for = [:user]
115
115
 
116
116
  badge.reset = lambda { |model|
117
- case model
118
- when User
119
- Decidim::Coauthorship.where(
120
- coauthorable_type: "Decidim::Proposals::Proposal",
121
- author: model,
122
- user_group: nil
123
- ).count
124
- when UserGroup
125
- Decidim::Coauthorship.where(
126
- coauthorable_type: "Decidim::Proposals::Proposal",
127
- user_group: model
128
- ).count
129
- end
117
+ Decidim::Coauthorship.where(
118
+ coauthorable_type: "Decidim::Proposals::Proposal",
119
+ author: model
120
+ ).count
130
121
  }
131
122
  end
132
123
 
133
124
  Decidim::Gamification.register_badge(:accepted_proposals) do |badge|
134
125
  badge.levels = [1, 5, 15, 30, 50]
135
126
 
136
- badge.valid_for = [:user, :user_group]
127
+ badge.valid_for = [:user]
137
128
 
138
129
  badge.reset = lambda { |model|
139
- proposal_ids = case model
140
- when User
141
- Decidim::Coauthorship.where(
142
- coauthorable_type: "Decidim::Proposals::Proposal",
143
- author: model,
144
- user_group: nil
145
- ).select(:coauthorable_id)
146
- when UserGroup
147
- Decidim::Coauthorship.where(
148
- coauthorable_type: "Decidim::Proposals::Proposal",
149
- user_group: model
150
- ).select(:coauthorable_id)
151
- end
130
+ proposal_ids = Decidim::Coauthorship.where(
131
+ coauthorable_type: "Decidim::Proposals::Proposal",
132
+ author: model
133
+ ).select(:coauthorable_id)
152
134
 
153
135
  Decidim::Proposals::Proposal.where(id: proposal_ids).accepted.count
154
136
  }
@@ -163,60 +145,7 @@ module Decidim
163
145
  end
164
146
  end
165
147
 
166
- initializer "decidim_proposals.register_metrics" do
167
- Decidim.metrics_registry.register(:proposals) do |metric_registry|
168
- metric_registry.manager_class = "Decidim::Proposals::Metrics::ProposalsMetricManage"
169
-
170
- metric_registry.settings do |settings|
171
- settings.attribute :highlighted, type: :boolean, default: true
172
- settings.attribute :scopes, type: :array, default: %w(home participatory_process)
173
- settings.attribute :weight, type: :integer, default: 2
174
- settings.attribute :stat_block, type: :string, default: "medium"
175
- end
176
- end
177
-
178
- Decidim.metrics_registry.register(:accepted_proposals) do |metric_registry|
179
- metric_registry.manager_class = "Decidim::Proposals::Metrics::AcceptedProposalsMetricManage"
180
-
181
- metric_registry.settings do |settings|
182
- settings.attribute :highlighted, type: :boolean, default: false
183
- settings.attribute :scopes, type: :array, default: %w(home participatory_process)
184
- settings.attribute :weight, type: :integer, default: 3
185
- settings.attribute :stat_block, type: :string, default: "small"
186
- end
187
- end
188
-
189
- Decidim.metrics_registry.register(:votes) do |metric_registry|
190
- metric_registry.manager_class = "Decidim::Proposals::Metrics::VotesMetricManage"
191
-
192
- metric_registry.settings do |settings|
193
- settings.attribute :highlighted, type: :boolean, default: true
194
- settings.attribute :scopes, type: :array, default: %w(home participatory_process)
195
- settings.attribute :weight, type: :integer, default: 3
196
- settings.attribute :stat_block, type: :string, default: "medium"
197
- end
198
- end
199
-
200
- Decidim.metrics_registry.register(:endorsements) do |metric_registry|
201
- metric_registry.manager_class = "Decidim::Proposals::Metrics::EndorsementsMetricManage"
202
-
203
- metric_registry.settings do |settings|
204
- settings.attribute :highlighted, type: :boolean, default: false
205
- settings.attribute :scopes, type: :array, default: %w(participatory_process)
206
- settings.attribute :weight, type: :integer, default: 4
207
- settings.attribute :stat_block, type: :string, default: "medium"
208
- end
209
- end
210
-
211
- Decidim.metrics_operation.register(:participants, :proposals) do |metric_operation|
212
- metric_operation.manager_class = "Decidim::Proposals::Metrics::ProposalParticipantsMetricMeasure"
213
- end
214
- Decidim.metrics_operation.register(:followers, :proposals) do |metric_operation|
215
- metric_operation.manager_class = "Decidim::Proposals::Metrics::ProposalFollowersMetricMeasure"
216
- end
217
- end
218
-
219
- initializer "decidim_proposals.webpacker.assets_path" do
148
+ initializer "decidim_proposals.shakapacker.assets_path" do
220
149
  Decidim.register_assets_path File.expand_path("app/packs", root)
221
150
  end
222
151
 
@@ -235,6 +164,12 @@ module Decidim
235
164
  end
236
165
  end
237
166
  end
167
+
168
+ initializer "decidim_proposals.register_mutations", before: "decidim_api.graphiql" do
169
+ Decidim::MutationRegistry.instance.register(
170
+ Decidim::Proposals::ProposalsMutationType
171
+ )
172
+ end
238
173
  end
239
174
  end
240
175
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ # A set of methods and features related to proposal evaluations.
6
+ module Evaluable
7
+ extend ActiveSupport::Concern
8
+ include Decidim::Comments::Commentable
9
+
10
+ included do
11
+ has_many :evaluation_assignments, foreign_key: "decidim_proposal_id", dependent: :destroy,
12
+ counter_cache: :evaluation_assignments_count, class_name: "Decidim::Proposals::EvaluationAssignment"
13
+
14
+ def evaluators
15
+ evaluator_role_ids = evaluation_assignments.where(proposal: self).pluck(:evaluator_role_id)
16
+ user_ids = participatory_space.user_roles(:evaluator).where(id: evaluator_role_ids).pluck(:decidim_user_id)
17
+ participatory_space.organization.users.where(id: user_ids)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -26,7 +26,7 @@ module Decidim
26
26
  #
27
27
  # Returns a proposal
28
28
  def produce
29
- resource.add_coauthor(context[:current_user], user_group: context[:user_group])
29
+ resource.add_coauthor(context[:current_user])
30
30
 
31
31
  resource
32
32
  end
@@ -40,9 +40,9 @@ module Decidim
40
40
  answered_at: proposal.answered_at,
41
41
  votes: (proposal.proposal_votes_count unless
42
42
  proposal.component.current_settings.votes_hidden?),
43
- endorsements: {
44
- total_count: proposal.endorsements.size,
45
- user_endorsements:
43
+ likes: {
44
+ total_count: proposal.likes.size,
45
+ user_likes:
46
46
  },
47
47
  comments: proposal.comments_count,
48
48
  attachments: proposal.attachments.size,
@@ -89,8 +89,8 @@ module Decidim
89
89
  Decidim::ResourceLocatorPresenter.new(proposal).url
90
90
  end
91
91
 
92
- def user_endorsements
93
- proposal.endorsements.for_listing.map { |identity| identity.normalized_author&.name }
92
+ def user_likes
93
+ proposal.likes.for_listing.map { |identity| identity.author&.name }
94
94
  end
95
95
 
96
96
  def original_proposal_url
@@ -107,22 +107,20 @@ module Decidim
107
107
  end
108
108
 
109
109
  def author_fields
110
- is_author_user_group = resource.coauthorships.map(&:decidim_user_group_id).any?
111
-
112
110
  {
113
111
  id: resource.authors.map(&:id),
114
112
  name: resource.authors.map do |author|
115
- author_name(is_author_user_group ? resource.coauthorships.first.user_group : author)
113
+ author_name(author)
116
114
  end,
117
115
  url: resource.authors.map do |author|
118
- author_url(is_author_user_group ? resource.coauthorships.first.user_group : author)
116
+ author_url(author)
119
117
  end
120
118
  }
121
119
  end
122
120
 
123
121
  def author_name(author)
124
122
  if author.respond_to?(:name)
125
- translated_attribute(author.name) # is a Decidim::User or Decidim::Organization or Decidim::UserGroup
123
+ translated_attribute(author.name) # is a Decidim::User or Decidim::Organization
126
124
  elsif author.respond_to?(:title)
127
125
  translated_attribute(author.title) # is a Decidim::Meetings::Meeting
128
126
  end
@@ -130,7 +128,7 @@ module Decidim
130
128
 
131
129
  def author_url(author)
132
130
  if author.respond_to?(:nickname)
133
- profile_url(author) # is a Decidim::User or Decidim::UserGroup
131
+ profile_url(author) # is a Decidim::User
134
132
  elsif author.respond_to?(:title)
135
133
  meeting_url(author) # is a Decidim::Meetings::Meeting
136
134
  else
@@ -17,7 +17,9 @@ module Decidim
17
17
 
18
18
  Decidim::Proposals.create_default_states!(component, admin_user)
19
19
 
20
- 5.times do |n|
20
+ number_of_records = slow_seeds? ? 10 : rand(25..50)
21
+
22
+ (5..number_of_records).to_a.sample.times do |n|
21
23
  proposal = create_proposal!(component:)
22
24
 
23
25
  if proposal.state.nil? && component.settings.amendments_enabled?
@@ -50,7 +52,12 @@ module Decidim
50
52
 
51
53
  def create_component!
52
54
  step_settings = if participatory_space.allows_steps?
53
- { participatory_space.active_step.id => { votes_enabled: true, votes_blocked: false, creation_enabled: true } }
55
+ { participatory_space.active_step.id => {
56
+ votes_enabled: true,
57
+ votes_blocked: [false, true].sample,
58
+ votes_hidden: [false, true].sample,
59
+ creation_enabled: true
60
+ } }
54
61
  else
55
62
  {}
56
63
  end
@@ -61,7 +68,10 @@ module Decidim
61
68
  published_at: Time.current,
62
69
  participatory_space:,
63
70
  settings: {
64
- vote_limit: 0,
71
+ minimum_votes_per_user: (0..2).to_a.sample,
72
+ vote_limit: (0..5).to_a.sample,
73
+ threshold_per_proposal: [0, (10..100).to_a.sample].sample,
74
+ can_accumulate_votes_beyond_threshold: [true, false].sample,
65
75
  attachments_allowed: [true, false].sample,
66
76
  amendments_enabled: participatory_space.id.odd?,
67
77
  collaborative_drafts_enabled: true,
@@ -146,15 +156,13 @@ module Decidim
146
156
  end
147
157
 
148
158
  def random_coauthor
149
- n = rand(5)
150
- n = 3 if n == 2 && !Decidim.module_installed?(:meetings)
159
+ n = rand(4)
160
+ n = 2 if n == 1 && !Decidim.module_installed?(:meetings)
151
161
 
152
162
  case n
153
163
  when 0
154
164
  Decidim::User.where(organization:).sample
155
165
  when 1
156
- Decidim::UserGroup.where(organization:).sample
157
- when 2
158
166
  meeting_component = participatory_space.components.find_by(manifest_name: "meetings")
159
167
 
160
168
  Decidim::Meetings::Meeting.where(component: meeting_component).sample
@@ -176,25 +184,6 @@ module Decidim
176
184
  def create_emendation!(proposal:)
177
185
  author = find_or_initialize_user_by(email: random_email(suffix: "amendment"))
178
186
 
179
- group = Decidim::UserGroup.create!(
180
- name: ::Faker::Name.name,
181
- nickname: random_nickname,
182
- email: ::Faker::Internet.email,
183
- extended_data: {
184
- document_number: ::Faker::Code.isbn,
185
- phone: ::Faker::PhoneNumber.phone_number,
186
- verified_at: Time.current
187
- },
188
- organization:,
189
- confirmed_at: Time.current
190
- )
191
-
192
- Decidim::UserGroupMembership.create!(
193
- user: author,
194
- role: "creator",
195
- user_group: group
196
- )
197
-
198
187
  params = {
199
188
  component: proposal.component,
200
189
  title: Decidim::Faker::Localized.literal(proposal.title[I18n.locale]),
@@ -212,7 +201,7 @@ module Decidim
212
201
  visibility: "public-only"
213
202
  ) do
214
203
  emendation = Decidim::Proposals::Proposal.new(params)
215
- emendation.add_coauthor(author, user_group: author.user_groups.first)
204
+ emendation.add_coauthor(author)
216
205
  emendation.save!
217
206
  emendation
218
207
  end