decidim-surveys 0.29.2 → 0.30.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/surveys/survey_card_metadata_cell.rb +43 -0
  3. data/app/cells/decidim/surveys/survey_cell.rb +26 -0
  4. data/app/cells/decidim/surveys/survey_l_cell.rb +34 -0
  5. data/app/cells/decidim/surveys/survey_s_cell.rb +21 -0
  6. data/app/commands/decidim/surveys/admin/create_survey.rb +21 -0
  7. data/app/commands/decidim/surveys/admin/publish_survey.rb +58 -0
  8. data/app/commands/decidim/surveys/admin/unpublish_survey.rb +44 -0
  9. data/app/commands/decidim/surveys/admin/update_survey.rb +62 -0
  10. data/app/commands/decidim/surveys/publish_answers.rb +55 -0
  11. data/app/commands/decidim/surveys/unpublish_answers.rb +55 -0
  12. data/app/controllers/concerns/decidim/surveys/admin/filterable.rb +23 -0
  13. data/app/controllers/decidim/surveys/admin/answers_controller.rb +73 -0
  14. data/app/controllers/decidim/surveys/admin/publish_answers_controller.rb +66 -0
  15. data/app/controllers/decidim/surveys/admin/surveys_controller.rb +99 -11
  16. data/app/controllers/decidim/surveys/surveys_controller.rb +50 -5
  17. data/app/forms/decidim/surveys/admin/survey_form.rb +18 -0
  18. data/app/helpers/decidim/surveys/application_helper.rb +34 -0
  19. data/app/helpers/decidim/surveys/publish_answers_helper.rb +104 -0
  20. data/app/helpers/decidim/surveys/survey_helper.rb +4 -0
  21. data/app/models/decidim/surveys/survey.rb +67 -12
  22. data/app/permissions/decidim/surveys/admin/permissions.rb +10 -1
  23. data/app/permissions/decidim/surveys/permissions.rb +0 -2
  24. data/app/presenters/decidim/surveys/admin_log/survey_presenter.rb +34 -0
  25. data/app/queries/decidim/surveys/metrics/answers_metric_manage.rb +3 -3
  26. data/app/queries/decidim/surveys/metrics/survey_participants_metric_measure.rb +2 -2
  27. data/app/views/decidim/surveys/admin/answers/index.html.erb +49 -0
  28. data/app/views/decidim/surveys/admin/answers/show.html.erb +43 -0
  29. data/app/views/decidim/surveys/admin/publish_answers/_toggle_button.html.erb +22 -0
  30. data/app/views/decidim/surveys/admin/publish_answers/index.html.erb +44 -0
  31. data/app/views/decidim/surveys/admin/surveys/_form.html.erb +28 -0
  32. data/app/views/decidim/surveys/admin/surveys/edit.html.erb +4 -21
  33. data/app/views/decidim/surveys/admin/surveys/edit_questions.html.erb +47 -0
  34. data/app/views/decidim/surveys/admin/surveys/index.html.erb +51 -0
  35. data/app/views/decidim/surveys/surveys/_published_questions_answers.html.erb +13 -0
  36. data/app/views/decidim/surveys/surveys/_surveys.html.erb +13 -0
  37. data/app/views/decidim/surveys/surveys/index.html.erb +27 -0
  38. data/app/views/decidim/surveys/surveys/index.js.erb +4 -0
  39. data/app/views/decidim/surveys/surveys/not_allowed.html.erb +22 -0
  40. data/config/locales/ar.yml +4 -3
  41. data/config/locales/bg.yml +0 -14
  42. data/config/locales/ca.yml +83 -14
  43. data/config/locales/cs.yml +87 -14
  44. data/config/locales/de.yml +83 -14
  45. data/config/locales/el.yml +0 -11
  46. data/config/locales/en.yml +83 -14
  47. data/config/locales/es-MX.yml +83 -14
  48. data/config/locales/es-PY.yml +83 -14
  49. data/config/locales/es.yml +83 -14
  50. data/config/locales/eu.yml +83 -14
  51. data/config/locales/fi-plain.yml +83 -14
  52. data/config/locales/fi.yml +83 -14
  53. data/config/locales/fr-CA.yml +74 -14
  54. data/config/locales/fr.yml +74 -14
  55. data/config/locales/ga-IE.yml +0 -4
  56. data/config/locales/gl.yml +0 -10
  57. data/config/locales/hu.yml +0 -3
  58. data/config/locales/id-ID.yml +0 -2
  59. data/config/locales/is-IS.yml +0 -2
  60. data/config/locales/it.yml +3 -10
  61. data/config/locales/ja.yml +80 -13
  62. data/config/locales/lb.yml +0 -10
  63. data/config/locales/lt.yml +0 -11
  64. data/config/locales/lv.yml +0 -3
  65. data/config/locales/nl.yml +0 -10
  66. data/config/locales/no.yml +0 -10
  67. data/config/locales/pl.yml +0 -14
  68. data/config/locales/pt-BR.yml +0 -14
  69. data/config/locales/pt.yml +0 -10
  70. data/config/locales/ro-RO.yml +0 -11
  71. data/config/locales/ru.yml +0 -2
  72. data/config/locales/sk.yml +0 -3
  73. data/config/locales/sv.yml +0 -14
  74. data/config/locales/tr-TR.yml +0 -10
  75. data/config/locales/uk.yml +0 -2
  76. data/config/locales/zh-CN.yml +0 -6
  77. data/config/locales/zh-TW.yml +0 -11
  78. data/db/migrate/20240828103030_add_deleted_at_to_decidim_surveys_surveys.rb +8 -0
  79. data/db/migrate/20240925124312_add_settings_to_decidim_surveys_surveys.rb +42 -0
  80. data/db/migrate/20250115193836_add_allow_survey_editing.rb +7 -0
  81. data/decidim-surveys.gemspec +1 -1
  82. data/lib/decidim/api/survey_type.rb +2 -2
  83. data/lib/decidim/api/surveys_type.rb +4 -5
  84. data/lib/decidim/surveys/admin_engine.rb +15 -5
  85. data/lib/decidim/surveys/component.rb +7 -24
  86. data/lib/decidim/surveys/engine.rb +2 -2
  87. data/lib/decidim/surveys/seeds.rb +115 -10
  88. data/lib/decidim/surveys/test/factories.rb +24 -0
  89. data/lib/decidim/surveys/version.rb +1 -1
  90. metadata +48 -18
  91. data/app/commands/decidim/surveys/create_survey.rb +0 -19
  92. data/app/views/decidim/surveys/admin/component/_actions.html.erb +0 -44
