decidim-proposals 0.28.5 → 0.29.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -18
- data/app/cells/decidim/proposals/cost_report_cell.rb +0 -3
- data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +11 -11
- data/app/cells/decidim/proposals/highlighted_proposals_for_component_cell.rb +1 -1
- data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +1 -1
- data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +2 -3
- data/app/cells/decidim/proposals/proposal_cell.rb +2 -0
- data/app/cells/decidim/proposals/proposal_g/show.erb +23 -0
- data/app/cells/decidim/proposals/proposal_g_cell.rb +48 -0
- data/app/cells/decidim/proposals/proposal_l_cell.rb +18 -19
- data/app/cells/decidim/proposals/proposal_metadata_cell.rb +23 -15
- data/app/commands/decidim/proposals/admin/answer_proposal.rb +2 -1
- data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +7 -5
- data/app/commands/decidim/proposals/admin/create_proposal.rb +4 -6
- data/app/commands/decidim/proposals/admin/create_proposal_state.rb +15 -0
- data/app/commands/decidim/proposals/admin/destroy_proposal_state.rb +10 -0
- data/app/commands/decidim/proposals/admin/import_proposals.rb +10 -2
- data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +4 -21
- data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +6 -4
- data/app/commands/decidim/proposals/admin/update_proposal_state.rb +13 -0
- data/app/commands/decidim/proposals/create_proposal.rb +21 -2
- data/app/commands/decidim/proposals/update_proposal.rb +2 -2
- data/app/commands/decidim/proposals/vote_proposal.rb +1 -1
- data/app/commands/decidim/proposals/withdraw_proposal.rb +3 -7
- data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +10 -22
- data/app/controllers/decidim/proposals/admin/proposal_states_controller.rb +86 -0
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +4 -0
- data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +8 -11
- data/app/controllers/decidim/proposals/proposals_controller.rb +38 -39
- data/app/events/decidim/proposals/proposal_state_changed_event.rb +37 -0
- data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +8 -4
- data/app/forms/decidim/proposals/admin/proposal_form.rb +1 -1
- data/app/forms/decidim/proposals/admin/proposal_state_form.rb +22 -0
- data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -1
- data/app/forms/decidim/proposals/admin/proposals_import_form.rb +1 -1
- data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +12 -14
- data/app/forms/decidim/proposals/proposal_form.rb +25 -4
- data/app/forms/decidim/proposals/reject_access_to_collaborative_draft_form.rb +1 -1
- data/app/forms/decidim/proposals/request_access_to_collaborative_draft_form.rb +1 -1
- data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +7 -17
- data/app/helpers/decidim/proposals/admin/proposals_helper.rb +13 -89
- data/app/helpers/decidim/proposals/application_helper.rb +16 -10
- data/app/helpers/decidim/proposals/map_helper.rb +1 -1
- data/app/helpers/decidim/proposals/proposal_cells_helper.rb +6 -2
- data/app/helpers/decidim/proposals/proposal_votes_helper.rb +3 -3
- data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +5 -8
- data/app/helpers/decidim/proposals/proposals_helper.rb +18 -24
- data/app/models/decidim/proposals/proposal.rb +83 -29
- data/app/models/decidim/proposals/proposal_state.rb +58 -0
- data/app/packs/documents/decidim/proposals/participatory_texts/participatory_text.md +1 -3
- data/app/packs/images/decidim/proposals/proposal-placeholder-card-g.svg +15 -0
- data/app/packs/src/decidim/proposals/add_proposal.js +2 -0
- data/app/packs/src/decidim/proposals/admin/proposals.js +43 -8
- data/app/packs/stylesheets/decidim/proposals/proposals.scss +39 -1
- data/app/permissions/decidim/proposals/admin/permissions.rb +16 -4
- data/app/permissions/decidim/proposals/permissions.rb +3 -4
- data/app/presenters/decidim/proposals/admin_log/proposal_state_presenter.rb +21 -0
- data/app/presenters/decidim/proposals/proposal_presenter.rb +12 -3
- data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +1 -1
- data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +1 -1
- data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +4 -4
- data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +1 -1
- data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +1 -1
- data/app/services/decidim/proposals/diff_renderer.rb +1 -3
- data/app/services/decidim/proposals/proposal_builder.rb +1 -1
- data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +1 -1
- data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +3 -2
- data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +3 -3
- data/app/views/decidim/proposals/admin/proposal_states/_form.html.erb +67 -0
- data/app/views/decidim/proposals/admin/proposal_states/edit.html.erb +18 -0
- data/app/views/decidim/proposals/admin/proposal_states/index.html.erb +50 -0
- data/app/views/decidim/proposals/admin/proposal_states/new.html.erb +18 -0
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +6 -12
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +6 -6
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +11 -7
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +7 -5
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_recategorize.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_split.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +11 -7
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_valuators_picker.html.erb +12 -0
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +11 -7
- data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +1 -1
- data/app/views/decidim/proposals/admin/proposals/show.html.erb +3 -2
- data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +3 -3
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +12 -5
- data/app/views/decidim/proposals/proposals/_proposal.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_proposals.html.erb +9 -3
- data/app/views/decidim/proposals/proposals/_vote_button.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +3 -3
- data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +0 -1
- data/app/views/decidim/proposals/proposals/index.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/index.js.erb +0 -12
- data/app/views/decidim/proposals/proposals/new.html.erb +2 -7
- data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +4 -4
- data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_votes_count.html.erb +8 -8
- data/app/views/decidim/proposals/proposals/preview.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/show.html.erb +3 -3
- data/config/locales/ar.yml +9 -115
- data/config/locales/bg.yml +117 -111
- data/config/locales/ca.yml +86 -83
- data/config/locales/cs.yml +65 -127
- data/config/locales/de.yml +128 -125
- data/config/locales/el.yml +8 -121
- data/config/locales/en.yml +110 -107
- data/config/locales/es-MX.yml +85 -82
- data/config/locales/es-PY.yml +88 -85
- data/config/locales/es.yml +83 -80
- data/config/locales/eu.yml +166 -170
- data/config/locales/fi-plain.yml +90 -87
- data/config/locales/fi.yml +139 -136
- data/config/locales/fr-CA.yml +92 -87
- data/config/locales/fr.yml +83 -78
- data/config/locales/ga-IE.yml +1 -27
- data/config/locales/gl.yml +11 -107
- data/config/locales/he-IL.yml +0 -17
- data/config/locales/hu.yml +18 -90
- data/config/locales/id-ID.yml +6 -106
- data/config/locales/is-IS.yml +8 -33
- data/config/locales/it.yml +14 -103
- data/config/locales/ja.yml +117 -112
- data/config/locales/lb.yml +1 -0
- data/config/locales/lt.yml +6 -123
- data/config/locales/lv.yml +4 -101
- data/config/locales/nl.yml +11 -102
- data/config/locales/no.yml +7 -108
- data/config/locales/pl.yml +110 -115
- data/config/locales/pt-BR.yml +10 -84
- data/config/locales/pt.yml +9 -109
- data/config/locales/ro-RO.yml +15 -117
- data/config/locales/ru.yml +9 -53
- data/config/locales/sk.yml +5 -109
- data/config/locales/sl.yml +4 -0
- data/config/locales/sv.yml +142 -337
- data/config/locales/tr-TR.yml +64 -108
- data/config/locales/uk.yml +11 -55
- data/config/locales/zh-CN.yml +5 -100
- data/config/locales/zh-TW.yml +8 -119
- data/db/migrate/20240110203500_add_withdrawn_at_field_to_proposals.rb +27 -0
- data/db/migrate/20240110203501_create_decidim_proposals_proposal_state.rb +14 -0
- data/db/migrate/20240110203502_add_state_id_to_decidim_proposals_proposals.rb +13 -0
- data/db/migrate/20240110203503_remove_state_from_decidim_proposals_proposals.rb +11 -0
- data/db/migrate/20240110203504_create_default_proposal_states.rb +31 -0
- data/db/migrate/20240209092404_change_color_fields_on_proposals_states.rb +54 -0
- data/decidim-proposals.gemspec +3 -3
- data/lib/decidim/api/proposal_type.rb +4 -13
- data/lib/decidim/api/proposals_type.rb +3 -1
- data/lib/decidim/proposals/admin_engine.rb +8 -0
- data/lib/decidim/proposals/admin_filter.rb +37 -0
- data/lib/decidim/proposals/component.rb +8 -5
- data/lib/decidim/proposals/engine.rb +1 -15
- data/lib/decidim/proposals/import/proposal_answer_creator.rb +6 -6
- data/lib/decidim/proposals/import/proposal_creator.rb +1 -1
- data/lib/decidim/proposals/markdown_to_proposals.rb +2 -8
- data/lib/decidim/proposals/proposal_serializer.rb +8 -9
- data/lib/decidim/proposals/seeds.rb +60 -51
- data/lib/decidim/proposals/test/factories.rb +69 -14
- data/lib/decidim/proposals/version.rb +1 -1
- data/lib/decidim/proposals.rb +84 -12
- data/lib/tasks/proposals/upgrade/{decdim_proposals_upgrade_tasks.rake → decidim_proposals_upgrade_tasks.rake} +0 -13
- metadata +51 -40
- data/app/events/decidim/proposals/accepted_proposal_event.rb +0 -17
- data/app/events/decidim/proposals/evaluating_proposal_event.rb +0 -11
- data/app/events/decidim/proposals/rejected_proposal_event.rb +0 -17
- data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +0 -44
- data/app/queries/decidim/proposals/similar_proposals.rb +0 -67
- data/app/services/decidim/proposals/collaborative_draft_diff_renderer.rb +0 -22
- data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +0 -0
- data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +0 -3
- data/app/views/decidim/proposals/proposals/compare.html.erb +0 -24
- data/app/views/decidim/proposals/proposals/complete.html.erb +0 -31
- data/config/locales/bn-BD.yml +0 -1
- data/config/locales/bs-BA.yml +0 -100
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateDefaultProposalStates < ActiveRecord::Migration[6.1]
|
4
|
+
class Proposal < ApplicationRecord
|
5
|
+
belongs_to :proposal_state,
|
6
|
+
class_name: "Decidim::Proposals::ProposalState",
|
7
|
+
foreign_key: "decidim_proposals_proposal_state_id",
|
8
|
+
inverse_of: :proposals,
|
9
|
+
optional: true
|
10
|
+
|
11
|
+
self.table_name = :decidim_proposals_proposals
|
12
|
+
STATES = { not_answered: 0, evaluating: 10, accepted: 20, rejected: -10 }.freeze
|
13
|
+
enum old_state: STATES, _default: "not_answered"
|
14
|
+
end
|
15
|
+
|
16
|
+
def up
|
17
|
+
Decidim::Component.where(manifest_name: "proposals").find_each do |component|
|
18
|
+
admin_user = component.organization.admins.first
|
19
|
+
|
20
|
+
default_states = Decidim::Proposals.create_default_states!(component, admin_user)
|
21
|
+
|
22
|
+
Proposal.where(decidim_component_id: component.id).find_each do |proposal|
|
23
|
+
proposal.update!(proposal_state: default_states.dig(proposal.old_state.to_sym, :object))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def down
|
29
|
+
raise ActiveRecord::IrreversibleMigration
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ChangeColorFieldsOnProposalsStates < ActiveRecord::Migration[6.1]
|
4
|
+
class ProposalState < ApplicationRecord
|
5
|
+
self.table_name = :decidim_proposals_proposal_states
|
6
|
+
|
7
|
+
def self.colors
|
8
|
+
{
|
9
|
+
gray: {
|
10
|
+
background: "#F6F8FA",
|
11
|
+
foreground: "#4B5058"
|
12
|
+
},
|
13
|
+
green: {
|
14
|
+
background: "#E3FCE9",
|
15
|
+
foreground: "#15602C"
|
16
|
+
},
|
17
|
+
orange: {
|
18
|
+
background: "#FFF1E5",
|
19
|
+
foreground: "#BC4C00"
|
20
|
+
},
|
21
|
+
red: {
|
22
|
+
background: "#FFEBE9",
|
23
|
+
foreground: "#D1242F"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def up
|
30
|
+
colors = ProposalState.colors
|
31
|
+
|
32
|
+
add_column :decidim_proposals_proposal_states, :bg_color, :string, default: colors[:gray][:background], null: false
|
33
|
+
add_column :decidim_proposals_proposal_states, :text_color, :string, default: colors[:gray][:foreground], null: false
|
34
|
+
remove_column :decidim_proposals_proposal_states, :css_class
|
35
|
+
|
36
|
+
# rubocop:disable Rails/SkipsModelValidations
|
37
|
+
ProposalState.where(token: :accepted).update_all(
|
38
|
+
bg_color: colors[:green][:background], text_color: colors[:green][:foreground]
|
39
|
+
)
|
40
|
+
ProposalState.where(token: :evaluating).update_all(
|
41
|
+
bg_color: colors[:orange][:background], text_color: colors[:orange][:foreground]
|
42
|
+
)
|
43
|
+
ProposalState.where(token: :rejected).update_all(
|
44
|
+
bg_color: colors[:red][:background], text_color: colors[:red][:foreground]
|
45
|
+
)
|
46
|
+
# rubocop:enable Rails/SkipsModelValidations
|
47
|
+
end
|
48
|
+
|
49
|
+
def down
|
50
|
+
remove_column :decidim_proposals_proposal_states, :bg_color
|
51
|
+
remove_column :decidim_proposals_proposal_states, :text_color
|
52
|
+
add_column :decidim_proposals_proposal_states, :css_class, :string
|
53
|
+
end
|
54
|
+
end
|
data/decidim-proposals.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.version = Decidim::Proposals.version
|
11
11
|
s.authors = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
|
12
12
|
s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
|
13
|
-
s.license = "AGPL-3.0
|
13
|
+
s.license = "AGPL-3.0"
|
14
14
|
s.homepage = "https://decidim.org"
|
15
15
|
s.metadata = {
|
16
16
|
"bug_tracker_uri" => "https://github.com/decidim/decidim/issues",
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
"homepage_uri" => "https://decidim.org",
|
20
20
|
"source_code_uri" => "https://github.com/decidim/decidim"
|
21
21
|
}
|
22
|
-
s.required_ruby_version = "~> 3.
|
22
|
+
s.required_ruby_version = "~> 3.2.0"
|
23
23
|
|
24
24
|
s.name = "decidim-proposals"
|
25
25
|
s.summary = "Decidim proposals module"
|
@@ -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.7"
|
38
38
|
s.add_dependency "redcarpet", "~> 3.5", ">= 3.5.1"
|
39
39
|
|
40
40
|
s.add_development_dependency "decidim-admin", Decidim::Proposals.version
|
@@ -26,6 +26,7 @@ module Decidim
|
|
26
26
|
def coordinates
|
27
27
|
[object.latitude, object.longitude]
|
28
28
|
end
|
29
|
+
|
29
30
|
field :reference, GraphQL::Types::String, "This proposal's unique reference", null: true
|
30
31
|
field :state, GraphQL::Types::String, "The answer status in which proposal is in", null: true
|
31
32
|
field :answer, Decidim::Core::TranslatedFieldType, "The answer feedback for the status for this proposal", null: true
|
@@ -41,6 +42,9 @@ module Decidim
|
|
41
42
|
field :created_in_meeting, GraphQL::Types::Boolean, "Whether this proposal comes from a meeting or not", method: :official_meeting?, null: true
|
42
43
|
field :meeting, Decidim::Meetings::MeetingType, description: "If the proposal comes from a meeting, the related meeting", null: true
|
43
44
|
|
45
|
+
field :withdrawn_at, Decidim::Core::DateTimeType, description: "The date and time this proposal was withdrawn", null: true
|
46
|
+
field :withdrawn, GraphQL::Types::Boolean, "Whether this proposal has been withdrawn or not", method: :withdrawn?, null: true
|
47
|
+
|
44
48
|
def meeting
|
45
49
|
object.authors.first if object.official_meeting?
|
46
50
|
end
|
@@ -51,19 +55,6 @@ module Decidim
|
|
51
55
|
current_component = object.component
|
52
56
|
object.proposal_votes_count unless current_component.current_settings.votes_hidden?
|
53
57
|
end
|
54
|
-
|
55
|
-
def self.authorized?(object, context)
|
56
|
-
context[:proposal] = object
|
57
|
-
|
58
|
-
chain = [
|
59
|
-
allowed_to?(:read, :proposal, object, context),
|
60
|
-
object.published?
|
61
|
-
].all?
|
62
|
-
|
63
|
-
super && chain
|
64
|
-
rescue Decidim::PermissionAction::PermissionNotSetError
|
65
|
-
false
|
66
|
-
end
|
67
58
|
end
|
68
59
|
end
|
69
60
|
end
|
@@ -16,7 +16,9 @@ module Decidim
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
class ProposalsType < Decidim::
|
19
|
+
class ProposalsType < Decidim::Api::Types::BaseObject
|
20
|
+
implements Decidim::Core::ComponentInterface
|
21
|
+
|
20
22
|
graphql_name "Proposals"
|
21
23
|
description "A proposals component of a participatory space."
|
22
24
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "decidim/proposals/admin_filter"
|
4
|
+
|
3
5
|
module Decidim
|
4
6
|
module Proposals
|
5
7
|
# This is the engine that runs on the public interface of `decidim-proposals`.
|
@@ -25,6 +27,8 @@ module Decidim
|
|
25
27
|
resources :proposal_notes, only: [:create]
|
26
28
|
end
|
27
29
|
|
30
|
+
resources :proposal_states
|
31
|
+
|
28
32
|
resources :participatory_texts, only: [:index] do
|
29
33
|
collection do
|
30
34
|
get :new_import
|
@@ -38,6 +42,10 @@ module Decidim
|
|
38
42
|
root to: "proposals#index"
|
39
43
|
end
|
40
44
|
|
45
|
+
initializer "decidim_proposals.admin_filters" do
|
46
|
+
Decidim::Proposals::AdminFilter.register_filter!
|
47
|
+
end
|
48
|
+
|
41
49
|
def load_seed
|
42
50
|
nil
|
43
51
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
class AdminFilter
|
6
|
+
def self.register_filter!
|
7
|
+
Decidim.admin_filter(:proposals) do |configuration|
|
8
|
+
configuration.add_filters(
|
9
|
+
:is_emendation_true,
|
10
|
+
:state_eq,
|
11
|
+
:with_any_state,
|
12
|
+
:scope_id_eq,
|
13
|
+
:category_id_eq,
|
14
|
+
:valuator_role_ids_has
|
15
|
+
)
|
16
|
+
|
17
|
+
configuration.add_filters_with_values(
|
18
|
+
is_emendation_true: %w(true false),
|
19
|
+
state_eq: state_eq_values,
|
20
|
+
with_any_state: %w(state_published state_not_published),
|
21
|
+
scope_id_eq: scope_ids_hash(scopes.top_level),
|
22
|
+
category_id_eq: category_ids_hash(categories.first_class),
|
23
|
+
valuator_role_ids_has: valuator_role_ids
|
24
|
+
)
|
25
|
+
|
26
|
+
configuration.add_dynamically_translated_filters(
|
27
|
+
:scope_id_eq,
|
28
|
+
:category_id_eq,
|
29
|
+
:valuator_role_ids_has,
|
30
|
+
:proposal_state_id_eq,
|
31
|
+
:state_eq
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -11,6 +11,11 @@ Decidim.register_component(:proposals) do |component|
|
|
11
11
|
raise "Cannot destroy this component when there are proposals" if Decidim::Proposals::Proposal.where(component: instance).any?
|
12
12
|
end
|
13
13
|
|
14
|
+
component.on(:create) do |instance|
|
15
|
+
admin_user = GlobalID::Locator.locate(instance.versions.first.whodunnit)
|
16
|
+
Decidim::Proposals.create_default_states!(instance, admin_user)
|
17
|
+
end
|
18
|
+
|
14
19
|
component.data_portable_entities = ["Decidim::Proposals::Proposal"]
|
15
20
|
|
16
21
|
component.newsletter_participant_entities = ["Decidim::Proposals::Proposal"]
|
@@ -33,7 +38,7 @@ Decidim.register_component(:proposals) do |component|
|
|
33
38
|
settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: -> { %w(limited infinite) }
|
34
39
|
settings.attribute :proposal_edit_before_minutes, type: :integer, default: 5, required: true
|
35
40
|
settings.attribute :threshold_per_proposal, type: :integer, default: 0, required: true
|
36
|
-
settings.attribute :
|
41
|
+
settings.attribute :can_accumulate_votes_beyond_threshold, type: :boolean, default: false
|
37
42
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
38
43
|
settings.attribute :default_sort_order, type: :select, default: "automatic", choices: -> { POSSIBLE_SORT_ORDERS }
|
39
44
|
settings.attribute :official_proposals_enabled, type: :boolean, default: true
|
@@ -56,8 +61,6 @@ Decidim.register_component(:proposals) do |component|
|
|
56
61
|
settings.attribute :new_proposal_help_text, type: :text, translated: true, editor: true
|
57
62
|
settings.attribute :proposal_wizard_step_1_help_text, type: :text, translated: true, editor: true
|
58
63
|
settings.attribute :proposal_wizard_step_2_help_text, type: :text, translated: true, editor: true
|
59
|
-
settings.attribute :proposal_wizard_step_3_help_text, type: :text, translated: true, editor: true
|
60
|
-
settings.attribute :proposal_wizard_step_4_help_text, type: :text, translated: true, editor: true
|
61
64
|
end
|
62
65
|
|
63
66
|
component.settings(:step) do |settings|
|
@@ -99,14 +102,14 @@ Decidim.register_component(:proposals) do |component|
|
|
99
102
|
end
|
100
103
|
|
101
104
|
component.register_stat :proposals_count, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
102
|
-
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.
|
105
|
+
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_withdrawn.not_hidden.count
|
103
106
|
end
|
104
107
|
|
105
108
|
component.register_stat :proposals_accepted, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
106
109
|
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).accepted.not_hidden.count
|
107
110
|
end
|
108
111
|
|
109
|
-
component.register_stat :
|
112
|
+
component.register_stat :votes_count, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
110
113
|
proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
|
111
114
|
Decidim::Proposals::ProposalVote.where(proposal: proposals).count
|
112
115
|
end
|
@@ -13,8 +13,6 @@ module Decidim
|
|
13
13
|
routes do
|
14
14
|
resources :proposals, except: [:destroy] do
|
15
15
|
member do
|
16
|
-
get :compare
|
17
|
-
get :complete
|
18
16
|
get :edit_draft
|
19
17
|
patch :update_draft
|
20
18
|
get :preview
|
@@ -57,6 +55,7 @@ module Decidim
|
|
57
55
|
Decidim.icons.register(name: "arrow-right-s-fill", icon: "arrow-right-s-fill", category: "system", description: "", engine: :proposals)
|
58
56
|
Decidim.icons.register(name: "bar-chart-2-line", icon: "bar-chart-2-line", category: "system", description: "", engine: :proposals)
|
59
57
|
Decidim.icons.register(name: "scales-line", icon: "scales-line", category: "system", description: "", engine: :proposals)
|
58
|
+
Decidim.icons.register(name: "layout-grid-fill", icon: "layout-grid-fill", category: "system", description: "", engine: :proposals)
|
60
59
|
end
|
61
60
|
|
62
61
|
initializer "decidim_proposals.content_processors" do |_app|
|
@@ -92,19 +91,6 @@ module Decidim
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
95
|
-
# Subscribes to ActiveSupport::Notifications that may affect a Proposal.
|
96
|
-
initializer "decidim_proposals.subscribe_to_events" do
|
97
|
-
# when a proposal is linked from a result
|
98
|
-
event_name = "decidim.resourceable.included_proposals.created"
|
99
|
-
ActiveSupport::Notifications.subscribe event_name do |_name, _started, _finished, _unique_id, data|
|
100
|
-
payload = data[:this]
|
101
|
-
if payload[:from_type] == Decidim::Accountability::Result.name && payload[:to_type] == Proposal.name
|
102
|
-
proposal = Proposal.find(payload[:to_id])
|
103
|
-
proposal.update(state: "accepted", state_published_at: Time.current)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
94
|
initializer "decidim_proposals.add_cells_view_paths" do
|
109
95
|
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Proposals::Engine.root}/app/cells")
|
110
96
|
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Proposals::Engine.root}/app/views") # for proposal partials
|
@@ -6,9 +6,7 @@ module Decidim
|
|
6
6
|
# This class is responsible for creating the imported proposal answers
|
7
7
|
# and must be included in proposals component's import manifest.
|
8
8
|
class ProposalAnswerCreator < Decidim::Admin::Import::Creator
|
9
|
-
|
10
|
-
|
11
|
-
# Retuns the resource class to be created with the provided data.
|
9
|
+
# Returns the resource class to be created with the provided data.
|
12
10
|
def self.resource_klass
|
13
11
|
Decidim::Proposals::Proposal
|
14
12
|
end
|
@@ -58,10 +56,12 @@ module Decidim
|
|
58
56
|
|
59
57
|
proposal.answer = answer
|
60
58
|
proposal.answered_at = Time.current
|
61
|
-
@initial_state = proposal.
|
59
|
+
@initial_state = proposal.proposal_state
|
60
|
+
|
61
|
+
proposal_state = Decidim::Proposals::ProposalState.where(component:, token: state).first
|
62
62
|
|
63
|
-
if
|
64
|
-
proposal.
|
63
|
+
if proposal_state.present?
|
64
|
+
proposal.proposal_state = proposal_state
|
65
65
|
proposal.state_published_at = Time.current if component.current_settings.publish_answers_immediately?
|
66
66
|
else
|
67
67
|
proposal.errors.add(:state, :invalid)
|
@@ -6,7 +6,7 @@ module Decidim
|
|
6
6
|
# This class is responsible for creating the imported proposals
|
7
7
|
# and must be included in proposals component's import manifest.
|
8
8
|
class ProposalCreator < Decidim::Admin::Import::Creator
|
9
|
-
#
|
9
|
+
# Returns the resource class to be created with the provided data.
|
10
10
|
def self.resource_klass
|
11
11
|
Decidim::Proposals::Proposal
|
12
12
|
end
|
@@ -41,14 +41,8 @@ module Decidim
|
|
41
41
|
|
42
42
|
# Block-level calls ######################
|
43
43
|
|
44
|
-
# Recarpet callback to preprocess the document.
|
45
|
-
# Removes the HTML comment from the markdown file
|
46
|
-
def preprocess(document)
|
47
|
-
document.gsub(/<!--.*-->/, "")
|
48
|
-
end
|
49
|
-
|
50
44
|
# Recarpet callback to process headers.
|
51
|
-
# Creates
|
45
|
+
# Creates Participatory Text Proposals at Section and Subsection levels.
|
52
46
|
def header(title, level)
|
53
47
|
participatory_text_level = if level > 1
|
54
48
|
Decidim::Proposals::ParticipatoryTextSection::LEVELS[:sub_section]
|
@@ -63,7 +57,7 @@ module Decidim
|
|
63
57
|
end
|
64
58
|
|
65
59
|
# Recarpet callback to process paragraphs.
|
66
|
-
# Creates
|
60
|
+
# Creates Participatory Text Proposals at Article level.
|
67
61
|
def paragraph(text)
|
68
62
|
return if text.blank?
|
69
63
|
|
@@ -44,14 +44,13 @@ module Decidim
|
|
44
44
|
reference: proposal.reference,
|
45
45
|
answer: ensure_translatable(proposal.answer),
|
46
46
|
answered_at: proposal.answered_at,
|
47
|
-
|
48
|
-
proposal.component.current_settings.votes_hidden?),
|
47
|
+
votes: proposal.proposal_votes_count,
|
49
48
|
endorsements: {
|
50
49
|
total_count: proposal.endorsements.size,
|
51
50
|
user_endorsements:
|
52
51
|
},
|
53
52
|
comments: proposal.comments_count,
|
54
|
-
attachments: proposal.attachments.
|
53
|
+
attachments: proposal.attachments.size,
|
55
54
|
followers: proposal.follows.size,
|
56
55
|
published_at: proposal.published_at,
|
57
56
|
url:,
|
@@ -61,7 +60,9 @@ module Decidim
|
|
61
60
|
original_proposal: {
|
62
61
|
title: proposal&.amendable&.title,
|
63
62
|
url: original_proposal_url
|
64
|
-
}
|
63
|
+
},
|
64
|
+
withdrawn: proposal.withdrawn?,
|
65
|
+
withdrawn_at: proposal.withdrawn_at
|
65
66
|
}
|
66
67
|
end
|
67
68
|
|
@@ -131,7 +132,7 @@ module Decidim
|
|
131
132
|
|
132
133
|
def author_url(author)
|
133
134
|
if author.respond_to?(:nickname)
|
134
|
-
profile_url(author) # is a Decidim::User or Decidim::UserGroup
|
135
|
+
profile_url(author.nickname) # is a Decidim::User or Decidim::UserGroup
|
135
136
|
elsif author.respond_to?(:title)
|
136
137
|
meeting_url(author) # is a Decidim::Meetings::Meeting
|
137
138
|
else
|
@@ -139,10 +140,8 @@ module Decidim
|
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
|
-
def profile_url(
|
143
|
-
|
144
|
-
|
145
|
-
Decidim::Core::Engine.routes.url_helpers.profile_url(author.nickname, host:)
|
143
|
+
def profile_url(nickname)
|
144
|
+
Decidim::Core::Engine.routes.url_helpers.profile_url(nickname, host:)
|
146
145
|
end
|
147
146
|
|
148
147
|
def meeting_url(meeting)
|
@@ -15,6 +15,8 @@ module Decidim
|
|
15
15
|
def call
|
16
16
|
component = create_component!
|
17
17
|
|
18
|
+
Decidim::Proposals.create_default_states!(component, admin_user)
|
19
|
+
|
18
20
|
5.times do |n|
|
19
21
|
proposal = create_proposal!(component:)
|
20
22
|
|
@@ -34,6 +36,9 @@ module Decidim
|
|
34
36
|
end
|
35
37
|
|
36
38
|
update_traceability!(component:)
|
39
|
+
|
40
|
+
create_report!(reportable: Decidim::Proposals::Proposal.take, current_user: Decidim::User.take)
|
41
|
+
hide_report!(reportable: Decidim::Proposals::Proposal.take)
|
37
42
|
end
|
38
43
|
|
39
44
|
def organization
|
@@ -54,6 +59,7 @@ module Decidim
|
|
54
59
|
participatory_space:,
|
55
60
|
settings: {
|
56
61
|
vote_limit: 0,
|
62
|
+
attachments_allowed: [true, false].sample,
|
57
63
|
collaborative_drafts_enabled: true
|
58
64
|
},
|
59
65
|
step_settings:
|
@@ -69,20 +75,9 @@ module Decidim
|
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
72
|
-
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
73
78
|
def create_proposal!(component:)
|
74
|
-
|
75
|
-
|
76
|
-
["accepted", Decidim::Faker::Localized.sentence(word_count: 10), Time.current]
|
77
|
-
elsif n > 2
|
78
|
-
["rejected", nil, Time.current]
|
79
|
-
elsif n > 1
|
80
|
-
["evaluating", nil, Time.current]
|
81
|
-
elsif n.positive?
|
82
|
-
["accepted", Decidim::Faker::Localized.sentence(word_count: 10), nil]
|
83
|
-
else
|
84
|
-
["not_answered", nil, nil]
|
85
|
-
end
|
79
|
+
proposal_state, answer, state_published_at = random_state_answer
|
80
|
+
proposal_state = Decidim::Proposals::ProposalState.where(component:, token: proposal_state).first
|
86
81
|
|
87
82
|
params = {
|
88
83
|
component:,
|
@@ -90,9 +85,9 @@ module Decidim
|
|
90
85
|
scope: random_scope(participatory_space:),
|
91
86
|
title: { en: ::Faker::Lorem.sentence(word_count: 2) },
|
92
87
|
body: { en: ::Faker::Lorem.paragraphs(number: 2).join("\n") },
|
93
|
-
|
88
|
+
proposal_state:,
|
94
89
|
answer:,
|
95
|
-
answered_at:
|
90
|
+
answered_at: proposal_state.present? ? Time.current : nil,
|
96
91
|
state_published_at:,
|
97
92
|
published_at: Time.current
|
98
93
|
}
|
@@ -104,26 +99,58 @@ module Decidim
|
|
104
99
|
visibility: "all"
|
105
100
|
) do
|
106
101
|
proposal = Decidim::Proposals::Proposal.new(params)
|
107
|
-
|
108
|
-
|
109
|
-
coauthor = case n
|
110
|
-
when 0
|
111
|
-
Decidim::User.where(organization:).sample
|
112
|
-
when 1
|
113
|
-
Decidim::UserGroup.where(organization:).sample
|
114
|
-
when 2
|
115
|
-
meeting_component = participatory_space.components.find_by(manifest_name: "meetings")
|
116
|
-
|
117
|
-
Decidim::Meetings::Meeting.where(component: meeting_component).sample
|
118
|
-
else
|
119
|
-
organization
|
120
|
-
end
|
102
|
+
coauthor = random_coauthor
|
121
103
|
proposal.add_coauthor(coauthor)
|
122
104
|
proposal.save!
|
105
|
+
|
106
|
+
Decidim::EventsManager.publish(
|
107
|
+
event: "decidim.events.proposals.proposal_published_for_space",
|
108
|
+
event_class: Decidim::Proposals::PublishProposalEvent,
|
109
|
+
resource: proposal,
|
110
|
+
followers: proposal.participatory_space.followers
|
111
|
+
)
|
112
|
+
|
123
113
|
proposal
|
124
114
|
end
|
115
|
+
|
116
|
+
create_attachment(attached_to: proposal, filename: "city.jpeg") if component.settings.attachments_allowed?
|
117
|
+
|
118
|
+
proposal
|
119
|
+
end
|
120
|
+
|
121
|
+
def random_state_answer
|
122
|
+
n = rand(5)
|
123
|
+
|
124
|
+
if n > 3
|
125
|
+
[:accepted, Decidim::Faker::Localized.sentence(word_count: 10), Time.current]
|
126
|
+
elsif n > 2
|
127
|
+
[:rejected, nil, Time.current]
|
128
|
+
elsif n > 1
|
129
|
+
[:evaluating, nil, Time.current]
|
130
|
+
elsif n.positive?
|
131
|
+
[:accepted, Decidim::Faker::Localized.sentence(word_count: 10), nil]
|
132
|
+
else
|
133
|
+
[:not_answered, nil, nil]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def random_coauthor
|
138
|
+
n = rand(5)
|
139
|
+
n = 3 if n == 2 && !Decidim.module_installed?(:meetings)
|
140
|
+
|
141
|
+
case n
|
142
|
+
when 0
|
143
|
+
Decidim::User.where(organization:).sample
|
144
|
+
when 1
|
145
|
+
Decidim::UserGroup.where(organization:).sample
|
146
|
+
when 2
|
147
|
+
meeting_component = participatory_space.components.find_by(manifest_name: "meetings")
|
148
|
+
|
149
|
+
Decidim::Meetings::Meeting.where(component: meeting_component).sample
|
150
|
+
else
|
151
|
+
organization
|
152
|
+
end
|
125
153
|
end
|
126
|
-
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
127
154
|
|
128
155
|
def random_nickname
|
129
156
|
"#{::Faker::Twitter.unique.screen_name}-#{SecureRandom.hex(4)}"[0, 20]
|
@@ -136,15 +163,7 @@ module Decidim
|
|
136
163
|
end
|
137
164
|
|
138
165
|
def create_emendation!(proposal:)
|
139
|
-
author =
|
140
|
-
author.update!(
|
141
|
-
password: "decidim123456789",
|
142
|
-
name: "#{::Faker::Name.name} #{participatory_space.id}",
|
143
|
-
nickname: random_nickname,
|
144
|
-
organization:,
|
145
|
-
tos_agreement: "1",
|
146
|
-
confirmed_at: Time.current
|
147
|
-
)
|
166
|
+
author = find_or_initialize_user_by(email: random_email(suffix: "amendment"))
|
148
167
|
|
149
168
|
group = Decidim::UserGroup.create!(
|
150
169
|
name: ::Faker::Name.name,
|
@@ -171,7 +190,7 @@ module Decidim
|
|
171
190
|
scope: random_scope(participatory_space:),
|
172
191
|
title: { en: "#{proposal.title["en"]} #{::Faker::Lorem.sentence(word_count: 1)}" },
|
173
192
|
body: { en: "#{proposal.body["en"]} #{::Faker::Lorem.sentence(word_count: 3)}" },
|
174
|
-
|
193
|
+
proposal_state: Decidim::Proposals::ProposalState.where(component: proposal.component, token: :evaluating).first,
|
175
194
|
answer: nil,
|
176
195
|
answered_at: Time.current,
|
177
196
|
published_at: Time.current
|
@@ -200,17 +219,7 @@ module Decidim
|
|
200
219
|
end
|
201
220
|
|
202
221
|
def create_proposal_votes!(proposal:, emendation: nil)
|
203
|
-
author =
|
204
|
-
author.update!(
|
205
|
-
password: "decidim123456789",
|
206
|
-
name: "#{::Faker::Name.name} #{participatory_space.id}",
|
207
|
-
nickname: random_nickname,
|
208
|
-
organization:,
|
209
|
-
tos_agreement: "1",
|
210
|
-
confirmed_at: Time.current,
|
211
|
-
personal_url: ::Faker::Internet.url,
|
212
|
-
about: ::Faker::Lorem.paragraph(sentence_count: 2)
|
213
|
-
)
|
222
|
+
author = find_or_initialize_user_by(email: random_email(suffix: "vote"))
|
214
223
|
|
215
224
|
Decidim::Proposals::ProposalVote.create!(proposal:, author:) unless proposal.published_state? && proposal.rejected?
|
216
225
|
Decidim::Proposals::ProposalVote.create!(proposal: emendation, author:) if emendation
|