diff --git a/OVERLOADS.md b/OVERLOADS.md index 0cb89b3..102ec45 100644 --- a/OVERLOADS.md +++ b/OVERLOADS.md @@ -127,3 +127,6 @@ de6d804 - fix multipart object tagging (#40) (#41), 2021-12-24 * `lib/tasks/restore_dump.rake` 705e0ad - Run rubocop, 2021-12-01 + +* `app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb` +Local backport of https://github.com/decidim/decidim/commit/420623d647d2020665cfbaa118514f5e92672c68 \ No newline at end of file diff --git a/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb b/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb new file mode 100644 index 0000000..7440b12 --- /dev/null +++ b/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb @@ -0,0 +1,153 @@ +# frozen_string_literal: true + +module Decidim + module Forms + module Admin + module Concerns + # Questionnaires can be related to any class in Decidim, in order to + # manage the questionnaires for a given type, you should create a new + # controller and include this concern. + # + # The only requirement is to define a `questionnaire_for` method that + # returns an instance of the model that questionnaire belongs to. + module HasQuestionnaire + extend ActiveSupport::Concern + + included do + helper Decidim::Forms::Admin::ApplicationHelper + include Decidim::TranslatableAttributes + + helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :blank_matrix_row, + :blank_display_condition, :question_types, :display_condition_types, :update_url, :public_url, :answer_options_url, :edit_questionnaire_title + + if defined?(Decidim::Templates::Admin::Concerns::Templatable) + include Decidim::Templates::Admin::Concerns::Templatable + helper Decidim::Templates::Admin::TemplatesHelper + + def templatable_type + "Decidim::Forms::Questionnaire" + end + + def templatable + questionnaire + end + end + + def edit + enforce_permission_to :update, :questionnaire, questionnaire: questionnaire + + @form = form(Admin::QuestionnaireForm).from_model(questionnaire) + + render template: "decidim/forms/admin/questionnaires/edit" + end + + def update + enforce_permission_to :update, :questionnaire, questionnaire: questionnaire + + params["published_at"] = Time.current if params.has_key? "save_and_publish" + @form = form(Admin::QuestionnaireForm).from_params(params) + + Admin::UpdateQuestionnaire.call(@form, questionnaire) do + on(:ok) do + # i18n-tasks-use t("decidim.forms.admin.questionnaires.update.success") + flash[:notice] = I18n.t("update.success", scope: i18n_flashes_scope) + redirect_to after_update_url + end + + on(:invalid) do + # i18n-tasks-use t("decidim.forms.admin.questionnaires.update.invalid") + flash.now[:alert] = I18n.t("update.invalid", scope: i18n_flashes_scope) + render template: "decidim/forms/admin/questionnaires/edit" + end + end + end + + def answer_options + respond_to do |format| + format.json do + question_id = params["id"] + question = Question.find_by(id: question_id) + render json: question.answer_options.map { |answer_option| AnswerOptionPresenter.new(answer_option).as_json } if question.present? + end + end + end + + # Public: The only method to be implemented at the controller. You need to + # return the object that will hold the questionnaire. + def questionnaire_for + raise "#{self.class.name} is expected to implement #questionnaire_for" + end + + # You can implement this method in your controller to change the URL + # where the questionnaire will be submitted. + def update_url + url_for(questionnaire.questionnaire_for) + end + + # You can implement this method in your controller to change the URL + # where the user will be redirected after updating the questionnaire + def after_update_url + url_for(questionnaire.questionnaire_for) + end + + # Implement this method in your controller to set the URL + # where the questionnaire can be answered. + def public_url + raise "#{self.class.name} is expected to implement #public_url" + end + + # Returns the url to get the answer options json (for the display conditions form) + # for the question with id = params[:id] + def answer_options_url(params) + url_for([questionnaire.questionnaire_for, { action: :answer_options, format: :json, **params }]) + end + + # Implement this method in your controller to set the title + # of the edit form. + def edit_questionnaire_title + t(:title, scope: "decidim.forms.admin.questionnaires.form", questionnaire_for: translated_attribute(questionnaire_for.try(:title))) + end + + private + + def i18n_flashes_scope + "decidim.forms.admin.questionnaires" + end + + def questionnaire + @questionnaire ||= Questionnaire.find_by(questionnaire_for: questionnaire_for) + end + + def blank_question + @blank_question ||= Admin::QuestionForm.new + end + + def blank_answer_option + @blank_answer_option ||= Admin::AnswerOptionForm.new + end + + def blank_display_condition + @blank_display_condition ||= Admin::DisplayConditionForm.new + end + + def blank_matrix_row + @blank_matrix_row ||= Admin::QuestionMatrixRowForm.new + end + + def question_types + @question_types ||= Question::QUESTION_TYPES.map do |question_type| + [question_type, I18n.t("decidim.forms.question_types.#{question_type}")] + end + end + + def display_condition_types + @display_condition_types ||= DisplayCondition.condition_types.keys.map do |condition_type| + [condition_type, I18n.t("decidim.forms.admin.questionnaires.display_condition.condition_types.#{condition_type}")] + end + end + end + end + end + end + end +end