decidim-elections 0.22.0 → 0.23.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/decidim_elections_manifest.js +2 -0
- data/app/assets/javascripts/decidim/elections/vote.js.es6 +170 -0
- data/app/assets/stylesheets/decidim/elections/elections.scss +10 -0
- data/app/assets/stylesheets/decidim/elections/focus/_evote.scss +279 -0
- data/app/assets/stylesheets/decidim/elections/focus/_focus.scss +128 -0
- data/app/cells/decidim/elections/election_cell.rb +22 -0
- data/app/cells/decidim/elections/election_m/data.erb +19 -0
- data/app/cells/decidim/elections/election_m/footer.erb +5 -0
- data/app/cells/decidim/elections/election_m_cell.rb +103 -0
- data/app/cells/decidim/elections/voting_step_navigation/show.erb +29 -0
- data/app/cells/decidim/elections/voting_step_navigation_cell.rb +42 -0
- data/app/commands/decidim/elections/admin/create_election.rb +14 -3
- data/app/commands/decidim/elections/admin/create_question.rb +2 -1
- data/app/commands/decidim/elections/admin/destroy_election.rb +4 -0
- data/app/commands/decidim/elections/admin/import_proposals_to_elections.rb +87 -0
- data/app/commands/decidim/elections/admin/publish_election.rb +54 -0
- data/app/commands/decidim/elections/admin/unpublish_election.rb +43 -0
- data/app/commands/decidim/elections/admin/update_election.rb +15 -3
- data/app/commands/decidim/elections/admin/update_question.rb +2 -1
- data/app/controllers/concerns/decidim/elections/orderable.rb +36 -0
- data/app/controllers/decidim/elections/admin/answers_controller.rb +9 -1
- data/app/controllers/decidim/elections/admin/elections_controller.rb +26 -0
- data/app/controllers/decidim/elections/admin/proposals_imports_controller.rb +53 -0
- data/app/controllers/decidim/elections/elections_controller.rb +68 -0
- data/app/controllers/decidim/elections/votes_controller.rb +50 -0
- data/app/events/decidim/elections/election_published_event.rb +8 -0
- data/app/forms/decidim/elections/admin/answer_import_proposals_form.rb +41 -0
- data/app/forms/decidim/elections/admin/election_form.rb +15 -2
- data/app/forms/decidim/elections/admin/question_form.rb +1 -0
- data/app/helpers/decidim/elections/application_helper.rb +12 -0
- data/app/helpers/decidim/elections/election_cells_helper.rb +12 -0
- data/app/helpers/decidim/elections/votes_helper.rb +21 -0
- data/app/models/decidim/elections/answer.rb +5 -1
- data/app/models/decidim/elections/election.rb +69 -0
- data/app/models/decidim/elections/question.rb +9 -2
- data/app/permissions/decidim/elections/admin/permissions.rb +13 -3
- data/app/permissions/decidim/elections/permissions.rb +35 -0
- data/app/presenters/decidim/elections/admin_log/election_presenter.rb +41 -0
- data/app/presenters/decidim/elections/election_presenter.rb +28 -0
- data/app/queries/decidim/elections/filtered_elections.rb +37 -0
- data/app/services/decidim/elections/election_search.rb +35 -0
- data/app/types/decidim/elections/election_question_type.rb +2 -2
- data/app/types/decidim/elections/election_type.rb +2 -1
- data/app/types/decidim/elections/elections_type.rb +1 -1
- data/app/views/decidim/elections/admin/answers/index.html.erb +2 -1
- data/app/views/decidim/elections/admin/elections/_form.html.erb +2 -4
- data/app/views/decidim/elections/admin/elections/index.html.erb +23 -1
- data/app/views/decidim/elections/admin/proposals_imports/new.html.erb +24 -0
- data/app/views/decidim/elections/admin/questions/_form.html.erb +4 -0
- data/app/views/decidim/elections/admin/questions/index.html.erb +3 -1
- data/app/views/decidim/elections/elections/_count.html.erb +1 -0
- data/app/views/decidim/elections/elections/_election.html.erb +1 -0
- data/app/views/decidim/elections/elections/_elections.html.erb +24 -0
- data/app/views/decidim/elections/elections/_filters.html.erb +24 -0
- data/app/views/decidim/elections/elections/_filters_small_view.html.erb +18 -0
- data/app/views/decidim/elections/elections/index.html.erb +24 -0
- data/app/views/decidim/elections/elections/index.js.erb +10 -0
- data/app/views/decidim/elections/elections/show.html.erb +64 -0
- data/app/views/decidim/elections/votes/_election_votes_confirm.html.erb +53 -0
- data/app/views/decidim/elections/votes/_election_votes_confirm_footer.html.erb +24 -0
- data/app/views/decidim/elections/votes/_election_votes_confirmed.html.erb +26 -0
- data/app/views/decidim/elections/votes/_election_votes_encrypting.html.erb +20 -0
- data/app/views/decidim/elections/votes/_election_votes_header.html.erb +8 -0
- data/app/views/decidim/elections/votes/_election_votes_modal.html.erb +46 -0
- data/app/views/decidim/elections/votes/_election_votes_question.html.erb +49 -0
- data/app/views/decidim/elections/votes/_election_votes_steps_header.html.erb +12 -0
- data/app/views/decidim/elections/votes/new.html.erb +44 -0
- data/app/views/layouts/decidim/_election_votes_header.html.erb +13 -0
- data/app/views/layouts/decidim/election_votes.html.erb +24 -0
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/bg.yml +7 -0
- data/config/locales/ca.yml +136 -6
- data/config/locales/cs.yml +133 -1
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +134 -4
- data/config/locales/el.yml +11 -1
- data/config/locales/en.yml +131 -1
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +131 -1
- data/config/locales/es-PY.yml +131 -1
- data/config/locales/es.yml +134 -4
- data/config/locales/et.yml +1 -0
- data/config/locales/fi-plain.yml +131 -1
- data/config/locales/fi.yml +131 -1
- data/config/locales/fr-CA.yml +131 -1
- data/config/locales/fr.yml +131 -1
- data/config/locales/gl.yml +111 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +18 -0
- data/config/locales/is.yml +1 -0
- data/config/locales/it.yml +98 -1
- data/config/locales/ja-JP.yml +95 -8
- data/config/locales/ja.yml +254 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/{lv-LV.yml → lv.yml} +11 -1
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +92 -1
- data/config/locales/no.yml +63 -0
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +126 -1
- data/config/locales/pt.yml +84 -1
- data/config/locales/ro-RO.yml +85 -1
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sv.yml +122 -2
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +261 -0
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +254 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20200601141412_add_published_at_to_elections.rb +7 -0
- data/db/migrate/20200807125040_remove_subtitle_from_decidim_elections.rb +7 -0
- data/db/migrate/20200910103648_add_min_selections_to_decidim_elections_questions.rb +7 -0
- data/lib/decidim/elections.rb +5 -0
- data/lib/decidim/elections/admin_engine.rb +7 -0
- data/lib/decidim/elections/bulletin_board_client.rb +35 -0
- data/lib/decidim/elections/component.rb +17 -12
- data/lib/decidim/elections/engine.rb +8 -1
- data/lib/decidim/elections/test/factories.rb +59 -6
- data/lib/decidim/elections/version.rb +1 -1
- data/lib/tasks/decidim_elections.rake +16 -0
- metadata +84 -16
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
module Admin
|
6
|
+
# A form object to be used when admin users want to import a collection of proposals
|
7
|
+
# from another component into answers resource.
|
8
|
+
class AnswerImportProposalsForm < Decidim::Form
|
9
|
+
mimic :proposals_import
|
10
|
+
|
11
|
+
attribute :origin_component_id, Integer
|
12
|
+
attribute :import_all_accepted_proposals, Boolean
|
13
|
+
attribute :weight, Integer, default: 0
|
14
|
+
|
15
|
+
validates :origin_component_id, :origin_component, :current_component, presence: true
|
16
|
+
|
17
|
+
def origin_component
|
18
|
+
@origin_component ||= origin_components.find_by(id: origin_component_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def origin_components
|
22
|
+
@origin_components ||= current_participatory_space.components.where(manifest_name: :proposals)
|
23
|
+
end
|
24
|
+
|
25
|
+
def origin_components_collection
|
26
|
+
origin_components.map do |component|
|
27
|
+
[component.name[I18n.locale.to_s], component.id]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def election
|
32
|
+
@election ||= context[:election]
|
33
|
+
end
|
34
|
+
|
35
|
+
def question
|
36
|
+
@question ||= context[:question]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -8,16 +8,29 @@ module Decidim
|
|
8
8
|
include TranslatableAttributes
|
9
9
|
|
10
10
|
translatable_attribute :title, String
|
11
|
-
translatable_attribute :subtitle, String
|
12
11
|
translatable_attribute :description, String
|
13
12
|
attribute :start_time, Decidim::Attributes::TimeWithZone
|
14
13
|
attribute :end_time, Decidim::Attributes::TimeWithZone
|
14
|
+
attribute :attachment, AttachmentForm
|
15
|
+
attribute :photos, Array[String]
|
16
|
+
attribute :add_photos, Array
|
15
17
|
|
16
18
|
validates :title, translatable_presence: true
|
17
|
-
validates :subtitle, translatable_presence: true
|
18
19
|
validates :description, translatable_presence: true
|
19
20
|
validates :start_time, presence: true, date: { before: :end_time }
|
20
21
|
validates :end_time, presence: true, date: { after: :start_time }
|
22
|
+
validate :notify_missing_attachment_if_errored
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# This method will add an error to the `photos` field only if there's
|
27
|
+
# any error in any other field. This is needed because when the form has
|
28
|
+
# an error, the attachment is lost, so we need a way to inform the user of
|
29
|
+
# this problem.
|
30
|
+
def notify_missing_attachment_if_errored
|
31
|
+
errors.add(:attachment, :needs_to_be_reattached) if errors.any? && attachment.present?
|
32
|
+
errors.add(:add_photos, :needs_to_be_reattached) if errors.any? && add_photos.present?
|
33
|
+
end
|
21
34
|
end
|
22
35
|
end
|
23
36
|
end
|
@@ -12,6 +12,7 @@ module Decidim
|
|
12
12
|
attribute :max_selections, Integer, default: 1
|
13
13
|
attribute :weight, Integer, default: 0
|
14
14
|
attribute :random_answers_order, Boolean, default: true
|
15
|
+
attribute :min_selections, Integer, default: 1
|
15
16
|
|
16
17
|
validates :title, translatable_presence: true
|
17
18
|
validates :description, translatable_presence: true
|
@@ -5,6 +5,18 @@ module Decidim
|
|
5
5
|
# Custom helpers, scoped to the elections engine.
|
6
6
|
#
|
7
7
|
module ApplicationHelper
|
8
|
+
include Decidim::CheckBoxesTreeHelper
|
9
|
+
|
10
|
+
def state_filter_values
|
11
|
+
TreeNode.new(
|
12
|
+
TreePoint.new("", t("elections.elections.filters.all", scope: "decidim")),
|
13
|
+
[
|
14
|
+
TreePoint.new("active", t("elections.elections.filters.active", scope: "decidim")),
|
15
|
+
TreePoint.new("upcoming", t("elections.elections.filters.upcoming", scope: "decidim")),
|
16
|
+
TreePoint.new("finished", t("elections.elections.filters.finished", scope: "decidim"))
|
17
|
+
]
|
18
|
+
)
|
19
|
+
end
|
8
20
|
end
|
9
21
|
end
|
10
22
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
# Custom helpers for the voting booth views.
|
6
|
+
#
|
7
|
+
module VotesHelper
|
8
|
+
def ordered_answers(question)
|
9
|
+
if question.random_answers_order
|
10
|
+
question.answers.shuffle
|
11
|
+
else
|
12
|
+
question.answers.sort_by { |answer| [answer.weight, answer.id] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def more_information?(answer)
|
17
|
+
answer.description || answer.proposals.any? || answer.photos.any?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -11,13 +11,17 @@ module Decidim
|
|
11
11
|
include Traceable
|
12
12
|
include Loggable
|
13
13
|
|
14
|
-
delegate :component, to: :question
|
15
14
|
delegate :organization, :participatory_space, to: :component
|
16
15
|
|
17
16
|
belongs_to :question, foreign_key: "decidim_elections_question_id", class_name: "Decidim::Elections::Question", inverse_of: :answers
|
17
|
+
has_one :election, through: :question, foreign_key: "decidim_elections_election_id", class_name: "Decidim::Elections::Election"
|
18
|
+
has_one :component, through: :election, foreign_key: "decidim_component_id", class_name: "Decidim::Component"
|
18
19
|
|
19
20
|
default_scope { order(weight: :asc, id: :asc) }
|
20
21
|
|
22
|
+
# Public: Get all the proposals related to the answer
|
23
|
+
#
|
24
|
+
# Returns an ActiveRecord::Relation.
|
21
25
|
def proposals
|
22
26
|
linked_resources(:proposals, "related_proposals")
|
23
27
|
end
|
@@ -5,18 +5,87 @@ module Decidim
|
|
5
5
|
# The data store for an Election in the Decidim::Elections component. It stores a
|
6
6
|
# title, description and any other useful information to perform an election.
|
7
7
|
class Election < ApplicationRecord
|
8
|
+
include Decidim::HasAttachments
|
9
|
+
include Decidim::HasAttachmentCollections
|
10
|
+
include Decidim::Publicable
|
8
11
|
include Decidim::Resourceable
|
9
12
|
include Decidim::HasComponent
|
13
|
+
include Decidim::TranslatableResource
|
10
14
|
include Traceable
|
11
15
|
include Loggable
|
12
16
|
|
17
|
+
translatable_fields :title, :description
|
18
|
+
|
13
19
|
component_manifest_name "elections"
|
14
20
|
|
15
21
|
has_many :questions, foreign_key: "decidim_elections_election_id", class_name: "Decidim::Elections::Question", inverse_of: :election, dependent: :destroy
|
16
22
|
|
23
|
+
scope :active, lambda {
|
24
|
+
where("start_time <= ?", Time.current)
|
25
|
+
.where("end_time >= ?", Time.current)
|
26
|
+
}
|
27
|
+
|
28
|
+
scope :upcoming, lambda {
|
29
|
+
where("start_time > ?", Time.current)
|
30
|
+
.where("end_time > ?", Time.current)
|
31
|
+
}
|
32
|
+
|
33
|
+
scope :finished, lambda {
|
34
|
+
where("start_time < ?", Time.current)
|
35
|
+
.where("end_time < ?", Time.current)
|
36
|
+
}
|
37
|
+
|
38
|
+
def self.log_presenter_class_for(_log)
|
39
|
+
Decidim::Elections::AdminLog::ElectionPresenter
|
40
|
+
end
|
41
|
+
|
42
|
+
# Public: Checks if the election started
|
43
|
+
#
|
44
|
+
# Returns a boolean.
|
17
45
|
def started?
|
18
46
|
start_time <= Time.current
|
19
47
|
end
|
48
|
+
|
49
|
+
# Public: Checks if the election finished
|
50
|
+
#
|
51
|
+
# Returns a boolean.
|
52
|
+
def finished?
|
53
|
+
end_time < Time.current
|
54
|
+
end
|
55
|
+
|
56
|
+
# Public: Checks if the election ongoing now
|
57
|
+
#
|
58
|
+
# Returns a boolean.
|
59
|
+
def ongoing?
|
60
|
+
started? && !finished?
|
61
|
+
end
|
62
|
+
|
63
|
+
# Public: Checks if the election questions are valid
|
64
|
+
#
|
65
|
+
# Returns a boolean.
|
66
|
+
def valid_questions?
|
67
|
+
questions.each do |question|
|
68
|
+
return false unless question.valid_max_selection?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Public: Gets the voting period status of the election
|
73
|
+
#
|
74
|
+
# Returns one of these symbols: upcoming, ongoing or finished
|
75
|
+
def voting_period_status
|
76
|
+
if finished?
|
77
|
+
:finished
|
78
|
+
elsif started?
|
79
|
+
:ongoing
|
80
|
+
else
|
81
|
+
:upcoming
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Public: Overrides the Resourceable concern method to allow setting permissions at resource level
|
86
|
+
def allow_resource_permissions?
|
87
|
+
true
|
88
|
+
end
|
20
89
|
end
|
21
90
|
end
|
22
91
|
end
|
@@ -9,12 +9,19 @@ module Decidim
|
|
9
9
|
include Traceable
|
10
10
|
include Loggable
|
11
11
|
|
12
|
-
delegate :component, to: :election
|
13
|
-
|
14
12
|
belongs_to :election, foreign_key: "decidim_elections_election_id", class_name: "Decidim::Elections::Election", inverse_of: :questions
|
15
13
|
has_many :answers, foreign_key: "decidim_elections_question_id", class_name: "Decidim::Elections::Answer", inverse_of: :question, dependent: :destroy
|
16
14
|
|
15
|
+
has_one :component, through: :election, foreign_key: "decidim_component_id", class_name: "Decidim::Component"
|
16
|
+
|
17
17
|
default_scope { order(weight: :asc, id: :asc) }
|
18
|
+
|
19
|
+
# Public: Checks if enough answers are given for max_selections attribute
|
20
|
+
#
|
21
|
+
# Returns a boolean.
|
22
|
+
def valid_max_selection?
|
23
|
+
max_selections <= answers.count
|
24
|
+
end
|
18
25
|
end
|
19
26
|
end
|
20
27
|
end
|
@@ -12,15 +12,17 @@ module Decidim
|
|
12
12
|
case permission_action.action
|
13
13
|
when :create, :update, :delete
|
14
14
|
allow_if_not_started
|
15
|
+
when :import_proposals
|
16
|
+
allow_if_not_started
|
15
17
|
end
|
16
18
|
when :election
|
17
19
|
case permission_action.action
|
18
20
|
when :create, :read
|
19
21
|
allow!
|
20
|
-
when :update
|
21
|
-
toggle_allow(election)
|
22
|
-
when :delete
|
22
|
+
when :delete, :update, :unpublish
|
23
23
|
allow_if_not_started
|
24
|
+
when :publish
|
25
|
+
allow_if_valid_and_not_started
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -33,9 +35,17 @@ module Decidim
|
|
33
35
|
@election ||= context.fetch(:election, nil)
|
34
36
|
end
|
35
37
|
|
38
|
+
def question
|
39
|
+
@question ||= context.fetch(:question, nil)
|
40
|
+
end
|
41
|
+
|
36
42
|
def allow_if_not_started
|
37
43
|
toggle_allow(election && !election.started?)
|
38
44
|
end
|
45
|
+
|
46
|
+
def allow_if_valid_and_not_started
|
47
|
+
toggle_allow(election && !election.started? && election.valid_questions?)
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
41
51
|
end
|
@@ -4,13 +4,48 @@ module Decidim
|
|
4
4
|
module Elections
|
5
5
|
class Permissions < Decidim::DefaultPermissions
|
6
6
|
def permissions
|
7
|
+
# Anonymous users can only view elections
|
8
|
+
toggle_allow(can_view?) if permission_action.scope == :public && permission_action.subject == :election && permission_action.action == :view
|
9
|
+
|
7
10
|
return permission_action unless user
|
8
11
|
|
9
12
|
# Delegate the admin permission checks to the admin permissions class
|
10
13
|
return Decidim::Elections::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
|
11
14
|
|
15
|
+
return permission_action if permission_action.scope != :public
|
16
|
+
return permission_action if permission_action.subject != :election
|
17
|
+
|
18
|
+
case permission_action.action
|
19
|
+
when :vote
|
20
|
+
toggle_allow(can_vote?)
|
21
|
+
when :preview
|
22
|
+
toggle_allow(can_preview?)
|
23
|
+
end
|
24
|
+
|
12
25
|
permission_action
|
13
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def can_view?
|
31
|
+
election.published? || user&.admin?
|
32
|
+
end
|
33
|
+
|
34
|
+
def can_vote?
|
35
|
+
election.published? && election.ongoing? && authorized_to_vote?
|
36
|
+
end
|
37
|
+
|
38
|
+
def can_preview?
|
39
|
+
user.admin? && !can_vote?
|
40
|
+
end
|
41
|
+
|
42
|
+
def authorized_to_vote?
|
43
|
+
authorized?(:vote, resource: election)
|
44
|
+
end
|
45
|
+
|
46
|
+
def election
|
47
|
+
@election ||= context[:election]
|
48
|
+
end
|
14
49
|
end
|
15
50
|
end
|
16
51
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
module AdminLog
|
6
|
+
# This class holds the logic to present a `Decidim::Election`
|
7
|
+
# for the `AdminLog` log.
|
8
|
+
#
|
9
|
+
# Usage should be automatic and you shouldn't need to call this class
|
10
|
+
# directly, but here's an example:
|
11
|
+
#
|
12
|
+
# action_log = Decidim::ActionLog.last
|
13
|
+
# view_helpers # => this comes from the views
|
14
|
+
# ElectionPresenter.new(action_log, view_helpers).present
|
15
|
+
class ElectionPresenter < Decidim::Log::BasePresenter
|
16
|
+
private
|
17
|
+
|
18
|
+
def diff_fields_mapping
|
19
|
+
{
|
20
|
+
name: :i18n,
|
21
|
+
published_at: :date,
|
22
|
+
weight: :integer
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def i18n_labels_scope
|
27
|
+
"activemodel.attributes.election"
|
28
|
+
end
|
29
|
+
|
30
|
+
def action_string
|
31
|
+
case action
|
32
|
+
when "publish", "unpublish"
|
33
|
+
"decidim.elections.admin_log.election.#{action}"
|
34
|
+
else
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
#
|
6
|
+
# Decorator for election
|
7
|
+
#
|
8
|
+
class ElectionPresenter < SimpleDelegator
|
9
|
+
include Decidim::SanitizeHelper
|
10
|
+
include Decidim::TranslatableAttributes
|
11
|
+
|
12
|
+
def election
|
13
|
+
__getobj__
|
14
|
+
end
|
15
|
+
|
16
|
+
def title
|
17
|
+
content = translated_attribute(election.title)
|
18
|
+
decidim_html_escape(content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def description(strip_tags: false)
|
22
|
+
content = translated_attribute(election.description)
|
23
|
+
content = strip_tags(content) if strip_tags
|
24
|
+
content
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
# A class used to find elections filtered by its state
|
6
|
+
class FilteredElections < Rectify::Query
|
7
|
+
# Syntactic sugar to initialize the class and return the queried objects.
|
8
|
+
#
|
9
|
+
# components - An array of Decidim::Component
|
10
|
+
# start_at - A date to filter resources created after it
|
11
|
+
# end_at - A date to filter resources created before it.
|
12
|
+
def self.for(components, start_at = nil, end_at = nil)
|
13
|
+
new(components, start_at, end_at).query
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initializes the class.
|
17
|
+
#
|
18
|
+
# components - An array of Decidim::Component
|
19
|
+
# start_at - A date to filter resources created after it
|
20
|
+
# end_at - A date to filter resources created before it.
|
21
|
+
def initialize(components, start_at = nil, end_at = nil)
|
22
|
+
@components = components
|
23
|
+
@start_at = start_at
|
24
|
+
@end_at = end_at
|
25
|
+
end
|
26
|
+
|
27
|
+
# Finds the Projects scoped to an array of components and filtered
|
28
|
+
# by a range of dates.
|
29
|
+
def query
|
30
|
+
elections = Decidim::Elections::Election.where(component: @components)
|
31
|
+
elections = elections.where("created_at >= ?", @start_at) if @start_at.present?
|
32
|
+
elections = elections.where("created_at <= ?", @end_at) if @end_at.present?
|
33
|
+
elections
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|