decidim-templates 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +31 -0
  4. data/Rakefile +9 -0
  5. data/app/assets/config/decidim_templates_manifest.css +3 -0
  6. data/app/assets/config/decidim_templates_manifest.js +0 -0
  7. data/app/assets/images/decidim/templates/icon.svg +1 -0
  8. data/app/assets/stylesheets/decidim/templates/templates.scss +14 -0
  9. data/app/commands/decidim/templates/admin/apply_questionnaire_template.rb +74 -0
  10. data/app/commands/decidim/templates/admin/copy_questionnaire_template.rb +79 -0
  11. data/app/commands/decidim/templates/admin/create_questionnaire_template.rb +34 -0
  12. data/app/commands/decidim/templates/admin/destroy_template.rb +41 -0
  13. data/app/commands/decidim/templates/admin/update_template.rb +35 -0
  14. data/app/controllers/decidim/templates/admin/application_controller.rb +34 -0
  15. data/app/controllers/decidim/templates/admin/concerns/templatable.rb +46 -0
  16. data/app/controllers/decidim/templates/admin/questionnaire_templates/questionnaires_controller.rb +38 -0
  17. data/app/controllers/decidim/templates/admin/questionnaire_templates_controller.rb +156 -0
  18. data/app/controllers/decidim/templates/application_controller.rb +13 -0
  19. data/app/forms/decidim/templates/admin/template_form.rb +17 -0
  20. data/app/helpers/decidim/templates/admin/templates_helper.rb +32 -0
  21. data/app/helpers/decidim/templates/application_helper.rb +10 -0
  22. data/app/models/concerns/decidim/templates/templatable.rb +24 -0
  23. data/app/models/decidim/templates/application_record.rb +10 -0
  24. data/app/models/decidim/templates/template.rb +33 -0
  25. data/app/permissions/decidim/templates/admin/permissions.rb +26 -0
  26. data/app/views/decidim/templates/admin/questionnaire_templates/_choose.html.erb +35 -0
  27. data/app/views/decidim/templates/admin/questionnaire_templates/_form.html.erb +16 -0
  28. data/app/views/decidim/templates/admin/questionnaire_templates/_preview.html.erb +73 -0
  29. data/app/views/decidim/templates/admin/questionnaire_templates/edit.html.erb +20 -0
  30. data/app/views/decidim/templates/admin/questionnaire_templates/index.html.erb +52 -0
  31. data/app/views/decidim/templates/admin/questionnaire_templates/new.html.erb +7 -0
  32. data/app/views/decidim/templates/admin/questionnaire_templates/preview.js.erb +11 -0
  33. data/app/views/layouts/decidim/admin/templates.html.erb +21 -0
  34. data/config/locales/am-ET.yml +1 -0
  35. data/config/locales/ar.yml +1 -0
  36. data/config/locales/bg.yml +1 -0
  37. data/config/locales/ca.yml +60 -0
  38. data/config/locales/cs.yml +60 -0
  39. data/config/locales/da.yml +1 -0
  40. data/config/locales/de.yml +54 -0
  41. data/config/locales/el.yml +1 -0
  42. data/config/locales/en.yml +61 -0
  43. data/config/locales/eo.yml +1 -0
  44. data/config/locales/es-MX.yml +60 -0
  45. data/config/locales/es-PY.yml +60 -0
  46. data/config/locales/es.yml +60 -0
  47. data/config/locales/et.yml +1 -0
  48. data/config/locales/eu.yml +1 -0
  49. data/config/locales/fi-plain.yml +60 -0
  50. data/config/locales/fi.yml +60 -0
  51. data/config/locales/fr-CA.yml +60 -0
  52. data/config/locales/fr.yml +60 -0
  53. data/config/locales/ga-IE.yml +1 -0
  54. data/config/locales/gl.yml +1 -0
  55. data/config/locales/hr.yml +1 -0
  56. data/config/locales/hu.yml +1 -0
  57. data/config/locales/id-ID.yml +1 -0
  58. data/config/locales/is-IS.yml +1 -0
  59. data/config/locales/it.yml +60 -0
  60. data/config/locales/ja.yml +60 -0
  61. data/config/locales/ko-KR.yml +1 -0
  62. data/config/locales/ko.yml +1 -0
  63. data/config/locales/lt.yml +1 -0
  64. data/config/locales/lv.yml +1 -0
  65. data/config/locales/mt.yml +1 -0
  66. data/config/locales/nl.yml +60 -0
  67. data/config/locales/no.yml +5 -0
  68. data/config/locales/om-ET.yml +1 -0
  69. data/config/locales/pl.yml +1 -0
  70. data/config/locales/pt-BR.yml +1 -0
  71. data/config/locales/pt.yml +1 -0
  72. data/config/locales/ro-RO.yml +1 -0
  73. data/config/locales/ru.yml +1 -0
  74. data/config/locales/sk.yml +1 -0
  75. data/config/locales/sl.yml +1 -0
  76. data/config/locales/so-SO.yml +1 -0
  77. data/config/locales/sr-CS.yml +1 -0
  78. data/config/locales/sv.yml +1 -0
  79. data/config/locales/ti-ER.yml +1 -0
  80. data/config/locales/tr-TR.yml +1 -0
  81. data/config/locales/uk.yml +1 -0
  82. data/config/locales/vi-VN.yml +1 -0
  83. data/config/locales/vi.yml +1 -0
  84. data/config/locales/zh-CN.yml +60 -0
  85. data/config/locales/zh-TW.yml +1 -0
  86. data/lib/decidim/templates.rb +12 -0
  87. data/lib/decidim/templates/admin.rb +10 -0
  88. data/lib/decidim/templates/admin_engine.rb +54 -0
  89. data/lib/decidim/templates/engine.rb +23 -0
  90. data/lib/decidim/templates/test/factories.rb +27 -0
  91. data/lib/decidim/templates/test/shared_examples/uses_questionnaire_templates.rb +108 -0
  92. data/lib/decidim/templates/version.rb +10 -0
  93. metadata +191 -0
