From eda4b12260e9e2de2d60f8baee5f1e116ef97bf1 Mon Sep 17 00:00:00 2001 From: Selase Krakani <849886+s3lase@users.noreply.github.com> Date: Thu, 4 Apr 2024 10:25:22 +0000 Subject: [PATCH] DEV: Add form template support for composer's `openNewTopic` action (#26489) * DEV: Spike form template support for composer's openNewTopic * DEV: Add tests --- .../app/components/composer-editor.hbs | 1 + .../discourse/app/components/d-editor.js | 2 +- .../discourse/app/services/composer.js | 12 +++ .../acceptance/composer-form-template-test.js | 83 +++++++++++++++---- 4 files changed, 82 insertions(+), 16 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/composer-editor.hbs b/app/assets/javascripts/discourse/app/components/composer-editor.hbs index 5bb55afd328..33672a3afa9 100644 --- a/app/assets/javascripts/discourse/app/components/composer-editor.hbs +++ b/app/assets/javascripts/discourse/app/components/composer-editor.hbs @@ -16,6 +16,7 @@ @onExpandPopupMenuOptions={{action "onExpandPopupMenuOptions"}} @onPopupMenuAction={{this.onPopupMenuAction}} @popupMenuOptions={{this.popupMenuOptions}} + @formTemplateId={{this.composer.formTemplateId}} @formTemplateIds={{this.formTemplateIds}} @formTemplateInitialValues={{@formTemplateInitialValues}} @onSelectFormTemplate={{@onSelectFormTemplate}} diff --git a/app/assets/javascripts/discourse/app/components/d-editor.js b/app/assets/javascripts/discourse/app/components/d-editor.js index 941eec6c5e4..14885c04a9b 100644 --- a/app/assets/javascripts/discourse/app/components/d-editor.js +++ b/app/assets/javascripts/discourse/app/components/d-editor.js @@ -243,7 +243,7 @@ export default Component.extend(TextareaTextManipulation, { return this._selectedFormTemplateId; } - return this.formTemplateIds?.[0]; + return this.formTemplateId || this.formTemplateIds?.[0]; }, set(key, value) { diff --git a/app/assets/javascripts/discourse/app/services/composer.js b/app/assets/javascripts/discourse/app/services/composer.js index 4513b8256da..e6949c2f4ae 100644 --- a/app/assets/javascripts/discourse/app/services/composer.js +++ b/app/assets/javascripts/discourse/app/services/composer.js @@ -1289,6 +1289,7 @@ export default class ComposerService extends Service { @param {Boolean} [opts.disableScopedCategory] @param {Number} [opts.categoryId] Sets `scopedCategoryId` and `categoryId` on the Composer model @param {Number} [opts.prioritizedCategoryId] + @param {Number} [opts.formTemplateId] @param {String} [opts.draftSequence] @param {Boolean} [opts.skipDraftCheck] @param {Boolean} [opts.skipJumpOnSave] Option to skip navigating to the post when saved in this composer session @@ -1438,6 +1439,7 @@ export default class ComposerService extends Service { body, category, tags, + formTemplate, preferDraft = false, } = {}) { if (preferDraft && this.currentUser.has_topic_draft) { @@ -1446,6 +1448,7 @@ export default class ComposerService extends Service { return this.open({ prioritizedCategoryId: category?.id, topicCategoryId: category?.id, + formTemplateId: formTemplate?.id, topicTitle: title, topicBody: body, topicTags: tags, @@ -1532,6 +1535,15 @@ export default class ComposerService extends Service { this.model.set("reply", opts.topicBody); } + if ( + opts.formTemplateId && + this.model + .get("category.form_template_ids") + ?.includes(opts.formTemplateId) + ) { + this.model.set("formTemplateId", opts.formTemplateId); + } + if (opts.prependText && !this.model.reply?.includes(opts.prependText)) { this.model.prependText(opts.prependText, { new_line: true, diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-form-template-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-form-template-test.js index 05ad1d80092..d55e6c799a9 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/composer-form-template-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/composer-form-template-test.js @@ -1,4 +1,4 @@ -import { click, fillIn, visit } from "@ember/test-helpers"; +import { click, fillIn, settled, visit } from "@ember/test-helpers"; import { test } from "qunit"; import { toggleCheckDraftPopup } from "discourse/services/composer"; import TopicFixtures from "discourse/tests/fixtures/topic"; @@ -6,6 +6,38 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { cloneJSON } from "discourse-common/lib/object"; +const FORM_TEMPLATES = [ + { + id: 1, + name: "Testing", + template: ` + - type: input + id: full-name + attributes: + label: "Full name" + description: "What is your full name?" + - type: textarea + id: description + attributes: + label: "Description" + `, + }, + { + id: 2, + name: "Another Test", + template: ` + - type: input + id: activity-date + attributes: + label: "Activity Date" + placeholder: "Please select activity date" + validations: + required: true + type: date + `, + }, +]; + acceptance("Composer Form Template", function (needs) { needs.user({ id: 5, @@ -26,7 +58,7 @@ acceptance("Composer Form Template", function (needs) { slug: "general", permission: 1, topic_template: null, - form_template_ids: [1], + form_template_ids: [1, 2], }, { id: 2, @@ -40,20 +72,19 @@ acceptance("Composer Form Template", function (needs) { needs.pretender((server, helper) => { server.put("/u/kris.json", () => helper.response({ user: {} })); - server.get("/form-templates/1.json", () => { + server.get("/form-templates.json", () => { return helper.response({ - form_template: { - name: "Testing", - template: `- type: input - id: full-name - attributes: - label: "Full name" - description: "What is your full name?" -- type: textarea - id: description - attributes: - label: "Description"`, - }, + form_templates: FORM_TEMPLATES, + }); + }); + + [1, 2].forEach((id) => { + server.get(`/form-templates/${id}.json`, () => { + const index = id - 1; + + return helper.response({ + form_template: FORM_TEMPLATES[index], + }); }); }); @@ -82,6 +113,10 @@ acceptance("Composer Form Template", function (needs) { await visit("/"); await click("#create-topic"); + assert.strictEqual( + selectKit(".form-template-chooser").header().value(), + "1" + ); assert.strictEqual(selectKit(".category-chooser").header().value(), "1"); assert.ok( @@ -125,4 +160,22 @@ acceptance("Composer Form Template", function (needs) { "keeps the value of the textarea field when composer is re-opened from draft mode" ); }); + + test("Composer opens with the specified form template selected", async function (assert) { + await visit("/"); + + const composer = this.owner.lookup("service:composer"); + const formTemplate = FORM_TEMPLATES[1]; + + await composer.openNewTopic({ formTemplate }); + await settled(); + + assert.strictEqual( + selectKit(".form-template-chooser").header().value(), + "2" + ); + assert + .dom(".form-template-field__input[name='activity-date']") + .exists("it renders form template field"); + }); });