decidim-proposals 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/app/assets/config/admin/decidim_proposals_manifest.js +1 -0
- data/app/assets/javascripts/decidim/proposals/admin/proposals.es6 +113 -0
- data/app/assets/javascripts/decidim/proposals/identity_selector_dialog.js.es6 +56 -0
- data/app/commands/decidim/proposals/admin/answer_proposal.rb +11 -5
- data/app/commands/decidim/proposals/admin/create_proposal.rb +25 -3
- data/app/commands/decidim/proposals/admin/create_proposal_note.rb +13 -8
- data/app/commands/decidim/proposals/admin/import_proposals.rb +83 -0
- data/app/commands/decidim/proposals/admin/update_proposal_category.rb +68 -0
- data/app/commands/decidim/proposals/create_proposal.rb +0 -12
- data/app/commands/decidim/proposals/endorse_proposal.rb +56 -0
- data/app/commands/decidim/proposals/publish_proposal.rb +60 -0
- data/app/commands/decidim/proposals/unendorse_proposal.rb +40 -0
- data/app/commands/decidim/proposals/update_proposal.rb +3 -3
- data/app/commands/decidim/proposals/vote_proposal.rb +1 -1
- data/app/commands/decidim/proposals/withdraw_proposal.rb +1 -1
- data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +1 -1
- data/app/controllers/decidim/proposals/admin/proposal_notes_controller.rb +2 -2
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +50 -1
- data/app/controllers/decidim/proposals/admin/proposals_imports_controller.rb +35 -0
- data/app/controllers/decidim/proposals/proposal_endorsements_controller.rb +56 -0
- data/app/controllers/decidim/proposals/proposals_controller.rb +82 -9
- data/app/events/decidim/proposals/admin/update_proposal_category_event.rb +11 -0
- data/app/events/decidim/proposals/creation_enabled_event.rb +8 -0
- data/app/events/decidim/proposals/endorsing_enabled_event.rb +8 -0
- data/app/events/decidim/proposals/proposal_endorsed_event.rb +29 -0
- data/app/events/decidim/proposals/publish_proposal_event.rb +21 -0
- data/app/events/decidim/proposals/voting_enabled_event.rb +8 -0
- data/app/forms/decidim/proposals/admin/proposal_form.rb +9 -2
- data/app/forms/decidim/proposals/admin/proposals_import_form.rb +60 -0
- data/app/forms/decidim/proposals/proposal_form.rb +16 -5
- data/app/helpers/decidim/proposals/application_helper.rb +1 -0
- data/app/helpers/decidim/proposals/proposal_endorsements_helper.rb +117 -0
- data/app/helpers/decidim/proposals/proposal_votes_helper.rb +13 -6
- data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +105 -0
- data/app/jobs/decidim/proposals/settings_change_job.rb +48 -0
- data/app/models/decidim/proposals/abilities/current_user_ability.rb +30 -8
- data/app/models/decidim/proposals/proposal.rb +38 -38
- data/app/models/decidim/proposals/proposal_endorsement.rb +31 -0
- data/app/models/decidim/proposals/proposal_note.rb +7 -0
- data/app/presenters/decidim/proposals/admin_log/proposal_note_presenter.rb +39 -0
- data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +47 -0
- data/app/presenters/decidim/proposals/admin_log/value_types/proposal_state_presenter.rb +16 -0
- data/app/queries/decidim/proposals/similar_proposals.rb +53 -0
- data/app/types/decidim/proposals/proposal_type.rb +34 -0
- data/app/types/decidim/proposals/proposals_type.rb +34 -0
- data/app/views/decidim/participatory_processes/participatory_process_groups/_highlighted_proposals.html.erb +8 -0
- data/app/views/decidim/participatory_processes/participatory_process_groups/_proposal.html.erb +27 -0
- data/app/views/decidim/participatory_spaces/_highlighted_proposals.html.erb +10 -0
- data/app/views/decidim/participatory_spaces/_proposal.html.erb +27 -0
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/_js-callout.html.erb +6 -0
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +63 -0
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +12 -73
- data/app/views/decidim/proposals/admin/proposals/update_category.js.erb +25 -0
- data/app/views/decidim/proposals/admin/proposals_imports/new.html.erb +28 -0
- data/app/views/decidim/proposals/proposal_endorsements/_identity.html.erb +4 -0
- data/app/views/decidim/proposals/proposal_endorsements/identities.html.erb +12 -0
- data/app/views/decidim/proposals/proposal_endorsements/update_buttons_and_counters.js.erb +9 -0
- data/app/views/decidim/proposals/proposals/_endorsement_button.html.erb +11 -0
- data/app/views/decidim/proposals/proposals/_endorsement_identities_cabin.html.erb +13 -0
- data/app/views/decidim/proposals/proposals/_endorsement_xxs.html.erb +9 -0
- data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +22 -0
- data/app/views/decidim/proposals/proposals/_endorsements_count.html.erb +5 -0
- data/app/views/decidim/proposals/proposals/_endorsements_listing.html.erb +34 -0
- data/app/views/decidim/proposals/proposals/_proposal.html.erb +2 -2
- data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +36 -0
- data/app/views/decidim/proposals/proposals/_proposal_similar.html.erb +21 -0
- data/app/views/decidim/proposals/proposals/_vote_button.html.erb +8 -8
- data/app/views/decidim/proposals/proposals/_votes_count.html.erb +23 -6
- data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +7 -3
- data/app/views/decidim/proposals/proposals/_wizard_aside.html.erb +16 -0
- data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +31 -0
- data/app/views/decidim/proposals/proposals/compare.html.erb +19 -0
- data/app/views/decidim/proposals/proposals/edit_draft.html.erb +55 -0
- data/app/views/decidim/proposals/proposals/new.html.erb +7 -20
- data/app/views/decidim/proposals/proposals/preview.html.erb +18 -0
- data/app/views/decidim/proposals/proposals/show.html.erb +13 -4
- data/config/locales/ca.yml +156 -15
- data/config/locales/en.yml +156 -15
- data/config/locales/es.yml +157 -16
- data/config/locales/eu.yml +151 -7
- data/config/locales/fi.yml +151 -7
- data/config/locales/fr.yml +153 -9
- data/config/locales/gl.yml +151 -7
- data/config/locales/it.yml +151 -7
- data/config/locales/nl.yml +151 -7
- data/config/locales/pl.yml +148 -22
- data/config/locales/pt-BR.yml +151 -7
- data/config/locales/pt.yml +151 -7
- data/config/locales/ru.yml +0 -9
- data/config/locales/sv.yml +151 -7
- data/config/locales/uk.yml +87 -13
- data/db/migrate/20170307085300_migrate_proposal_reports_data_to_reports.rb +1 -1
- data/db/migrate/20171201115434_create_proposal_endorsements.rb +16 -0
- data/db/migrate/20171201122623_add_counter_cache_endorsements_to_proposals.rb +8 -0
- data/db/migrate/20171212102250_enable_pg_extensions.rb +7 -0
- data/db/migrate/20171220084719_add_published_at_to_proposals.rb +14 -0
- data/lib/decidim/proposals.rb +15 -0
- data/lib/decidim/proposals/admin_engine.rb +8 -0
- data/lib/decidim/proposals/commentable_proposal.rb +39 -0
- data/lib/decidim/proposals/engine.rb +69 -1
- data/lib/decidim/proposals/feature.rb +51 -6
- data/lib/decidim/proposals/test/factories.rb +78 -2
- data/lib/decidim/proposals/version.rb +1 -1
- metadata +76 -20
- data/app/events/decidim/proposals/create_proposal_event.rb +0 -9
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen-string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
class ProposalEndorsedEvent < Decidim::Events::SimpleEvent
|
6
|
+
i18n_attributes :endorser_nickname, :endorser_name, :endorser_path, :nickname
|
7
|
+
|
8
|
+
delegate :nickname, :name, to: :endorser, prefix: true
|
9
|
+
|
10
|
+
def nickname
|
11
|
+
endorser_nickname
|
12
|
+
end
|
13
|
+
|
14
|
+
def endorser_path
|
15
|
+
endorser.profile_path
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def endorser
|
21
|
+
@endorser ||= Decidim::UserPresenter.new(endorser_user)
|
22
|
+
end
|
23
|
+
|
24
|
+
def endorser_user
|
25
|
+
@endorser_user ||= Decidim::User.find_by(id: extra[:endorser_id])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen-string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
class PublishProposalEvent < Decidim::Events::SimpleEvent
|
6
|
+
include Decidim::Events::AuthorEvent
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def i18n_scope
|
11
|
+
return super unless participatory_space_event?
|
12
|
+
|
13
|
+
"decidim.events.proposals.proposal_published_for_space"
|
14
|
+
end
|
15
|
+
|
16
|
+
def participatory_space_event?
|
17
|
+
extra.dig(:participatory_space)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -20,7 +20,8 @@ module Decidim
|
|
20
20
|
validates :address, geocoding: true, if: -> { current_feature.settings.geocoding_enabled? }
|
21
21
|
validates :category, presence: true, if: ->(form) { form.category_id.present? }
|
22
22
|
validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
|
23
|
-
|
23
|
+
|
24
|
+
validate :scope_belongs_to_participatory_space_scope
|
24
25
|
|
25
26
|
delegate :categories, to: :current_feature
|
26
27
|
|
@@ -43,7 +44,7 @@ module Decidim
|
|
43
44
|
#
|
44
45
|
# Returns a Decidim::Scope
|
45
46
|
def scope
|
46
|
-
@scope ||= @scope_id ?
|
47
|
+
@scope ||= @scope_id ? current_participatory_space.scopes.find_by(id: @scope_id) : current_participatory_space.scope
|
47
48
|
end
|
48
49
|
|
49
50
|
# Scope identifier
|
@@ -52,6 +53,12 @@ module Decidim
|
|
52
53
|
def scope_id
|
53
54
|
@scope_id || scope&.id
|
54
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def scope_belongs_to_participatory_space_scope
|
60
|
+
errors.add(:scope_id, :invalid) if current_participatory_space.out_of_scope?(scope)
|
61
|
+
end
|
55
62
|
end
|
56
63
|
end
|
57
64
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Admin
|
6
|
+
# A form object to be used when admin users want to import a collection of proposals
|
7
|
+
# from another component.
|
8
|
+
class ProposalsImportForm < Decidim::Form
|
9
|
+
mimic :proposals_import
|
10
|
+
|
11
|
+
attribute :origin_feature_id, Integer
|
12
|
+
attribute :import_proposals, Boolean
|
13
|
+
attribute :states, Array
|
14
|
+
|
15
|
+
validates :origin_feature_id, :origin_feature, :states, :current_feature, presence: true
|
16
|
+
validates :import_proposals, allow_nil: false, acceptance: true
|
17
|
+
validate :valid_states
|
18
|
+
|
19
|
+
VALID_STATES = %w(accepted not_answered evaluating rejected withdrawn).freeze
|
20
|
+
|
21
|
+
def states_collection
|
22
|
+
VALID_STATES.map do |state|
|
23
|
+
OpenStruct.new(
|
24
|
+
name: I18n.t(state, scope: "decidim.proposals.answers"),
|
25
|
+
value: state
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def states
|
31
|
+
super.reject(&:blank?)
|
32
|
+
end
|
33
|
+
|
34
|
+
def origin_feature
|
35
|
+
@origin_feature ||= origin_features.find_by(id: origin_feature_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def origin_features
|
39
|
+
@origin_features ||= current_participatory_space.features.where.not(id: current_feature.id).where(manifest_name: :proposals)
|
40
|
+
end
|
41
|
+
|
42
|
+
def origin_features_collection
|
43
|
+
origin_features.map do |feature|
|
44
|
+
[feature.name[I18n.locale.to_s], feature.id]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def valid_states
|
51
|
+
return if states.all? do |state|
|
52
|
+
VALID_STATES.include?(state)
|
53
|
+
end
|
54
|
+
|
55
|
+
errors.add(:states, :invalid)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -16,15 +16,15 @@ module Decidim
|
|
16
16
|
attribute :user_group_id, Integer
|
17
17
|
attribute :has_address, Boolean
|
18
18
|
attribute :attachment, AttachmentForm
|
19
|
-
|
20
19
|
validates :title, :body, presence: true, etiquette: true
|
21
20
|
validates :title, length: { maximum: 150 }
|
22
|
-
validates :body, length: { maximum: 500 }, etiquette: true
|
23
21
|
validates :address, geocoding: true, if: ->(form) { Decidim.geocoder.present? && form.has_address? }
|
24
22
|
validates :address, presence: true, if: ->(form) { form.has_address? }
|
25
23
|
validates :category, presence: true, if: ->(form) { form.category_id.present? }
|
26
24
|
validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
|
27
|
-
|
25
|
+
|
26
|
+
validate :proposal_length
|
27
|
+
validate :scope_belongs_to_participatory_space_scope
|
28
28
|
|
29
29
|
delegate :categories, to: :current_feature
|
30
30
|
|
@@ -35,7 +35,6 @@ module Decidim
|
|
35
35
|
end
|
36
36
|
|
37
37
|
alias feature current_feature
|
38
|
-
|
39
38
|
# Finds the Category from the category_id.
|
40
39
|
#
|
41
40
|
# Returns a Decidim::Category
|
@@ -47,7 +46,7 @@ module Decidim
|
|
47
46
|
#
|
48
47
|
# Returns a Decidim::Scope
|
49
48
|
def scope
|
50
|
-
@scope ||= @scope_id ?
|
49
|
+
@scope ||= @scope_id ? current_participatory_space.scopes.find_by(id: @scope_id) : current_participatory_space.scope
|
51
50
|
end
|
52
51
|
|
53
52
|
# Scope identifier
|
@@ -60,6 +59,18 @@ module Decidim
|
|
60
59
|
def has_address?
|
61
60
|
current_feature.settings.geocoding_enabled? && has_address
|
62
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def proposal_length
|
66
|
+
return unless body.presence
|
67
|
+
length = current_feature.settings.proposal_length
|
68
|
+
errors.add(:body, :too_long, count: length) if body.length > length
|
69
|
+
end
|
70
|
+
|
71
|
+
def scope_belongs_to_participatory_space_scope
|
72
|
+
errors.add(:scope_id, :invalid) if current_participatory_space.out_of_scope?(scope)
|
73
|
+
end
|
63
74
|
end
|
64
75
|
end
|
65
76
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
# Simple helper to handle markup variations for proposal endorsements partials
|
6
|
+
module ProposalEndorsementsHelper
|
7
|
+
# Returns the css classes used for proposal endorsements count in both proposals list and show pages
|
8
|
+
#
|
9
|
+
# from_proposals_list - A boolean to indicate if the template is rendered from the proposals list page
|
10
|
+
#
|
11
|
+
# Returns a hash with the css classes for the count number and label
|
12
|
+
def endorsements_count_classes(from_proposals_list)
|
13
|
+
return { number: "card__support__number", label: "" } if from_proposals_list
|
14
|
+
{ number: "extra__suport-number", label: "extra__suport-text" }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the css classes used for proposal endorsement button in both proposals list and show pages
|
18
|
+
#
|
19
|
+
# from_proposals_list - A boolean to indicate if the template is rendered from the proposals list page
|
20
|
+
#
|
21
|
+
# Returns a string with the value of the css classes.
|
22
|
+
def endorsement_button_classes(from_proposals_list)
|
23
|
+
return "small" if from_proposals_list
|
24
|
+
"small compact light button--sc expanded"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Checks if endorsement are enabled in this step.
|
28
|
+
#
|
29
|
+
# Returns true if enabled, false otherwise.
|
30
|
+
def endorsements_enabled?
|
31
|
+
current_settings.endorsements_enabled
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public: Checks if endorsements are blocked in this step.
|
35
|
+
#
|
36
|
+
# Returns true if blocked, false otherwise.
|
37
|
+
def endorsements_blocked?
|
38
|
+
current_settings.endorsements_blocked
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Checks if the current user is allowed to endorse in this step.
|
42
|
+
#
|
43
|
+
# Returns true if the current user can endorse, false otherwise.
|
44
|
+
def current_user_can_endorse?
|
45
|
+
current_user && endorsements_enabled? && !endorsements_blocked?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: Checks if the card for endorsements should be rendered.
|
49
|
+
#
|
50
|
+
# Returns true if the endorsements card should be rendered, false otherwise.
|
51
|
+
def show_endorsements_card?
|
52
|
+
endorsements_enabled?
|
53
|
+
end
|
54
|
+
|
55
|
+
def endorsement_identity(endorsement)
|
56
|
+
endorsement.user_group ? endorsement.user_group : endorsement.author
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Renders a button to endorse the given proposal.
|
60
|
+
# To override the translation for both buttons: endorse and unendorse (use to be the name of the user/user_group).
|
61
|
+
#
|
62
|
+
# @params (mandatory): proposal, from_proposals_list
|
63
|
+
# @params (optional) : user_group, btn_label
|
64
|
+
def endorsement_button(proposal, from_proposals_list, btn_label = nil, user_group = nil)
|
65
|
+
current_endorsement_url = proposal_proposal_endorsement_path(
|
66
|
+
proposal_id: proposal,
|
67
|
+
from_proposals_list: from_proposals_list,
|
68
|
+
user_group_id: user_group&.id
|
69
|
+
)
|
70
|
+
endorse_label = btn_label || t(".endorse")
|
71
|
+
unendorse_label = btn_label || t("decidim.proposals.proposal_endorsements_helper.endorsement_button.already_endorsed")
|
72
|
+
|
73
|
+
render partial: "decidim/proposals/proposals/endorsement_button", locals: { proposal: proposal,
|
74
|
+
from_proposals_list: from_proposals_list, user_group: user_group,
|
75
|
+
current_endorsement_url: current_endorsement_url,
|
76
|
+
endorse_label: endorse_label, unendorse_label: unendorse_label }
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Public: Checks if the given Proposal has been endorsed by all identities of the user.
|
81
|
+
#
|
82
|
+
# @param proposal: The Proposal from which endorsements will be checked against.
|
83
|
+
# @param user: The user whose identities and endorsements will be checked against.
|
84
|
+
#
|
85
|
+
def fully_endorsed?(proposal, user)
|
86
|
+
return false unless user
|
87
|
+
|
88
|
+
user_group_endorsements = user.user_groups.verified.all? { |user_group| proposal.endorsed_by?(user, user_group) }
|
89
|
+
|
90
|
+
user_group_endorsements && proposal.endorsed_by?(user)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Public: Renders an identity for endorsement.
|
94
|
+
#
|
95
|
+
# @params (mandatory): proposal, from_proposals_list
|
96
|
+
# @params (mandatory): user, the user that is endorsing at the end.
|
97
|
+
# @params (optional) : user_group, the user_group on behalf of which the endorsement is being done
|
98
|
+
def render_endorsement_identity(proposal, user, user_group = nil)
|
99
|
+
current_endorsement_url = proposal_proposal_endorsement_path(
|
100
|
+
proposal_id: proposal,
|
101
|
+
from_proposals_list: false,
|
102
|
+
user_group_id: user_group&.id,
|
103
|
+
authenticity_token: form_authenticity_token
|
104
|
+
)
|
105
|
+
presenter = if user_group
|
106
|
+
Decidim::UserGroupPresenter.new(user_group)
|
107
|
+
else
|
108
|
+
Decidim::UserPresenter.new(user)
|
109
|
+
end
|
110
|
+
selected = proposal.endorsed_by?(user, user_group)
|
111
|
+
http_method = selected ? :delete : :post
|
112
|
+
render partial: "decidim/proposals/proposal_endorsements/identity", locals:
|
113
|
+
{ identity: presenter, selected: selected, current_endorsement_url: current_endorsement_url, http_method: http_method }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -39,19 +39,26 @@ module Decidim
|
|
39
39
|
vote_limit.present?
|
40
40
|
end
|
41
41
|
|
42
|
-
# Public: Checks if
|
42
|
+
# Public: Checks if threshold per proposal are set.
|
43
43
|
#
|
44
44
|
# Returns true if set, false otherwise.
|
45
|
-
def
|
46
|
-
|
45
|
+
def threshold_per_proposal_enabled?
|
46
|
+
threshold_per_proposal.present?
|
47
47
|
end
|
48
48
|
|
49
49
|
# Public: Fetches the maximum amount of votes per proposal.
|
50
50
|
#
|
51
51
|
# Returns an Integer with the maximum amount of votes, nil otherwise.
|
52
|
-
def
|
53
|
-
return nil unless feature_settings.
|
54
|
-
feature_settings.
|
52
|
+
def threshold_per_proposal
|
53
|
+
return nil unless feature_settings.threshold_per_proposal.positive?
|
54
|
+
feature_settings.threshold_per_proposal
|
55
|
+
end
|
56
|
+
|
57
|
+
# Public: Checks if can accumulate more than maxium is enabled
|
58
|
+
#
|
59
|
+
# Returns true if enabled, false otherwise.
|
60
|
+
def can_accumulate_supports_beyond_threshold?
|
61
|
+
feature_settings.can_accumulate_supports_beyond_threshold
|
55
62
|
end
|
56
63
|
|
57
64
|
# Public: Checks if voting is enabled in this step.
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
# Simple helpers to handle markup variations for proposal wizard partials
|
6
|
+
module ProposalWizardHelper
|
7
|
+
# Returns the css classes used for the proposal wizard for the desired step
|
8
|
+
#
|
9
|
+
# step - A symbol of the target step
|
10
|
+
# current_step - A symbol of the current step
|
11
|
+
#
|
12
|
+
# Returns a string with the css classes for the desired step
|
13
|
+
def proposal_wizard_step_classes(step, current_step)
|
14
|
+
step_i = step.to_s.split("_").last.to_i
|
15
|
+
if step_i == proposal_wizard_step_number(current_step)
|
16
|
+
%(step--active #{step} #{current_step})
|
17
|
+
elsif step_i < proposal_wizard_step_number(current_step)
|
18
|
+
%(step--past #{step})
|
19
|
+
else
|
20
|
+
%()
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the number of the step
|
25
|
+
#
|
26
|
+
# step - A symbol of the target step
|
27
|
+
def proposal_wizard_step_number(step)
|
28
|
+
step.to_s.split("_").last.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the name of the step, translated
|
32
|
+
#
|
33
|
+
# step - A symbol of the target step
|
34
|
+
def proposal_wizard_step_name(step)
|
35
|
+
t(:"decidim.proposals.proposals.wizard_steps.#{step}")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the page title of the given step, translated
|
39
|
+
#
|
40
|
+
# action_name - A string of the rendered action
|
41
|
+
def proposal_wizard_step_title(action_name)
|
42
|
+
step_title = case action_name
|
43
|
+
when "create"
|
44
|
+
"new"
|
45
|
+
when "update_draft"
|
46
|
+
"edit_draft"
|
47
|
+
else
|
48
|
+
action_name
|
49
|
+
end
|
50
|
+
|
51
|
+
t("decidim.proposals.proposals.#{step_title}.title")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the list item of the given step, in html
|
55
|
+
#
|
56
|
+
# step - A symbol of the target step
|
57
|
+
# current_step - A symbol of the current step
|
58
|
+
def proposal_wizard_stepper_step(step, current_step)
|
59
|
+
content_tag(:li, proposal_wizard_step_name(step), class: proposal_wizard_step_classes(step, current_step).to_s)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the list with all the steps, in html
|
63
|
+
#
|
64
|
+
# current_step - A symbol of the current step
|
65
|
+
def proposal_wizard_stepper(current_step)
|
66
|
+
content_tag :ol, class: "wizard__steps" do
|
67
|
+
%(
|
68
|
+
#{proposal_wizard_stepper_step(:step_1, current_step)}
|
69
|
+
#{proposal_wizard_stepper_step(:step_2, current_step)}
|
70
|
+
#{proposal_wizard_stepper_step(:step_3, current_step)}
|
71
|
+
).html_safe
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns a string with the current step number and the total steps number
|
76
|
+
#
|
77
|
+
# step - A symbol of the target step
|
78
|
+
def proposal_wizard_current_step_of(step)
|
79
|
+
current_step_num = proposal_wizard_step_number(step)
|
80
|
+
content_tag :span, class: "text-small" do
|
81
|
+
concat t(:"decidim.proposals.proposals.wizard_steps.step_of", current_step_num: current_step_num, total_steps: 3)
|
82
|
+
concat " ("
|
83
|
+
concat content_tag :a, t(:"decidim.proposals.proposals.wizard_steps.see_steps"), "data-toggle": "steps"
|
84
|
+
concat ")"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns a boolean if the step has a help text defined
|
89
|
+
#
|
90
|
+
# step - A symbol of the target step
|
91
|
+
def proposal_wizard_step_help_text?(step)
|
92
|
+
translated_attribute(feature_settings.try("proposal_wizard_#{step}_help_text")).present?
|
93
|
+
end
|
94
|
+
|
95
|
+
# Renders a user_group select field in a form.
|
96
|
+
# form - FormBuilder object
|
97
|
+
# name - attribute user_group_id
|
98
|
+
#
|
99
|
+
# Returns nothing.
|
100
|
+
def user_group_select_field(form, name)
|
101
|
+
form.select(name, current_user.user_groups.verified.map { |g| [g.name, g.id] }, prompt: current_user.name)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|