@@ -3,43 +3,131 @@
3
3
  module Decidim
4
4
  module Surveys
5
5
  module Admin
6
- # This controller allows the user to update a Page.
6
+ # This controller allows the user create and edit questionnaires for Surveys.
7
7
  class SurveysController < Admin::ApplicationController
8
8
  include Decidim::Forms::Admin::Concerns::HasQuestionnaire
9
- include Decidim::Forms::Admin::Concerns::HasQuestionnaireAnswers
9
+ include Decidim::Forms::Admin::Concerns::HasQuestionnaireAnswersUrlHelper
10
+ include Decidim::Surveys::Admin::Filterable
11
+
12
+ helper_method :surveys
13
+
14
+ def index; end
15
+
16
+ def create
17
+ enforce_permission_to(:create, :questionnaire)
18
+ Decidim::Surveys::Admin::CreateSurvey.call(current_component) do
19
+ on(:ok) do |survey|
20
+ flash[:notice] = I18n.t("create.success", scope: "decidim.surveys.admin.surveys")
21
+ redirect_to edit_survey_path(survey)
22
+ end
23
+
24
+ on(:invalid) do
25
+ flash.now[:alert] = I18n.t("create.invalid", scope: "decidim.surveys.admin.surveys")
26
+ render action: "index"
27
+ end
28
+ end
29
+ end
10
30
 
11
31
  def edit
12
32
  enforce_permission_to(:update, :questionnaire, questionnaire:)
