decidim-elections 0.22.0

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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +31 -0
  3. data/Rakefile +3 -0
  4. data/app/assets/config/decidim_elections_manifest.js +0 -0
  5. data/app/assets/images/decidim/elections/icon.svg +1 -0
  6. data/app/commands/decidim/elections/admin/create_answer.rb +71 -0
  7. data/app/commands/decidim/elections/admin/create_election.rb +48 -0
  8. data/app/commands/decidim/elections/admin/create_question.rb +52 -0
  9. data/app/commands/decidim/elections/admin/destroy_answer.rb +50 -0
  10. data/app/commands/decidim/elections/admin/destroy_election.rb +46 -0
  11. data/app/commands/decidim/elections/admin/destroy_question.rb +46 -0
  12. data/app/commands/decidim/elections/admin/update_answer.rb +73 -0
  13. data/app/commands/decidim/elections/admin/update_election.rb +48 -0
  14. data/app/commands/decidim/elections/admin/update_question.rb +52 -0
  15. data/app/controllers/decidim/elections/admin/answers_controller.rb +92 -0
  16. data/app/controllers/decidim/elections/admin/application_controller.rb +15 -0
  17. data/app/controllers/decidim/elections/admin/elections_controller.rb +82 -0
  18. data/app/controllers/decidim/elections/admin/questions_controller.rb +86 -0
  19. data/app/controllers/decidim/elections/application_controller.rb +13 -0
  20. data/app/controllers/decidim/elections/elections_controller.rb +9 -0
  21. data/app/forms/decidim/elections/admin/answer_form.rb +53 -0
  22. data/app/forms/decidim/elections/admin/election_form.rb +24 -0
  23. data/app/forms/decidim/elections/admin/question_form.rb +26 -0
  24. data/app/helpers/decidim/elections/application_helper.rb +10 -0
  25. data/app/models/decidim/elections/answer.rb +26 -0
  26. data/app/models/decidim/elections/application_record.rb +10 -0
  27. data/app/models/decidim/elections/election.rb +22 -0
  28. data/app/models/decidim/elections/question.rb +20 -0
  29. data/app/permissions/decidim/elections/admin/permissions.rb +42 -0
  30. data/app/permissions/decidim/elections/permissions.rb +16 -0
  31. data/app/types/decidim/elections/election_answer_type.rb +24 -0
  32. data/app/types/decidim/elections/election_question_type.rb +25 -0
  33. data/app/types/decidim/elections/election_type.rb +26 -0
  34. data/app/types/decidim/elections/elections_type.rb +32 -0
  35. data/app/views/decidim/elections/admin/answers/_form.html.erb +25 -0
  36. data/app/views/decidim/elections/admin/answers/edit.html.erb +7 -0
  37. data/app/views/decidim/elections/admin/answers/index.html.erb +46 -0
  38. data/app/views/decidim/elections/admin/answers/new.html.erb +7 -0
  39. data/app/views/decidim/elections/admin/answers/proposals_picker.html.erb +1 -0
  40. data/app/views/decidim/elections/admin/elections/_form.html.erb +28 -0
  41. data/app/views/decidim/elections/admin/elections/edit.html.erb +7 -0
  42. data/app/views/decidim/elections/admin/elections/index.html.erb +54 -0
  43. data/app/views/decidim/elections/admin/elections/new.html.erb +7 -0
  44. data/app/views/decidim/elections/admin/questions/_form.html.erb +27 -0
  45. data/app/views/decidim/elections/admin/questions/edit.html.erb +7 -0
  46. data/app/views/decidim/elections/admin/questions/index.html.erb +53 -0
  47. data/app/views/decidim/elections/admin/questions/new.html.erb +7 -0
  48. data/app/views/decidim/elections/elections/index.html.erb +1 -0
  49. data/app/views/decidim/elections/elections/show.html.erb +0 -0
  50. data/config/i18n-tasks.yml +10 -0
  51. data/config/locales/ar.yml +1 -0
  52. data/config/locales/bg-BG.yml +7 -0
  53. data/config/locales/ca.yml +132 -0
  54. data/config/locales/cs.yml +138 -0
  55. data/config/locales/da-DK.yml +1 -0
  56. data/config/locales/de.yml +132 -0
  57. data/config/locales/el.yml +132 -0
  58. data/config/locales/en.yml +133 -0
  59. data/config/locales/eo-UY.yml +1 -0
  60. data/config/locales/es-MX.yml +132 -0
  61. data/config/locales/es-PY.yml +132 -0
  62. data/config/locales/es.yml +132 -0
  63. data/config/locales/et-EE.yml +1 -0
  64. data/config/locales/eu.yml +1 -0
  65. data/config/locales/fi-plain.yml +132 -0
  66. data/config/locales/fi.yml +132 -0
  67. data/config/locales/fr-CA.yml +132 -0
  68. data/config/locales/fr.yml +132 -0
  69. data/config/locales/ga-IE.yml +1 -0
  70. data/config/locales/gl.yml +1 -0
  71. data/config/locales/hr-HR.yml +1 -0
  72. data/config/locales/hu.yml +1 -0
  73. data/config/locales/id-ID.yml +1 -0
  74. data/config/locales/is-IS.yml +1 -0
  75. data/config/locales/it.yml +132 -0
  76. data/config/locales/ja-JP.yml +129 -0
  77. data/config/locales/lt-LT.yml +1 -0
  78. data/config/locales/lv-LV.yml +135 -0
  79. data/config/locales/mt-MT.yml +1 -0
  80. data/config/locales/nl.yml +132 -0
  81. data/config/locales/no.yml +9 -0
  82. data/config/locales/pl.yml +138 -0
  83. data/config/locales/pt-BR.yml +1 -0
  84. data/config/locales/pt.yml +132 -0
  85. data/config/locales/ro-RO.yml +135 -0
  86. data/config/locales/ru.yml +1 -0
  87. data/config/locales/sk.yml +1 -0
  88. data/config/locales/sl.yml +5 -0
  89. data/config/locales/sr-CS.yml +1 -0
  90. data/config/locales/sv.yml +132 -0
  91. data/config/locales/tr-TR.yml +1 -0
  92. data/config/locales/uk.yml +1 -0
  93. data/db/migrate/20200430083618_create_decidim_elections_elections.rb +15 -0
  94. data/db/migrate/20200518082327_create_decidim_elections_questions.rb +14 -0
  95. data/db/migrate/20200518084144_create_decidim_elections_answers.rb +12 -0
  96. data/lib/decidim/elections.rb +13 -0
  97. data/lib/decidim/elections/admin.rb +10 -0
  98. data/lib/decidim/elections/admin_engine.rb +29 -0
  99. data/lib/decidim/elections/component.rb +123 -0
  100. data/lib/decidim/elections/engine.rb +23 -0
  101. data/lib/decidim/elections/seeds/city.jpeg +0 -0
  102. data/lib/decidim/elections/test/factories.rb +52 -0
  103. data/lib/decidim/elections/version.rb +10 -0
  104. metadata +201 -0
