decidim-forms 0.19.1 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/commands/decidim/forms/answer_questionnaire.rb +6 -2
- data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +49 -2
- data/app/forms/decidim/forms/questionnaire_form.rb +8 -0
- data/app/models/decidim/forms/answer.rb +2 -2
- data/app/models/decidim/forms/questionnaire.rb +2 -1
- data/app/queries/decidim/forms/questionnaire_user_answers.rb +1 -1
- data/app/views/decidim/forms/questionnaires/show.html.erb +3 -2
- data/config/locales/ar.yml +3 -0
- data/config/locales/cs.yml +6 -0
- data/config/locales/en.yml +6 -0
- data/config/locales/fi-plain.yml +6 -0
- data/config/locales/fi.yml +6 -0
- data/config/locales/fr.yml +6 -0
- data/config/locales/hu.yml +6 -0
- data/config/locales/it.yml +6 -0
- data/config/locales/nl.yml +6 -0
- data/config/locales/sv.yml +6 -0
- data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +17 -0
- data/db/migrate/20190930094710_add_ip_hash_to_decidim_form_answers.rb +12 -0
- data/lib/decidim/forms/test/factories.rb +30 -11
- data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +8 -8
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +1 -1
- data/lib/decidim/forms/user_answers_serializer.rb +2 -0
- data/lib/decidim/forms/version.rb +1 -1
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d333400b35dde698ec6eb56578ce6d339d056abb654a32cf5429b6e525af594
|
4
|
+
data.tar.gz: 8bf35eecf87210818501d217c61522f8db293a86f35624ec76642a8a665aa678
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4aa63f125fbaf07ef76c0e209d79df0333c374e6675948e310e7787521a74fff17326c7b6e30414bc6ff99bd7f1d39af34bd0f9b68b2d03480e04f0da62105a
|
7
|
+
data.tar.gz: 138359228e76cd3b79dc0e4f46ced204204a03e31b0815627074ffbb17a7e301220a12eab0f9209a3a2fb24683ffad4da8aea67e01e24dfb1cf787cb2be1995f
|
data/README.md
CHANGED
@@ -54,7 +54,7 @@ See [Decidim](https://github.com/decidim/decidim).
|
|
54
54
|
|
55
55
|
## Seeds
|
56
56
|
|
57
|
-
Since questionnaires cannot exist without a
|
57
|
+
Since questionnaires cannot exist without a component we are not including specific seeds for this engine.
|
58
58
|
|
59
59
|
Other engines are free to include questionnaires on their seeds like this:
|
60
60
|
|
@@ -24,16 +24,20 @@ module Decidim
|
|
24
24
|
broadcast(:ok)
|
25
25
|
end
|
26
26
|
|
27
|
+
attr_reader :form
|
28
|
+
|
27
29
|
private
|
28
30
|
|
29
31
|
def answer_questionnaire
|
30
32
|
Answer.transaction do
|
31
|
-
|
33
|
+
form.answers.each do |form_answer|
|
32
34
|
answer = Answer.new(
|
33
35
|
user: @current_user,
|
34
36
|
questionnaire: @questionnaire,
|
35
37
|
question: form_answer.question,
|
36
|
-
body: form_answer.body
|
38
|
+
body: form_answer.body,
|
39
|
+
session_token: form.context.session_token,
|
40
|
+
ip_hash: form.context.ip_hash
|
37
41
|
)
|
38
42
|
|
39
43
|
form_answer.selected_choices.each do |choice|
|
@@ -16,7 +16,9 @@ module Decidim
|
|
16
16
|
helper Decidim::Forms::ApplicationHelper
|
17
17
|
include FormFactory
|
18
18
|
|
19
|
-
helper_method :questionnaire_for, :questionnaire, :allow_answers?, :update_url
|
19
|
+
helper_method :questionnaire_for, :questionnaire, :allow_answers?, :visitor_can_answer?, :visitor_already_answered?, :update_url
|
20
|
+
|
21
|
+
invisible_captcha on_spam: :spam_detected
|
20
22
|
|
21
23
|
def show
|
22
24
|
@form = form(Decidim::Forms::QuestionnaireForm).from_model(questionnaire)
|
@@ -26,7 +28,7 @@ module Decidim
|
|
26
28
|
def answer
|
27
29
|
enforce_permission_to :answer, :questionnaire
|
28
30
|
|
29
|
-
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params)
|
31
|
+
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token: session_token)
|
30
32
|
|
31
33
|
Decidim::Forms::AnswerQuestionnaire.call(@form, current_user, questionnaire) do
|
32
34
|
on(:ok) do
|
@@ -49,6 +51,22 @@ module Decidim
|
|
49
51
|
raise "#{self.class.name} is expected to implement #allow_answers?"
|
50
52
|
end
|
51
53
|
|
54
|
+
# Public: Method to be implemented at the controller if needed. You need to
|
55
|
+
# return true if the questionnaire can receive answers by unregistered users
|
56
|
+
def allow_unregistered?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: return true if the current user (if logged) can answer the questionnaire
|
61
|
+
def visitor_can_answer?
|
62
|
+
current_user || allow_unregistered?
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: return true if the current user (or session visitor) can answer the questionnaire
|
66
|
+
def visitor_already_answered?
|
67
|
+
questionnaire.answered_by?(current_user || tokenize(session[:session_id]))
|
68
|
+
end
|
69
|
+
|
52
70
|
# Public: Returns a String or Object that will be passed to `redirect_to` after
|
53
71
|
# answering the questionnaire. By default it redirects to the questionnaire_for.
|
54
72
|
#
|
@@ -78,6 +96,35 @@ module Decidim
|
|
78
96
|
def questionnaire
|
79
97
|
@questionnaire ||= Questionnaire.includes(questions: :answer_options).find_by(questionnaire_for: questionnaire_for)
|
80
98
|
end
|
99
|
+
|
100
|
+
def spam_detected
|
101
|
+
enforce_permission_to :answer, :questionnaire
|
102
|
+
|
103
|
+
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params)
|
104
|
+
|
105
|
+
flash.now[:alert] = I18n.t("answer.spam_detected", scope: i18n_flashes_scope)
|
106
|
+
render template: "decidim/forms/questionnaires/show"
|
107
|
+
end
|
108
|
+
|
109
|
+
def ip_hash
|
110
|
+
return nil unless request&.remote_ip
|
111
|
+
|
112
|
+
@ip_hash ||= tokenize(request&.remote_ip)
|
113
|
+
end
|
114
|
+
|
115
|
+
# token is used as a substitute of user_id if unregistered
|
116
|
+
def session_token
|
117
|
+
id = current_user&.id
|
118
|
+
session_id = request.session[:session_id] if request&.session
|
119
|
+
|
120
|
+
return nil unless id || session_id
|
121
|
+
|
122
|
+
@session_token ||= tokenize(id || session_id)
|
123
|
+
end
|
124
|
+
|
125
|
+
def tokenize(id)
|
126
|
+
Digest::MD5.hexdigest("#{id}-#{Rails.application.secrets.secret_key_base}")
|
127
|
+
end
|
81
128
|
end
|
82
129
|
end
|
83
130
|
end
|
@@ -8,7 +8,9 @@ module Decidim
|
|
8
8
|
attribute :user_group_id, Integer
|
9
9
|
|
10
10
|
attribute :tos_agreement, Boolean
|
11
|
+
|
11
12
|
validates :tos_agreement, allow_nil: false, acceptance: true
|
13
|
+
validate :session_token_in_context
|
12
14
|
|
13
15
|
# Private: Create the answers from the questionnaire questions
|
14
16
|
#
|
@@ -18,6 +20,12 @@ module Decidim
|
|
18
20
|
AnswerForm.from_model(Decidim::Forms::Answer.new(question: question))
|
19
21
|
end
|
20
22
|
end
|
23
|
+
|
24
|
+
def session_token_in_context
|
25
|
+
return if context&.session_token
|
26
|
+
|
27
|
+
errors.add(:tos_agreement, I18n.t("activemodel.errors.models.questionnaire.request_invalid"))
|
28
|
+
end
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
@@ -7,7 +7,7 @@ module Decidim
|
|
7
7
|
include Decidim::DataPortability
|
8
8
|
include Decidim::NewsletterParticipant
|
9
9
|
|
10
|
-
belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id"
|
10
|
+
belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id", optional: true
|
11
11
|
belongs_to :questionnaire, class_name: "Questionnaire", foreign_key: "decidim_questionnaire_id"
|
12
12
|
belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id"
|
13
13
|
|
@@ -45,7 +45,7 @@ module Decidim
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def user_questionnaire_same_organization
|
48
|
-
return if user&.organization == questionnaire.questionnaire_for&.organization
|
48
|
+
return if user.nil? || user&.organization == questionnaire.questionnaire_for&.organization
|
49
49
|
|
50
50
|
errors.add(:user, :invalid)
|
51
51
|
end
|
@@ -16,7 +16,8 @@ module Decidim
|
|
16
16
|
|
17
17
|
# Public: returns whether the questionnaire is answered by the user or not.
|
18
18
|
def answered_by?(user)
|
19
|
-
|
19
|
+
query = user.is_a?(String) ? { session_token: user } : { user: user }
|
20
|
+
answers.where(query).any? if questions.present?
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -21,7 +21,7 @@ module Decidim
|
|
21
21
|
# Finds and group answers by user for each questionnaire's question.
|
22
22
|
def query
|
23
23
|
answers = Answer.where(questionnaire: @questionnaire)
|
24
|
-
answers.sort_by { |answer| answer.question.position }.group_by
|
24
|
+
answers.sort_by { |answer| answer.question.position }.group_by { |a| a.user || a.session_token }.values
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -19,8 +19,8 @@
|
|
19
19
|
<div class="card">
|
20
20
|
<div class="card__content">
|
21
21
|
<% if allow_answers? %>
|
22
|
-
<% if
|
23
|
-
<% if
|
22
|
+
<% if visitor_can_answer? %>
|
23
|
+
<% if visitor_already_answered? %>
|
24
24
|
<div class="section">
|
25
25
|
<div class="callout success">
|
26
26
|
<h5><%= t(".questionnaire_answered.title") %></h5>
|
@@ -39,6 +39,7 @@
|
|
39
39
|
<% end %>
|
40
40
|
|
41
41
|
<%= decidim_form_for(@form, url: update_url, method: :post, html: { class: "form answer-questionnaire" }) do |form| %>
|
42
|
+
<%= invisible_captcha %>
|
42
43
|
<% @form.answers.each_with_index do |answer, answer_idx| %>
|
43
44
|
<div class="row column">
|
44
45
|
<%= fields_for "questionnaire[answers][#{answer_idx}]", answer do |answer_form| %>
|
data/config/locales/ar.yml
CHANGED
data/config/locales/cs.yml
CHANGED
@@ -15,6 +15,8 @@ cs:
|
|
15
15
|
choices:
|
16
16
|
missing: nejsou úplné
|
17
17
|
too_many: jsou příliš mnoho
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Při zpracování požadavku došlo k chybě. Prosím zkuste to znovu
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ cs:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Zodpovězeno
|
82
84
|
id: ID odpovědi
|
85
|
+
ip_hash: Ip Hash
|
86
|
+
registered: Registrován
|
87
|
+
unregistered: Neregistrovaný
|
88
|
+
user_status: Stav uživatele
|
data/config/locales/en.yml
CHANGED
@@ -16,6 +16,8 @@ en:
|
|
16
16
|
choices:
|
17
17
|
missing: are not complete
|
18
18
|
too_many: are too many
|
19
|
+
questionnaire:
|
20
|
+
request_invalid: There's been an error handling the request. Please try again
|
19
21
|
decidim:
|
20
22
|
forms:
|
21
23
|
admin:
|
@@ -81,3 +83,7 @@ en:
|
|
81
83
|
user_answers_serializer:
|
82
84
|
created_at: Answered on
|
83
85
|
id: Answer ID
|
86
|
+
ip_hash: Ip Hash
|
87
|
+
registered: Registered
|
88
|
+
unregistered: Unregistered
|
89
|
+
user_status: User status
|
data/config/locales/fi-plain.yml
CHANGED
@@ -15,6 +15,8 @@ fi-pl:
|
|
15
15
|
choices:
|
16
16
|
missing: ovat puutteellisia
|
17
17
|
too_many: liian monta
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Pyynnön käsittely ei onnistunut. Yritä uudestaan myöhemmin
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ fi-pl:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Vastattu
|
82
84
|
id: Vastaa tunnus
|
85
|
+
ip_hash: IP-tarkistesumma
|
86
|
+
registered: Rekisteröitynyt
|
87
|
+
unregistered: Ei rekisteröitynyt
|
88
|
+
user_status: Käyttäjän tila
|
data/config/locales/fi.yml
CHANGED
@@ -15,6 +15,8 @@ fi:
|
|
15
15
|
choices:
|
16
16
|
missing: ovat puutteellisia
|
17
17
|
too_many: liian monta
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Pyynnön käsittely ei onnistunut. Yritä uudestaan myöhemmin
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ fi:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Vastauksen ajankohta
|
82
84
|
id: Vastauksen ID
|
85
|
+
ip_hash: IP-tarkistesumma
|
86
|
+
registered: Rekisteröitynyt
|
87
|
+
unregistered: Ei rekisteröitynyt
|
88
|
+
user_status: Käyttäjän tila
|
data/config/locales/fr.yml
CHANGED
@@ -15,6 +15,8 @@ fr:
|
|
15
15
|
choices:
|
16
16
|
missing: ne sont pas complets
|
17
17
|
too_many: sont trop nombreux
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Il y a eu une erreur lors du traitement de la demande. Veuillez réessayer
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ fr:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Répondu le
|
82
84
|
id: ID de réponse
|
85
|
+
ip_hash: Hachage Ip
|
86
|
+
registered: Enregistré
|
87
|
+
unregistered: Non enregistré
|
88
|
+
user_status: Statut de l'utilisateur
|
data/config/locales/hu.yml
CHANGED
@@ -15,6 +15,8 @@ hu:
|
|
15
15
|
choices:
|
16
16
|
missing: nem teljesek
|
17
17
|
too_many: túl sok
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: A kérés teljesítése során hiba történt. Kérjük próbálkozzon újra
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ hu:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Válaszolt
|
82
84
|
id: Válasz azonosító
|
85
|
+
ip_hash: Ip Hash
|
86
|
+
registered: Regisztrált
|
87
|
+
unregistered: Nem regisztrált
|
88
|
+
user_status: Felhasználó státusza
|
data/config/locales/it.yml
CHANGED
@@ -15,6 +15,8 @@ it:
|
|
15
15
|
choices:
|
16
16
|
missing: non sono completi
|
17
17
|
too_many: sono troppi
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: C'è stato un errore di gestione della richiesta. Si prega di riprovare
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ it:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Risposto
|
82
84
|
id: ID risposta
|
85
|
+
ip_hash: Hash Ip
|
86
|
+
registered: Registrato
|
87
|
+
unregistered: Non registrato
|
88
|
+
user_status: Stato utente
|
data/config/locales/nl.yml
CHANGED
@@ -15,6 +15,8 @@ nl:
|
|
15
15
|
choices:
|
16
16
|
missing: zijn niet compleet
|
17
17
|
too_many: zijn te veel
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Er is een fout opgetreden bij het verwerken van het verzoek. Probeer het opnieuw
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ nl:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Beantwoord
|
82
84
|
id: Antwoord ID
|
85
|
+
ip_hash: Ip Hash
|
86
|
+
registered: Geregistreerd
|
87
|
+
unregistered: Niet-geregistreerd
|
88
|
+
user_status: Gebruiker-status
|
data/config/locales/sv.yml
CHANGED
@@ -15,6 +15,8 @@ sv:
|
|
15
15
|
choices:
|
16
16
|
missing: är inte fullständiga
|
17
17
|
too_many: är för många
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Ett fel uppstod när begäran skulle hanteras. Vänligen försök igen
|
18
20
|
decidim:
|
19
21
|
forms:
|
20
22
|
admin:
|
@@ -80,3 +82,7 @@ sv:
|
|
80
82
|
user_answers_serializer:
|
81
83
|
created_at: Besvarad
|
82
84
|
id: Svars-ID
|
85
|
+
ip_hash: Ip Hash
|
86
|
+
registered: Registrerad
|
87
|
+
unregistered: Oregistrerad
|
88
|
+
user_status: Användarstatus
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddSessionTokenToDecidimFormsAnswers < ActiveRecord::Migration[5.2]
|
4
|
+
class Answer < ApplicationRecord
|
5
|
+
self.table_name = :decidim_forms_answers
|
6
|
+
end
|
7
|
+
|
8
|
+
def change
|
9
|
+
add_column :decidim_forms_answers, :session_token, :string, null: false, default: ""
|
10
|
+
add_index :decidim_forms_answers, :session_token
|
11
|
+
|
12
|
+
Answer.find_each do |answer|
|
13
|
+
answer.session_token = Digest::MD5.hexdigest("#{answer.decidim_user_id}-#{Rails.application.secrets.secret_key_base}")
|
14
|
+
answer.save!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddIpHashToDecidimFormAnswers < ActiveRecord::Migration[5.2]
|
4
|
+
class Answer < ApplicationRecord
|
5
|
+
self.table_name = :decidim_forms_answers
|
6
|
+
end
|
7
|
+
|
8
|
+
def change
|
9
|
+
add_column :decidim_forms_answers, :ip_hash, :string
|
10
|
+
add_index :decidim_forms_answers, :ip_hash
|
11
|
+
end
|
12
|
+
end
|
@@ -4,7 +4,7 @@ require "decidim/core/test/factories"
|
|
4
4
|
require "decidim/participatory_processes/test/factories"
|
5
5
|
|
6
6
|
FactoryBot.define do
|
7
|
-
factory :questionnaire, class:
|
7
|
+
factory :questionnaire, class: Decidim::Forms::Questionnaire do
|
8
8
|
title { generate_localized_title }
|
9
9
|
description do
|
10
10
|
Decidim::Faker::Localized.wrapped("<p>", "</p>") do
|
@@ -13,11 +13,21 @@ FactoryBot.define do
|
|
13
13
|
end
|
14
14
|
tos { generate_localized_title }
|
15
15
|
questionnaire_for { build(:participatory_process) }
|
16
|
+
|
17
|
+
trait :with_questions do
|
18
|
+
questions do
|
19
|
+
qs = %w(short_answer long_answer).collect do |text_question_type|
|
20
|
+
build(:questionnaire_question, question_type: text_question_type)
|
21
|
+
end
|
22
|
+
qs << build(:questionnaire_question, :with_answer_options, question_type: :single_option)
|
23
|
+
qs
|
24
|
+
end
|
25
|
+
end
|
16
26
|
end
|
17
27
|
|
18
|
-
factory :questionnaire_question, class:
|
28
|
+
factory :questionnaire_question, class: Decidim::Forms::Question do
|
19
29
|
transient do
|
20
|
-
|
30
|
+
options { [] }
|
21
31
|
end
|
22
32
|
|
23
33
|
body { generate_localized_title }
|
@@ -27,28 +37,37 @@ FactoryBot.define do
|
|
27
37
|
questionnaire
|
28
38
|
|
29
39
|
before(:create) do |question, evaluator|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
if question.answer_options.empty?
|
41
|
+
evaluator.options.each do |option|
|
42
|
+
question.answer_options.build(
|
43
|
+
body: option["body"],
|
44
|
+
free_text: option["free_text"]
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
trait :with_answer_options do
|
51
|
+
answer_options do
|
52
|
+
Array.new(3).collect { build(:answer_option) }
|
35
53
|
end
|
36
54
|
end
|
37
55
|
end
|
38
56
|
|
39
|
-
factory :answer, class:
|
57
|
+
factory :answer, class: Decidim::Forms::Answer do
|
40
58
|
body { "hola" }
|
41
59
|
questionnaire
|
42
60
|
question { create(:questionnaire_question, questionnaire: questionnaire) }
|
43
61
|
user { create(:user, organization: questionnaire.questionnaire_for.organization) }
|
44
62
|
end
|
45
63
|
|
46
|
-
factory :answer_option, class:
|
64
|
+
factory :answer_option, class: Decidim::Forms::AnswerOption do
|
47
65
|
question { create(:questionnaire_question) }
|
48
66
|
body { generate_localized_title }
|
67
|
+
free_text { false }
|
49
68
|
end
|
50
69
|
|
51
|
-
factory :answer_choice, class:
|
70
|
+
factory :answer_choice, class: Decidim::Forms::AnswerChoice do
|
52
71
|
answer
|
53
72
|
answer_option { create(:answer_option, question: answer.question) }
|
54
73
|
end
|
@@ -54,7 +54,7 @@ shared_examples_for "has questionnaire" do
|
|
54
54
|
questionnaire: questionnaire,
|
55
55
|
question_type: "single_option",
|
56
56
|
position: 0,
|
57
|
-
|
57
|
+
options: [
|
58
58
|
{ "body" => Decidim::Faker::Localized.sentence },
|
59
59
|
{ "body" => Decidim::Faker::Localized.sentence }
|
60
60
|
]
|
@@ -163,7 +163,7 @@ shared_examples_for "has questionnaire" do
|
|
163
163
|
question_type: "single_option",
|
164
164
|
position: 0,
|
165
165
|
mandatory: true,
|
166
|
-
|
166
|
+
options: [
|
167
167
|
{ "body" => Decidim::Faker::Localized.sentence },
|
168
168
|
{ "body" => Decidim::Faker::Localized.sentence }
|
169
169
|
]
|
@@ -205,7 +205,7 @@ shared_examples_for "has questionnaire" do
|
|
205
205
|
:questionnaire_question,
|
206
206
|
questionnaire: questionnaire,
|
207
207
|
question_type: question_type,
|
208
|
-
|
208
|
+
options: [
|
209
209
|
{ "body" => answer_option_bodies[0] },
|
210
210
|
{ "body" => answer_option_bodies[1] },
|
211
211
|
{ "body" => answer_option_bodies[2], "free_text" => true }
|
@@ -219,7 +219,7 @@ shared_examples_for "has questionnaire" do
|
|
219
219
|
questionnaire: questionnaire,
|
220
220
|
question_type: "multiple_option",
|
221
221
|
max_choices: 2,
|
222
|
-
|
222
|
+
options: [
|
223
223
|
{ "body" => Decidim::Faker::Localized.sentence },
|
224
224
|
{ "body" => Decidim::Faker::Localized.sentence },
|
225
225
|
{ "body" => Decidim::Faker::Localized.sentence }
|
@@ -346,7 +346,7 @@ shared_examples_for "has questionnaire" do
|
|
346
346
|
|
347
347
|
context "when question type is single option" do
|
348
348
|
let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
349
|
-
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "single_option",
|
349
|
+
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "single_option", options: answer_options) }
|
350
350
|
|
351
351
|
it "renders answers as a collection of radio buttons" do
|
352
352
|
visit questionnaire_public_path
|
@@ -372,7 +372,7 @@ shared_examples_for "has questionnaire" do
|
|
372
372
|
|
373
373
|
context "when question type is multiple option" do
|
374
374
|
let(:answer_options) { Array.new(3) { { "body" => Decidim::Faker::Localized.sentence } } }
|
375
|
-
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option",
|
375
|
+
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option", options: answer_options) }
|
376
376
|
|
377
377
|
it "renders answers as a collection of radio buttons" do
|
378
378
|
visit questionnaire_public_path
|
@@ -431,7 +431,7 @@ shared_examples_for "has questionnaire" do
|
|
431
431
|
|
432
432
|
context "when question type is multiple option" do
|
433
433
|
let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
434
|
-
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option",
|
434
|
+
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option", options: answer_options) }
|
435
435
|
|
436
436
|
it "renders the question answers as a collection of radio buttons" do
|
437
437
|
visit questionnaire_public_path
|
@@ -462,7 +462,7 @@ shared_examples_for "has questionnaire" do
|
|
462
462
|
:questionnaire_question,
|
463
463
|
questionnaire: questionnaire,
|
464
464
|
question_type: "sorting",
|
465
|
-
|
465
|
+
options: [
|
466
466
|
{ "body" => "idiotas" },
|
467
467
|
{ "body" => "trates" },
|
468
468
|
{ "body" => "No" },
|
@@ -440,7 +440,7 @@ shared_examples_for "manage questionnaires" do
|
|
440
440
|
questionnaire: questionnaire,
|
441
441
|
body: body,
|
442
442
|
question_type: "single_option",
|
443
|
-
|
443
|
+
options: [
|
444
444
|
{ "body" => { "en" => "cacarua" } },
|
445
445
|
{ "body" => { "en" => "cat" } },
|
446
446
|
{ "body" => { "en" => "dog" } }
|
@@ -18,6 +18,8 @@ module Decidim
|
|
18
18
|
serialized.update(
|
19
19
|
answer_translated_attribute_name(:id) => answer.id,
|
20
20
|
answer_translated_attribute_name(:created_at) => answer.created_at.to_s(:db),
|
21
|
+
answer_translated_attribute_name(:ip_hash) => answer.ip_hash,
|
22
|
+
answer_translated_attribute_name(:user_status) => answer_translated_attribute_name(answer.decidim_user_id.present? ? "registered" : "unregistered"),
|
21
23
|
"#{idx + 1}. #{translated_attribute(answer.question.body)}" => normalize_body(answer)
|
22
24
|
)
|
23
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decidim-forms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep Jaume Rey Peroy
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2020-01-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: decidim-core
|
@@ -19,42 +19,42 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - '='
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.20.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.20.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: decidim-admin
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
34
|
- - '='
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: 0.
|
36
|
+
version: 0.20.0
|
37
37
|
type: :development
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - '='
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
43
|
+
version: 0.20.0
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: decidim-dev
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
48
|
- - '='
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.
|
50
|
+
version: 0.20.0
|
51
51
|
type: :development
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
55
|
- - '='
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 0.
|
57
|
+
version: 0.20.0
|
58
58
|
description: A forms gem for decidim.
|
59
59
|
email:
|
60
60
|
- josepjaume@gmail.com
|
@@ -143,6 +143,8 @@ files:
|
|
143
143
|
- db/migrate/20170515144119_create_decidim_forms_answers.rb
|
144
144
|
- db/migrate/20180405015012_create_decidim_forms_answer_options.rb
|
145
145
|
- db/migrate/20180405015147_create_decidim_forms_answer_choices.rb
|
146
|
+
- db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb
|
147
|
+
- db/migrate/20190930094710_add_ip_hash_to_decidim_form_answers.rb
|
146
148
|
- lib/decidim/forms.rb
|
147
149
|
- lib/decidim/forms/admin.rb
|
148
150
|
- lib/decidim/forms/admin_engine.rb
|