33
+ @form = form(Admin::SurveyForm).from_model(survey)
34
+ end
35
+
36
+ def update
37
+ enforce_permission_to(:update, :questionnaire, questionnaire:)
38
+ @form = form(Admin::SurveyForm).from_params(params)
39
+
40
+ Admin::UpdateSurvey.call(@form, survey, current_user) do
41
+ on(:ok) do
42
+ flash[:notice] = I18n.t("update.success", scope: "decidim.surveys.admin.surveys")
43
+ redirect_to(surveys_path) && return
44
+ end
45
+
46
+ on(:invalid) do
47
+ flash.now[:alert] = I18n.t("update.invalid", scope: "decidim.surveys.admin.surveys")
48
+ render action: "edit"
49
+ end
50
+ end
51
+ end
52
+
53
+ def publish
54
+ enforce_permission_to(:update, :questionnaire, questionnaire:)
55
+ Decidim::Surveys::Admin::PublishSurvey.call(survey, current_user) do
56
+ on(:ok) do
57
+ flash[:notice] = I18n.t("publish.success", scope: "decidim.surveys.admin.surveys")
58
+ redirect_to surveys_path
59
+ end
60
+
61
+ on(:invalid) do
62
+ flash.now[:alert] = I18n.t("publish.invalid", scope: "decidim.surveys.admin.surveys")
63
+ render action: "index"
64
+ end
65
+ end
66
+ end
67
+
68
+ def unpublish
69
+ enforce_permission_to(:update, :questionnaire, questionnaire:)
70
+ Decidim::Surveys::Admin::UnpublishSurvey.call(survey, current_user) do
71
+ on(:ok) do
72
+ flash[:notice] = I18n.t("unpublish.success", scope: "decidim.surveys.admin.surveys")
73
+ redirect_to surveys_path
74
+ end
75
+
76
+ on(:invalid) do
77
+ flash.now[:alert] = I18n.t("unpublish.invalid", scope: "decidim.surveys.admin.surveys")
78
+ render action: "index"
79
+ end
80
+ end
81
+ end
13
82
 
14
- @form = form(Decidim::Forms::Admin::QuestionnaireForm).from_model(questionnaire)
83
+ def destroy
84
+ enforce_permission_to(:destroy, :questionnaire, questionnaire:)
85
+ Decidim::Commands::DestroyResource.call(survey, current_user) do
86
+ on(:ok) do
87
+ flash[:notice] = I18n.t("destroy.success", scope: "decidim.surveys.admin.surveys")
88
+
89
+ redirect_to surveys_path
90
+ end
91
+ end
92
+ end
93
+
94
+ def edit_questions_template
95
+ "decidim/surveys/admin/surveys/edit_questions"
15
96
  end
16
97
 
17
98
  def questionnaire_for
18
99
  survey
19
100
  end
20
101
 
102
+ def after_update_url
103
+ surveys_path
104
+ end
105
+
106
+ def questionnaire_participants_url
107
+ Decidim::EngineRouter.admin_proxy(survey.component).survey_answers_path(survey)
108
+ end
109
+
21
110
  # Specify the public url from which the survey can be viewed and answered
22
111
  def public_url
23
112
  Decidim::EngineRouter.main_proxy(current_component).survey_path(survey)
24
113
  end
25
114
 
26
- # Specify where to redirect after exporting a user response
27
- def questionnaire_participant_answers_url(session_token)
28
- Decidim::EngineRouter.admin_proxy(survey.component).show_survey_path(session_token:)
29
- end
30
-
31
115
  def edit_questionnaire_title
32
116
  t(:title, scope: "decidim.forms.admin.questionnaires.form", questionnaire_for: translated_attribute(current_component.name))
33
117
  end
34
118
 
35
119
  private
36
120
 
37
- def i18n_flashes_scope
38
- "decidim.surveys.admin.surveys"
121
+ def surveys
122
+ @surveys ||= filtered_collection
39
123
  end
40
124
 
41
125
  def survey
42
- @survey ||= Survey.find_by(component: current_component)
126
+ @survey ||= collection.find(params[:id])
127
+ end
128
+
129
+ def collection
130
+ @collection ||= Decidim::Surveys::Survey.where(component: current_component)
43
131
  end
44
132
  end
45
133
  end
@@ -7,12 +7,24 @@ module Decidim
7
7
  include Decidim::Forms::Concerns::HasQuestionnaire
8
8
  include Decidim::ComponentPathHelper
9
9
  include Decidim::Surveys::SurveyHelper
10
+ include FilterResource
11
+ include Paginable
10
12
 
11
- helper_method :authorizations
13
+ helper PublishAnswersHelper
14
+ helper_method :authorizations, :surveys, :show_published_questions_answers?
12
15
 
13
- delegate :allow_unregistered?, to: :current_settings
16
+ before_action :check_permissions, except: [:index]
17
+ before_action :check_editable, only: [:edit]
14
18
 
