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.
- checksums.yaml +4 -4
- data/app/cells/decidim/proposals/collaborative_draft_metadata_cell.rb +1 -1
- data/app/cells/decidim/proposals/proposal_g_cell.rb +4 -4
- data/app/cells/decidim/proposals/proposal_l_cell.rb +4 -4
- data/app/cells/decidim/proposals/proposal_metadata_cell.rb +2 -2
- data/app/commands/decidim/proposals/admin/{assign_proposals_to_valuator.rb → assign_proposals_to_evaluator.rb} +16 -16
- data/app/commands/decidim/proposals/admin/create_proposal.rb +1 -2
- data/app/commands/decidim/proposals/admin/create_proposal_note.rb +4 -4
- data/app/commands/decidim/proposals/admin/merge_proposals.rb +60 -13
- data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +2 -2
- data/app/commands/decidim/proposals/admin/proposal_notes_methods.rb +5 -5
- data/app/commands/decidim/proposals/admin/reply_proposal_note.rb +1 -1
- data/app/commands/decidim/proposals/admin/{unassign_proposals_from_valuator.rb → unassign_proposals_from_evaluator.rb} +7 -7
- data/app/commands/decidim/proposals/admin/update_proposal.rb +1 -2
- data/app/commands/decidim/proposals/create_collaborative_draft.rb +3 -8
- data/app/commands/decidim/proposals/create_proposal.rb +4 -17
- data/app/commands/decidim/proposals/publish_collaborative_draft.rb +2 -2
- data/app/commands/decidim/proposals/publish_proposal.rb +1 -5
- data/app/commands/decidim/proposals/update_collaborative_draft.rb +2 -4
- data/app/commands/decidim/proposals/update_proposal.rb +5 -18
- data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +6 -6
- data/app/controllers/concerns/decidim/proposals/orderable.rb +3 -3
- data/app/controllers/decidim/proposals/admin/evaluation_assignments_controller.rb +55 -0
- data/app/controllers/decidim/proposals/admin/participatory_texts_controller.rb +6 -6
- data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +1 -1
- data/app/controllers/decidim/proposals/admin/proposal_states_controller.rb +2 -2
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +2 -2
- data/app/controllers/decidim/proposals/admin/proposals_imports_controller.rb +1 -1
- data/app/controllers/decidim/proposals/admin/proposals_merges_controller.rb +12 -3
- data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +2 -3
- data/app/controllers/decidim/proposals/proposals_controller.rb +5 -6
- data/app/events/decidim/proposals/admin/{proposal_assigned_to_valuator_event.rb → proposal_assigned_to_evaluator_event.rb} +1 -1
- data/app/events/decidim/proposals/{endorsing_enabled_event.rb → liking_enabled_event.rb} +1 -1
- data/app/events/decidim/proposals/merged_proposal_event.rb +9 -0
- data/app/events/decidim/proposals/proposal_liked_event.rb +33 -0
- data/app/forms/decidim/proposals/admin/evaluation_assignment_form.rb +38 -0
- data/app/forms/decidim/proposals/admin/proposal_base_form.rb +1 -27
- data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -1
- data/app/forms/decidim/proposals/admin/proposals_merge_form.rb +58 -2
- data/app/forms/decidim/proposals/collaborative_draft_form.rb +1 -5
- data/app/forms/decidim/proposals/proposal_form.rb +0 -29
- data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +8 -8
- data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +6 -6
- data/app/helpers/decidim/proposals/admin/proposals_helper.rb +2 -17
- data/app/helpers/decidim/proposals/application_helper.rb +3 -6
- data/app/jobs/decidim/proposals/settings_change_job.rb +6 -6
- data/app/models/decidim/proposals/collaborative_draft.rb +1 -1
- data/app/models/decidim/proposals/{valuation_assignment.rb → evaluation_assignment.rb} +7 -7
- data/app/models/decidim/proposals/proposal.rb +22 -32
- data/app/packs/entrypoints/decidim_proposals_admin.js +1 -0
- data/app/packs/src/decidim/proposals/add_proposal.js +1 -1
- data/app/packs/src/decidim/proposals/admin/proposals.js +22 -11
- data/app/packs/src/decidim/proposals/admin/proposals_form.js +1 -1
- data/app/packs/src/decidim/proposals/admin/proposals_merge.js +92 -0
- data/app/packs/src/decidim/proposals/choose_proposals.js +1 -1
- data/app/packs/src/decidim/proposals/exit_handler.js +1 -1
- data/app/packs/src/decidim/proposals/utils.js +1 -1
- data/app/packs/stylesheets/decidim/proposals/proposals.scss +29 -1
- data/app/permissions/decidim/proposals/admin/permissions.rb +20 -20
- data/app/presenters/decidim/proposals/admin_log/{valuation_assignment_presenter.rb → evaluation_assignment_presenter.rb} +7 -7
- data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +15 -0
- data/app/presenters/decidim/proposals/admin_log/value_types/{valuator_role_user_presenter.rb → evaluator_role_user_presenter.rb} +2 -2
- data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +1 -1
- data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +1 -6
- data/app/presenters/decidim/proposals/log/{valuation_assignment_presenter.rb → evaluation_assignment_presenter.rb} +1 -1
- data/app/presenters/decidim/proposals/proposal_presenter.rb +9 -13
- data/app/services/decidim/proposals/diff_renderer.rb +0 -1
- data/app/services/decidim/proposals/proposal_builder.rb +5 -10
- data/app/views/decidim/proposals/admin/participatory_texts/_article-preview.html.erb +1 -1
- data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +1 -2
- data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposal_states/index.html.erb +42 -12
- data/app/views/decidim/proposals/admin/proposals/_actions.html.erb +87 -21
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +9 -13
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +2 -24
- data/app/views/decidim/proposals/admin/proposals/_likes.html.erb +25 -0
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +13 -12
- data/app/views/decidim/proposals/admin/proposals/_proposals-thead.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_evaluator.html.erb +19 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +45 -49
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/{_valuators_picker.html.erb → _evaluators_picker.html.erb} +4 -4
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +7 -14
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_evaluator.html.erb +19 -0
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +9 -5
- data/app/views/decidim/proposals/admin/proposals/manage_trash.html.erb +2 -1
- data/app/views/decidim/proposals/admin/proposals/show.html.erb +17 -17
- data/app/views/decidim/proposals/admin/proposals_merges/_form.html.erb +49 -0
- data/app/views/decidim/proposals/admin/proposals_merges/new.html.erb +14 -0
- data/app/views/decidim/proposals/collaborative_drafts/_collaborative_actions.html.erb +2 -2
- data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +1 -21
- data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_actions.html.erb +2 -2
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +1 -21
- data/app/views/decidim/proposals/proposals/_proposal_actions.html.erb +4 -4
- data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +2 -2
- data/app/views/decidim/proposals/proposals/_proposal_voting_rules.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/participatory_texts/_view_index.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/preview.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/show.html.erb +2 -2
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +0 -65
- data/config/locales/bg.yml +0 -71
- data/config/locales/bs-BA.yml +0 -25
- data/config/locales/ca-IT.yml +64 -72
- data/config/locales/ca.yml +64 -72
- data/config/locales/cs.yml +52 -81
- data/config/locales/de.yml +66 -73
- data/config/locales/el.yml +0 -66
- data/config/locales/en.yml +69 -77
- data/config/locales/es-MX.yml +68 -76
- data/config/locales/es-PY.yml +68 -76
- data/config/locales/es.yml +68 -76
- data/config/locales/eu.yml +66 -74
- data/config/locales/fi-plain.yml +67 -75
- data/config/locales/fi.yml +67 -75
- data/config/locales/fr-CA.yml +49 -74
- data/config/locales/fr.yml +49 -74
- data/config/locales/ga-IE.yml +0 -22
- data/config/locales/gl.yml +0 -47
- data/config/locales/hu.yml +0 -64
- data/config/locales/id-ID.yml +0 -34
- data/config/locales/is-IS.yml +0 -14
- data/config/locales/it.yml +0 -58
- data/config/locales/ja.yml +68 -76
- data/config/locales/lb.yml +0 -3
- data/config/locales/lt.yml +0 -68
- data/config/locales/lv.yml +0 -62
- data/config/locales/nl.yml +0 -63
- data/config/locales/no.yml +0 -42
- data/config/locales/pl.yml +0 -73
- data/config/locales/pt-BR.yml +0 -59
- data/config/locales/pt.yml +0 -60
- data/config/locales/ro-RO.yml +45 -64
- data/config/locales/ru.yml +0 -15
- data/config/locales/sk.yml +0 -60
- data/config/locales/sr-CS.yml +0 -25
- data/config/locales/sv.yml +58 -76
- data/config/locales/tr-TR.yml +0 -58
- data/config/locales/uk.yml +0 -15
- data/config/locales/zh-CN.yml +0 -57
- data/config/locales/zh-TW.yml +0 -65
- data/db/migrate/20240110203500_add_withdrawn_at_field_to_proposals.rb +1 -1
- data/db/migrate/20240110203504_create_default_proposal_states.rb +1 -1
- data/db/migrate/20250121110014_rename_proposal_valuation_assignments_to_evaluation_assignments.rb +15 -0
- data/db/migrate/20250121110904_rename_valuation_assignments_count_to_evaluation_assignments_count.rb +16 -0
- data/db/migrate/20250211141313_rename_valuator_columns.rb +8 -0
- data/db/migrate/20250515132351_rename_proposals_endorsements_count_to_likes.rb +7 -0
- data/decidim-proposals.gemspec +1 -1
- data/lib/decidim/api/mutations/answer_proposal_attributes.rb +17 -0
- data/lib/decidim/api/mutations/proposal_answer_type.rb +57 -0
- data/lib/decidim/api/mutations/proposal_mutation_type.rb +14 -0
- data/lib/decidim/api/mutations/proposals_mutation_type.rb +23 -0
- data/lib/decidim/api/proposal_input_sort.rb +1 -1
- data/lib/decidim/api/proposal_state_type.rb +16 -0
- data/lib/decidim/api/proposal_type.rb +59 -9
- data/lib/decidim/proposals/admin_engine.rb +3 -3
- data/lib/decidim/proposals/admin_filter.rb +3 -3
- data/lib/decidim/proposals/api.rb +5 -0
- data/lib/decidim/proposals/component.rb +44 -24
- data/lib/decidim/proposals/engine.rb +18 -83
- data/lib/decidim/proposals/evaluable.rb +22 -0
- data/lib/decidim/proposals/import/proposal_creator.rb +1 -1
- data/lib/decidim/proposals/proposal_serializer.rb +9 -11
- data/lib/decidim/proposals/seeds.rb +16 -27
- data/lib/decidim/proposals/test/factories.rb +21 -53
- data/lib/decidim/proposals/version.rb +1 -1
- data/lib/decidim/proposals.rb +3 -3
- data/lib/tasks/proposals/upgrade/decidim_proposals_upgrade_tasks.rake +11 -11
- metadata +57 -47
- data/app/commands/decidim/proposals/hashtags_methods.rb +0 -36
- data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +0 -55
- data/app/events/decidim/proposals/proposal_endorsed_event.rb +0 -33
- data/app/forms/decidim/proposals/admin/proposals_file_import_form.rb +0 -31
- data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +0 -38
- data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +0 -32
- data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +0 -58
- data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +0 -58
- data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +0 -74
- data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +0 -48
- data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +0 -52
- data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +0 -11
- data/app/views/decidim/proposals/admin/proposals/_endorsers.html.erb +0 -25
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +0 -19
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +0 -19
- data/lib/decidim/proposals/valuatable.rb +0 -22
@@ -36,8 +36,8 @@ module Decidim
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
proposal.
|
39
|
+
def likes_presenters_for(proposal)
|
40
|
+
proposal.likes.for_listing.map { |identity| present(identity.author) }
|
41
41
|
end
|
42
42
|
|
43
43
|
def proposal_complete_state(proposal)
|
@@ -46,21 +46,6 @@ module Decidim
|
|
46
46
|
|
47
47
|
translated_attribute(proposal&.proposal_state&.title)
|
48
48
|
end
|
49
|
-
|
50
|
-
def icon_with_link_to_proposal(proposal)
|
51
|
-
icon, tooltip = if allowed_to?(:create, :proposal_answer, proposal:) && !proposal.emendation?
|
52
|
-
[
|
53
|
-
"question-answer-line",
|
54
|
-
t(:answer_proposal, scope: "decidim.proposals.actions")
|
55
|
-
]
|
56
|
-
else
|
57
|
-
[
|
58
|
-
"information-line",
|
59
|
-
t(:show, scope: "decidim.proposals.actions")
|
60
|
-
]
|
61
|
-
end
|
62
|
-
icon_link_to(icon, proposal_path(proposal), tooltip, class: "icon--small action-icon--show-proposal")
|
63
|
-
end
|
64
49
|
end
|
65
50
|
end
|
66
51
|
end
|
@@ -8,7 +8,7 @@ module Decidim
|
|
8
8
|
include Decidim::Comments::CommentsHelper
|
9
9
|
include PaginateHelper
|
10
10
|
include ProposalVotesHelper
|
11
|
-
include ::Decidim::
|
11
|
+
include ::Decidim::LikeableHelper
|
12
12
|
include ::Decidim::FollowableHelper
|
13
13
|
include Decidim::MapHelper
|
14
14
|
include Decidim::Proposals::MapHelper
|
@@ -118,9 +118,8 @@ module Decidim
|
|
118
118
|
# Returns :text_area or :editor based on the organization' settings.
|
119
119
|
def text_editor_for_proposal_body(form)
|
120
120
|
options = {
|
121
|
-
|
122
|
-
|
123
|
-
value: form_presenter.body(extras: false, strip_tags: !current_organization.rich_text_editor_in_public_views).strip
|
121
|
+
value: form_presenter.body(strip_tags: !current_organization.rich_text_editor_in_public_views).strip,
|
122
|
+
data: { controller: "character-counter" }
|
124
123
|
}
|
125
124
|
|
126
125
|
text_editor_for(form, :body, options)
|
@@ -171,7 +170,6 @@ module Decidim
|
|
171
170
|
# Explicitly commenting the used I18n keys so their are not flagged as unused
|
172
171
|
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.official')
|
173
172
|
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.participants')
|
174
|
-
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.user_groups')
|
175
173
|
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.official')
|
176
174
|
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.meetings')
|
177
175
|
# i18n-tasks-use t('decidim.proposals.application_helper.filter_origin_values.all')
|
@@ -180,7 +178,6 @@ module Decidim
|
|
180
178
|
origin_values = []
|
181
179
|
origin_values << TreePoint.new("official", t("official", scope:)) if component_settings.official_proposals_enabled
|
182
180
|
origin_values << TreePoint.new("participants", t("participants", scope:))
|
183
|
-
origin_values << TreePoint.new("user_group", t("user_groups", scope:)) if current_organization.user_groups_enabled?
|
184
181
|
origin_values << TreePoint.new("meeting", t("meetings", scope:))
|
185
182
|
|
186
183
|
TreeNode.new(
|
@@ -12,9 +12,9 @@ module Decidim
|
|
12
12
|
elsif voting_enabled?(previous_settings, current_settings)
|
13
13
|
event = "decidim.events.proposals.voting_enabled"
|
14
14
|
event_class = Decidim::Proposals::VotingEnabledEvent
|
15
|
-
elsif
|
16
|
-
event = "decidim.events.proposals.
|
17
|
-
event_class = Decidim::Proposals::
|
15
|
+
elsif liking_enabled?(previous_settings, current_settings)
|
16
|
+
event = "decidim.events.proposals.liking_enabled"
|
17
|
+
event_class = Decidim::Proposals::LikingEnabledEvent
|
18
18
|
end
|
19
19
|
|
20
20
|
return unless event && event_class
|
@@ -40,9 +40,9 @@ module Decidim
|
|
40
40
|
(!!previous_settings[:votes_enabled] == false || previous_settings[:votes_blocked] == true)
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
(current_settings[:
|
45
|
-
(!!previous_settings[:
|
43
|
+
def liking_enabled?(previous_settings, current_settings)
|
44
|
+
(current_settings[:likes_enabled] == true && !!current_settings[:likes_blocked] == false) &&
|
45
|
+
(!!previous_settings[:likes_enabled] == false || previous_settings[:likes_blocked] == true)
|
46
46
|
end
|
47
47
|
# rubocop:enable Style/DoubleNegation
|
48
48
|
end
|
@@ -34,7 +34,7 @@ module Decidim
|
|
34
34
|
|
35
35
|
STATES = { open: 0, published: 10, withdrawn: -1 }.freeze
|
36
36
|
|
37
|
-
enum state
|
37
|
+
enum :state, STATES, default: "open"
|
38
38
|
scope :except_withdrawn, -> { not_withdrawn.or(where(state: nil)) }
|
39
39
|
|
40
40
|
scope_search_multi :with_any_state, [:open, :published, :withdrawn]
|
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
module Decidim
|
4
4
|
module Proposals
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# An evaluation assignment links a proposal and an Evaluator user role.
|
6
|
+
# Evaluators will be users in charge of defining the monetary cost of a
|
7
7
|
# proposal.
|
8
|
-
class
|
8
|
+
class EvaluationAssignment < ApplicationRecord
|
9
9
|
include Decidim::Traceable
|
10
10
|
include Decidim::Loggable
|
11
11
|
|
12
12
|
belongs_to :proposal, foreign_key: "decidim_proposal_id", class_name: "Decidim::Proposals::Proposal",
|
13
13
|
counter_cache: true
|
14
|
-
belongs_to :
|
14
|
+
belongs_to :evaluator_role, polymorphic: true
|
15
15
|
|
16
16
|
def self.log_presenter_class_for(_log)
|
17
|
-
Decidim::Proposals::AdminLog::
|
17
|
+
Decidim::Proposals::AdminLog::EvaluationAssignmentPresenter
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def evaluator
|
21
|
+
evaluator_role.user
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -24,12 +24,13 @@ module Decidim
|
|
24
24
|
include Decidim::Amendable
|
25
25
|
include Decidim::NewsletterParticipant
|
26
26
|
include Decidim::Randomable
|
27
|
-
include Decidim::
|
28
|
-
include Decidim::Proposals::
|
27
|
+
include Decidim::Likeable
|
28
|
+
include Decidim::Proposals::Evaluable
|
29
29
|
include Decidim::TranslatableResource
|
30
30
|
include Decidim::TranslatableAttributes
|
31
31
|
include Decidim::FilterableResource
|
32
32
|
include Decidim::SoftDeletable
|
33
|
+
include Decidim::Publicable
|
33
34
|
|
34
35
|
def assign_state(token)
|
35
36
|
proposal_state = Decidim::Proposals::ProposalState.where(component:, token:).first
|
@@ -94,7 +95,6 @@ module Decidim
|
|
94
95
|
scope :not_withdrawn, -> { where(withdrawn_at: nil) }
|
95
96
|
|
96
97
|
scope :drafts, -> { where(published_at: nil) }
|
97
|
-
scope :published, -> { where.not(published_at: nil) }
|
98
98
|
scope :order_by_most_recent, -> { order(created_at: :desc) }
|
99
99
|
|
100
100
|
scope :with_availability, lambda { |state_key|
|
@@ -121,12 +121,12 @@ module Decidim
|
|
121
121
|
includes(:votes).where(decidim_proposals_proposal_votes: { decidim_author_id: user })
|
122
122
|
}
|
123
123
|
|
124
|
-
scope :
|
125
|
-
order(
|
124
|
+
scope :sort_by_evaluation_assignments_count_asc, lambda {
|
125
|
+
order(evaluation_assignments_count: :asc)
|
126
126
|
}
|
127
127
|
|
128
|
-
scope :
|
129
|
-
order(
|
128
|
+
scope :sort_by_evaluation_assignments_count_desc, lambda {
|
129
|
+
order(evaluation_assignments_count: :desc)
|
130
130
|
}
|
131
131
|
|
132
132
|
scope :state_eq, lambda { |state|
|
@@ -158,11 +158,11 @@ module Decidim
|
|
158
158
|
scoped_query
|
159
159
|
}
|
160
160
|
|
161
|
-
def self.
|
162
|
-
|
161
|
+
def self.with_evaluation_assigned_to(user, space)
|
162
|
+
evaluator_roles = space.user_roles(:evaluator).where(user:)
|
163
163
|
|
164
|
-
includes(:
|
165
|
-
.where(
|
164
|
+
includes(:evaluation_assignments)
|
165
|
+
.where(decidim_proposals_evaluation_assignments: { evaluator_role_id: evaluator_roles })
|
166
166
|
end
|
167
167
|
|
168
168
|
acts_as_list scope: :decidim_component_id
|
@@ -193,7 +193,7 @@ module Decidim
|
|
193
193
|
|
194
194
|
def self.retrieve_proposals_for(component)
|
195
195
|
Decidim::Proposals::Proposal.where(component:).joins(:coauthorships)
|
196
|
-
.includes(:votes, :
|
196
|
+
.includes(:votes, :likes)
|
197
197
|
.where(decidim_coauthorships: { decidim_author_type: "Decidim::UserBaseEntity" })
|
198
198
|
.not_hidden
|
199
199
|
.published
|
@@ -207,13 +207,13 @@ module Decidim
|
|
207
207
|
|
208
208
|
participants_has_voted_ids = Decidim::Proposals::ProposalVote.joins(:proposal).where(proposal: proposals).joins(:author).map(&:decidim_author_id).flatten.compact.uniq
|
209
209
|
|
210
|
-
|
211
|
-
|
212
|
-
|
210
|
+
likes_participants_ids = Decidim::Like.where(resource: proposals)
|
211
|
+
.where(decidim_author_type: "Decidim::UserBaseEntity")
|
212
|
+
.pluck(:decidim_author_id).to_a.compact.uniq
|
213
213
|
|
214
214
|
commentators_ids = Decidim::Comments::Comment.user_commentators_ids_in(proposals)
|
215
215
|
|
216
|
-
(
|
216
|
+
(likes_participants_ids + participants_has_voted_ids + coauthors_recipients_ids + commentators_ids).flatten.compact.uniq
|
217
217
|
end
|
218
218
|
|
219
219
|
# Public: Updates the vote count of this proposal.
|
@@ -232,13 +232,6 @@ module Decidim
|
|
232
232
|
ProposalVote.where(proposal: self, author: user).any?
|
233
233
|
end
|
234
234
|
|
235
|
-
# Public: Checks if the proposal has been published or not.
|
236
|
-
#
|
237
|
-
# Returns Boolean.
|
238
|
-
def published?
|
239
|
-
published_at.present?
|
240
|
-
end
|
241
|
-
|
242
235
|
# Public: Returns the published state of the proposal.
|
243
236
|
#
|
244
237
|
# Returns Boolean.
|
@@ -249,9 +242,6 @@ module Decidim
|
|
249
242
|
proposal_state&.token || "not_answered"
|
250
243
|
end
|
251
244
|
|
252
|
-
# This is only used to define the setter, as the getter will be overridden below.
|
253
|
-
alias_attribute :internal_state, :state
|
254
|
-
|
255
245
|
# Public: Returns the internal state of the proposal.
|
256
246
|
#
|
257
247
|
# Returns Boolean.
|
@@ -386,13 +376,13 @@ module Decidim
|
|
386
376
|
ProposalSearch.new(self, params, options)
|
387
377
|
end
|
388
378
|
|
389
|
-
# method to filter by assigned
|
390
|
-
def self.
|
379
|
+
# method to filter by assigned evaluator role ID
|
380
|
+
def self.evaluator_role_ids_has(value)
|
391
381
|
query = <<-SQL.squish
|
392
382
|
:value = any(
|
393
|
-
(SELECT
|
394
|
-
FROM
|
395
|
-
WHERE
|
383
|
+
(SELECT decidim_proposals_evaluation_assignments.evaluator_role_id
|
384
|
+
FROM decidim_proposals_evaluation_assignments
|
385
|
+
WHERE decidim_proposals_evaluation_assignments.decidim_proposal_id = decidim_proposals_proposals.id
|
396
386
|
)
|
397
387
|
)
|
398
388
|
SQL
|
@@ -400,7 +390,7 @@ module Decidim
|
|
400
390
|
end
|
401
391
|
|
402
392
|
def self.ransackable_scopes(_auth_object = nil)
|
403
|
-
[:with_any_origin, :with_any_state, :state_eq, :voted_by, :coauthored_by, :related_to, :with_any_taxonomies, :
|
393
|
+
[:with_any_origin, :with_any_state, :state_eq, :voted_by, :coauthored_by, :related_to, :with_any_taxonomies, :evaluator_role_ids_has]
|
404
394
|
end
|
405
395
|
|
406
396
|
# Create i18n ransackers for :title and :body.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import attachGeocoding from "src/decidim/geocoding/attach_input"
|
2
2
|
import getCoordinateInputName from "src/decidim/geocoding/coordinate_input";
|
3
3
|
|
4
|
-
|
4
|
+
document.addEventListener("turbo:load", () => {
|
5
5
|
const $map = $("#address_map");
|
6
6
|
const $addressInputField = $("[data-decidim-geocoding]");
|
7
7
|
|
@@ -4,7 +4,12 @@
|
|
4
4
|
|
5
5
|
import TomSelect from "tom-select/dist/cjs/tom-select.popular";
|
6
6
|
|
7
|
-
|
7
|
+
document.addEventListener("turbo:load", () => {
|
8
|
+
let isMergeProposalsClicked = false;
|
9
|
+
$('button[data-action="merge-proposals"]').on("click", function() {
|
10
|
+
isMergeProposalsClicked = true;
|
11
|
+
});
|
12
|
+
|
8
13
|
const selectedProposalsCount = function() {
|
9
14
|
return $(".table-list .js-check-all-proposal:checked").length
|
10
15
|
}
|
@@ -24,8 +29,8 @@ $(() => {
|
|
24
29
|
|
25
30
|
if (selectedProposals === 0) {
|
26
31
|
$("#js-selected-proposals-count").text("")
|
27
|
-
$("#js-assign-proposals-to-
|
28
|
-
$("#js-unassign-proposals-from-
|
32
|
+
$("#js-assign-proposals-to-evaluator-actions").addClass("hide");
|
33
|
+
$("#js-unassign-proposals-from-evaluator-actions").addClass("hide");
|
29
34
|
$("#js-taxonomy-change-proposals-actions").addClass("hide");
|
30
35
|
} else {
|
31
36
|
$("#js-selected-proposals-count").text(selectedProposals);
|
@@ -72,10 +77,16 @@ $(() => {
|
|
72
77
|
}
|
73
78
|
|
74
79
|
const showOtherActionsButtons = function() {
|
80
|
+
if (isMergeProposalsClicked) {
|
81
|
+
return;
|
82
|
+
}
|
75
83
|
$("#js-other-actions-wrapper").removeClass("hide");
|
76
84
|
}
|
77
85
|
|
78
86
|
const hideOtherActionsButtons = function() {
|
87
|
+
if (isMergeProposalsClicked) {
|
88
|
+
return;
|
89
|
+
}
|
79
90
|
$("#js-other-actions-wrapper").addClass("hide");
|
80
91
|
}
|
81
92
|
|
@@ -98,14 +109,14 @@ $(() => {
|
|
98
109
|
hideBulkActionForms();
|
99
110
|
$("#js-bulk-actions-button").addClass("hide");
|
100
111
|
|
101
|
-
$("#js-bulk-actions-dropdown
|
112
|
+
$("#js-bulk-actions-dropdown li button").click(function (e) {
|
102
113
|
$("#js-bulk-actions-dropdown").removeClass("is-open");
|
103
114
|
hideBulkActionForms();
|
104
115
|
|
105
116
|
let action = $(e.target).data("action");
|
106
117
|
const panelActions = [
|
107
|
-
"assign-proposals-to-
|
108
|
-
"unassign-proposals-from-
|
118
|
+
"assign-proposals-to-evaluator",
|
119
|
+
"unassign-proposals-from-evaluator",
|
109
120
|
"taxonomy-change-proposals"
|
110
121
|
];
|
111
122
|
|
@@ -125,7 +136,7 @@ $(() => {
|
|
125
136
|
});
|
126
137
|
|
127
138
|
$(`#js-${action}-actions`).removeClass("hide");
|
128
|
-
hideBulkActionsButton(
|
139
|
+
hideBulkActionsButton(!isMergeProposalsClicked);
|
129
140
|
hideOtherActionsButtons();
|
130
141
|
}
|
131
142
|
});
|
@@ -184,12 +195,12 @@ $(() => {
|
|
184
195
|
}
|
185
196
|
});
|
186
197
|
|
187
|
-
document.addEventListener("
|
188
|
-
const
|
189
|
-
".js-
|
198
|
+
document.addEventListener("turbo:load", () => {
|
199
|
+
const evaluatorMultiselectContainers = document.querySelectorAll(
|
200
|
+
".js-evaluator-multiselect"
|
190
201
|
);
|
191
202
|
|
192
|
-
|
203
|
+
evaluatorMultiselectContainers.forEach((container) => {
|
193
204
|
const config = {
|
194
205
|
plugins: ["remove_button", "dropdown_input"],
|
195
206
|
allowEmptyOption: true
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import { createDialog } from "src/decidim/a11y"
|
2
|
+
import createEditor from "src/decidim/editor";
|
3
|
+
import attachGeocoding from "src/decidim/geocoding/attach_input";
|
4
|
+
import { initializeUploadFields } from "src/decidim/direct_uploads/upload_field";
|
5
|
+
import { initializeReverseGeocoding } from "src/decidim/geocoding/reverse_geocoding"
|
6
|
+
|
7
|
+
document.addEventListener("decidim:loaded", () => {
|
8
|
+
document.querySelectorAll('button[data-action="merge-proposals"]').forEach((button) => {
|
9
|
+
const url = button.dataset.mergeUrl;
|
10
|
+
const drawer = window.Decidim.currentDialogs[button.dataset.mergeDialog];
|
11
|
+
const container = drawer.dialog.querySelector("#merge-proposals-actions");
|
12
|
+
|
13
|
+
// Handles changes on the form
|
14
|
+
const activateDrawerForm = () => {
|
15
|
+
const saveForm = drawer.dialog.querySelector("#form-merge-proposals");
|
16
|
+
|
17
|
+
// Handles editor initialization
|
18
|
+
saveForm.querySelectorAll(".editor-container").forEach((element) => createEditor(element));
|
19
|
+
const form = document.querySelector(".proposals_merge_form_admin");
|
20
|
+
|
21
|
+
// Handles meeting checkbox
|
22
|
+
if (form) {
|
23
|
+
const proposalCreatedInMeeting = form.querySelector("#proposals_merge_created_in_meeting");
|
24
|
+
const proposalMeeting = form.querySelector("#proposals_merge_meeting");
|
25
|
+
|
26
|
+
const toggleDisabledHiddenFields = () => {
|
27
|
+
const enabledMeeting = proposalCreatedInMeeting.checked;
|
28
|
+
proposalMeeting.querySelector("select").setAttribute("disabled", "disabled");
|
29
|
+
|
30
|
+
proposalMeeting.classList.add("hidden");
|
31
|
+
|
32
|
+
if (enabledMeeting) {
|
33
|
+
proposalMeeting.querySelector("select").removeAttribute("disabled");
|
34
|
+
proposalMeeting.classList.remove("hidden");
|
35
|
+
}
|
36
|
+
};
|
37
|
+
|
38
|
+
proposalCreatedInMeeting.addEventListener("change", toggleDisabledHiddenFields);
|
39
|
+
toggleDisabledHiddenFields();
|
40
|
+
}
|
41
|
+
|
42
|
+
// Handles address input (requires jQuery for the moment)
|
43
|
+
attachGeocoding($(document.getElementById("proposals_merge_address")));
|
44
|
+
|
45
|
+
// Handles address reverse_geocoding initialization
|
46
|
+
initializeReverseGeocoding()
|
47
|
+
|
48
|
+
// Handles upload files initialization
|
49
|
+
saveForm.querySelectorAll("[data-dialog]").forEach((component) => createDialog(component));
|
50
|
+
initializeUploadFields(saveForm.querySelectorAll("button[data-upload]"));
|
51
|
+
|
52
|
+
// Handles form errors and success
|
53
|
+
if (saveForm) {
|
54
|
+
saveForm.addEventListener("ajax:success", (event) => {
|
55
|
+
const response = event.detail[0];
|
56
|
+
|
57
|
+
if (response.status === "ok") {
|
58
|
+
window.location.reload();
|
59
|
+
} else {
|
60
|
+
window.location.href = response.redirect_url;
|
61
|
+
}
|
62
|
+
});
|
63
|
+
|
64
|
+
saveForm.addEventListener("ajax:error", (event) => {
|
65
|
+
const response = event.detail[2];
|
66
|
+
container.innerHTML = response.responseText;
|
67
|
+
activateDrawerForm();
|
68
|
+
});
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
const fetchUrl = (urlToFetch) => {
|
73
|
+
container.classList.add("spinner-container");
|
74
|
+
fetch(urlToFetch).then((response) => response.text()).then((html) => {
|
75
|
+
container.innerHTML = html;
|
76
|
+
container.classList.remove("spinner-container");
|
77
|
+
// We still need foundation for form validations
|
78
|
+
$(container).foundation();
|
79
|
+
activateDrawerForm();
|
80
|
+
});
|
81
|
+
};
|
82
|
+
|
83
|
+
button.addEventListener("click", () => {
|
84
|
+
const selectedProposals = Array.from(document.querySelectorAll(".js-check-all-proposal:checked")).map((checkbox) => checkbox.value);
|
85
|
+
const uniqueProposals = [...new Set(selectedProposals)];
|
86
|
+
|
87
|
+
const queryParams = uniqueProposals.map((id) => `proposal_ids[]=${encodeURIComponent(id)}`).join("&")
|
88
|
+
fetchUrl(`${url}?${queryParams}`);
|
89
|
+
drawer.open();
|
90
|
+
});
|
91
|
+
})
|
92
|
+
});
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import TomSelect from "tom-select/dist/cjs/tom-select.popular";
|
2
2
|
|
3
|
-
document.addEventListener("
|
3
|
+
document.addEventListener("turbo:load", () => {
|
4
4
|
const tagContainers = document.querySelectorAll("#proposals_list");
|
5
5
|
tagContainers.forEach((container) => {
|
6
6
|
const { tmName, tmItems, tmNoResults } = container.dataset
|
@@ -6,7 +6,7 @@ const allowExitFrom = (el) => {
|
|
6
6
|
return false;
|
7
7
|
};
|
8
8
|
|
9
|
-
document.addEventListener("
|
9
|
+
document.addEventListener("turbo:load", () => {
|
10
10
|
const exitNotification = document.getElementById("exit-proposal-notification");
|
11
11
|
const exitLink = document.getElementById("exit-proposal-notification-link");
|
12
12
|
if (!exitLink) {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
@
|
1
|
+
@use "tom-select/dist/scss/tom-select";
|
2
2
|
|
3
3
|
.proposal-list {
|
4
4
|
&__aside {
|
@@ -405,6 +405,34 @@
|
|
405
405
|
}
|
406
406
|
}
|
407
407
|
|
408
|
+
#form-merge-proposals {
|
409
|
+
.custom-inputs {
|
410
|
+
input {
|
411
|
+
@apply mt-0;
|
412
|
+
}
|
413
|
+
}
|
414
|
+
|
415
|
+
.upload-modal__files-container {
|
416
|
+
label {
|
417
|
+
@apply mb-0;
|
418
|
+
}
|
419
|
+
|
420
|
+
button {
|
421
|
+
@apply mt-0;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
.form__wrapper,
|
427
|
+
.form-proposals-merge-styles {
|
428
|
+
.proposal-field-custom-style {
|
429
|
+
& label:not(&-checkbox-label),
|
430
|
+
&-block label:not(&-checkbox-label) {
|
431
|
+
@apply font-normal text-sm;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
408
436
|
.proposal__aside-vote {
|
409
437
|
button[disabled] {
|
410
438
|
@apply bg-[var(--secondary)] opacity-50 text-white border-current cursor-not-allowed;
|
@@ -8,12 +8,12 @@ module Decidim
|
|
8
8
|
# The public part needs to be implemented yet
|
9
9
|
return permission_action if permission_action.scope != :admin
|
10
10
|
|
11
|
-
#
|
12
|
-
if
|
13
|
-
if
|
11
|
+
# Evaluators can only perform these actions
|
12
|
+
if user_is_evaluator?
|
13
|
+
if evaluator_assigned_to_proposal?
|
14
14
|
can_create_proposal_note?
|
15
15
|
can_create_proposal_answer?
|
16
|
-
|
16
|
+
can_assign_evaluator_to_proposal?
|
17
17
|
end
|
18
18
|
can_export_proposals?
|
19
19
|
|
@@ -45,11 +45,11 @@ module Decidim
|
|
45
45
|
# Every user allowed by the space can split proposals to another component
|
46
46
|
allow! if permission_action.subject == :proposals && permission_action.action == :split
|
47
47
|
|
48
|
-
# Every user allowed by the space can assign proposals to a
|
49
|
-
|
48
|
+
# Every user allowed by the space can assign proposals to a evaluator
|
49
|
+
can_assign_evaluator_to_proposal?
|
50
50
|
|
51
|
-
# Every user allowed by the space can unassign a
|
52
|
-
|
51
|
+
# Every user allowed by the space can unassign a evaluator from proposals
|
52
|
+
can_unassign_evaluator_from_proposals?
|
53
53
|
|
54
54
|
# Only admin users can publish many answers at once
|
55
55
|
toggle_allow(user.admin?) if permission_action.subject == :proposals && permission_action.action == :publish_answers
|
@@ -80,20 +80,20 @@ module Decidim
|
|
80
80
|
@proposal ||= context.fetch(:proposal, nil)
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
84
|
-
@
|
83
|
+
def user_evaluator_role
|
84
|
+
@user_evaluator_role ||= space.user_roles(:evaluator).find_by(user:)
|
85
85
|
end
|
86
86
|
|
87
|
-
def
|
87
|
+
def user_is_evaluator?
|
88
88
|
return if user.admin?
|
89
89
|
|
90
|
-
|
90
|
+
user_evaluator_role.present?
|
91
91
|
end
|
92
92
|
|
93
|
-
def
|
94
|
-
@
|
95
|
-
Decidim::Proposals::
|
96
|
-
.where(proposal:,
|
93
|
+
def evaluator_assigned_to_proposal?
|
94
|
+
@evaluator_assigned_to_proposal ||=
|
95
|
+
Decidim::Proposals::EvaluationAssignment
|
96
|
+
.where(proposal:, evaluator_role: user_evaluator_role)
|
97
97
|
.any?
|
98
98
|
end
|
99
99
|
|
@@ -142,12 +142,12 @@ module Decidim
|
|
142
142
|
toggle_allow(admin_proposal_answering_is_enabled?) if permission_action.subject == :proposal_answer
|
143
143
|
end
|
144
144
|
|
145
|
-
def
|
146
|
-
allow! if permission_action.subject == :proposals && permission_action.action == :
|
145
|
+
def can_unassign_evaluator_from_proposals?
|
146
|
+
allow! if permission_action.subject == :proposals && permission_action.action == :unassign_from_evaluator
|
147
147
|
end
|
148
148
|
|
149
|
-
def
|
150
|
-
allow! if permission_action.subject == :proposals && permission_action.action == :
|
149
|
+
def can_assign_evaluator_to_proposal?
|
150
|
+
allow! if permission_action.subject == :proposals && permission_action.action == :assign_to_evaluator
|
151
151
|
end
|
152
152
|
|
153
153
|
def can_export_proposals?
|