decidim-proposals 0.28.1 → 0.29.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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_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 +0 -2
- 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 +2 -2
- 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/concerns/decidim/proposals/orderable.rb +1 -1
- 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 +30 -35
- data/app/events/decidim/proposals/proposal_state_changed_event.rb +37 -0
- data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +5 -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 +17 -11
- 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 +78 -28
- 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/entrypoints/participatory_texts_admin.js +2 -0
- 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/admin/participatory_texts.scss +23 -0
- data/app/packs/stylesheets/decidim/proposals/proposals.scss +39 -1
- data/app/permissions/decidim/proposals/admin/permissions.rb +16 -4
- data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -5
- data/app/presenters/decidim/proposals/admin_log/proposal_state_presenter.rb +21 -0
- data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +1 -3
- data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +1 -1
- 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 -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 +9 -5
- data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +1 -1
- 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 +0 -2
- 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 -5
- 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 +5 -3
- 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/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/show.html.erb +1 -1
- data/config/assets.rb +1 -0
- data/config/locales/ar.yml +5 -119
- data/config/locales/bg.yml +741 -42
- data/config/locales/ca.yml +88 -85
- data/config/locales/cs.yml +62 -124
- data/config/locales/de.yml +111 -108
- data/config/locales/el.yml +2 -123
- data/config/locales/en.yml +113 -110
- data/config/locales/es-MX.yml +86 -83
- data/config/locales/es-PY.yml +88 -85
- data/config/locales/es.yml +87 -84
- data/config/locales/eu.yml +104 -108
- data/config/locales/fi-plain.yml +91 -88
- data/config/locales/fi.yml +113 -110
- data/config/locales/fr-CA.yml +89 -86
- data/config/locales/fr.yml +81 -78
- data/config/locales/ga-IE.yml +1 -21
- data/config/locales/gl.yml +4 -109
- data/config/locales/he-IL.yml +0 -13
- data/config/locales/hu.yml +14 -91
- data/config/locales/id-ID.yml +1 -98
- data/config/locales/is-IS.yml +0 -35
- data/config/locales/it.yml +5 -97
- data/config/locales/ja.yml +112 -109
- data/config/locales/lb.yml +1 -0
- data/config/locales/lt.yml +2 -127
- data/config/locales/lv.yml +1 -97
- data/config/locales/nl.yml +5 -100
- data/config/locales/no.yml +2 -112
- data/config/locales/pl.yml +201 -107
- data/config/locales/pt-BR.yml +4 -82
- data/config/locales/pt.yml +4 -112
- data/config/locales/ro-RO.yml +5 -114
- data/config/locales/ru.yml +1 -55
- data/config/locales/sk.yml +1 -104
- data/config/locales/sv.yml +20 -108
- data/config/locales/tr-TR.yml +57 -103
- data/config/locales/uk.yml +2 -56
- data/config/locales/zh-CN.yml +1 -100
- data/config/locales/zh-TW.yml +2 -121
- 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 +2 -2
- data/lib/decidim/api/proposal_type.rb +4 -0
- data/lib/decidim/proposals/admin_engine.rb +8 -0
- data/lib/decidim/proposals/admin_filter.rb +37 -0
- data/lib/decidim/proposals/component.rb +10 -9
- 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 +56 -3
- data/lib/decidim/proposals/seeds.rb +60 -47
- data/lib/decidim/proposals/test/factories.rb +77 -9
- data/lib/decidim/proposals/version.rb +1 -1
- data/lib/decidim/proposals.rb +84 -12
- data/lib/tasks/proposals/upgrade/decidim_proposals_upgrade_tasks.rake +32 -0
- metadata +55 -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/presenters/decidim/proposals/log/resource_presenter.rb +0 -22
- data/app/queries/decidim/proposals/similar_proposals.rb +0 -67
- 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/lib/tasks/proposals/upgrade/decdim_proposal_upgrade_tasks.rake +0 -34
@@ -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
@@ -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
|
@@ -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
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "decidim/meetings"
|
4
|
-
|
5
3
|
Decidim.register_component(:proposals) do |component|
|
6
4
|
component.engine = Decidim::Proposals::Engine
|
7
5
|
component.admin_engine = Decidim::Proposals::AdminEngine
|
@@ -13,6 +11,11 @@ Decidim.register_component(:proposals) do |component|
|
|
13
11
|
raise "Cannot destroy this component when there are proposals" if Decidim::Proposals::Proposal.where(component: instance).any?
|
14
12
|
end
|
15
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
|
+
|
16
19
|
component.data_portable_entities = ["Decidim::Proposals::Proposal"]
|
17
20
|
|
18
21
|
component.newsletter_participant_entities = ["Decidim::Proposals::Proposal"]
|
@@ -23,7 +26,7 @@ Decidim.register_component(:proposals) do |component|
|
|
23
26
|
|
24
27
|
component.permissions_class_name = "Decidim::Proposals::Permissions"
|
25
28
|
|
26
|
-
POSSIBLE_SORT_ORDERS = %w(
|
29
|
+
POSSIBLE_SORT_ORDERS = %w(automatic random recent most_endorsed most_voted most_commented most_followed with_more_authors).freeze
|
27
30
|
|
28
31
|
component.settings(:global) do |settings|
|
29
32
|
settings.attribute :scopes_enabled, type: :boolean, default: false
|
@@ -35,9 +38,9 @@ Decidim.register_component(:proposals) do |component|
|
|
35
38
|
settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: -> { %w(limited infinite) }
|
36
39
|
settings.attribute :proposal_edit_before_minutes, type: :integer, default: 5, required: true
|
37
40
|
settings.attribute :threshold_per_proposal, type: :integer, default: 0, required: true
|
38
|
-
settings.attribute :
|
41
|
+
settings.attribute :can_accumulate_votes_beyond_threshold, type: :boolean, default: false
|
39
42
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
40
|
-
settings.attribute :default_sort_order, type: :select, default: "
|
43
|
+
settings.attribute :default_sort_order, type: :select, default: "automatic", choices: -> { POSSIBLE_SORT_ORDERS }
|
41
44
|
settings.attribute :official_proposals_enabled, type: :boolean, default: true
|
42
45
|
settings.attribute :comments_enabled, type: :boolean, default: true
|
43
46
|
settings.attribute :comments_max_length, type: :integer, required: true
|
@@ -58,8 +61,6 @@ Decidim.register_component(:proposals) do |component|
|
|
58
61
|
settings.attribute :new_proposal_help_text, type: :text, translated: true, editor: true
|
59
62
|
settings.attribute :proposal_wizard_step_1_help_text, type: :text, translated: true, editor: true
|
60
63
|
settings.attribute :proposal_wizard_step_2_help_text, type: :text, translated: true, editor: true
|
61
|
-
settings.attribute :proposal_wizard_step_3_help_text, type: :text, translated: true, editor: true
|
62
|
-
settings.attribute :proposal_wizard_step_4_help_text, type: :text, translated: true, editor: true
|
63
64
|
end
|
64
65
|
|
65
66
|
component.settings(:step) do |settings|
|
@@ -101,14 +102,14 @@ Decidim.register_component(:proposals) do |component|
|
|
101
102
|
end
|
102
103
|
|
103
104
|
component.register_stat :proposals_count, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
104
|
-
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
|
105
106
|
end
|
106
107
|
|
107
108
|
component.register_stat :proposals_accepted, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
108
109
|
Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).accepted.not_hidden.count
|
109
110
|
end
|
110
111
|
|
111
|
-
component.register_stat :
|
112
|
+
component.register_stat :votes_count, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
|
112
113
|
proposals = Decidim::Proposals::FilteredProposals.for(components, start_at, end_at).published.not_hidden
|
113
114
|
Decidim::Proposals::ProposalVote.where(proposal: proposals).count
|
114
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
|
|
@@ -19,6 +19,9 @@ module Decidim
|
|
19
19
|
def serialize
|
20
20
|
{
|
21
21
|
id: proposal.id,
|
22
|
+
author: {
|
23
|
+
**author_fields
|
24
|
+
},
|
22
25
|
category: {
|
23
26
|
id: proposal.category.try(:id),
|
24
27
|
name: proposal.category.try(:name) || empty_translatable
|
@@ -41,13 +44,13 @@ module Decidim
|
|
41
44
|
reference: proposal.reference,
|
42
45
|
answer: ensure_translatable(proposal.answer),
|
43
46
|
answered_at: proposal.answered_at,
|
44
|
-
|
47
|
+
votes: proposal.proposal_votes_count,
|
45
48
|
endorsements: {
|
46
49
|
total_count: proposal.endorsements.size,
|
47
50
|
user_endorsements:
|
48
51
|
},
|
49
52
|
comments: proposal.comments_count,
|
50
|
-
attachments: proposal.attachments.
|
53
|
+
attachments: proposal.attachments.size,
|
51
54
|
followers: proposal.follows.size,
|
52
55
|
published_at: proposal.published_at,
|
53
56
|
url:,
|
@@ -57,7 +60,9 @@ module Decidim
|
|
57
60
|
original_proposal: {
|
58
61
|
title: proposal&.amendable&.title,
|
59
62
|
url: original_proposal_url
|
60
|
-
}
|
63
|
+
},
|
64
|
+
withdrawn: proposal.withdrawn?,
|
65
|
+
withdrawn_at: proposal.withdrawn_at
|
61
66
|
}
|
62
67
|
end
|
63
68
|
|
@@ -102,6 +107,54 @@ module Decidim
|
|
102
107
|
|
103
108
|
convert_to_text(value)
|
104
109
|
end
|
110
|
+
|
111
|
+
def author_fields
|
112
|
+
is_author_user_group = resource.coauthorships.map(&:decidim_user_group_id).any?
|
113
|
+
|
114
|
+
{
|
115
|
+
id: resource.authors.map(&:id),
|
116
|
+
name: resource.authors.map do |author|
|
117
|
+
author_name(is_author_user_group ? resource.coauthorships.first.user_group : author)
|
118
|
+
end,
|
119
|
+
url: resource.authors.map do |author|
|
120
|
+
author_url(is_author_user_group ? resource.coauthorships.first.user_group : author)
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def author_name(author)
|
126
|
+
if author.respond_to?(:name)
|
127
|
+
translated_attribute(author.name) # is a Decidim::User or Decidim::Organization or Decidim::UserGroup
|
128
|
+
elsif author.respond_to?(:title)
|
129
|
+
translated_attribute(author.title) # is a Decidim::Meetings::Meeting
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def author_url(author)
|
134
|
+
if author.respond_to?(:nickname)
|
135
|
+
profile_url(author.nickname) # is a Decidim::User or Decidim::UserGroup
|
136
|
+
elsif author.respond_to?(:title)
|
137
|
+
meeting_url(author) # is a Decidim::Meetings::Meeting
|
138
|
+
else
|
139
|
+
root_url # is a Decidim::Organization
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def profile_url(nickname)
|
144
|
+
Decidim::Core::Engine.routes.url_helpers.profile_url(nickname, host:)
|
145
|
+
end
|
146
|
+
|
147
|
+
def meeting_url(meeting)
|
148
|
+
Decidim::EngineRouter.main_proxy(meeting.component).meeting_url(id: meeting.id, host:)
|
149
|
+
end
|
150
|
+
|
151
|
+
def root_url
|
152
|
+
Decidim::Core::Engine.routes.url_helpers.root_url(host:)
|
153
|
+
end
|
154
|
+
|
155
|
+
def host
|
156
|
+
resource.organization.host
|
157
|
+
end
|
105
158
|
end
|
106
159
|
end
|
107
160
|
end
|
@@ -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:
|
@@ -70,18 +76,8 @@ module Decidim
|
|
70
76
|
end
|
71
77
|
|
72
78
|
def create_proposal!(component:)
|
73
|
-
|
74
|
-
|
75
|
-
["accepted", Decidim::Faker::Localized.sentence(word_count: 10), Time.current]
|
76
|
-
elsif n > 2
|
77
|
-
["rejected", nil, Time.current]
|
78
|
-
elsif n > 1
|
79
|
-
["evaluating", nil, Time.current]
|
80
|
-
elsif n.positive?
|
81
|
-
["accepted", Decidim::Faker::Localized.sentence(word_count: 10), nil]
|
82
|
-
else
|
83
|
-
["not_answered", nil, nil]
|
84
|
-
end
|
79
|
+
proposal_state, answer, state_published_at = random_state_answer
|
80
|
+
proposal_state = Decidim::Proposals::ProposalState.where(component:, token: proposal_state).first
|
85
81
|
|
86
82
|
params = {
|
87
83
|
component:,
|
@@ -89,9 +85,9 @@ module Decidim
|
|
89
85
|
scope: random_scope(participatory_space:),
|
90
86
|
title: { en: ::Faker::Lorem.sentence(word_count: 2) },
|
91
87
|
body: { en: ::Faker::Lorem.paragraphs(number: 2).join("\n") },
|
92
|
-
|
88
|
+
proposal_state:,
|
93
89
|
answer:,
|
94
|
-
answered_at:
|
90
|
+
answered_at: proposal_state.present? ? Time.current : nil,
|
95
91
|
state_published_at:,
|
96
92
|
published_at: Time.current
|
97
93
|
}
|
@@ -103,22 +99,57 @@ module Decidim
|
|
103
99
|
visibility: "all"
|
104
100
|
) do
|
105
101
|
proposal = Decidim::Proposals::Proposal.new(params)
|
106
|
-
|
107
|
-
|
108
|
-
coauthor = case n
|
109
|
-
when 0
|
110
|
-
Decidim::User.where(organization:).sample
|
111
|
-
when 1
|
112
|
-
Decidim::UserGroup.where(organization:).sample
|
113
|
-
when 2
|
114
|
-
Decidim::Meetings::Meeting.where(component: meeting_component).sample
|
115
|
-
else
|
116
|
-
organization
|
117
|
-
end
|
102
|
+
coauthor = random_coauthor
|
118
103
|
proposal.add_coauthor(coauthor)
|
119
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
|
+
|
120
113
|
proposal
|
121
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
|
122
153
|
end
|
123
154
|
|
124
155
|
def random_nickname
|
@@ -132,15 +163,7 @@ module Decidim
|
|
132
163
|
end
|
133
164
|
|
134
165
|
def create_emendation!(proposal:)
|
135
|
-
author =
|
136
|
-
author.update!(
|
137
|
-
password: "decidim123456789",
|
138
|
-
name: "#{::Faker::Name.name} #{participatory_space.id}",
|
139
|
-
nickname: random_nickname,
|
140
|
-
organization:,
|
141
|
-
tos_agreement: "1",
|
142
|
-
confirmed_at: Time.current
|
143
|
-
)
|
166
|
+
author = find_or_initialize_user_by(email: random_email(suffix: "amendment"))
|
144
167
|
|
145
168
|
group = Decidim::UserGroup.create!(
|
146
169
|
name: ::Faker::Name.name,
|
@@ -167,7 +190,7 @@ module Decidim
|
|
167
190
|
scope: random_scope(participatory_space:),
|
168
191
|
title: { en: "#{proposal.title["en"]} #{::Faker::Lorem.sentence(word_count: 1)}" },
|
169
192
|
body: { en: "#{proposal.body["en"]} #{::Faker::Lorem.sentence(word_count: 3)}" },
|
170
|
-
|
193
|
+
proposal_state: Decidim::Proposals::ProposalState.where(component: proposal.component, token: :evaluating).first,
|
171
194
|
answer: nil,
|
172
195
|
answered_at: Time.current,
|
173
196
|
published_at: Time.current
|
@@ -196,17 +219,7 @@ module Decidim
|
|
196
219
|
end
|
197
220
|
|
198
221
|
def create_proposal_votes!(proposal:, emendation: nil)
|
199
|
-
author =
|
200
|
-
author.update!(
|
201
|
-
password: "decidim123456789",
|
202
|
-
name: "#{::Faker::Name.name} #{participatory_space.id}",
|
203
|
-
nickname: random_nickname,
|
204
|
-
organization:,
|
205
|
-
tos_agreement: "1",
|
206
|
-
confirmed_at: Time.current,
|
207
|
-
personal_url: ::Faker::Internet.url,
|
208
|
-
about: ::Faker::Lorem.paragraph(sentence_count: 2)
|
209
|
-
)
|
222
|
+
author = find_or_initialize_user_by(email: random_email(suffix: "vote"))
|
210
223
|
|
211
224
|
Decidim::Proposals::ProposalVote.create!(proposal:, author:) unless proposal.published_state? && proposal.rejected?
|
212
225
|
Decidim::Proposals::ProposalVote.create!(proposal: emendation, author:) if emendation
|