15
- before_action :check_permissions
19
+ def index; end
20
+
21
+ def edit
22
+ @form = form(Decidim::Forms::QuestionnaireForm).from_model(questionnaire)
23
+ @form.add_answers!(questionnaire:, session_token:, ip_hash:)
24
+ @form.allow_editing_answers = questionnaire.questionnaire_for&.allow_editing_answers?
25
+
26
+ render template: "decidim/forms/questionnaires/edit"
27
+ end
16
28
 
17
29
  def check_permissions
18
30
  render :no_permission unless action_authorized_to(:answer, resource: survey).ok?
@@ -24,8 +36,27 @@ module Decidim
24
36
 
25
37
  protected
26
38
 
39
+ def check_editable
40
+ return if allow_editing_answers?
41
+
42
+ flash.now[:error] = t("decidim.forms.step_navigation.show.disallowed")
43
+ render :not_allowed
44
+ end
45
+
46
+ def allow_editing_answers?
47
+ visitor_can_edit_answers? && survey.open?
48
+ end
49
+
50
+ def show_published_questions_answers?
51
+ survey.closed? && survey.questionnaire.questions.pluck(:survey_answers_published_at).any?
52
+ end
53
+
27
54
  def allow_answers?
28
- !current_component.published? || (current_settings.allow_answers? && survey.open?)
55
+ !current_component.published? || survey.open?
56
+ end
57
+
58
+ def allow_unregistered?
59
+ survey.allow_unregistered
29
60
  end
30
61
 
31
62
  def form_path
@@ -38,8 +69,22 @@ module Decidim
38
69
  "decidim.surveys.surveys"
39
70
  end
40
71
 
72
+ def surveys
73
+ paginate(search.result).published
74
+ end
75
+
41
76
  def survey
42
- @survey ||= Survey.find_by(component: current_component)
77
+ @survey ||= search_collection.find_by(id: params[:id])
78
+ end
79
+
80
+ def search_collection
81
+ @search_collection ||= Decidim::Surveys::Survey.where(component: current_component)
82
+ end
83
+
84
+ def default_filter_params
85
+ {
86
+ with_any_state: %w(open)
87
+ }
43
88
  end
44
89
  end
