decidim-surveys 0.30.3 → 0.31.0.rc2
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/README.md +3 -3
 - data/app/commands/decidim/surveys/admin/create_survey.rb +14 -2
 - data/app/commands/decidim/surveys/admin/publish_survey.rb +3 -3
 - data/app/commands/decidim/surveys/admin/update_survey.rb +0 -13
 - data/app/commands/decidim/surveys/admin/update_survey_settings.rb +53 -0
 - data/app/commands/decidim/surveys/{publish_answers.rb → publish_responses.rb} +8 -8
 - data/app/commands/decidim/surveys/{unpublish_answers.rb → unpublish_responses.rb} +8 -8
 - data/app/controllers/decidim/surveys/admin/application_controller.rb +13 -0
 - data/app/controllers/decidim/surveys/admin/{publish_answers_controller.rb → publish_responses_controller.rb} +9 -9
 - data/app/controllers/decidim/surveys/admin/questions/surveys_controller.rb +48 -0
 - data/app/controllers/decidim/surveys/admin/{answers_controller.rb → responses_controller.rb} +18 -13
 - data/app/controllers/decidim/surveys/admin/settings/surveys_controller.rb +42 -0
 - data/app/controllers/decidim/surveys/admin/surveys_controller.rb +20 -39
 - data/app/controllers/decidim/surveys/surveys_controller.rb +15 -12
 - data/app/forms/decidim/surveys/admin/survey_form.rb +3 -7
 - data/app/forms/decidim/surveys/admin/survey_settings_form.rb +18 -0
 - data/app/helpers/decidim/surveys/{publish_answers_helper.rb → publish_responses_helper.rb} +11 -11
 - data/app/helpers/decidim/surveys/survey_helper.rb +1 -1
 - data/app/jobs/decidim/surveys/{clean_survey_answers_job.rb → clean_survey_responses_job.rb} +4 -4
 - data/app/jobs/decidim/surveys/settings_change_job.rb +5 -5
 - data/app/mailers/decidim/surveys/survey_confirmation_mailer.rb +6 -6
 - data/app/models/decidim/surveys/survey.rb +4 -4
 - data/app/permissions/decidim/surveys/admin/permissions.rb +4 -4
 - data/app/permissions/decidim/surveys/permissions.rb +1 -1
 - data/app/serializers/decidim/surveys/data_importer.rb +5 -5
 - data/app/serializers/decidim/surveys/data_serializer.rb +5 -5
 - data/app/views/decidim/surveys/admin/publish_responses/_toggle_button.html.erb +22 -0
 - data/app/views/decidim/surveys/admin/{publish_answers → publish_responses}/index.html.erb +5 -5
 - data/app/views/decidim/surveys/admin/questions/surveys/edit.html.erb +44 -0
 - data/app/views/decidim/surveys/admin/responses/index.html.erb +101 -0
 - data/app/views/decidim/surveys/admin/responses/show.html.erb +43 -0
 - data/app/views/decidim/surveys/admin/{surveys → settings/surveys}/_form.html.erb +2 -3
 - data/app/views/decidim/surveys/admin/settings/surveys/edit.html.erb +23 -0
 - data/app/views/decidim/surveys/admin/surveys/_tabs_menu.html.erb +11 -0
 - data/app/views/decidim/surveys/admin/surveys/edit.html.erb +18 -18
 - data/app/views/decidim/surveys/admin/surveys/index.html.erb +101 -23
 - data/app/views/decidim/surveys/admin/surveys/new.html.erb +23 -0
 - data/app/views/decidim/surveys/survey_confirmation_mailer/confirmation.html.erb +1 -1
 - data/app/views/decidim/surveys/surveys/{_published_questions_answers.html.erb → _published_questions_responses.html.erb} +2 -2
 - data/app/views/decidim/surveys/surveys/not_allowed.html.erb +2 -2
 - data/app/views/layouts/decidim/admin/surveys.html.erb +18 -0
 - data/config/assets.rb +1 -1
 - data/config/locales/ar.yml +0 -20
 - data/config/locales/bg.yml +0 -28
 - data/config/locales/ca-IT.yml +50 -29
 - data/config/locales/ca.yml +50 -29
 - data/config/locales/cs.yml +37 -39
 - data/config/locales/de.yml +42 -26
 - data/config/locales/el.yml +0 -23
 - data/config/locales/en.yml +54 -33
 - data/config/locales/es-MX.yml +49 -28
 - data/config/locales/es-PY.yml +49 -28
 - data/config/locales/es.yml +49 -28
 - data/config/locales/eu.yml +48 -27
 - data/config/locales/fi-plain.yml +46 -25
 - data/config/locales/fi.yml +46 -25
 - data/config/locales/fr-CA.yml +40 -32
 - data/config/locales/fr.yml +40 -32
 - data/config/locales/ga-IE.yml +0 -13
 - data/config/locales/gl.yml +0 -22
 - data/config/locales/hu.yml +0 -16
 - data/config/locales/id-ID.yml +0 -15
 - data/config/locales/is-IS.yml +0 -2
 - data/config/locales/it.yml +0 -22
 - data/config/locales/ja.yml +48 -27
 - data/config/locales/lb.yml +0 -22
 - data/config/locales/lt.yml +0 -25
 - data/config/locales/lv.yml +0 -17
 - data/config/locales/nl.yml +0 -22
 - data/config/locales/no.yml +0 -22
 - data/config/locales/pl.yml +0 -30
 - data/config/locales/pt-BR.yml +0 -22
 - data/config/locales/pt.yml +0 -22
 - data/config/locales/ro-RO.yml +18 -23
 - data/config/locales/ru.yml +0 -13
 - data/config/locales/sk.yml +0 -18
 - data/config/locales/sl.yml +0 -8
 - data/config/locales/sv.yml +13 -23
 - data/config/locales/tr-TR.yml +0 -22
 - data/config/locales/uk.yml +0 -13
 - data/config/locales/zh-CN.yml +0 -15
 - data/config/locales/zh-TW.yml +0 -22
 - data/db/migrate/20250317110501_rename_answer_to_response_in_decidim_surveys.rb +8 -0
 - data/lib/decidim/api/survey_type.rb +12 -0
 - data/lib/decidim/surveys/admin_engine.rb +46 -7
 - data/lib/decidim/surveys/component.rb +24 -19
 - data/lib/decidim/surveys/engine.rb +8 -25
 - data/lib/decidim/surveys/seeds.rb +42 -42
 - data/lib/decidim/surveys/test/factories.rb +3 -3
 - data/lib/decidim/surveys/version.rb +1 -1
 - data/lib/tasks/surveys/upgrade/decidim_surveys_upgrade_tasks.rake +16 -82
 - metadata +35 -28
 - data/app/queries/decidim/surveys/metrics/answers_metric_manage.rb +0 -65
 - data/app/queries/decidim/surveys/metrics/survey_participants_metric_measure.rb +0 -30
 - data/app/views/decidim/surveys/admin/answers/index.html.erb +0 -49
 - data/app/views/decidim/surveys/admin/answers/show.html.erb +0 -43
 - data/app/views/decidim/surveys/admin/publish_answers/_toggle_button.html.erb +0 -22
 - data/app/views/decidim/surveys/admin/surveys/edit_questions.html.erb +0 -47
 
