decidim-elections 0.25.2 → 0.26.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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/ca.yml +2 -17
- data/config/locales/cs.yml +45 -13
- data/config/locales/de.yml +0 -15
- data/config/locales/en.yml +41 -11
- data/config/locales/es-MX.yml +2 -17
- data/config/locales/es-PY.yml +2 -17
- data/config/locales/es.yml +43 -15
- data/config/locales/eu.yml +24 -17
- data/config/locales/fi-plain.yml +41 -13
- data/config/locales/fi.yml +41 -13
- data/config/locales/fr-CA.yml +32 -14
- data/config/locales/fr.yml +32 -14
- data/config/locales/ga-IE.yml +0 -9
- data/config/locales/gl.yml +21 -9
- data/config/locales/hu.yml +0 -5
- data/config/locales/it.yml +36 -12
- data/config/locales/ja.yml +234 -16
- data/config/locales/lb-LU.yml +24 -0
- data/config/locales/nl.yml +224 -11
- data/config/locales/no.yml +0 -5
- data/config/locales/pl.yml +13 -12
- data/config/locales/pt-BR.yml +5 -16
- data/config/locales/pt.yml +43 -10
- data/config/locales/ro-RO.yml +24 -17
- data/config/locales/sv.yml +3 -8
- data/config/locales/tr-TR.yml +3 -9
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/zh-CN.yml +0 -4
- 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 +31 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bc8a779cca40d6e069fdbdff54905690f2f58dbd33cdcca28c81e8b0c63a2a81
|
|
4
|
+
data.tar.gz: c8453d445d3d6406ef3dc6f27aed2b1ecbeaa8f69e9e8f221d3a0dae8e61c3c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89e34b56ab3fe554dd329b790d60fe79e8d5a53ddfd8829b8aaf29c624ee6e860f4d80d7d4dd6d96fa7daa6bb6bbc4d5dd5eb307df187efdc08d6b579f1ebae5
|
|
7
|
+
data.tar.gz: f0c23adcd2198063a4ce7e9e27a3100c57fe881123d94e1922a891cab82fa1d1fbc8b26c00a10291eb3cc52f8cc26572870489794cad903e3f8483f9c7fae088
|
|
@@ -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
|
+
});
|