45
90
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Surveys
5
+ module Admin
6
+ class SurveyForm < Decidim::Forms::Admin::QuestionnaireForm
7
+ translatable_attribute :announcement, String
8
+
9
+ attribute :allow_answers, Boolean
10
+ attribute :allow_unregistered, Boolean
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
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Surveys
5
+ # Custom helpers, scoped to the surveys engine.
6
+ #
7
+ module ApplicationHelper
8
+ include PaginateHelper
9
+ include Decidim::SanitizeHelper
10
+ include Decidim::CheckBoxesTreeHelper
11
+ include Decidim::RichTextEditorHelper
12
+
13
+ # Returns a TreeNode to be used in the list filters to filter surveys by
14
+ # its state.
15
+ def filter_surveys_date_values
16
+ [
17
+ ["all", t("all", scope: "decidim.surveys.surveys.filters")],
18
+ ["open", { checked: true }, t("open", scope: "decidim.surveys.surveys.filters.state_values")],
19
+ ["closed", t("closed", scope: "decidim.surveys.surveys.filters.state_values")]
20
+ ]
21
+ end
22
+
23
+ def filter_sections
24
+ @filter_sections ||= [{
25
+ method: :with_any_state,
26
+ collection: filter_surveys_date_values,
27
+ label: t("decidim.proposals.proposals.filters.state"),
28
+ id: "state",
29
+ type: :radio_buttons
30
+ }]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Surveys
5
+ module PublishAnswersHelper
6
+ def question_answer_is_publicable(question_type)
7
+ ignored_question_types = %w(short_answer long_answer separator files).freeze
8
+
9
+ ignored_question_types.exclude?(question_type)
10
+ end
11
+
12
+ # Renders the chart for the given question.
13
+ # Uses chartkick to render the chart.
14
+ #
15
+ # @param question_id [Integer] the question id for Decidim:
16
+ def chart_for_question(question_id)
17
+ question = Decidim::Forms::Question.includes(answers: { choices: [:answer_option, :matrix_row] }).find(question_id)
18
+
19
+ Chartkick.options = {
20
+ library: { animation: { easing: "easeOutQuart" } },
21
+ colors: colors_list
22
+ }
23
+
24
+ case question.question_type
25
+ when "single_option", "multiple_option"
26
+ options_column_chart_wrapper(question)
27
+ when "matrix_single", "matrix_multiple"
28
+ matrix_stack_chart_wrapper(question)
29
+ when "sorting"
30
+ sorting_stack_chart_wrapper(question)
31
+ else
32
+ "Unknown question type"
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def sorting_stack_chart_wrapper(question)
39
+ counts = Hash.new { |hash, key| hash[key] = Hash.new(0) }
40
+
41
+ question.answers.each do |answer|
42
+ answer.choices.each do |choice|
43
+ name = translated_attribute(choice.answer_option.body)
44
+ row = choice.position + 1
45
+
46
+ counts[row][name] += 1
47
+ end
48
+ end
49
+
50
+ tally = counts.map do |name, row_data|
51
+ {
52
+ name:,
53
+ data: row_data.map { |row, count| [row, count] }
54
+ }
55
+ end
56
+
57
+ bar_chart(tally.sort_by { |data| data[:name] }, stacked: true, download: true)
58
+ end
59
+
60
+ def matrix_stack_chart_wrapper(question)
61
+ counts = Hash.new { |hash, key| hash[key] = Hash.new(0) }
62
+
63
+ question.answers.each do |answer|
64
+ answer.choices.each do |choice|
65
+ name = translated_attribute(choice.answer_option.body)
66
+ row = translated_attribute(choice.matrix_row.body)
67
+
68
+ counts[name][row] += 1
69
+ end
70
+ end
71
+
72
+ tally = counts.map do |name, row_data|
73
+ {
74
+ name:,
75
+ data: row_data.map { |row, count| [row, count] }
76
+ }
77
+ end
78
+
79
+ column_chart(tally, stacked: true, legend: :right, download: true)
80
+ end
81
+
82
+ def options_column_chart_wrapper(question)
83
+ tally = question.answers.map { |answer| answer.choices.map { |choice| translated_attribute(choice.answer_option.body) } }.tally
84
+
85
+ column_chart(tally, download: true)
86
+ end
87
+
88
+ def colors_list
89
+ %w(
90
+ #3366CC
91
+ #DC3912
92
+ #FF9900
93
+ #109618
94
+ #3B3EAC
95
+ #0099C6
96
+ #DD4477
97
+ #66AA00
98
+ #B82E2E
99
+ #316395
100
+ )
101
+ end
102
+ end
103
+ end
104
+ end
@@ -26,6 +26,10 @@ module Decidim
26
26
  def authorizations
27
27
  @authorizations ||= action_authorized_to(:answer, resource: questionnaire_for)
28
28
  end
29
+
30
+ def filter_date_values
31
+ flat_filter_values(:all, :open, :closed, scope: "decidim.surveys.surveys.filters.date_values")
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -7,33 +7,88 @@ module Decidim
7
7
  include Decidim::Resourceable
8
8
  include Decidim::Forms::HasQuestionnaire
9
9
  include Decidim::HasComponent
10
+ include Decidim::FilterableResource
11
+ include Decidim::Publicable
10
12
 
11
13
  component_manifest_name "surveys"
12
14
 
13
15
  delegate :title, to: :questionnaire
16
+ delegate :description, to: :questionnaire
17
+ delegate :tos, to: :questionnaire
14
18
 
15
19
  validates :questionnaire, presence: true
16
20
 
17
- def clean_after_publish?
18
- component.settings.clean_after_publish?
21
+ scope :open, lambda {
22
+ where(allow_answers: true)
23
+ .where(starts_at: nil, ends_at: nil).or(
24
+ where("starts_at <= ? AND (ends_at IS NULL OR ends_at > ?)", Time.current, Time.current)
25
+ ).or(
26
+ where("ends_at > ? AND (starts_at IS NULL OR starts_at <= ?)", Time.current, Time.current)
27
+ )
28
+ }
29
+ scope :closed, lambda {
30
+ where(allow_answers: false).or(
31
+ where("starts_at > ?", Time.current).or(
32
+ where(ends_at: ...Time.current)
33
+ )
34
+ )
35
+ }
36
+ scope :published, -> { where.not(published_at: nil) }
37
+
38
+ scope_search_multi :with_any_state, [:open, :closed]
39
+
40
+ def open?
41
+ return false if allow_answers.blank?
42
+ return true if time_indefinite?
43
+ return true if started_but_no_end?
44
+ return true if no_start_but_ends_later?
45
+
46
+ return within_time_range? if time_range_defined?
47
+
48
+ false
19
49
  end