| 
         @@ -2,16 +2,19 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Decidim
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Surveys
         
     | 
| 
       5 
     | 
    
         
            -
                # Exposes the survey resource so users can view and  
     | 
| 
      
 5 
     | 
    
         
            +
                # Exposes the survey resource so users can view and respond them.
         
     | 
| 
       6 
6 
     | 
    
         
             
                class SurveysController < Decidim::Surveys::ApplicationController
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # i18n-tasks-use t('decidim.surveys.surveys.response.invalid')
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # i18n-tasks-use t('decidim.surveys.surveys.response.spam_detected')
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # i18n-tasks-use t('decidim.surveys.surveys.response.success')
         
     | 
| 
       7 
10 
     | 
    
         
             
                  include Decidim::Forms::Concerns::HasQuestionnaire
         
     | 
| 
       8 
11 
     | 
    
         
             
                  include Decidim::ComponentPathHelper
         
     | 
| 
       9 
12 
     | 
    
         
             
                  include Decidim::Surveys::SurveyHelper
         
     | 
| 
       10 
13 
     | 
    
         
             
                  include FilterResource
         
     | 
| 
       11 
14 
     | 
    
         
             
                  include Paginable
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                  helper  
     | 
| 
       14 
     | 
    
         
            -
                  helper_method :authorizations, :surveys, : 
     | 
| 
      
 16 
     | 
    
         
            +
                  helper PublishResponsesHelper
         
     | 
| 
      
 17 
     | 
    
         
            +
                  helper_method :authorizations, :surveys, :show_published_questions_responses?
         
     | 
| 
       15 
18 
     | 
    
         | 
| 
       16 
19 
     | 
    
         
             
                  before_action :check_permissions, except: [:index]
         
     | 
| 
       17 
20 
     | 
    
         
             
                  before_action :check_editable, only: [:edit]
         
     | 
| 
         @@ -20,14 +23,14 @@ module Decidim 
     | 
|
| 
       20 
23 
     | 
    
         | 
| 
       21 
24 
     | 
    
         
             
                  def edit
         
     | 
| 
       22 
25 
     | 
    
         
             
                    @form = form(Decidim::Forms::QuestionnaireForm).from_model(questionnaire)
         
     | 
| 
       23 
     | 
    
         
            -
                    @form. 
     | 
| 
       24 
     | 
    
         
            -
                    @form. 
     | 
| 
      
 26 
     | 
    
         
            +
                    @form.add_responses!(questionnaire:, session_token:, ip_hash:)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @form.allow_editing_responses = questionnaire.questionnaire_for&.allow_editing_responses?
         
     | 
| 
       25 
28 
     | 
    
         | 
| 
       26 
29 
     | 
    
         
             
                    render template: "decidim/forms/questionnaires/edit"
         
     | 
| 
       27 
30 
     | 
    
         
             
                  end
         
     | 
| 
       28 
31 
     | 
    
         | 
| 
       29 
32 
     | 
    
         
             
                  def check_permissions
         
     | 
