decidim-proposals 0.30.5 → 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/show.erb +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/cells/decidim/proposals/proposal_vote/show.erb +1 -1
- 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 +5 -22
- 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 +24 -34
- 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 +10 -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/_votes_count.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 +66 -74
- data/config/locales/ca.yml +66 -74
- data/config/locales/cs.yml +52 -81
- data/config/locales/de.yml +66 -75
- 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 +73 -81
- data/config/locales/fi-plain.yml +67 -75
- data/config/locales/fi.yml +68 -76
- 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 -69
- 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 +1 -469
- data/config/locales/pt.yml +0 -60
- data/config/locales/ro-RO.yml +45 -72
- 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 +82 -113
- 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 -36
- 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 +17 -28
- 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
|
@@ -10,7 +10,7 @@ class CreateDefaultProposalStates < ActiveRecord::Migration[6.1]
|
|
|
10
10
|
|
|
11
11
|
self.table_name = :decidim_proposals_proposals
|
|
12
12
|
STATES = { not_answered: 0, evaluating: 10, accepted: 20, rejected: -10 }.freeze
|
|
13
|
-
enum old_state
|
|
13
|
+
enum :old_state, STATES, default: "not_answered"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def up
|
data/db/migrate/20250121110014_rename_proposal_valuation_assignments_to_evaluation_assignments.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class RenameProposalValuationAssignmentsToEvaluationAssignments < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
rename_table :decidim_proposals_valuation_assignments, :decidim_proposals_evaluation_assignments
|
|
6
|
+
|
|
7
|
+
rename_index :decidim_proposals_evaluation_assignments,
|
|
8
|
+
"decidim_proposals_valuation_assignment_proposal",
|
|
9
|
+
"decidim_proposals_evaluation_assignment_proposal"
|
|
10
|
+
|
|
11
|
+
rename_index :decidim_proposals_evaluation_assignments,
|
|
12
|
+
"decidim_proposals_valuation_assignment_valuator_role",
|
|
13
|
+
"decidim_proposals_evaluation_assignment_valuator_role"
|
|
14
|
+
end
|
|
15
|
+
end
|
data/db/migrate/20250121110904_rename_valuation_assignments_count_to_evaluation_assignments_count.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class RenameValuationAssignmentsCountToEvaluationAssignmentsCount < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
rename_column :decidim_proposals_proposals, :valuation_assignments_count, :evaluation_assignments_count
|
|
6
|
+
|
|
7
|
+
reversible do |dir|
|
|
8
|
+
dir.up do
|
|
9
|
+
Decidim::Proposals::Proposal.reset_column_information
|
|
10
|
+
Decidim::Proposals::Proposal.unscoped.find_each do |record|
|
|
11
|
+
Decidim::Proposals::Proposal.reset_counters(record.id, :evaluation_assignments)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class RenameValuatorColumns < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
rename_column :decidim_proposals_evaluation_assignments, :valuator_role_type, :evaluator_role_type
|
|
6
|
+
rename_column :decidim_proposals_evaluation_assignments, :valuator_role_id, :evaluator_role_id
|
|
7
|
+
end
|
|
8
|
+
end
|
data/decidim-proposals.gemspec
CHANGED
|
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
|
|
35
35
|
s.add_dependency "decidim-comments", Decidim::Proposals.version
|
|
36
36
|
s.add_dependency "decidim-core", Decidim::Proposals.version
|
|
37
|
-
s.add_dependency "doc2text", "~> 0.4.
|
|
37
|
+
s.add_dependency "doc2text", "~> 0.4.0", ">= 0.4.8"
|
|
38
38
|
s.add_dependency "redcarpet", "~> 3.5", ">= 3.5.1"
|
|
39
39
|
|
|
40
40
|
s.add_development_dependency "decidim-admin", Decidim::Proposals.version
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
class AnswerProposalAttributes < Decidim::Api::Types::BaseInputObject
|
|
6
|
+
graphql_name "ProposalAttributes"
|
|
7
|
+
description "Attributes of a proposal"
|
|
8
|
+
|
|
9
|
+
argument :answer_content, GraphQL::Types::JSON, description: "The answer feedback for the status for this proposal", required: false
|
|
10
|
+
argument :cost, GraphQL::Types::Float, description: "Estimated cost of the proposal", required: false
|
|
11
|
+
argument :cost_report, GraphQL::Types::JSON, description: "Report on expenses", required: false
|
|
12
|
+
argument :execution_period, GraphQL::Types::JSON, description: "Report on the execution period", required: false
|
|
13
|
+
argument :state, GraphQL::Types::String,
|
|
14
|
+
description: "The answer status in which the proposal is in. Can be one of 'accepted', 'rejected' or 'evaluating'", required: false
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
class ProposalAnswerType < Decidim::Api::Types::BaseMutation
|
|
6
|
+
graphql_name "Answer"
|
|
7
|
+
|
|
8
|
+
description "Answers a proposal"
|
|
9
|
+
type Decidim::Proposals::ProposalType
|
|
10
|
+
|
|
11
|
+
argument :attributes, AnswerProposalAttributes, description: "input attributes of a proposal", required: true
|
|
12
|
+
|
|
13
|
+
def resolve(attributes:)
|
|
14
|
+
answer_content = attributes.to_h.fetch(:answer_content, object.answer)
|
|
15
|
+
internal_state = attributes.to_h.fetch(:state, object.internal_state)
|
|
16
|
+
params = attributes.to_h.reverse_merge(
|
|
17
|
+
internal_state:,
|
|
18
|
+
answer: answer_content,
|
|
19
|
+
cost: object.cost,
|
|
20
|
+
cost_report: object.cost_report,
|
|
21
|
+
execution_period: object.execution_period
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
form = Decidim::Proposals::Admin::ProposalAnswerForm.from_params(
|
|
25
|
+
params
|
|
26
|
+
).with_context(
|
|
27
|
+
current_component: object.component,
|
|
28
|
+
current_user:,
|
|
29
|
+
current_organization: current_user.organization
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
Admin::AnswerProposal.call(form, object) do
|
|
33
|
+
on(:ok) do
|
|
34
|
+
return object
|
|
35
|
+
end
|
|
36
|
+
on(:invalid) do
|
|
37
|
+
return GraphQL::ExecutionError.new(
|
|
38
|
+
form.errors.full_messages.join(", ")
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
GraphQL::ExecutionError.new(
|
|
43
|
+
I18n.t("decidim.proposals.admin.proposals.answer.invalid")
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def authorized?(attributes:)
|
|
49
|
+
super && allowed_to?(:create, :proposal_answer, object, context, scope: :admin)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def current_user
|
|
53
|
+
context[:current_user]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
class ProposalMutationType < Decidim::Api::Types::BaseObject
|
|
6
|
+
include Decidim::ApiResponseHelper
|
|
7
|
+
|
|
8
|
+
graphql_name "ProposalMutation"
|
|
9
|
+
description "a proposal which includes its available mutations"
|
|
10
|
+
|
|
11
|
+
field :answer, mutation: Decidim::Proposals::ProposalAnswerType, description: "Answers a proposal"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
class ProposalsMutationType < Decidim::Core::ComponentType
|
|
6
|
+
description "A proposals of a component."
|
|
7
|
+
|
|
8
|
+
field :proposal, type: Decidim::Proposals::ProposalMutationType, description: "Mutates a proposal", null: true do
|
|
9
|
+
argument :id, GraphQL::Types::ID, "The ID of the proposal", required: true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def proposal(id:)
|
|
13
|
+
collection.find(id)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def collection
|
|
19
|
+
Proposal.where(component: object).not_hidden.published
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -4,7 +4,7 @@ module Decidim
|
|
|
4
4
|
module Proposals
|
|
5
5
|
class ProposalInputSort < Decidim::Core::BaseInputSort
|
|
6
6
|
include Decidim::Core::HasPublishableInputSort
|
|
7
|
-
include Decidim::Core::
|
|
7
|
+
include Decidim::Core::HasLikeableInputSort
|
|
8
8
|
|
|
9
9
|
graphql_name "ProposalSort"
|
|
10
10
|
description "A type used for sorting proposals"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
class ProposalStateType < Decidim::Api::Types::BaseObject
|
|
6
|
+
description "A proposal state"
|
|
7
|
+
|
|
8
|
+
field :announcement_title, Decidim::Core::TranslatedFieldType, "The announcement for this proposal state", null: true
|
|
9
|
+
field :bg_color, GraphQL::Types::String, description: "The background color of proposal state label", null: true
|
|
10
|
+
field :id, GraphQL::Types::ID, "The id of the proposal state", null: false
|
|
11
|
+
field :proposals_count, GraphQL::Types::Int, "The number of proposals having this state", null: true
|
|
12
|
+
field :text_color, GraphQL::Types::String, description: "The text color of this proposal state label", null: true
|
|
13
|
+
field :title, Decidim::Core::TranslatedFieldType, "The title for this proposal state", null: true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -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::
|
|
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 :
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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 :
|
|
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 :
|
|
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
|
-
:
|
|
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
|
-
|
|
21
|
+
evaluator_role_ids_has: evaluator_role_ids
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
configuration.add_dynamically_translated_filters(
|
|
25
|
-
:
|
|
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
|
|
@@ -16,29 +16,17 @@ Decidim.register_component(:proposals) do |component|
|
|
|
16
16
|
Decidim::Proposals.create_default_states!(instance, admin_user)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
component.on(:publish) do |instance|
|
|
20
|
-
Decidim::Proposals::Proposal.where(component: instance).find_in_batches(batch_size: 100) do |batch|
|
|
21
|
-
Decidim::UpdateSearchIndexesJob.perform_later(batch)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
component.on(:unpublish) do |instance|
|
|
26
|
-
Decidim::Proposals::Proposal.where(component: instance).find_in_batches(batch_size: 100) do |batch|
|
|
27
|
-
Decidim::RemoveSearchIndexesJob.perform_later(batch)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
19
|
component.data_portable_entities = ["Decidim::Proposals::Proposal"]
|
|
32
20
|
|
|
33
21
|
component.newsletter_participant_entities = ["Decidim::Proposals::Proposal"]
|
|
34
22
|
|
|
35
|
-
component.actions = %w(
|
|
23
|
+
component.actions = %w(like vote create withdraw amend comment vote_comment)
|
|
36
24
|
|
|
37
25
|
component.query_type = "Decidim::Proposals::ProposalsType"
|
|
38
26
|
|
|
39
27
|
component.permissions_class_name = "Decidim::Proposals::Permissions"
|
|
40
28
|
|
|
41
|
-
POSSIBLE_SORT_ORDERS = %w(automatic random recent
|
|
29
|
+
POSSIBLE_SORT_ORDERS = %w(automatic random recent most_liked most_voted most_commented most_followed with_more_authors).freeze
|
|
42
30
|
|
|
43
31
|
component.settings(:global) do |settings|
|
|
44
32
|
settings.attribute :taxonomy_filters, type: :taxonomy_filters
|
|
@@ -46,12 +34,12 @@ Decidim.register_component(:proposals) do |component|
|
|
|
46
34
|
settings.attribute :minimum_votes_per_user, type: :integer, default: 0, required: true
|
|
47
35
|
settings.attribute :proposal_limit, type: :integer, default: 0, required: true
|
|
48
36
|
settings.attribute :proposal_length, type: :integer, default: 500
|
|
49
|
-
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) }
|
|
50
38
|
settings.attribute :edit_time, type: :integer_with_units, default: [5, "minutes"], required: true, units: %w(minutes hours days)
|
|
51
39
|
settings.attribute :threshold_per_proposal, type: :integer, default: 0, required: true
|
|
52
40
|
settings.attribute :can_accumulate_votes_beyond_threshold, type: :boolean, default: false
|
|
53
41
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
|
54
|
-
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 }
|
|
55
43
|
settings.attribute :official_proposals_enabled, type: :boolean, default: true
|
|
56
44
|
settings.attribute :comments_enabled, type: :boolean, default: true
|
|
57
45
|
settings.attribute :comments_max_length, type: :integer, required: true
|
|
@@ -75,8 +63,8 @@ Decidim.register_component(:proposals) do |component|
|
|
|
75
63
|
end
|
|
76
64
|
|
|
77
65
|
component.settings(:step) do |settings|
|
|
78
|
-
settings.attribute :
|
|
79
|
-
settings.attribute :
|
|
66
|
+
settings.attribute :likes_enabled, type: :boolean, default: true
|
|
67
|
+
settings.attribute :likes_blocked, type: :boolean
|
|
80
68
|
settings.attribute :votes_enabled, type: :boolean
|
|
81
69
|
settings.attribute :votes_blocked, type: :boolean
|
|
82
70
|
settings.attribute :votes_hidden, type: :boolean, default: false
|
|
@@ -85,16 +73,14 @@ Decidim.register_component(:proposals) do |component|
|
|
|
85
73
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
|
86
74
|
settings.attribute :publish_answers_immediately, type: :boolean, default: true
|
|
87
75
|
settings.attribute :answers_with_costs, type: :boolean, default: false
|
|
88
|
-
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 }
|
|
89
77
|
settings.attribute :amendment_creation_enabled, type: :boolean, default: true
|
|
90
78
|
settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
|
|
91
79
|
settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
|
|
92
80
|
settings.attribute :amendments_visibility,
|
|
93
81
|
type: :enum, default: "all",
|
|
94
|
-
choices: -> { Decidim.config.amendments_visibility_options }
|
|
82
|
+
choices: ->(_context) { Decidim.config.amendments_visibility_options }
|
|
95
83
|
settings.attribute :announcement, type: :text, translated: true, editor: true
|
|
96
|
-
settings.attribute :automatic_hashtags, type: :text, editor: false, required: false
|
|
97
|
-
settings.attribute :suggested_hashtags, type: :text, editor: false, required: false
|
|
98
84
|
end
|
|
99
85
|
|
|
100
86
|
component.register_resource(:proposal) do |resource|
|
|
@@ -102,7 +88,7 @@ Decidim.register_component(:proposals) do |component|
|
|
|
102
88
|
resource.template = "decidim/proposals/proposals/linked_proposals"
|
|
103
89
|
resource.card = "decidim/proposals/proposal"
|
|
104
90
|
resource.reported_content_cell = "decidim/proposals/reported_content"
|
|
105
|
-
resource.actions = %w(
|
|
91
|
+
resource.actions = %w(like vote amend comment vote_comment)
|
|
106
92
|
resource.searchable = true
|
|
107
93
|
end
|
|
108
94
|
|
|
@@ -112,30 +98,55 @@ Decidim.register_component(:proposals) do |component|
|
|
|
112
98
|
resource.reported_content_cell = "decidim/proposals/collaborative_drafts/reported_content"
|
|
113
99
|
end
|
|
114
100
|
|
|
115
|
-
component.register_stat :proposals_count,
|
|
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|
|
|
116
107
|
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_withdrawn.not_hidden.count
|
|
117
108
|
end
|
|
118
109
|
|
|
119
|
-
component.register_stat :
|
|
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|
|
|
120
123
|
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).accepted.not_hidden.count
|
|
121
124
|
end
|
|
122
125
|
|
|
123
|
-
component.register_stat :votes_count, priority: Decidim::StatsRegistry::
|
|
126
|
+
component.register_stat :votes_count, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
|
|
124
127
|
proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
|
|
125
128
|
Decidim::Proposals::ProposalVote.where(proposal: proposals).count
|
|
126
129
|
end
|
|
127
130
|
|
|
128
|
-
component.register_stat :
|
|
131
|
+
component.register_stat :likes_count, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
|
|
129
132
|
proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).not_hidden
|
|
130
|
-
proposals.sum(:
|
|
133
|
+
proposals.sum(:likes_count)
|
|
131
134
|
end
|
|
132
135
|
|
|
133
|
-
component.register_stat :comments_count,
|
|
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|
|
|
134
141
|
proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
|
|
135
142
|
proposals.sum(:comments_count)
|
|
136
143
|
end
|
|
137
144
|
|
|
138
|
-
component.register_stat :followers_count,
|
|
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|
|
|
139
150
|
proposals_ids = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden.pluck(:id)
|
|
140
151
|
Decidim::Follow.where(decidim_followable_type: "Decidim::Proposals::Proposal", decidim_followable_id: proposals_ids).count
|
|
141
152
|
end
|
|
@@ -150,8 +161,8 @@ Decidim.register_component(:proposals) do |component|
|
|
|
150
161
|
.where(component: component_instance)
|
|
151
162
|
.includes(:taxonomies, :component)
|
|
152
163
|
|
|
153
|
-
if space.user_roles(:
|
|
154
|
-
collection.
|
|
164
|
+
if space.user_roles(:evaluator).where(user:).any?
|
|
165
|
+
collection.with_evaluation_assigned_to(user, space)
|
|
155
166
|
else
|
|
156
167
|
collection
|
|
157
168
|
end
|
|
@@ -166,7 +177,7 @@ Decidim.register_component(:proposals) do |component|
|
|
|
166
177
|
exports.collection do |component_instance|
|
|
167
178
|
Decidim::Comments::Export.comments_for_resource(
|
|
168
179
|
Decidim::Proposals::Proposal, component_instance
|
|
169
|
-
).includes(:author,
|
|
180
|
+
).includes(:author, root_commentable: { component: { participatory_space: :organization } })
|
|
170
181
|
end
|
|
171
182
|
|
|
172
183
|
exports.include_in_open_data = true
|
|
@@ -175,9 +186,6 @@ Decidim.register_component(:proposals) do |component|
|
|
|
175
186
|
end
|
|
176
187
|
|
|
177
188
|
component.imports :proposals do |imports|
|
|
178
|
-
imports.form_view = "decidim/proposals/admin/imports/proposals_fields"
|
|
179
|
-
imports.form_class_name = "Decidim::Proposals::Admin::ProposalsFileImportForm"
|
|
180
|
-
|
|
181
189
|
imports.messages do |msg|
|
|
182
190
|
msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.proposals", count:) }
|
|
183
191
|
msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.proposals") }
|