@@ -0,0 +1,31 @@
1
+ # Decidim::Templates
2
+
3
+ This module provides a solution to create templates for different Decidim models, such as Proposals and Questionnaires.
4
+
5
+ ## Usage
6
+
7
+ Templates will be available in their own section in the admin
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'decidim-templates'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ ```bash
20
+ bundle
21
+ bundle exec rails decidim_templates:install:migrations
22
+ bundle exec rails db:migrate
23
+ ```
24
+
25
+ ## Contributing
26
+
27
+ See [Decidim](https://github.com/decidim/decidim).
28
+
29
+ ## License
30
+
31
+ This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
4
+
5
+ desc "Generates a dummy app for testing"
6
+ task test_app: "decidim:generate_external_test_app"
7
+
8
+ desc "Generates a development app."
9
+ task development_app: "decidim:generate_external_development_app"
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= link decidim/templates/templates.scss
3
+ */
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
@@ -0,0 +1,14 @@
1
+ .questionnaire-template-preview{
2
+ margin: 2rem;
3
+ padding: 1rem;
4
+
5
+ .card{
6
+ width: 75%;
7
+ margin: auto;
8
+ border: none;
9
+ }
10
+ }
11
+
12
+ .choose-template-preview{
13
+ min-height: 10rem;
14
+ }
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ # A command with all the business logic when duplicating a questionnaire template
6
+ module Admin
7
+ class ApplyQuestionnaireTemplate < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # template - The template we want to apply
11
+ # questionnaire - The questionnaire we want to use the template
12
+ def initialize(questionnaire, template)
13
+ @questionnaire = questionnaire
14
+ @template = template
15
+ end
16
+
17
+ # Executes the command. Broadcasts these events:
18
+ #
19
+ # - :ok when everything is valid.
20
+ # - :invalid if the form wasn't valid and we couldn't proceed.
21
+ #
22
+ # Returns nothing.
23
+ def call
24
+ return broadcast(:invalid) unless @template.valid?
25
+
26
+ Template.transaction do
27
+ apply_template
28
+ copy_questionnaire_questions(@template.templatable, @questionnaire)
29
+ end
30
+
31
+ broadcast(:ok, @questionnaire)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :form
37
+
38
+ def apply_template
39
+ @questionnaire.update!(
40
+ title: @template.templatable.title,
41
+ description: @template.templatable.description,
42
+ tos: @template.templatable.tos
43
+ )
44
+ end
45
+
46
+ def copy_questionnaire_questions(original_questionnaire, new_questionnaire)
47
+ original_questionnaire.questions.each do |original_question|
48
+ new_question = original_question.dup
49
+ new_question.questionnaire = new_questionnaire
50
+ new_question.save!
51
+ copy_questionnaire_answer_options(original_question, new_question)
52
+ copy_questionnaire_matrix_rows(original_question, new_question)
53
+ end
54
+ end
55
+
56
+ def copy_questionnaire_answer_options(original_question, new_question)
57
+ original_question.answer_options.each do |original_answer_option|
58
+ new_answer_option = original_answer_option.dup
59
+ new_answer_option.question = new_question
60
+ new_answer_option.save!
61
+ end
62
+ end
63
+
64
+ def copy_questionnaire_matrix_rows(original_question, new_question)
65
+ original_question.matrix_rows.each do |original_matrix_row|
66
+ new_matrix_row = original_matrix_row.dup
67
+ new_matrix_row.question = new_question
68
+ new_matrix_row.save!
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ # A command with all the business logic when duplicating a questionnaire template
6
+ module Admin
7
+ class CopyQuestionnaireTemplate < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # template - A template we want to duplicate
11
+ def initialize(template)
12
+ @template = template
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid.
18
+ # - :invalid if the form wasn't valid and we couldn't proceed.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ return broadcast(:invalid) unless @template.valid?
23
+
24
+ Template.transaction do
25
+ copy_template
26
+ copy_questionnaire_questions(@template.templatable, @copied_template.templatable)
27
+ end
28
+
29
+ broadcast(:ok, @copied_template)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :form
35
+
36
+ def copy_template
37
+ @copied_template = Template.create!(
38
+ organization: @template.organization,
39
+ name: @template.name,
40
+ description: @template.description
41
+ )
42
+ @resource = Decidim::Forms::Questionnaire.create!(
43
+ @template.templatable.dup.attributes.merge(
44
+ questionnaire_for: @copied_template
45
+ )
46
+ )
47
+
48
+ @copied_template.update!(templatable: @resource)
49
+ end
50
+
51
+ def copy_questionnaire_questions(original_questionnaire, new_questionnaire)
52
+ original_questionnaire.questions.each do |original_question|
53
+ new_question = original_question.dup
54
+ new_question.questionnaire = new_questionnaire
55
+ new_question.save!
56
+ copy_questionnaire_answer_options(original_question, new_question)
57
+ copy_questionnaire_matrix_rows(original_question, new_question)
58
+ end
59
+ end
60
+
61
+ def copy_questionnaire_answer_options(original_question, new_question)
62
+ original_question.answer_options.each do |original_answer_option|
63
+ new_answer_option = original_answer_option.dup
64
+ new_answer_option.question = new_question
65
+ new_answer_option.save!
66
+ end
67
+ end
68
+
69
+ def copy_questionnaire_matrix_rows(original_question, new_question)
70
+ original_question.matrix_rows.each do |original_matrix_row|
71
+ new_matrix_row = original_matrix_row.dup
72
+ new_matrix_row.question = new_question
73
+ new_matrix_row.save!
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ module Admin
6
+ # Creates a QuestionnaireTemplate.
7
+ class CreateQuestionnaireTemplate < Rectify::Command
8
+ # Initializes the command.
9
+ #
10
+ # form - The source for this QuestionnaireTemplate.
11
+ def initialize(form)
12
+ @form = form
13
+ end
14
+
15
+ def call
16
+ return broadcast(:invalid) unless @form.valid?
17
+
18
+ @template = Decidim.traceability.create!(
19
+ Template,
20
+ @form.current_user,
21
+ name: @form.name,
22
+ description: @form.description,
23
+ organization: @form.current_organization
24
+ )
25
+
26
+ @questionnaire = Decidim::Forms::Questionnaire.create!(questionnaire_for: @template)
27
+ @template.update!(templatable: @questionnaire)
28
+
29
+ broadcast(:ok, @template)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ module Admin
6
+ # This command deals with destroying a template from the admin panel.
7
+ class DestroyTemplate < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # template - The Template to be destroyed.
11
+ # user - The user that destroys the template.
12
+ def initialize(template, current_user)
13
+ @template = template
14
+ @current_user = current_user
15
+ end
16
+
17
+ # Public: Executes the command.
18
+ #
19
+ # Broadcasts :ok if it got destroyed
20
+ def call
21
+ destroy_template
22
+ broadcast(:ok)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :template, :current_user
28
+
29
+ def destroy_template
30
+ Decidim.traceability.perform_action!(
31
+ :delete,
32
+ template,
33
+ current_user
34
+ ) do
35
+ template.destroy!
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ module Admin
6
+ # Updates the questionnaire template given form data.
7
+ class UpdateTemplate < Rectify::Command
8
+ # Initializes the command.
9
+ #
10
+ # template - The Template to update.
11
+ # form - The form object containing the data to update.
12
+ # user - The user that updates the template.
13
+ def initialize(template, form, user)
14
+ @template = template
15
+ @form = form
16
+ @user = user
17
+ end
18
+
19
+ def call
20
+ return broadcast(:invalid) unless @form.valid?
21
+ return broadcast(:invalid) unless @user.organization == @template.organization
22
+
23
+ @template = Decidim.traceability.update!(
24
+ @template,
25
+ @user,
26
+ name: @form.name,
27
+ description: @form.description
28
+ )
29
+
30
+ broadcast(:ok, @template)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ module Admin
6
+ # This controller is the abstract class from which all other controllers of
7
+ # this engine inherit.
8
+ #
9
+ # Note that it inherits from `Decidim::Admin::ApplicationController`, which
10
+ # override its layout and provide all kinds of useful methods.
11
+ #
12
+ # i18n-tasks-use t('decidim.admin.titles.template_types.questionnaires')
13
+ class ApplicationController < Decidim::Admin::ApplicationController
14
+ layout "decidim/admin/templates"
15
+
16
+ helper_method :template_types
17
+
18
+ register_permissions(::Decidim::Templates::Admin::ApplicationController,
19
+ ::Decidim::Templates::Admin::Permissions,
20
+ ::Decidim::Admin::Permissions)
21
+
22
+ def permission_class_chain
23
+ ::Decidim.permissions_registry.chain_for(::Decidim::Templates::Admin::ApplicationController)
24
+ end
25
+
26
+ def template_types
27
+ @template_types ||= {
28
+ I18n.t("template_types.questionnaires", scope: "decidim.templates") => decidim_admin_templates.questionnaire_templates_path
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Templates
7
+ module Admin
8
+ module Concerns
9
+ module Templatable
10
+ # Common logic to load template-related resources in controller
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ helper_method :templates, :choose_template?
15
+
16
+ def templates
17
+ @templates = current_organization.templates.where(templatable_type: templatable_type)
18
+ @templates = @templates.where.not(id: params[:id]) if templates_path?
19
+ @templates
20
+ end
21
+
22
+ def templates_path?
23
+ controller_path.match?("^decidim/templates/.*")
24
+ end
25
+
26
+ def choose_template?
27
+ return false if templatable.is_a? Decidim::Templates::Template
28
+
29
+ templates.any? && templatable.pristine?
30
+ end
31
+
32
+ protected
33
+
34
+ def templatable
35
+ raise NotImplementedError, "Please set the templatable resource in your controller"
36
+ end
37
+
38
+ def templatable_type
39
+ raise NotImplementedError, "The templatable type is needed to load resources"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Templates
5
+ module Admin
6
+ module QuestionnaireTemplates
7
+ # This controller allows an admin to manage a questionnaire form for a questionnaire_template
8
+ class QuestionnairesController < Admin::ApplicationController
9
+ include Decidim::Forms::Admin::Concerns::HasQuestionnaire
10
+
11
+ helper Decidim::Admin::ExportsHelper
12
+
13
+ def questionnaire_for
14
+ template
15
+ end
16
+
17
+ def update_url
18
+ questionnaire_path(template)
19
+ end
20
+
21
+ def after_update_url
22
+ edit_questionnaire_template_path(id: template.id)
23
+ end
24
+
25
+ def public_url
26
+ nil
27
+ end
28
+
29
+ private
30
+
31
+ def template
32
+ @template ||= Template.find(params[:id])
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end