20
50
 
21
- def starts_at
22
- component.settings.starts_at
51
+ def closed?
52
+ !open?
23
53
  end
24
54
 
25
- def ends_at
26
- component.settings.ends_at
55
+ def self.ransackable_scopes(_auth_object = nil)
56
+ [:with_any_state]
27
57
  end
28
58
 
29
- def open?
30
- return true if starts_at.blank? && ends_at.blank?
31
- return true if ends_at.blank? && starts_at.past?
32
- return true if starts_at.blank? && ends_at.future?
59
+ def self.ransackable_attributes(_auth_object = nil)
60
+ %w(ends_at starts_at allow_answers)
61
+ end
33
62
 
34
- return Time.zone.now.between?(starts_at, ends_at) if starts_at.present? && ends_at.present?
63
+ def self.log_presenter_class_for(_log)
64
+ Decidim::Surveys::AdminLog::SurveyPresenter
65
+ end
35
66
 
36
- false
67
+ # Public: Overrides the `allow_resource_permissions?` Resourceable concern method.
68
+ def allow_resource_permissions?
69
+ true
70
+ end
71
+
72
+ private
73
+
74
+ def time_indefinite?
75
+ starts_at.blank? && ends_at.blank?
76
+ end
77
+
78
+ def started_but_no_end?
79
+ ends_at.blank? && starts_at.past?
80
+ end
81
+
82
+ def no_start_but_ends_later?
83
+ starts_at.blank? && ends_at.future?
84
+ end
85
+
86
+ def time_range_defined?
87
+ starts_at.present? && ends_at.present?
88
+ end
89
+
90
+ def within_time_range?
91
+ Time.zone.now.between?(starts_at, ends_at)
37
92
  end
38
93
  end
39
94
  end
@@ -12,7 +12,7 @@ module Decidim
12
12
  case permission_action.subject
13
13
  when :questionnaire
14
14
  case permission_action.action
15
- when :export_answers, :update
15
+ when :export_answers, :update, :create, :destroy
16
16
  permission_action.allow!
17
17
  end
18
18
  when :questionnaire_answers
@@ -20,6 +20,15 @@ module Decidim
20
20
  when :index, :show, :export_response
21
21
  permission_action.allow!
22
22
  end
23
+ when :questionnaire_publish_answers
24
+ case permission_action.action
25
+ when :index, :update, :destroy
26
+ if context.fetch(:survey).allow_answers
27
+ permission_action.disallow!
28
+ else
29
+ permission_action.allow!
30
+ end
31
+ end
23
32
  end
24
33
 
25
34
  permission_action
@@ -4,8 +4,6 @@ module Decidim
4
4
  module Surveys
5
5
  class Permissions < Decidim::DefaultPermissions
6
6
  def permissions
7
- return permission_action unless user || context[:current_settings].allow_unregistered?
8
-
9
7
  return Decidim::Surveys::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
10
8
  return permission_action if permission_action.scope != :public