@@ -0,0 +1 @@
1
+ ru:
@@ -0,0 +1 @@
1
+ sk:
@@ -0,0 +1,5 @@
1
+ sl:
2
+ activemodel:
3
+ attributes:
4
+ answer:
5
+ description: Opis
@@ -0,0 +1 @@
1
+ sr:
@@ -0,0 +1,132 @@
1
+ sv:
2
+ activemodel:
3
+ attributes:
4
+ answer:
5
+ description: Beskrivning
6
+ image: Bild
7
+ proposals: Relaterade förslag
8
+ title: Titel
9
+ election:
10
+ description: Beskrivning
11
+ end_time: Omröstningen slutar vid
12
+ start_time: Röstningsstart vid
13
+ subtitle: Undertext
14
+ title: Titel
15
+ question:
16
+ description: Beskrivning
17
+ max_selections: Maximalt antal val
18
+ title: Titel
19
+ errors:
20
+ models:
21
+ answer:
22
+ attributes:
23
+ attachment:
24
+ needs_to_be_reattached: Måste återknytas
25
+ activerecord:
26
+ models:
27
+ decidim/elections/answer:
28
+ one: Svar
29
+ other: Svar
30
+ decidim/elections/election:
31
+ one: Val
32
+ other: Val
33
+ decidim/elections/question:
34
+ one: Fråga
35
+ other: Frågor
36
+ decidim:
37
+ components:
38
+ elections:
39
+ name: Val
40
+ settings:
41
+ global:
42
+ announcement: Meddelande
43
+ step:
44
+ announcement: Meddelande
45
+ elections:
46
+ actions:
47
+ confirm_destroy: Är du säker?
48
+ destroy: Förstör
49
+ edit: Redigera
50
+ new: Ny %{name}
51
+ preview: Förhandsgranska
52
+ title: Åtgärder
53
+ admin:
54
+ answers:
55
+ create:
56
+ invalid: Det gick inte att skapa svaret
57
+ success: Svaret har skapats
58
+ destroy:
59
+ invalid: Det gick inte att ta bort svaret
60
+ success: Svaret har tagits bort
61
+ edit:
62
+ title: Redigera svar
63
+ update: Uppdatera svar
64
+ index:
65
+ title: Svar
66
+ new:
67
+ create: Skapa svar
68
+ title: Nytt svar
69
+ update:
70
+ invalid: Det gick inte att uppdatera svaret
71
+ success: Svaret har uppdaterats
72
+ elections:
73
+ create:
74
+ invalid: Det gick inte att skapa detta val
75
+ success: Val har skapats
76
+ destroy:
77
+ invalid: Det gick inte att ta bort valet
78
+ success: Val har tagits bort
79
+ edit:
80
+ title: Redigera val
81
+ update: Uppdatera val
82
+ index:
83
+ title: Val
84
+ new:
85
+ create: Skapa val
86
+ title: Nytt val
87
+ update:
88
+ invalid: Det gick inte att uppdatera valet
89
+ success: Val har uppdaterats
90
+ models:
91
+ answer:
92
+ name: Svar
93
+ election:
94
+ name: Val
95
+ question:
96
+ name: Fråga
97
+ questions:
98
+ create:
99
+ invalid: Det gick inte att skapa denna fråga
100
+ success: Frågan har skapats
101
+ destroy:
102
+ invalid: Det gick inte att ta bort denna fråga
103
+ success: Frågan har tagits bort
104
+ edit:
105
+ title: Redigera fråga
106
+ update: Uppdatera fråga
107
+ index:
108
+ title: Frågor
109
+ new:
110
+ create: Skapa fråga
111
+ title: Ny fråga
112
+ update:
113
+ invalid: Det gick inte att uppdatera denna fråga
114
+ success: Frågan har uppdaterats
115
+ models:
116
+ answer:
117
+ fields:
118
+ proposals: Förslag
119
+ title: Titel
120
+ election:
121
+ fields:
122
+ end_time: Avsluta vid
123
+ start_time: Börjar vid
124
+ title: Titel
125
+ question:
126
+ fields:
127
+ answers: Svar
128
+ max_selections: Max. val
129
+ title: Titel
130
+ participatory_processes:
131
+ statistics:
132
+ elections_count: Val
@@ -0,0 +1 @@
1
+ tr:
@@ -0,0 +1 @@
1
+ uk:
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimElectionsElections < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_elections_elections do |t|
6
+ t.jsonb :title
7
+ t.jsonb :subtitle
8
+ t.jsonb :description
9
+ t.datetime :start_time
10
+ t.datetime :end_time
11
+ t.references :decidim_component, index: true
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimElectionsQuestions < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_elections_questions do |t|
6
+ t.references :decidim_elections_election, null: false, index: { name: "decidim_elections_elections_questions" }
7
+ t.jsonb :title, null: false
8
+ t.jsonb :description
9
+ t.integer :max_selections, null: false, default: 1
10
+ t.integer :weight, null: false, default: 0
11
+ t.boolean :random_answers_order, null: false, default: true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimElectionsAnswers < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_elections_answers do |t|
6
+ t.references :decidim_elections_question, null: false, index: { name: "decidim_elections_questions_answers" }
7
+ t.jsonb :title, null: false
8
+ t.jsonb :description
9
+ t.integer :weight, null: false, default: 0
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/elections/admin"
4
+ require "decidim/elections/engine"
5
+ require "decidim/elections/admin_engine"
6
+ require "decidim/elections/component"
7
+
8
+ module Decidim
9
+ # This namespace holds the logic of the `Elections` component. This component
10
+ # allows users to create elections in a participatory space.
11
+ module Elections
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Elections
5
+ # This module contains all the domain logic associated to Decidim's Elections
6
+ # component admin panel.
7
+ module Admin
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Elections
5
+ # This is the engine that runs on the public interface of `Elections`.
6
+ class AdminEngine < ::Rails::Engine
7
+ isolate_namespace Decidim::Elections::Admin
8
+
9
+ paths["db/migrate"] = nil
10
+ paths["lib/tasks"] = nil
11
+
12
+ routes do
13
+ resources :elections do
14
+ resources :questions do
15
+ resources :answers do
16
+ get :proposals_picker, on: :collection
17
+ end
18
+ end
19
+ end
20
+
21
+ root to: "elections#index"
22
+ end
23
+
24
+ def load_seed
25
+ nil
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "decidim/components/namer"
4
+
5
+ Decidim.register_component(:elections) do |component|
6
+ component.engine = Decidim::Elections::Engine
7
+ component.admin_engine = Decidim::Elections::AdminEngine
8
+ component.icon = "decidim/elections/icon.svg"
9
+ component.permissions_class_name = "Decidim::Elections::Permissions"
10
+
11
+ # component.on(:before_destroy) do |instance|
12
+ # # Code executed before removing the component
13
+ # end
14
+
15
+ # These actions permissions can be configured in the admin panel
16
+ # component.actions = %w()
17
+
18
+ component.settings(:global) do |settings|
19
+ settings.attribute :announcement, type: :text, translated: true, editor: true
20
+ end
21
+
22
+ component.settings(:step) do |settings|
23
+ settings.attribute :announcement, type: :text, translated: true, editor: true
24
+ end
25
+
26
+ component.register_resource(:election) do |resource|
27
+ resource.model_class_name = "Decidim::Elections::Election"
28
+ end
29
+
30
+ component.register_resource(:question) do |resource|
31
+ resource.model_class_name = "Decidim::Elections::Question"
32
+ end
33
+
34
+ component.register_resource(:answer) do |resource|
35
+ resource.model_class_name = "Decidim::Elections::Answer"
36
+ end
37
+
38
+ component.register_stat :elections_count, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, _start_at, _end_at|
39
+ Decidim::Elections::Election.where(component: components).count
40
+ end
41
+
42
+ component.seeds do |participatory_space|
43
+ admin_user = Decidim::User.find_by(
44
+ organization: participatory_space.organization,
45
+ email: "admin@example.org"
46
+ )
47
+
48
+ params = {
49
+ name: Decidim::Components::Namer.new(participatory_space.organization.available_locales, :elections).i18n_name,
50
+ manifest_name: :elections,
51
+ published_at: Time.current,
52
+ participatory_space: participatory_space
53
+ }
54
+
55
+ component = Decidim.traceability.perform_action!(
56
+ "publish",
57
+ Decidim::Component,
58
+ admin_user,
59
+ visibility: "all"
60
+ ) do
61
+ Decidim::Component.create!(params)
62
+ end
63
+
64
+ 3.times do
65
+ election = Decidim.traceability.create!(
66
+ Decidim::Elections::Election,
67
+ admin_user,
68
+ {
69
+ component: component,
70
+ title: Decidim::Faker::Localized.sentence(2),
71
+ subtitle: Decidim::Faker::Localized.sentence(2),
72
+ description: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
73
+ Decidim::Faker::Localized.paragraph(3)
74
+ end,
75
+ start_time: 3.weeks.from_now,
76
+ end_time: 3.weeks.from_now + 4.hours
77
+ },
78
+ visibility: "all"
79
+ )
80
+
81
+ 2.times do
82
+ question = Decidim.traceability.create!(
83
+ Decidim::Elections::Question,
84
+ admin_user,
85
+ {
86
+ election: election,
87
+ title: Decidim::Faker::Localized.sentence(2),
88
+ description: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
89
+ Decidim::Faker::Localized.paragraph(3)
90
+ end,
91
+ max_selections: Faker::Number.between(0, 5),
92
+ weight: Faker::Number.number(1),
93
+ random_answers_order: Faker::Boolean.boolean(0.5)
94
+ },
95
+ visibility: "all"
96
+ )
97
+
98
+ Faker::Number.between(2, 5).times do
99
+ answer = Decidim.traceability.create!(
100
+ Decidim::Elections::Answer,
101
+ admin_user,
102
+ {
103
+ question: question,
104
+ title: Decidim::Faker::Localized.sentence(2),
105
+ description: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
106
+ Decidim::Faker::Localized.paragraph(3)
107
+ end,
108
+ weight: Faker::Number.number(1)
109
+ },
110
+ visibility: "all"
111
+ )
112
+
113
+ Decidim::Attachment.create!(
114
+ title: Decidim::Faker::Localized.sentence(2),
115
+ description: Decidim::Faker::Localized.sentence(5),
116
+ file: File.new(File.join(__dir__, "seeds", "city.jpeg")),
117
+ attached_to: answer
118
+ )
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "decidim/core"
5
+
6
+ module Decidim
7
+ module Elections
8
+ # This is the engine that runs on the public interface of elections.
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace Decidim::Elections
11
+
12
+ routes do
13
+ resources :elections, only: [:index, :show]
14
+
15
+ root to: "elections#index"
16
+ end
17
+
18
+ initializer "decidim_elections.assets" do |app|
19
+ app.config.assets.precompile += %w(decidim_elections_manifest.js decidim_elections_manifest.css)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/core/test/factories"
4
+
5
+ FactoryBot.define do
6
+ factory :elections_component, parent: :component do
7
+ name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :elections).i18n_name }
8
+ manifest_name { :elections }
9
+ participatory_space { create(:participatory_process, :with_steps) }
10
+ end
11
+
12
+ factory :election, class: "Decidim::Elections::Election" do
13
+ title { generate_localized_title }
14
+ subtitle { Decidim::Faker::Localized.sentence(3) }
15
+ description { Decidim::Faker::Localized.wrapped("<p>", "</p>") { generate_localized_title } }
16
+ start_time { 1.day.from_now }
17
+ end_time { 3.days.from_now }
18
+ component { create(:elections_component) }
19
+
20
+ trait :started do
21
+ start_time { 1.day.ago }
22
+ end
23
+
24
+ trait :complete do
25
+ after(:build) do |election, _evaluator|
26
+ build_list(:question, 2, :complete, election: election)
27
+ end
28
+ end
29
+ end
30
+
31
+ factory :question, class: "Decidim::Elections::Question" do
32
+ election
33
+ title { generate_localized_title }
34
+ description { Decidim::Faker::Localized.wrapped("<p>", "</p>") { generate_localized_title } }
35
+ max_selections { 1 }
36
+ weight { Faker::Number.number(1) }
37
+ random_answers_order { true }
38
+
39
+ trait :complete do
40
+ after(:build) do |question, _evaluator|
41
+ build_list(:election_answer, 2, question: question)
42
+ end
43
+ end
44
+ end
45
+
46
+ factory :election_answer, class: "Decidim::Elections::Answer" do
47
+ question
48
+ title { generate_localized_title }
49
+ description { Decidim::Faker::Localized.wrapped("<p>", "</p>") { generate_localized_title } }
50
+ weight { Faker::Number.number(1) }
51
+ end
52
+ end