diff --git a/app/controllers/mailings_controller.rb b/app/controllers/mailings_controller.rb index 518d57a..5ee2b45 100644 --- a/app/controllers/mailings_controller.rb +++ b/app/controllers/mailings_controller.rb @@ -166,19 +166,18 @@ class MailingsController < ApplicationController end def apply_template_if_needed - copy_template(params.dig(:mailing, :mail_template_id), :subject, :body_html, params[:use_template_content]) - copy_template(params.dig(:mailing, :mail_template_b_id), :subject_b, :body_html_b, params[:use_template_b_content]) + copy_template_if_blank(params.dig(:mailing, :mail_template_id), :subject, :body_html) + copy_template_if_blank(params.dig(:mailing, :mail_template_b_id), :subject_b, :body_html_b) end - def copy_template(template_id, subject_attr, body_attr, flag) + def copy_template_if_blank(template_id, subject_attr, body_attr) return if template_id.blank? - return unless ActiveModel::Type::Boolean.new.cast(flag) template = MailTemplate.for_project(current_project).find_by(id: template_id) return unless template - @mailing.public_send("#{subject_attr}=", template.subject) - @mailing.public_send("#{body_attr}=", template.body_html) + @mailing.public_send("#{subject_attr}=", template.subject) if @mailing.public_send(subject_attr).blank? + @mailing.public_send("#{body_attr}=", template.body_html) if @mailing.public_send(body_attr).blank? end def rebuild_recipients_if_needed diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 376a906..f10c715 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -21,6 +21,10 @@ module ApplicationHelper "w-full rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm text-zinc-900 placeholder:text-zinc-400 focus:border-zinc-400 focus:outline-none focus:ring-1 focus:ring-zinc-400 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100 dark:placeholder:text-zinc-500 dark:focus:border-zinc-500 dark:focus:ring-zinc-500" end + def mail_templates_picker_payload(templates) + Array(templates).map { |template| { id: template.id, subject: template.subject, body_html: template.body_html } } + end + def card_class "rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100" end diff --git a/app/javascript/controllers/template_picker_controller.js b/app/javascript/controllers/template_picker_controller.js new file mode 100644 index 0000000..c3e1c40 --- /dev/null +++ b/app/javascript/controllers/template_picker_controller.js @@ -0,0 +1,74 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = ["select", "subject"] + static values = { templates: Array } + + connect() { + this.pendingHtml = null + this.onEditorReady = this.onEditorReady.bind(this) + this.editorElement?.addEventListener("trix-initialize", this.onEditorReady) + if (this.shouldPrefill()) this.apply() + } + + disconnect() { + this.editorElement?.removeEventListener("trix-initialize", this.onEditorReady) + } + + apply() { + const template = this.currentTemplate() + if (!template) return + + if (this.hasSubjectTarget) { + this.subjectTarget.value = template.subject || "" + this.subjectTarget.dispatchEvent(new Event("input", { bubbles: true })) + } + + this.setBody(template.body_html || "") + } + + shouldPrefill() { + if (!this.selectTarget.value) return false + const subjectBlank = !this.hasSubjectTarget || this.subjectTarget.value.trim() === "" + return subjectBlank && this.bodyIsBlank() + } + + currentTemplate() { + const id = Number(this.selectTarget.value) + if (!id) return null + return (this.templatesValue || []).find((template) => Number(template.id) === id) || null + } + + setBody(html) { + this.pendingHtml = html + const editor = this.editorElement?.editor + if (editor) { + editor.loadHTML(html) + this.pendingHtml = null + return + } + if (this.hiddenInput) this.hiddenInput.value = html + } + + onEditorReady() { + if (this.pendingHtml != null) { + this.editorElement.editor?.loadHTML(this.pendingHtml) + this.pendingHtml = null + return + } + if (this.shouldPrefill()) this.apply() + } + + bodyIsBlank() { + const value = this.hiddenInput?.value || "" + return value.replace(/<[^>]*>/g, "").replace(/ /g, " ").trim() === "" + } + + get editorElement() { + return this.element.querySelector("trix-editor") + } + + get hiddenInput() { + return this.element.querySelector("[data-wysiwyg-target='input']") + } +} diff --git a/app/views/mailings/_form.html.erb b/app/views/mailings/_form.html.erb index 73d8ec6..c5e1490 100644 --- a/app/views/mailings/_form.html.erb +++ b/app/views/mailings/_form.html.erb @@ -37,7 +37,7 @@ <%= f.check_box :ab_test, { data: { ab_test_target: "checkbox", action: "ab-test#toggle" } } %> Test A/B su questa comunicazione - Due versioni di oggetto e HTML. Ogni destinatario riceve A o B. + Due versioni della stessa email. Carica un template A e un template B nelle colonne: ogni destinatario ne riceve una. @@ -48,48 +48,43 @@ + <% templates_payload = mail_templates_picker_payload(@mail_templates) %>
Scegliendo un template, oggetto e testo si copiano qui sotto. Poi puoi modificarli solo per questo invio.
Stesso meccanismo della variante A: il template riempie oggetto e corpo B.
Corpo dal template B
" + ) + + get new_mailing_path(project_code: @project.code) + assert_response :success + assert_match(/template-picker/, response.body) + assert_match(/Oggetto dal template B/, response.body) + assert_match(/Corpo dal template B/, response.body) + assert_includes response.body, template.id.to_s + end + + test "create copies blank variant B fields from selected template" do + login_as users(:admin) + follow_redirect! if response.redirect? + template_b = MailTemplate.create!( + project: @project, + name: "Template B server", + subject: "B {{societa}}", + body_html: "Versione B dal template
" + ) + + post mailings_path(project_code: @project.code), params: { + mailing: { + name: "AB da template", + mail_identity_id: @identity.id, + mail_template_b_id: template_b.id, + audience: "to_send", + ab_test: "1", + ab_assignment: "from_record", + subject: "Oggetto A", + body_html: "Versione A
", + subject_b: "", + body_html_b: "", + interval_seconds: 0 + } + } + mailing = Mailing.last + assert_redirected_to mailing_path(mailing, project_code: @project.code) + assert_equal "B {{societa}}", mailing.subject_b + assert_includes mailing.body_html_b, "Versione B dal template" + end end