decidim-elections 0.25.1 → 0.26.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/cells/decidim/elections/election_m_cell.rb +1 -1
- data/app/cells/decidim/votings/content_blocks/highlighted_votings_cell.rb +12 -0
- data/app/cells/decidim/votings/content_blocks/landing_page/description_cell.rb +1 -1
- data/app/cells/decidim/votings/voting_m_cell.rb +1 -1
- data/app/commands/decidim/elections/admin/add_user_as_trustee.rb +1 -1
- data/app/commands/decidim/elections/admin/report_missing_trustee.rb +68 -0
- data/app/commands/decidim/elections/admin/setup_election.rb +1 -1
- data/app/commands/decidim/elections/admin/start_tally.rb +1 -1
- data/app/commands/decidim/votings/admin/create_ballot_style.rb +8 -5
- data/app/commands/decidim/votings/admin/destroy_ballot_style.rb +11 -3
- data/app/commands/decidim/votings/admin/update_ballot_style.rb +6 -1
- data/app/commands/decidim/votings/census/admin/create_dataset.rb +13 -5
- data/app/controllers/concerns/decidim/monitoring_committee_polling_station_closures/admin/filterable.rb +1 -1
- data/app/controllers/concerns/decidim/polling_stations/admin/filterable.rb +1 -1
- data/app/controllers/decidim/elections/admin/steps_controller.rb +26 -7
- data/app/controllers/decidim/votings/admin/ballot_styles_controller.rb +1 -1
- data/app/forms/decidim/elections/admin/action_form.rb +4 -0
- data/app/forms/decidim/elections/admin/report_missing_trustee_form.rb +22 -0
- data/app/forms/decidim/elections/admin/setup_form.rb +4 -0
- data/app/models/decidim/elections/action.rb +1 -1
- data/app/models/decidim/elections/trustee.rb +4 -0
- data/app/models/decidim/votings/ballot_style.rb +6 -0
- data/app/models/decidim/votings/census/dataset.rb +2 -0
- data/app/models/decidim/votings/monitoring_committee_member.rb +6 -0
- data/app/models/decidim/votings/polling_officer.rb +5 -0
- data/app/models/decidim/votings/polling_station.rb +6 -0
- data/app/packs/entrypoints/decidim_elections_admin_trustees_process.js +1 -0
- data/app/packs/src/decidim/elections/admin/pending_action.js +1 -1
- data/app/packs/src/decidim/elections/admin/trustees_process.js +125 -0
- data/app/packs/src/decidim/elections/election_log.js +89 -73
- data/app/packs/src/decidim/elections/trustee/key_ceremony.js +3 -3
- data/app/packs/src/decidim/elections/trustee/tally.js +3 -3
- data/app/packs/src/decidim/elections/trustee/trustee_zone.js +29 -18
- data/app/packs/src/decidim/elections/voter/casting-vote.js +1 -1
- data/app/packs/src/decidim/elections/voter/setup-vote.js +5 -5
- data/app/packs/src/decidim/elections/voter/verify-vote.js +1 -1
- data/app/packs/src/decidim/votings/in-person-vote.js +1 -1
- data/app/presenters/decidim/elections/admin_log/election_presenter.rb +34 -9
- data/app/presenters/decidim/elections/admin_log/trustee_presenter.rb +50 -0
- data/app/presenters/decidim/elections/trustee_presenter.rb +5 -1
- data/app/presenters/decidim/votings/admin_log/ballot_style_presenter.rb +35 -0
- data/app/presenters/decidim/votings/admin_log/monitoring_committee_member_presenter.rb +50 -0
- data/app/presenters/decidim/votings/admin_log/polling_officer_presenter.rb +50 -0
- data/app/presenters/decidim/votings/admin_log/polling_station_presenter.rb +29 -0
- data/app/presenters/decidim/votings/admin_log/voting_presenter.rb +1 -1
- data/app/presenters/decidim/votings/census/admin_log/dataset_presenter.rb +7 -6
- data/app/services/decidim/votings/voting_search.rb +2 -2
- data/app/views/decidim/elections/admin/steps/_create_election.html.erb +3 -3
- data/app/views/decidim/elections/admin/steps/_key_ceremony.html.erb +44 -9
- data/app/views/decidim/elections/admin/steps/_tally.html.erb +60 -10
- data/app/views/decidim/elections/admin/steps/index.html.erb +17 -15
- data/app/views/decidim/elections/elections/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/elections/elections/election_log.html.erb +1 -1
- data/app/views/decidim/elections/elections/show.html.erb +1 -1
- data/app/views/decidim/elections/trustee_zone/elections/show.html.erb +1 -1
- data/app/views/decidim/elections/trustee_zone/trustees/show.html.erb +1 -1
- data/app/views/decidim/elections/votes/_onboarding_modal.html.erb +1 -1
- data/app/views/decidim/elections/votes/_show_casted.html.erb +1 -1
- data/app/views/decidim/elections/votes/_show_casting.html.erb +1 -1
- data/app/views/decidim/elections/votes/new.html.erb +3 -3
- data/app/views/decidim/elections/votes/verify.html.erb +1 -1
- data/app/views/decidim/votings/admin/votings/index.html.erb +1 -1
- data/app/views/decidim/votings/polling_officer_zone/closures/_modal_ballots_count_error.html.erb +3 -2
- data/app/views/decidim/votings/polling_officer_zone/closures/_modal_ballots_results_count_error.html.erb +3 -2
- data/app/views/decidim/votings/polling_officer_zone/closures/_sign_form.html.erb +4 -3
- data/app/views/decidim/votings/polling_officer_zone/closures/edit.html.erb +1 -1
- data/app/views/decidim/votings/polling_officer_zone/closures/new.html.erb +1 -1
- data/app/views/decidim/votings/polling_officer_zone/in_person_votes/new.html.erb +1 -1
- data/app/views/decidim/votings/polling_officer_zone/in_person_votes/show.html.erb +1 -1
- data/app/views/decidim/votings/votings/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/votings/votings/_promoted_voting.html.erb +1 -1
- data/config/assets.rb +1 -0
- data/config/locales/ar.yml +12 -0
- data/config/locales/ca.yml +45 -11
- data/config/locales/cs.yml +41 -11
- data/config/locales/de.yml +0 -13
- data/config/locales/en.yml +41 -11
- data/config/locales/es-MX.yml +45 -11
- data/config/locales/es-PY.yml +45 -11
- data/config/locales/es.yml +45 -11
- data/config/locales/eu.yml +23 -11
- data/config/locales/fi-plain.yml +41 -11
- data/config/locales/fi.yml +41 -11
- data/config/locales/fr-CA.yml +408 -11
- data/config/locales/fr.yml +457 -60
- data/config/locales/ga-IE.yml +0 -4
- data/config/locales/gl.yml +19 -3
- data/config/locales/hu.yml +108 -0
- data/config/locales/it.yml +33 -11
- data/config/locales/ja.yml +381 -17
- data/config/locales/lb-LU.yml +24 -0
- data/config/locales/nl.yml +232 -7
- data/config/locales/no.yml +498 -1
- data/config/locales/pl.yml +6 -11
- data/config/locales/pt-BR.yml +1 -14
- data/config/locales/pt.yml +40 -9
- data/config/locales/ro-RO.yml +57 -12
- data/config/locales/sv.yml +104 -6
- data/config/locales/tr-TR.yml +4 -9
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/zh-CN.yml +0 -5
- data/lib/decidim/elections/component.rb +2 -1
- data/lib/decidim/elections/test/factories.rb +2 -2
- data/lib/decidim/elections/version.rb +1 -1
- metadata +32 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48839ff2ece46c0bd66bc1360423d2bb996f91c0581547f8ef61ca837aaf4b71
|
4
|
+
data.tar.gz: a63a7431d25acbfe3d0967f84ed234359e4781537376bb139d2c4fc6f859bba8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 811ed896ec1b34ee134ad36cbe910e440f20cd538bfe2b74e288fd1e9505b4e1e02bd9b2e8156a9bc8da4716f45686fc06c6810ce5ed9d1f240cecb5a5300ef3
|
7
|
+
data.tar.gz: 2ab58f77f16b978ae5bd9c74f09b6faa3d11f1f8fb434aa0468c8a7a6d4ee24711c5c7d355cab744be1d6360eda41d2946205a6419d916b9298288685cbcda09
|
@@ -6,6 +6,10 @@ module Decidim
|
|
6
6
|
class HighlightedVotingsCell < Decidim::ViewModel
|
7
7
|
delegate :current_user, to: :controller
|
8
8
|
|
9
|
+
cache :show, expires_in: 10.minutes, if: :perform_caching? do
|
10
|
+
cache_hash
|
11
|
+
end
|
12
|
+
|
9
13
|
def show
|
10
14
|
render if highlighted_votings.any?
|
11
15
|
end
|
@@ -27,6 +31,14 @@ module Decidim
|
|
27
31
|
def decidim_votings
|
28
32
|
Decidim::Votings::Engine.routes.url_helpers
|
29
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def cache_hash
|
38
|
+
hash = []
|
39
|
+
hash.push(I18n.locale)
|
40
|
+
hash.join(Decidim.cache_key_separator)
|
41
|
+
end
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
@@ -16,7 +16,7 @@ module Decidim
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def description_text
|
19
|
-
|
19
|
+
decidim_sanitize_editor(translated_attribute(current_participatory_space.description))
|
20
20
|
end
|
21
21
|
|
22
22
|
def button_show_more_text
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
module Admin
|
6
|
+
# This command gets called to report a missing trustee during the tally process.
|
7
|
+
class ReportMissingTrustee < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A ReportMissingTrusteeForm object with the information needed to report the missing trustee.
|
11
|
+
def initialize(form)
|
12
|
+
@form = form
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: Reports the missing trustee for the Election tally process.
|
16
|
+
#
|
17
|
+
# Broadcasts :ok if it worked, :invalid otherwise.
|
18
|
+
def call
|
19
|
+
return broadcast(:invalid) if form.invalid?
|
20
|
+
|
21
|
+
transaction do
|
22
|
+
log_action
|
23
|
+
report_missing_trustee
|
24
|
+
end
|
25
|
+
|
26
|
+
broadcast(:ok)
|
27
|
+
rescue StandardError => e
|
28
|
+
broadcast(:invalid, e.message)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_accessor :form
|
34
|
+
|
35
|
+
delegate :election, :bulletin_board, :trustee, to: :form
|
36
|
+
|
37
|
+
def log_action
|
38
|
+
Decidim.traceability.perform_action!(
|
39
|
+
:report_missing_trustee,
|
40
|
+
election,
|
41
|
+
form.current_user,
|
42
|
+
extra: {
|
43
|
+
trustee_id: form.trustee_id,
|
44
|
+
name: trustee.name,
|
45
|
+
nickname: trustee.user.nickname
|
46
|
+
},
|
47
|
+
visibility: "all"
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def report_missing_trustee
|
52
|
+
bulletin_board.report_missing_trustee(election.id, form.trustee.slug) do |message_id|
|
53
|
+
create_election_action(message_id)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_election_action(message_id)
|
58
|
+
Decidim::Elections::Action.create!(
|
59
|
+
election: election,
|
60
|
+
action: :report_missing_trustee,
|
61
|
+
message_id: message_id,
|
62
|
+
status: :pending
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -7,7 +7,7 @@ module Decidim
|
|
7
7
|
class StartTally < Rectify::Command
|
8
8
|
# Public: Initializes the command.
|
9
9
|
#
|
10
|
-
# form -
|
10
|
+
# form - An ActionForm object with the information needed to perform an action
|
11
11
|
def initialize(form)
|
12
12
|
@form = form
|
13
13
|
end
|
@@ -34,13 +34,16 @@ module Decidim
|
|
34
34
|
attr_reader :form, :ballot_style
|
35
35
|
|
36
36
|
def create_ballot_style!
|
37
|
-
|
38
|
-
code: form.code
|
37
|
+
params = {
|
38
|
+
code: form.code,
|
39
|
+
voting: form.current_participatory_space
|
39
40
|
}
|
40
41
|
|
41
|
-
@ballot_style = Decidim
|
42
|
-
|
43
|
-
|
42
|
+
@ballot_style = Decidim.traceability.create!(
|
43
|
+
Decidim::Votings::BallotStyle,
|
44
|
+
form.current_user,
|
45
|
+
params,
|
46
|
+
visibility: "all"
|
44
47
|
)
|
45
48
|
end
|
46
49
|
|
@@ -5,8 +5,9 @@ module Decidim
|
|
5
5
|
module Admin
|
6
6
|
# A command with the business logic to delete the ballot style
|
7
7
|
class DestroyBallotStyle < Rectify::Command
|
8
|
-
def initialize(ballot_style)
|
8
|
+
def initialize(ballot_style, current_user)
|
9
9
|
@ballot_style = ballot_style
|
10
|
+
@current_user = current_user
|
10
11
|
end
|
11
12
|
|
12
13
|
# Executes the command. Broadcast this events:
|
@@ -22,10 +23,17 @@ module Decidim
|
|
22
23
|
|
23
24
|
private
|
24
25
|
|
25
|
-
attr_reader :ballot_style
|
26
|
+
attr_reader :ballot_style, :current_user
|
26
27
|
|
27
28
|
def destroy_ballot_style!
|
28
|
-
|
29
|
+
Decidim.traceability.perform_action!(
|
30
|
+
:delete,
|
31
|
+
ballot_style,
|
32
|
+
current_user,
|
33
|
+
visibility: "all"
|
34
|
+
) do
|
35
|
+
ballot_style.destroy!
|
36
|
+
end
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
@@ -31,7 +31,7 @@ module Decidim
|
|
31
31
|
end
|
32
32
|
|
33
33
|
if dataset
|
34
|
-
CSV.foreach(form.file.tempfile.path, col_sep: ";", headers: true) do |row|
|
34
|
+
CSV.foreach(form.file.tempfile.path, col_sep: ";", headers: true, converters: ->(f) { f&.strip }) do |row|
|
35
35
|
CreateDatumJob.perform_later(current_user, dataset, row.fields)
|
36
36
|
end
|
37
37
|
end
|
@@ -57,11 +57,19 @@ module Decidim
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def csv_header_invalid?
|
60
|
-
CSV.parse_line(File.open(form.file.tempfile.path
|
60
|
+
CSV.parse_line(File.open(form.file.tempfile.path), col_sep: ";", headers: true, header_converters: :symbol).headers != expected_headers
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
64
|
-
|
63
|
+
def headers
|
64
|
+
[:document_id, :document_type, :date_of_birth, :full_name, :full_address, :postal_code, :mobile_phone_number, :email_address]
|
65
|
+
end
|
66
|
+
|
67
|
+
def ballot_style_headers
|
68
|
+
headers.push(:ballot_style_code)
|
69
|
+
end
|
70
|
+
|
71
|
+
def expected_headers
|
72
|
+
@expected_headers ||= form.current_participatory_space.has_ballot_styles? ? ballot_style_headers : headers
|
65
73
|
end
|
66
74
|
|
67
75
|
def csv_rows
|
@@ -73,7 +81,7 @@ module Decidim
|
|
73
81
|
end
|
74
82
|
|
75
83
|
def file_lines_count(file_path)
|
76
|
-
`wc -l "#{file_path}"`.strip.split(" ")[0].to_i
|
84
|
+
`wc -l "#{file_path.shellescape}"`.strip.split(" ")[0].to_i
|
77
85
|
end
|
78
86
|
end
|
79
87
|
end
|
@@ -14,9 +14,9 @@ module Decidim
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def base_query
|
17
|
+
# Includes the officers (president and managers) and their correspective decidim users when they(=officers) are present
|
17
18
|
query =
|
18
19
|
collection
|
19
|
-
# Includes the officers (president and managers) and their correspective decidim users when they(=officers) are present
|
20
20
|
.joins("LEFT JOIN decidim_votings_polling_officers president ON president.presided_polling_station_id = decidim_votings_polling_stations.id
|
21
21
|
LEFT JOIN decidim_users president_user ON president_user.id = president.decidim_user_id
|
22
22
|
LEFT JOIN decidim_votings_polling_officers managers ON managers.managed_polling_station_id = decidim_votings_polling_stations.id
|
@@ -14,8 +14,8 @@ module Decidim
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def base_query
|
17
|
+
# Includes the officers (president and managers) and their correspective decidim users when they(=officers) are present
|
17
18
|
query = collection
|
18
|
-
# Includes the officers (president and managers) and their correspective decidim users when they(=officers) are present
|
19
19
|
.joins("LEFT JOIN decidim_votings_polling_officers president ON president.presided_polling_station_id = decidim_votings_polling_stations.id
|
20
20
|
LEFT JOIN decidim_users president_user ON president_user.id = president.decidim_user_id
|
21
21
|
LEFT JOIN decidim_votings_polling_officers managers ON managers.managed_polling_station_id = decidim_votings_polling_stations.id
|
@@ -5,8 +5,9 @@ module Decidim
|
|
5
5
|
module Admin
|
6
6
|
# This controller allows to manage the steps of an election.
|
7
7
|
class StepsController < Admin::ApplicationController
|
8
|
+
helper Decidim::ApplicationHelper
|
8
9
|
helper StepsHelper
|
9
|
-
helper_method :elections, :election, :current_step, :vote_stats, :bulletin_board_server
|
10
|
+
helper_method :elections, :election, :current_step, :vote_stats, :bulletin_board_server, :authority_public_key, :election_unique_id, :quorum, :missing_trustees_allowed
|
10
11
|
|
11
12
|
def index
|
12
13
|
enforce_permission_to :read, :steps, election: election
|
@@ -22,10 +23,12 @@ module Decidim
|
|
22
23
|
redirect_to election_steps_path(election) && return unless params[:id] == current_step
|
23
24
|
|
24
25
|
@form = form(current_step_form_class).from_params(params, election: election)
|
25
|
-
if @form.pending_action
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
Decidim::Elections::Admin::UpdateActionStatus.call(@form.pending_action) if @form.pending_action
|
27
|
+
|
28
|
+
# check pending action status mode
|
29
|
+
return render json: { status: @form.pending_action&.status } if params[:check_pending_action]
|
30
|
+
|
31
|
+
return redirect_to election_steps_path(election) if @form.pending_action
|
29
32
|
|
30
33
|
current_step_command_class.call(@form) do
|
31
34
|
on(:ok) do
|
@@ -45,8 +48,22 @@ module Decidim
|
|
45
48
|
|
46
49
|
private
|
47
50
|
|
48
|
-
|
49
|
-
|
51
|
+
delegate :bulletin_board_server, :authority_slug, :quorum, to: :bulletin_board_client
|
52
|
+
|
53
|
+
def bulletin_board_client
|
54
|
+
Decidim::Elections.bulletin_board
|
55
|
+
end
|
56
|
+
|
57
|
+
def missing_trustees_allowed
|
58
|
+
@missing_trustees_allowed ||= Decidim::Elections.bulletin_board.number_of_trustees - Decidim::Elections.bulletin_board.quorum
|
59
|
+
end
|
60
|
+
|
61
|
+
def election_unique_id
|
62
|
+
@election_unique_id ||= Decidim::BulletinBoard::MessageIdentifier.unique_election_id(authority_slug, election.id)
|
63
|
+
end
|
64
|
+
|
65
|
+
def authority_public_key
|
66
|
+
@authority_public_key ||= bulletin_board_client.authority_public_key.to_json
|
50
67
|
end
|
51
68
|
|
52
69
|
def current_step_form_class
|
@@ -56,6 +73,7 @@ module Decidim
|
|
56
73
|
"key_ceremony_ended" => VotePeriodForm,
|
57
74
|
"vote" => VotePeriodForm,
|
58
75
|
"vote_ended" => ActionForm,
|
76
|
+
"tally" => ReportMissingTrusteeForm,
|
59
77
|
"tally_ended" => ActionForm
|
60
78
|
}[current_step]
|
61
79
|
end
|
@@ -67,6 +85,7 @@ module Decidim
|
|
67
85
|
"key_ceremony_ended" => StartVote,
|
68
86
|
"vote" => EndVote,
|
69
87
|
"vote_ended" => StartTally,
|
88
|
+
"tally" => ReportMissingTrustee,
|
70
89
|
"tally_ended" => PublishResults
|
71
90
|
}[current_step]
|
72
91
|
end
|
@@ -60,7 +60,7 @@ module Decidim
|
|
60
60
|
def destroy
|
61
61
|
enforce_permission_to :delete, :ballot_style, ballot_style: current_ballot_style, voting: current_voting
|
62
62
|
|
63
|
-
DestroyBallotStyle.call(current_ballot_style) do
|
63
|
+
DestroyBallotStyle.call(current_ballot_style, current_user) do
|
64
64
|
on(:ok) do
|
65
65
|
flash[:notice] = t("destroy.success", scope: "decidim.votings.admin.ballot_styles")
|
66
66
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Elections
|
5
|
+
module Admin
|
6
|
+
# This class holds a form to report a missing trustee during the tally process.
|
7
|
+
class ReportMissingTrusteeForm < ActionForm
|
8
|
+
attribute :trustee_id, Integer
|
9
|
+
|
10
|
+
validates :trustee_id, presence: true
|
11
|
+
|
12
|
+
def trustee
|
13
|
+
@trustee ||= Decidim::Elections::Trustee.find(trustee_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def main_button?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -7,7 +7,7 @@ module Decidim
|
|
7
7
|
belongs_to :election, foreign_key: "decidim_elections_election_id", class_name: "Decidim::Elections::Election"
|
8
8
|
|
9
9
|
enum status: [:pending, :accepted, :rejected]
|
10
|
-
enum action: [:start_key_ceremony, :start_vote, :end_vote, :start_tally, :publish_results]
|
10
|
+
enum action: [:start_key_ceremony, :start_vote, :end_vote, :start_tally, :report_missing_trustee, :publish_results]
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -17,6 +17,8 @@ module Decidim
|
|
17
17
|
inverse_of: :ballot_style,
|
18
18
|
dependent: :nullify
|
19
19
|
|
20
|
+
alias participatory_space voting
|
21
|
+
|
20
22
|
def slug
|
21
23
|
"#{voting.slug}_#{code.parameterize}-#{id}"
|
22
24
|
end
|
@@ -24,6 +26,10 @@ module Decidim
|
|
24
26
|
def questions_for(election)
|
25
27
|
questions.where(election: election)
|
26
28
|
end
|
29
|
+
|
30
|
+
def self.log_presenter_class_for(_log)
|
31
|
+
Decidim::Votings::AdminLog::BallotStylePresenter
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -11,6 +11,12 @@ module Decidim
|
|
11
11
|
|
12
12
|
validate :user_and_voting_same_organization
|
13
13
|
|
14
|
+
alias participatory_space voting
|
15
|
+
|
16
|
+
def self.log_presenter_class_for(_log)
|
17
|
+
Decidim::Votings::AdminLog::MonitoringCommitteeMemberPresenter
|
18
|
+
end
|
19
|
+
|
14
20
|
private
|
15
21
|
|
16
22
|
# Private: check if the voting and the user have the same organization
|
@@ -22,6 +22,7 @@ module Decidim
|
|
22
22
|
validate :either_president_or_manager
|
23
23
|
|
24
24
|
delegate :name, :nickname, :email, to: :user
|
25
|
+
alias participatory_space voting
|
25
26
|
|
26
27
|
# Allow ransacker to search by presided/managed polling station title
|
27
28
|
%w(managed_station presided_station).each do |table|
|
@@ -56,6 +57,10 @@ module Decidim
|
|
56
57
|
presided_polling_station || managed_polling_station
|
57
58
|
end
|
58
59
|
|
60
|
+
def self.log_presenter_class_for(_log)
|
61
|
+
Decidim::Votings::AdminLog::PollingOfficerPresenter
|
62
|
+
end
|
63
|
+
|
59
64
|
private
|
60
65
|
|
61
66
|
# Private: check if the voting and the user have the same organization
|
@@ -34,6 +34,8 @@ module Decidim
|
|
34
34
|
validate :polling_station_managers_same_voting
|
35
35
|
validate :polling_station_president_same_voting
|
36
36
|
|
37
|
+
alias participatory_space voting
|
38
|
+
|
37
39
|
# Allow ransacker to search for a key in a hstore column (`title`.`en`)
|
38
40
|
ransacker :title do |parent|
|
39
41
|
Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s))
|
@@ -61,6 +63,10 @@ module Decidim
|
|
61
63
|
closures.find_by(election: election)
|
62
64
|
end
|
63
65
|
|
66
|
+
def self.log_presenter_class_for(_log)
|
67
|
+
Decidim::Votings::AdminLog::PollingStationPresenter
|
68
|
+
end
|
69
|
+
|
64
70
|
private
|
65
71
|
|
66
72
|
# Private: check if the president is in the same voting
|
@@ -0,0 +1 @@
|
|
1
|
+
import "src/decidim/elections/admin/trustees_process";
|
@@ -0,0 +1,125 @@
|
|
1
|
+
import {
|
2
|
+
Client,
|
3
|
+
Election,
|
4
|
+
MessageParser
|
5
|
+
} from "@decidim/decidim-bulletin_board";
|
6
|
+
|
7
|
+
const WAIT_TIME_MS = 10 * 1_000;
|
8
|
+
|
9
|
+
$(async () => {
|
10
|
+
const $trusteesProcess = $("#trustees_process");
|
11
|
+
const $checkingTrustees = $trusteesProcess.find(".trustee");
|
12
|
+
const electionUniqueId = $trusteesProcess.data("electionUniqueId");
|
13
|
+
const processType = $trusteesProcess.data("processType");
|
14
|
+
const bulletinBoardClient = new Client({
|
15
|
+
apiEndpointUrl: $trusteesProcess.data("apiEndpointUrl")
|
16
|
+
});
|
17
|
+
const election = new Election({
|
18
|
+
uniqueId: electionUniqueId,
|
19
|
+
bulletinBoardClient,
|
20
|
+
typesFilter: ["create_election", processType]
|
21
|
+
});
|
22
|
+
|
23
|
+
const authorityPublicKeyJSON = JSON.stringify(
|
24
|
+
$trusteesProcess.data("authorityPublicKey")
|
25
|
+
);
|
26
|
+
const parser = new MessageParser({ authorityPublicKeyJSON });
|
27
|
+
const trusteesStatuses = {};
|
28
|
+
let lastMessageIndex = 0;
|
29
|
+
|
30
|
+
const missingTrusteesAllowed = $trusteesProcess.data("missingTrusteesAllowed") || 0;
|
31
|
+
const checkPendingActionPath = $trusteesProcess.data("checkPendingActionPath");
|
32
|
+
|
33
|
+
// Fix buttons formaction, that is not working properly
|
34
|
+
const $form = $("form.step");
|
35
|
+
$form.find("button").on("click", (event) => {
|
36
|
+
$form.attr("action", $(event.currentTarget).attr("formaction"));
|
37
|
+
$form.trigger("submit");
|
38
|
+
});
|
39
|
+
|
40
|
+
const updateTrusteesStatuses = async () => {
|
41
|
+
await election.getLogEntries();
|
42
|
+
|
43
|
+
for (
|
44
|
+
;
|
45
|
+
lastMessageIndex < election.logEntries.length;
|
46
|
+
lastMessageIndex += 1
|
47
|
+
) {
|
48
|
+
const { messageIdentifier, decodedData } = await parser.parse(
|
49
|
+
election.logEntries[lastMessageIndex]
|
50
|
+
);
|
51
|
+
|
52
|
+
if (messageIdentifier.author.type === "t") {
|
53
|
+
trusteesStatuses[messageIdentifier.author.id] = true;
|
54
|
+
} else if (
|
55
|
+
messageIdentifier.type === "tally" &&
|
56
|
+
messageIdentifier.subtype === "missing_trustee" &&
|
57
|
+
!(decodedData.trustee_id in trusteesStatuses)
|
58
|
+
) {
|
59
|
+
trusteesStatuses[decodedData.trustee_id] = false;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
const checkPendingAction = async () => {
|
65
|
+
if (!checkPendingActionPath) {
|
66
|
+
return false
|
67
|
+
}
|
68
|
+
|
69
|
+
try {
|
70
|
+
const response = await $.ajax({
|
71
|
+
url: checkPendingActionPath,
|
72
|
+
method: "PATCH",
|
73
|
+
contentType: "application/json",
|
74
|
+
headers: {
|
75
|
+
"X-CSRF-Token": $("meta[name=csrf-token]").attr("content")
|
76
|
+
}
|
77
|
+
})
|
78
|
+
|
79
|
+
return response && response.status === "pending";
|
80
|
+
} catch (err) {
|
81
|
+
return true;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
const checkTrusteesActivity = async () => {
|
86
|
+
await updateTrusteesStatuses();
|
87
|
+
const pendingAction = await checkPendingAction();
|
88
|
+
const missingTrustees = Object.values(trusteesStatuses).filter(
|
89
|
+
(present) => !present
|
90
|
+
).length;
|
91
|
+
const allowReportMissing = missingTrustees < missingTrusteesAllowed;
|
92
|
+
|
93
|
+
$checkingTrustees.each((_index, trustee) => {
|
94
|
+
const $trustee = $(trustee);
|
95
|
+
const trusteeSlug = $trustee.data("trusteeSlug");
|
96
|
+
|
97
|
+
if (trusteeSlug in trusteesStatuses) {
|
98
|
+
if (missingTrusteesAllowed > 0) {
|
99
|
+
$trustee.find(".js-report-missing-trustee").addClass("hide");
|
100
|
+
}
|
101
|
+
$trustee.removeClass("loading");
|
102
|
+
$trustee.find(".loading").hide();
|
103
|
+
if (trusteesStatuses[trusteeSlug]) {
|
104
|
+
$trustee.find(".active").removeClass("hide");
|
105
|
+
$trustee.find(".missing").addClass("hide");
|
106
|
+
} else {
|
107
|
+
$trustee.find(".missing").removeClass("hide");
|
108
|
+
}
|
109
|
+
} else if (allowReportMissing && !pendingAction) {
|
110
|
+
$trustee.find(".js-report-missing-trustee").removeClass("hide");
|
111
|
+
}
|
112
|
+
});
|
113
|
+
|
114
|
+
if (
|
115
|
+
Object.keys(trusteesStatuses).length === $checkingTrustees.length &&
|
116
|
+
missingTrustees <= missingTrusteesAllowed && !pendingAction
|
117
|
+
) {
|
118
|
+
$(".js-continue-link").removeClass("disabled");
|
119
|
+
} else {
|
120
|
+
setTimeout(checkTrusteesActivity, WAIT_TIME_MS);
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
await checkTrusteesActivity();
|
125
|
+
});
|