| 
       30 
     | 
    
         
            -
                    render :no_permission unless action_authorized_to(: 
     | 
| 
      
 33 
     | 
    
         
            +
                    render :no_permission unless action_authorized_to(:response, resource: survey).ok?
         
     | 
| 
       31 
34 
     | 
    
         
             
                  end
         
     | 
| 
       32 
35 
     | 
    
         | 
| 
       33 
36 
     | 
    
         
             
                  def questionnaire_for
         
     | 
| 
         @@ -37,21 +40,21 @@ module Decidim 
     | 
|
| 
       37 
40 
     | 
    
         
             
                  protected
         
     | 
| 
       38 
41 
     | 
    
         | 
| 
       39 
42 
     | 
    
         
             
                  def check_editable
         
     | 
| 
       40 
     | 
    
         
            -
                    return if  
     | 
| 
      
 43 
     | 
    
         
            +
                    return if allow_editing_responses?
         
     | 
| 
       41 
44 
     | 
    
         | 
| 
       42 
45 
     | 
    
         
             
                    flash.now[:error] = t("decidim.forms.step_navigation.show.disallowed")
         
     | 
| 
       43 
46 
     | 
    
         
             
                    render :not_allowed
         
     | 
| 
       44 
47 
     | 
    
         
             
                  end
         
     | 
| 
       45 
48 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                  def  
     | 
| 
       47 
     | 
    
         
            -
                     
     | 
| 
      
 49 
     | 
    
         
            +
                  def allow_editing_responses?
         
     | 
| 
      
 50 
     | 
    
         
            +
                    visitor_can_edit_responses? && survey.open?
         
     | 
| 
       48 
51 
     | 
    
         
             
                  end
         
     | 
| 
       49 
52 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                  def  
     | 
| 
       51 
     | 
    
         
            -
                    survey.closed? && survey.questionnaire.questions.pluck(: 
     | 
| 
      
 53 
     | 
    
         
            +
                  def show_published_questions_responses?
         
     | 
| 
      
 54 
     | 
    
         
            +
                    survey.closed? && survey.questionnaire.questions.pluck(:survey_responses_published_at).any?
         
     | 
| 
       52 
55 
     | 
    
         
             
                  end
         
     | 
| 
       53 
56 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
                  def  
     | 
| 
      
 57 
     | 
    
         
            +
                  def allow_responses?
         
     | 
| 
       55 
58 
     | 
    
         
             
                    !current_component.published? || survey.open?
         
     | 
| 
       56 
59 
     | 
    
         
             
                  end
         
     | 
| 
       57 
60 
     | 
    
         | 
| 
         @@ -4,14 +4,10 @@ module Decidim 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Surveys
         
     | 
| 
       5 
5 
     | 
    
         
             
                module Admin
         
     | 
| 
       6 
6 
     | 
    
         
             
                  class SurveyForm < Decidim::Forms::Admin::QuestionnaireForm
         
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
      
 7 
     | 
    
         
            +
                    include TranslatableAttributes
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
                    attribute :clean_after_publish, Boolean
         
     | 
| 
       12 
     | 
    
         
            -
                    attribute :allow_editing_answers, Boolean
         
     | 
| 
       13 
     | 
    
         
            -
                    attribute :starts_at, Decidim::Attributes::TimeWithZone
         
     | 
| 
       14 
     | 
    
         
            -
                    attribute :ends_at, Decidim::Attributes::TimeWithZone
         
     | 
| 
      
 9 
     | 
    
         
            +
                    validates :title, translatable_presence: true
         
     | 
| 
      
 10 
     | 
    
         
            +
                    validates :tos, presence: true
         
     | 
| 
       15 
11 
     | 
    
         
             
                  end
         
     | 
| 
       16 
12 
     | 
    
         
             
                end
         
     | 
| 
       17 
13 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Decidim
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Surveys
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Admin
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class SurveySettingsForm < Decidim::Forms::Admin::QuestionnaireForm
         
     | 
| 
      
 7 
     | 
    
         
            +
                    translatable_attribute :announcement, String
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    attribute :allow_responses, Boolean
         
     | 
| 
      
 10 
     | 
    
         
            +
                    attribute :allow_unregistered, Boolean
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attribute :clean_after_publish, Boolean
         
     | 
| 
      
 12 
     | 
    
         
            +
                    attribute :allow_editing_responses, Boolean
         
     | 
| 
      
 13 
     | 
    
         
            +
                    attribute :starts_at, Decidim::Attributes::TimeWithZone
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attribute :ends_at, Decidim::Attributes::TimeWithZone
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -2,9 +2,9 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Decidim
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Surveys
         
     | 
| 
       5 
     | 
    
         
            -
                module  
     | 
| 
       6 
     | 
    
         
            -
                  def  
     | 
| 
       7 
     | 
    
         
            -
                    ignored_question_types = %w( 
     | 
| 
      
 5 
     | 
    
         
            +
                module PublishResponsesHelper
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def question_response_is_publicable(question_type)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    ignored_question_types = %w(short_response long_response separator files).freeze
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                    ignored_question_types.exclude?(question_type)
         
     | 
| 
       10 
10 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -14,7 +14,7 @@ module Decidim 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  #
         
     | 
| 
       15 
15 
     | 
    
         
             
                  # @param question_id [Integer] the question id for Decidim:
         
     | 
| 
       16 
16 
     | 
    
         
             
                  def chart_for_question(question_id)
         
     | 
| 
       17 
     | 
    
         
            -
                    question = Decidim::Forms::Question.includes( 
     | 
| 
      
 17 
     | 
    
         
            +
                    question = Decidim::Forms::Question.includes(responses: { choices: [:response_option, :matrix_row] }).find(question_id)
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                    Chartkick.options = {
         
     | 
| 
       20 
20 
     | 
    
         
             
                      library: { animation: { easing: "easeOutQuart" } },
         
     | 
| 
         @@ -38,9 +38,9 @@ module Decidim 
     | 
|
| 
       38 
38 
     | 
    
         
             
                  def sorting_stack_chart_wrapper(question)
         
     | 
| 
       39 
39 
     | 
    
         
             
                    counts = Hash.new { |hash, key| hash[key] = Hash.new(0) }
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                    question. 
     | 
| 
       42 
     | 
    
         
            -
                       
     | 
| 
       43 
     | 
    
         
            -
                        name = translated_attribute(choice. 
     | 
| 
      
 41 
     | 
    
         
            +
                    question.responses.each do |response|
         
     | 
| 
      
 42 
     | 
    
         
            +
                      response.choices.each do |choice|
         
     | 
| 
      
 43 
     | 
    
         
            +
                        name = translated_attribute(choice.response_option.body)
         
     | 
| 
       44 
44 
     | 
    
         
             
                        row = choice.position + 1
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                        counts[row][name] += 1
         
     | 
| 
         @@ -60,9 +60,9 @@ module Decidim 
     | 
|
| 
       60 
60 
     | 
    
         
             
                  def matrix_stack_chart_wrapper(question)
         
     | 
| 
       61 
61 
     | 
    
         
             
                    counts = Hash.new { |hash, key| hash[key] = Hash.new(0) }
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
                    question. 
     | 
| 
       64 
     | 
    
         
            -
                       
     | 
| 
       65 
     | 
    
         
            -
                        name = translated_attribute(choice. 
     | 
| 
      
 63 
     | 
    
         
            +
                    question.responses.each do |response|
         
     | 
| 
      
 64 
     | 
    
         
            +
                      response.choices.each do |choice|
         
     | 
| 
      
 65 
     | 
    
         
            +
                        name = translated_attribute(choice.response_option.body)
         
     | 
| 
       66 
66 
     | 
    
         
             
                        row = translated_attribute(choice.matrix_row.body)
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
68 
     | 
    
         
             
                        counts[name][row] += 1
         
     | 
| 
         @@ -80,7 +80,7 @@ module Decidim 
     | 
|
| 
       80 
80 
     | 
    
         
             
                  end
         
     | 
| 
       81 
81 
     | 
    
         | 
| 
       82 
82 
     | 
    
         
             
                  def options_column_chart_wrapper(question)
         
     | 
| 
       83 
     | 
    
         
            -
                    tally = question. 
     | 
| 
      
 83 
     | 
    
         
            +
                    tally = question.responses.map { |response| response.choices.map { |choice| translated_attribute(choice.response_option.body) } }.tally
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
85 
     | 
    
         
             
                    column_chart(tally, download: true)
         
     | 
| 
       86 
86 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Decidim
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Surveys
         
     | 
| 
       5 
     | 
    
         
            -
                class  
     | 
| 
      
 5 
     | 
    
         
            +
                class CleanSurveyResponsesJob < ApplicationJob
         
     | 
| 
       6 
6 
     | 
    
         
             
                  def perform(_event_name, data)
         
     | 
| 
       7 
7 
     | 
    
         
             
                    @component = data[:resource]
         
     | 
| 
       8 
8 
     | 
    
         
             
                    return unless component&.manifest_name == "surveys"
         
     | 
| 
         @@ -12,7 +12,7 @@ module Decidim 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                    case data[:event_class]
         
     | 
| 
       14 
14 
     | 
    
         
             
                    when "Decidim::ComponentPublishedEvent"
         
     | 
| 
       15 
     | 
    
         
            -
                       
     | 
| 
      
 15 
     | 
    
         
            +
                      clean_responses
         
     | 
| 
       16 
16 
     | 
    
         
             
                    end
         
     | 
| 
       17 
17 
     | 
    
         
             
                  end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
         @@ -20,10 +20,10 @@ module Decidim 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                  attr_reader :survey, :component
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                  def  
     | 
| 
      
 23 
     | 
    
         
            +
                  def clean_responses
         
     | 
| 
       24 
24 
     | 
    
         
             
                    return unless survey.clean_after_publish?
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                    survey.questionnaire. 
     | 
| 
      
 26 
     | 
    
         
            +
                    survey.questionnaire.responses.destroy_all
         
     | 
| 
       27 
27 
     | 
    
         
             
                    component.settings[:clean_after_publish] = false
         
     | 
| 
       28 
28 
     | 
    
         
             
                    component.save
         
     | 
| 
       29 
29 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -29,18 +29,18 @@ module Decidim 
     | 
|
| 
       29 
29 
     | 
    
         
             
                  private
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                  def unchanged?(previous_settings, current_settings)
         
     | 
| 
       32 
     | 
    
         
            -
                    current_settings[: 
     | 
| 
      
 32 
     | 
    
         
            +
                    current_settings[:allow_responses] == previous_settings[:allow_responses]
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
                  # rubocop:disable Style/DoubleNegation
         
     | 
| 
       36 
36 
     | 
    
         
             
                  def survey_opened?(previous_settings, current_settings)
         
     | 
| 
       37 
     | 
    
         
            -
                    current_settings[: 
     | 
| 
       38 
     | 
    
         
            -
                      !!previous_settings[: 
     | 
| 
      
 37 
     | 
    
         
            +
                    current_settings[:allow_responses] == true &&
         
     | 
| 
      
 38 
     | 
    
         
            +
                      !!previous_settings[:allow_responses] == false
         
     | 
| 
       39 
39 
     | 
    
         
             
                  end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                  def survey_closed?(previous_settings, current_settings)
         
     | 
| 
       42 
     | 
    
         
            -
                    !!current_settings[: 
     | 
| 
       43 
     | 
    
         
            -
                      previous_settings[: 
     | 
| 
      
 42 
     | 
    
         
            +
                    !!current_settings[:allow_responses] == false &&
         
     | 
| 
      
 43 
     | 
    
         
            +
                      previous_settings[:allow_responses] == true
         
     | 
| 
       44 
44 
     | 
    
         
             
                  end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                  def clean_after_publish_changed?(previous_settings, current_settings)
         
     | 
| 
         @@ -6,8 +6,8 @@ module Decidim 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  include TranslatableAttributes
         
     | 
| 
       7 
7 
     | 
    
         
             
                  helper Decidim::SanitizeHelper
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                  def confirmation(user, questionnaire,  
     | 
| 
       10 
     | 
    
         
            -
                    return if  
     | 
| 
      
 9 
     | 
    
         
            +
                  def confirmation(user, questionnaire, responses)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return if responses.blank? || user.nil?
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                    with_user(user) do
         
     | 
| 
       13 
13 
     | 
    
         
             
                      @user = user
         
     | 
| 
         @@ -15,7 +15,7 @@ module Decidim 
     | 
|
| 
       15 
15 
     | 
    
         
             
                      @participatory_space_title = translated_attribute(questionnaire.questionnaire_for.component.participatory_space.title)
         
     | 
| 
       16 
16 
     | 
    
         
             
                      @organization = user.organization
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                       
     | 
| 
      
 18 
     | 
    
         
            +
                      add_file_with_responses(responses)
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                      mail(to: "#{@user.name} <#{@user.email}>", subject: t(".subject", questionnaire_title: @questionnaire_title))
         
     | 
| 
       21 
21 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -23,11 +23,11 @@ module Decidim 
     | 
|
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                  private
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                  def  
     | 
| 
      
 26 
     | 
    
         
            +
                  def add_file_with_responses(responses)
         
     | 
| 
       27 
27 
     | 
    
         
             
                    export_name = t("decidim.surveys.survey_confirmation_mailer.export_name")
         
     | 
| 
       28 
     | 
    
         
            -
                    serializer = Decidim::Forms:: 
     | 
| 
      
 28 
     | 
    
         
            +
                    serializer = Decidim::Forms::UserResponsesSerializer
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                    export_data = Decidim::Exporters::FormPDF.new( 
     | 
| 
      
 30 
     | 
    
         
            +
                    export_data = Decidim::Exporters::FormPDF.new(responses, serializer).export
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                    filename = export_data.filename(export_name)
         
     | 
| 
       33 
33 
     | 
    
         
             
                    filename_without_extension = export_data.filename(export_name, extension: false)
         
     | 
| 
         @@ -19,7 +19,7 @@ module Decidim 
     | 
|
| 
       19 
19 
     | 
    
         
             
                  validates :questionnaire, presence: true
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                  scope :open, lambda {
         
     | 
| 
       22 
     | 
    
         
            -
                    where( 
     | 
| 
      
 22 
     | 
    
         
            +
                    where(allow_responses: true)
         
     | 
| 
       23 
23 
     | 
    
         
             
                      .where(starts_at: nil, ends_at: nil).or(
         
     | 
| 
       24 
24 
     | 
    
         
             
                        where("starts_at <= ? AND (ends_at IS NULL OR ends_at > ?)", Time.current, Time.current)
         
     | 
| 
       25 
25 
     | 
    
         
             
                      ).or(
         
     | 
| 
         @@ -27,7 +27,7 @@ module Decidim 
     | 
|
| 
       27 
27 
     | 
    
         
             
                      )
         
     | 
| 
       28 
28 
     | 
    
         
             
                  }
         
     | 
| 
       29 
29 
     | 
    
         
             
                  scope :closed, lambda {
         
     | 
| 
       30 
     | 
    
         
            -
                    where( 
     | 
| 
      
 30 
     | 
    
         
            +
                    where(allow_responses: false).or(
         
     | 
| 
       31 
31 
     | 
    
         
             
                      where("starts_at > ?", Time.current).or(
         
     | 
| 
       32 
32 
     | 
    
         
             
                        where(ends_at: ...Time.current)
         
     | 
| 
       33 
33 
     | 
    
         
             
                      )
         
     | 
| 
         @@ -38,7 +38,7 @@ module Decidim 
     | 
|
| 
       38 
38 
     | 
    
         
             
                  scope_search_multi :with_any_state, [:open, :closed]
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
40 
     | 
    
         
             
                  def open?
         
     | 
| 
       41 
     | 
    
         
            -
                    return false if  
     | 
| 
      
 41 
     | 
    
         
            +
                    return false if allow_responses.blank?
         
     | 
| 
       42 
42 
     | 
    
         
             
                    return true if time_indefinite?
         
     | 
| 
       43 
43 
     | 
    
         
             
                    return true if started_but_no_end?
         
     | 
| 
       44 
44 
     | 
    
         
             
                    return true if no_start_but_ends_later?
         
     | 
| 
         @@ -57,7 +57,7 @@ module Decidim 
     | 
|
| 
       57 
57 
     | 
    
         
             
                  end
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
                  def self.ransackable_attributes(_auth_object = nil)
         
     | 
| 
       60 
     | 
    
         
            -
                    %w(ends_at starts_at  
     | 
| 
      
 60 
     | 
    
         
            +
                    %w(ends_at starts_at allow_responses)
         
     | 
| 
       61 
61 
     | 
    
         
             
                  end
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
       63 
63 
     | 
    
         
             
                  def self.log_presenter_class_for(_log)
         
     | 
| 
         @@ -14,18 +14,18 @@ module Decidim 
     | 
|
| 
       14 
14 
     | 
    
         
             
                      case permission_action.subject
         
     | 
| 
       15 
15 
     | 
    
         
             
                      when :questionnaire
         
     | 
| 
       16 
16 
     | 
    
         
             
                        case permission_action.action
         
     | 
| 
       17 
     | 
    
         
            -
                        when : 
     | 
| 
      
 17 
     | 
    
         
            +
                        when :export_responses, :update, :create, :destroy, :preview
         
     | 
| 
       18 
18 
     | 
    
         
             
                          permission_action.allow!
         
     | 
| 
       19 
19 
     | 
    
         
             
                        end
         
     | 
| 
       20 
     | 
    
         
            -
                      when : 
     | 
| 
      
 20 
     | 
    
         
            +
                      when :questionnaire_responses
         
     | 
| 
       21 
21 
     | 
    
         
             
                        case permission_action.action
         
     | 
| 
       22 
22 
     | 
    
         
             
                        when :index, :show, :export_response
         
     | 
| 
       23 
23 
     | 
    
         
             
                          permission_action.allow!
         
     | 
| 
       24 
24 
     | 
    
         
             
                        end
         
     | 
| 
       25 
     | 
    
         
            -
                      when : 
     | 
| 
      
 25 
     | 
    
         
            +
                      when :questionnaire_publish_responses
         
     | 
| 
       26 
26 
     | 
    
         
             
                        case permission_action.action
         
     | 
| 
       27 
27 
     | 
    
         
             
                        when :index, :update, :destroy
         
     | 
| 
       28 
     | 
    
         
            -
                          if context.fetch(:survey). 
     | 
| 
      
 28 
     | 
    
         
            +
                          if context.fetch(:survey).allow_responses
         
     | 
| 
       29 
29 
     | 
    
         
             
                            permission_action.disallow!
         
     | 
| 
       30 
30 
     | 
    
         
             
                          else
         
     | 
| 
       31 
31 
     | 
    
         
             
                            permission_action.allow!
         
     | 
| 
         @@ -10,7 +10,7 @@ module Decidim 
     | 
|
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                  # Public: Creates a new Decidim::Surveys::Survey and Decidim::Forms::Questionnaire associated to the given +component+
         
     | 
| 
       12 
12 
     | 
    
         
             
                  #         for each serialized survey object.
         
     | 
| 
       13 
     | 
    
         
            -
                  # It imports the whole tree of Survey->Questionnaire->questions-> 
     | 
| 
      
 13 
     | 
    
         
            +
                  # It imports the whole tree of Survey->Questionnaire->questions->response_options.
         
     | 
| 
       14 
14 
     | 
    
         
             
                  #
         
     | 
| 
       15 
15 
     | 
    
         
             
                  # serialized        - The Hash of attributes for the Questionnaire and its relations.
         
     | 
| 
       16 
16 
     | 
    
         
             
                  # user              - The +user+ that is performing this action
         
     | 
| 
         @@ -47,17 +47,17 @@ module Decidim 
     | 
|
| 
       47 
47 
     | 
    
         
             
                    Survey.new(component: @component)
         
     | 
| 
       48 
48 
     | 
    
         
             
                  end
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                  # Builds a Decidim::Forms::Questionnaire with all its questions and  
     | 
| 
      
 50 
     | 
    
         
            +
                  # Builds a Decidim::Forms::Questionnaire with all its questions and response_options.
         
     | 
| 
       51 
51 
     | 
    
         
             
                  def build_questionnaire(survey, serialized_questionnaire)
         
     | 
| 
       52 
52 
     | 
    
         
             
                    survey.build_questionnaire(serialized_questionnaire.except(:id, :published_at))
         
     | 
| 
       53 
53 
     | 
    
         
             
                  end
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
       55 
55 
     | 
    
         
             
                  def import_questions(questionnaire, serialized_questions)
         
     | 
| 
       56 
56 
     | 
    
         
             
                    serialized_questions.each do |serialized_question|
         
     | 
| 
       57 
     | 
    
         
            -
                       
     | 
| 
      
 57 
     | 
    
         
            +
                      serialized_response_options = serialized_question.delete(:response_options)
         
     | 
| 
       58 
58 
     | 
    
         
             
                      question = questionnaire.questions.create!(serialized_question.except(:id, :created_at, :updated_at))
         
     | 
| 
       59 
     | 
    
         
            -
                       
     | 
| 
       60 
     | 
    
         
            -
                        question. 
     | 
| 
      
 59 
     | 
    
         
            +
                      serialized_response_options.each do |serialized_response_option|
         
     | 
| 
      
 60 
     | 
    
         
            +
                        question.response_options.create!(serialized_response_option.except(:id, :created_at, :updated_at))
         
     | 
| 
       61 
61 
     | 
    
         
             
                      end
         
     | 
| 
       62 
62 
     | 
    
         
             
                    end
         
     | 
| 
       63 
63 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -3,8 +3,8 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module Decidim
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Surveys
         
     | 
| 
       5 
5 
     | 
    
         
             
                # This class serializes the specific data in each Survey.
         
     | 
| 
       6 
     | 
    
         
            -
                # This is `Questionnaire->questions-> 
     | 
| 
       7 
     | 
    
         
            -
                # and ` 
     | 
| 
      
 6 
     | 
    
         
            +
                # This is `Questionnaire->questions->response_options` but not `responses`
         
     | 
| 
      
 7 
     | 
    
         
            +
                # and `response_choices`.
         
     | 
| 
       8 
8 
     | 
    
         
             
                class DataSerializer < Decidim::Exporters::Serializer
         
     | 
| 
       9 
9 
     | 
    
         
             
                  # Returns: Array of Decidim::Forms::Questionnaire as a json hash,
         
     | 
| 
       10 
10 
     | 
    
         
             
                  #     or nil if none exists.
         
     | 
| 
         @@ -31,13 +31,13 @@ module Decidim 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  def serialize_questions(questions)
         
     | 
| 
       32 
32 
     | 
    
         
             
                    questions.collect do |question|
         
     | 
| 
       33 
33 
     | 
    
         
             
                      json = question.attributes.as_json
         
     | 
| 
       34 
     | 
    
         
            -
                      json[: 
     | 
| 
      
 34 
     | 
    
         
            +
                      json[:response_options] = serialize_response_options(question.response_options)
         
     | 
| 
       35 
35 
     | 
    
         
             
                      json
         
     | 
| 
       36 
36 
     | 
    
         
             
                    end
         
     | 
| 
       37 
37 
     | 
    
         
             
                  end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                  def  
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
      
 39 
     | 
    
         
            +
                  def serialize_response_options(response_options)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    response_options.collect do |option|
         
     | 
| 
       41 
41 
     | 
    
         
             
                      option.attributes.as_json
         
     | 
| 
       42 
42 
     | 
    
         
             
                    end
         
     | 
| 
       43 
43 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <div class="toggle__switch-trigger float-right">
         
     | 
| 
      
 2 
     | 
    
         
            +
              <% label = "publish_response_#{question.id}" %>
         
     | 
| 
      
 3 
     | 
    
         
            +
              <label for="<%= label %>" class="toggle__switch-toggle">
         
     | 
| 
      
 4 
     | 
    
         
            +
                <span class="toggle__switch-trigger-text">
         
     | 
| 
      
 5 
     | 
    
         
            +
                  <%= content_tag(:span, class: "label success ml-[-8.5rem] mt-1 #{"hidden" if question.survey_responses_published_at.blank?}") { t("status.published", scope: "decidim.surveys.admin.publish_responses.index") } %>
         
     | 
| 
      
 6 
     | 
    
         
            +
                  <%= content_tag(:span, class: "label alert -ml-40 mt-1 #{"hidden" if question.survey_responses_published_at.present?}") { t("status.not_published", scope: "decidim.surveys.admin.publish_responses.index") } %>
         
     | 
| 
      
 7 
     | 
    
         
            +
                </span>
         
     | 
| 
      
 8 
     | 
    
         
            +
                <span>
         
     | 
| 
      
 9 
     | 
    
         
            +
                  <input
         
     | 
| 
      
 10 
     | 
    
         
            +
                  <%== %(checked="checked") if question.survey_responses_published_at.present? %>
         
     | 
| 
      
 11 
     | 
    
         
            +
                  id="<%= label %>"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  type="checkbox"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  name="<%= label %>"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  data-publish-question-response-action="<%= question.survey_responses_published_at.present? ? "unpublish" : "publish" %>"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  data-publish-question-response-question-url="<%= survey_publish_response_path(params[:survey_id], question) %>">
         
     | 
| 
      
 16 
     | 
    
         
            +
                  <span class="toggle__switch-toggle-content">
         
     | 
| 
      
 17 
     | 
    
         
            +
                  </span>
         
     | 
| 
      
 18 
     | 
    
         
            +
                  <%= icon "check-line", class: "toggle__switch-toggle-icon" %>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  <%= icon "close-line", class: "toggle__switch-toggle-icon" %>
         
     | 
| 
      
 20 
     | 
    
         
            +
                </span>
         
     | 
| 
      
 21 
     | 
    
         
            +
              </label>
         
     | 
| 
      
 22 
     | 
    
         
            +
            </div>
         
     | 
| 
         @@ -4,7 +4,7 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
              <div class="w-full">
         
     | 
| 
       5 
5 
     | 
    
         
             
                <h1 class="item_show__header-title">
         
     | 
| 
       6 
6 
     | 
    
         
             
                  <%= t(".title") %>
         
     | 
| 
       7 
     | 
    
         
            -
                  <%= link_to t("actions.back", scope: "decidim.forms.admin.questionnaires"),  
     | 
| 
      
 7 
     | 
    
         
            +
                  <%= link_to t("actions.back", scope: "decidim.forms.admin.questionnaires"), survey_responses_path, class: "button button__sm button__secondary new" %>
         
     | 
| 
       8 
8 
     | 
    
         
             
                </h1>
         
     | 
| 
       9 
9 
     | 
    
         
             
              </div>
         
     | 
| 
       10 
10 
     | 
    
         
             
            </div>
         
     | 
| 
         @@ -22,16 +22,16 @@ 
     | 
|
| 
       22 
22 
     | 
    
         
             
                    <% next if question.question_type == "separator" %>
         
     | 
| 
       23 
23 
     | 
    
         
             
                    <% next if question.question_type == "title_and_description" %>
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                    <li class="<%= "text-gray" unless  
     | 
| 
      
 25 
     | 
    
         
            +
                    <li class="<%= "text-gray" unless question_response_is_publicable(question.question_type) %> mb-6">
         
     | 
| 
       26 
26 
     | 
    
         
             
                      <div class="inline">
         
     | 
| 
       27 
     | 
    
         
            -
                        <span><%= translated_attribute question.body %> (<%= I18n.t("decidim.surveys.admin. 
     | 
| 
      
 27 
     | 
    
         
            +
                        <span><%= translated_attribute question.body %> (<%= I18n.t("decidim.surveys.admin.publish_responses.index.responses", count: question.responses.count) %>)</span>
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
                        <% if  
     | 
| 
      
 29 
     | 
    
         
            +
                        <% if question_response_is_publicable(question.question_type) %>
         
     | 
| 
       30 
30 
     | 
    
         
             
                          <%= render partial: "toggle_button", locals: { question: } %>
         
     | 
| 
       31 
31 
     | 
    
         
             
                        <% end %>
         
     | 
| 
       32 
32 
     | 
    
         
             
                      </div>
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                      <% if  
     | 
| 
      
 34 
     | 
    
         
            +
                      <% if question_response_is_publicable(question.question_type) %>
         
     | 
| 
       35 
35 
     | 
    
         
             
                        <div class="m-4">
         
     | 
| 
       36 
36 
     | 
    
         
             
                          <%= chart_for_question(question.id) %>
         
     | 
| 
       37 
37 
     | 
    
         
             
                        </div>
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <% add_decidim_page_title(t(".title")) %>
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            <% if templates_defined? && choose_template? %>
         
     | 
| 
      
 4 
     | 
    
         
            +
              <%= render "decidim/surveys/admin/surveys/tabs_menu" do %>
         
     | 
| 
      
 5 
     | 
    
         
            +
                <%= button_tag t("continue", scope: "decidim.templates.admin.questionnaire_templates.choose"), class: "main-tabs-menu__cta-button disabled", disabled: true, data: { disabled_button: true } %>
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                <%= link_to t("continue", scope: "decidim.templates.admin.questionnaire_templates.choose"), decidim_admin_templates.skip_questionnaire_templates_path(questionnaire_id: questionnaire, url: request.url), class: "main-tabs-menu__cta-button !hidden", data: { create_new_form_button: true }, method: :post %>
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                <%= button_tag t("continue", scope: "decidim.templates.admin.questionnaire_templates.choose"), class: "main-tabs-menu__cta-button !hidden", data: { with_template_button: true }, form: "choose-template-form" %>
         
     | 
| 
      
 10 
     | 
    
         
            +
              <% end %>
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              <%= render partial: "decidim/templates/admin/questionnaire_templates/choose", locals: { target: questionnaire, form_title: t(".title"), show_buttons: false } %>
         
     | 
| 
      
 13 
     | 
    
         
            +
            <% else %>
         
     | 
| 
      
 14 
     | 
    
         
            +
              <div class="questionnaire-questions">
         
     | 
| 
      
 15 
     | 
    
         
            +
                <div class="item_show__header" style="border-bottom: none;">
         
     | 
| 
      
 16 
     | 
    
         
            +
                  <h1 class="item_show__header-title">
         
     | 
| 
      
 17 
     | 
    
         
            +
                    <%= t(".title") %>
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                      <% if questionnaire.questions_editable? %>
         
     | 
| 
      
 20 
     | 
    
         
            +
                        <button class="button button__sm button__transparent-secondary add-question"><%= t("add_question", scope: "decidim.forms.admin.questionnaires.edit_questions") %></button>
         
     | 
| 
      
 21 
     | 
    
         
            +
                        <button class="button button__sm button__transparent-secondary add-separator"><%= t("add_separator", scope: "decidim.forms.admin.questionnaires.edit_questions") %></button>
         
     | 
| 
      
 22 
     | 
    
         
            +
                        <button class="button button__sm button__transparent-secondary add-title-and-description"><%= t("add_title_and_description", scope: "decidim.forms.admin.questionnaires.edit_questions") %></button>
         
     | 
| 
      
 23 
     | 
    
         
            +
                      <% end %>
         
     | 
| 
      
 24 
     | 
    
         
            +
                  </h1>
         
     | 
| 
      
 25 
     | 
    
         
            +
                </div>
         
     | 
| 
      
 26 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              <%= render "decidim/surveys/admin/surveys/tabs_menu" %>
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              <div class="grid-cols-1 2xl:mr-80">
         
     | 
| 
      
 31 
     | 
    
         
            +
                <div class="item__edit-form pb-24">
         
     | 
| 
      
 32 
     | 
    
         
            +
                  <%= decidim_form_for(@form, url: update_questions_questions_survey_path(@survey), method: :patch, html: { id: "survey-form", class: "form-defaults form edit_questions_survey" }) do |form| %>
         
     | 
| 
      
 33 
     | 
    
         
            +
                    <%= render partial: "decidim/forms/admin/questionnaires/questions_form", object: form %>
         
     | 
| 
      
 34 
     | 
    
         
            +
                  <% end %>
         
     | 
| 
      
 35 
     | 
    
         
            +
                </div>
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                <div class="item__edit-sticky">
         
     | 
| 
      
 38 
     | 
    
         
            +
                  <div class="item__edit-sticky-container">
         
     | 
| 
      
 39 
     | 
    
         
            +
                    <%= button_tag t("save", scope: "decidim.forms.admin.questionnaires.edit"), class: "button button__sm button__secondary", form: "survey-form" %>
         
     | 
| 
      
 40 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 41 
     | 
    
         
            +
                </div>
         
     | 
| 
      
 42 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            <% end %>
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <% add_decidim_page_title(t(".title", total: @total)) %>
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            <div class="item_show__header" style="border-bottom: none;">
         
     | 
| 
      
 4 
     | 
    
         
            +
              <h1 class="item_show__header-title">
         
     | 
| 
      
 5 
     | 
    
         
            +
                <%= t ".title", total: @total %>
         
     | 
| 
      
 6 
     | 
    
         
            +
                <% if @survey.questionnaire.responses.any? %>
         
     | 
| 
      
 7 
     | 
    
         
            +
                  <%= export_dropdown(current_component, @survey.questionnaire.id) if allowed_to? :export_responses, :questionnaire %>
         
     | 
| 
      
 8 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 9 
     | 
    
         
            +
              </h1>
         
     | 
| 
      
 10 
     | 
    
         
            +
            </div>
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            <%= render "decidim/surveys/admin/surveys/tabs_menu" %>
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            <% if @participants.count.zero? %>
         
     | 
| 
      
 15 
     | 
    
         
            +
              <%= cell("decidim/announcement", { body: t("decidim.surveys.admin.responses.index.no_responses") }) %>
         
     | 
| 
      
 16 
     | 
    
         
            +
            <% end %>
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            <div class="card 2xl:mr-80 mt-8" id="responses">
         
     | 
| 
      
 19 
     | 
    
         
            +
              <div class="table-stacked">
         
     | 
| 
      
 20 
     | 
    
         
            +
                <table class="table-list">
         
     | 
| 
      
 21 
     | 
    
         
            +
                  <thead>
         
     | 
| 
      
 22 
     | 
    
         
            +
                    <tr>
         
     | 
| 
      
 23 
     | 
    
         
            +
                      <th>#</th>
         
     | 
| 
      
 24 
     | 
    
         
            +
                      <th class="!text-left"><%= first_table_th(@participants.first) %></th>
         
     | 
| 
      
 25 
     | 
    
         
            +
                      <th><%= t("user_status", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 26 
     | 
    
         
            +
                      <th><%= t("ip_hash", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 27 
     | 
    
         
            +
                      <th><%= t("completion", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 28 
     | 
    
         
            +
                      <th><%= t("created_at", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 29 
     | 
    
         
            +
                      <th></th>
         
     | 
| 
      
 30 
     | 
    
         
            +
                    </tr>
         
     | 
| 
      
 31 
     | 
    
         
            +
                  </thead>
         
     | 
| 
      
 32 
     | 
    
         
            +
                  <tbody>
         
     | 
| 
      
 33 
     | 
    
         
            +
                    <% @participants.each_with_index do |participant, idx| %>
         
     | 
| 
      
 34 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 35 
     | 
    
         
            +
                        <td data-label="#"> <%= idx + 1 + page_offset %> </td>
         
     | 
| 
      
 36 
     | 
    
         
            +
                        <td class="!text-left" data-label="<%= first_table_th(@participants.first) %>">
         
     | 
| 
      
 37 
     | 
    
         
            +
                          <% if allowed_to? :show, :questionnaire_responses %>
         
     | 
| 
      
 38 
     | 
    
         
            +
                            <%= link_to first_table_td(participant), questionnaire_participant_responses_url(participant.session_token) %>
         
     | 
| 
      
 39 
     | 
    
         
            +
                          <% else %>
         
     | 
| 
      
 40 
     | 
    
         
            +
                            <%= first_table_td(participant) %>
         
     | 
| 
      
 41 
     | 
    
         
            +
                          <% end %>
         
     | 
| 
      
 42 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 43 
     | 
    
         
            +
                        <td data-label="<%= t("user_status", scope: "decidim.forms.user_responses_serializer") %>">
         
     | 
| 
      
 44 
     | 
    
         
            +
                          <%= participant.status %>
         
     | 
| 
      
 45 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 46 
     | 
    
         
            +
                        <td data-label="<%= t("ip_hash", scope: "decidim.forms.user_responses_serializer") %>">
         
     | 
| 
      
 47 
     | 
    
         
            +
                          <%= participant.ip_hash %>
         
     | 
| 
      
 48 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 49 
     | 
    
         
            +
                        <td data-label="<%= t("completion", scope: "decidim.forms.user_responses_serializer") %>">
         
     | 
| 
      
 50 
     | 
    
         
            +
                          <%= display_percentage(participant.completion) %>
         
     | 
| 
      
 51 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 52 
     | 
    
         
            +
                        <td data-label="<%= t("created_at", scope: "decidim.forms.user_responses_serializer") %>">
         
     | 
| 
      
 53 
     | 
    
         
            +
                          <%= l participant.responded_at, format: :short %>
         
     | 
| 
      
 54 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 55 
     | 
    
         
            +
                        <td data-label="<%= t("actions.title", scope: "decidim.surveys") %>" class="table-list__actions">
         
     | 
| 
      
 56 
     | 
    
         
            +
                          <button type="button" data-controller="dropdown" data-target="actions-participant-<%= idx %>" aria-label="<%= t("decidim.admin.actions.actions_label") %>">
         
     | 
| 
      
 57 
     | 
    
         
            +
                            <%= icon "more-fill", class: "text-secondary" %>
         
     | 
| 
      
 58 
     | 
    
         
            +
                          </button>
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                          <div class="inline-block relative">
         
     | 
| 
      
 61 
     | 
    
         
            +
                            <ul id="actions-participant-<%= idx %>" class="dropdown dropdown__action" aria-hidden="true">
         
     | 
| 
      
 62 
     | 
    
         
            +
                              <% if allowed_to? :show, :questionnaire_responses %>
         
     | 
| 
      
 63 
     | 
    
         
            +
                                <li class="dropdown__item">
         
     | 
| 
      
 64 
     | 
    
         
            +
                                  <%= link_to questionnaire_participant_responses_url(participant.session_token), target: "_blank", data: { "external-link": false }, class: "dropdown__button" do %>
         
     | 
| 
      
 65 
     | 
    
         
            +
                                    <%= icon "eye-line" %>
         
     | 
| 
      
 66 
     | 
    
         
            +
                                    <%= t("actions.show", scope: "decidim.forms.admin.questionnaires.responses") %>
         
     | 
| 
      
 67 
     | 
    
         
            +
                                  <% end %>
         
     | 
| 
      
 68 
     | 
    
         
            +
                                </li>
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                                <hr>
         
     | 
| 
      
 71 
     | 
    
         
            +
                              <% end %>
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                              <% if allowed_to? :export_response, :questionnaire_responses %>
         
     | 
| 
      
 74 
     | 
    
         
            +
                                <li class="dropdown__item">
         
     | 
| 
      
 75 
     | 
    
         
            +
                                  <%= link_to questionnaire_export_response_url(participant.session_token), class: "dropdown__button" do %>
         
     | 
| 
      
 76 
     | 
    
         
            +
                                    <%= icon "download-line" %>
         
     | 
| 
      
 77 
     | 
    
         
            +
                                    <%= t("actions.export", scope: "decidim.forms.admin.questionnaires.responses") %>
         
     | 
| 
      
 78 
     | 
    
         
            +
                                  <% end %>
         
     | 
| 
      
 79 
     | 
    
         
            +
                                </li>
         
     | 
| 
      
 80 
     | 
    
         
            +
                              <% end %>
         
     | 
| 
      
 81 
     | 
    
         
            +
                            </ul>
         
     | 
| 
      
 82 
     | 
    
         
            +
                          </div>
         
     | 
| 
      
 83 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 84 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 85 
     | 
    
         
            +
                    <% end %>
         
     | 
| 
      
 86 
     | 
    
         
            +
                  </tbody>
         
     | 
| 
      
 87 
     | 
    
         
            +
                </table>
         
     | 
| 
      
 88 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 89 
     | 
    
         
            +
            </div>
         
     | 
| 
      
 90 
     | 
    
         
            +
            <%= decidim_paginate @query %>
         
     | 
| 
      
 91 
     | 
    
         
            +
            <div class="item__edit-sticky">
         
     | 
| 
      
 92 
     | 
    
         
            +
              <div class="item__edit-sticky-container">
         
     | 
| 
      
 93 
     | 
    
         
            +
                <% if allowed_to? :index, :questionnaire_publish_responses, survey: @survey %>
         
     | 
| 
      
 94 
     | 
    
         
            +
                  <% if @participants.count.zero? %>
         
     | 
| 
      
 95 
     | 
    
         
            +
                      <%= link_to t("actions.publish_responses", scope: "decidim.forms.admin.questionnaires"), "#", class: "button button__sm button__secondary", disabled: true %>
         
     | 
| 
      
 96 
     | 
    
         
            +
                    <% else %>
         
     | 
| 
      
 97 
     | 
    
         
            +
                      <%= link_to t("actions.publish_responses", scope: "decidim.forms.admin.questionnaires"), survey_publish_responses_path(@survey), class: "button button__sm button__secondary" %>
         
     | 
| 
      
 98 
     | 
    
         
            +
                  <% end %>
         
     | 
| 
      
 99 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 100 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 101 
     | 
    
         
            +
            </div>
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <div class="card" id="responses">
         
     | 
| 
      
 2 
     | 
    
         
            +
              <div class="item_show__header">
         
     | 
| 
      
 3 
     | 
    
         
            +
                <h1 class="item_show__header-title">
         
     | 
| 
      
 4 
     | 
    
         
            +
                  <%= t ".title", number: current_idx %>
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  <%= link_to t("actions.next", scope: "decidim.forms.admin.questionnaires.responses").html_safe, next_url, rel: "next", class: "button button__sm button__secondary next" unless last? %>
         
     | 
| 
      
 7 
     | 
    
         
            +
                 <%= link_to t("actions.previous", scope: "decidim.forms.admin.questionnaires.responses").html_safe, prev_url, rel: "prev", class: "button button__sm button__secondary prev" unless first? %>
         
     | 
| 
      
 8 
     | 
    
         
            +
                  <%= link_to t("actions.export", scope: "decidim.forms.admin.questionnaires.responses"), questionnaire_export_response_url(@participant.session_token), class: "button button__sm button__secondary export" %>
         
     | 
| 
      
 9 
     | 
    
         
            +
                  <%= link_to t("actions.back", scope: "decidim.forms.admin.questionnaires.responses"), questionnaire_participants_url, class: "button button__sm button__secondary back" %>
         
     | 
| 
      
 10 
     | 
    
         
            +
                </h1>
         
     | 
| 
      
 11 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 12 
     | 
    
         
            +
              <div class="card-section">
         
     | 
| 
      
 13 
     | 
    
         
            +
                 <div class="table">
         
     | 
| 
      
 14 
     | 
    
         
            +
                  <table class="table-list">
         
     | 
| 
      
 15 
     | 
    
         
            +
                    <thead>
         
     | 
| 
      
 16 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 17 
     | 
    
         
            +
                        <th><%= t("session_token", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 18 
     | 
    
         
            +
                        <th><%= t("user_status", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 19 
     | 
    
         
            +
                        <th><%= t("ip_hash", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 20 
     | 
    
         
            +
                        <th><%= t("completion", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 21 
     | 
    
         
            +
                        <th><%= t("created_at", scope: "decidim.forms.user_responses_serializer") %></th>
         
     | 
| 
      
 22 
     | 
    
         
            +
                        <th></th>
         
     | 
| 
      
 23 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 24 
     | 
    
         
            +
                    </thead>
         
     | 
| 
      
 25 
     | 
    
         
            +
                    <tbody>
         
     | 
| 
      
 26 
     | 
    
         
            +
                      <tr>
         
     | 
| 
      
 27 
     | 
    
         
            +
                        <td><%= @participant.session_token %></td>
         
     | 
| 
      
 28 
     | 
    
         
            +
                        <td><%= @participant.status %></td>
         
     | 
| 
      
 29 
     | 
    
         
            +
                        <td><%= @participant.ip_hash %></td>
         
     | 
| 
      
 30 
     | 
    
         
            +
                        <td><%= display_percentage(@participant.completion) %></td>
         
     | 
| 
      
 31 
     | 
    
         
            +
                        <td><%= l @participant.responded_at, format: :short %></td>
         
     | 
| 
      
 32 
     | 
    
         
            +
                      </tr>
         
     | 
| 
      
 33 
     | 
    
         
            +
                    </tbody>
         
     | 
| 
      
 34 
     | 
    
         
            +
                  </table>
         
     | 
| 
      
 35 
     | 
    
         
            +
                </div>
         
     | 
| 
      
 36 
     | 
    
         
            +
                <dl class="p-4 [&_ul]:list-disc [&_ul]:pl-4">
         
     | 
| 
      
 37 
     | 
    
         
            +
                  <% @participant.responses.each do |response| %>
         
     | 
| 
      
 38 
     | 
    
         
            +
                    <dt class="font-semibold"><%= response.question %></dt>
         
     | 
| 
      
 39 
     | 
    
         
            +
                    <dd><%= response.body %></dd>
         
     | 
| 
      
 40 
     | 
    
         
            +
                  <% end %>
         
     | 
| 
      
 41 
     | 
    
         
            +
                </dl>
         
     | 
| 
      
 42 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 43 
     | 
    
         
            +
            </div>
         
     |