11
9
 
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Surveys
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::Surveys::Survey`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you should not need to call this class
10
+ # directly, but here is an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # SurveyPresenter.new(action_log, view_helpers).present
15
+ class SurveyPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ # i18n-tasks-use t("decidim.surveys.admin_log.survey.create")
19
+ # i18n-tasks-use t("decidim.surveys.admin_log.survey.delete")
20
+ # i18n-tasks-use t("decidim.surveys.admin_log.survey.publish")
21
+ # i18n-tasks-use t("decidim.surveys.admin_log.survey.unpublish")
22
+ # i18n-tasks-use t("decidim.surveys.admin_log.survey.update")
23
+ def action_string
24
+ case action
25
+ when "delete", "create", "update", "publish", "unpublish"
26
+ "decidim.surveys.admin_log.survey.#{action}"
27
+ else
28
+ super
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -16,7 +16,7 @@ module Decidim
16
16
  quantity_value = results[:quantity] || 0
17
17
  space_type, space_id, survey_id = key
18
18
  record = Decidim::Metric.find_or_initialize_by(day: @day.to_s, metric_type: @metric_name,
19
- organization: @organization, decidim_category_id: nil,
19
+ organization: @organization, decidim_taxonomy_id: nil,
20
20
  participatory_space_type: space_type, participatory_space_id: space_id,
21
21
  related_object_type: Decidim::Surveys::Survey.name, related_object_id: survey_id)
22
22
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
@@ -32,13 +32,13 @@ module Decidim
32
32
  @query = retrieve_surveys.each_with_object({}) do |survey, grouped_answers|
33
33
  answers = Decidim::Forms::Answer.joins(:questionnaire)
34
34
  .where(questionnaire: retrieve_questionnaires(survey))
35
- .where("decidim_forms_answers.created_at <= ?", end_time)
35
+ .where(decidim_forms_answers: { created_at: ..end_time })
36
36
  next grouped_answers unless answers
37
37
 
38
38
  group_key = generate_group_key(survey)
39
39
  grouped_answers[group_key] ||= { cumulative: 0, quantity: 0 }
40
40
  grouped_answers[group_key][:cumulative] += answers.count
41
- grouped_answers[group_key][:quantity] += answers.where("decidim_forms_answers.created_at >= ?", start_time).count
41
+ grouped_answers[group_key][:quantity] += answers.where(decidim_forms_answers: { created_at: start_time.. }).count
42
42
  end
43
43
  @query
44
44
  end
@@ -17,11 +17,11 @@ module Decidim
17
17
 
18
18
  answers = Decidim::Forms::Answer.joins(:questionnaire)
19
19
  .where(questionnaire: questionnaires)
20
- .where("decidim_forms_answers.created_at <= ?", end_time)
20
+ .where(decidim_forms_answers: { created_at: ..end_time })
21
21
 
22
22
  {
23
23
  cumulative_users: answers.pluck(:decidim_user_id).uniq,
24
- quantity_users: answers.where("decidim_forms_answers.created_at >= ?", start_time).pluck(:decidim_user_id).uniq
24
+ quantity_users: answers.where(decidim_forms_answers: { created_at: start_time.. }).pluck(:decidim_user_id).uniq
25
25
  }
26
26
  end
27
27
  end
@@ -0,0 +1,49 @@
1
+ <div class="card" id="answers">
2
+ <div class="item_show__header">
3
+ <h1 class="item_show__header-title">
4
+ <%= t ".title", total: @total %>
5
+ <%= link_to t("actions.back", scope: "decidim.forms.admin.questionnaires"), questionnaire_url, class: "button button__sm button__secondary new" %>
6
+ </h1>
7
+ </div>
8
+ <div class="table-scroll">
9
+ <table class="table-list">
10
+ <thead>
11
+ <tr>
12
+ <th>#</th>
13
+ <th><%= first_table_th(@participants.first) %></th>
14
+ <th><%= t("user_status", scope: "decidim.forms.user_answers_serializer") %></th>
15
+ <th><%= t("ip_hash", scope: "decidim.forms.user_answers_serializer") %></th>
16
+ <th><%= t("completion", scope: "decidim.forms.user_answers_serializer") %></th>
17
+ <th><%= t("created_at", scope: "decidim.forms.user_answers_serializer") %></th>
18
+ <th></th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ <% @participants.each_with_index do |participant, idx| %>
23
+ <tr>
24
+ <td><%= idx + 1 + page_offset %></td>
25
+ <td>
26
+ <% if allowed_to? :show, :questionnaire_answers %>
27
+ <%= link_to first_table_td(participant), questionnaire_participant_answers_url(participant.session_token) %>
28
+ <% else %>
29
+ <%= first_table_td(participant) %></td>
30
+ <% end %>
31
+ <td><%= participant.status %></td>
32
+ <td><%= participant.ip_hash %></td>
33
+ <td><%= display_percentage(participant.completion) %></td>
34
+ <td><%= l participant.answered_at, format: :short %></td>
35
+ <td class="table-list__actions">
36
+ <% if allowed_to? :show, :questionnaire_answers %>
37
+ <%= icon_link_to "eye-line", questionnaire_participant_answers_url(participant.session_token), t("actions.show", scope: "decidim.forms.admin.questionnaires.answers"), class: "action-icon--eye", target: "_blank", data: { "external-link": false } %>
38
+ <% end %>
39
+ <% if allowed_to? :export_response, :questionnaire_answers %>
40
+ <%= icon_link_to "download-line", questionnaire_export_response_url(participant.session_token), t("actions.export", scope: "decidim.forms.admin.questionnaires.answers"), class: "action-icon--data-transfer-download" %>
41
+ <% end %>
42
+ </td>
43
+ </tr>
44
+ <% end %>
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+ </div>
49
+ <%= decidim_paginate @query %>