From 7eb7b7eba6ccb5acbd78ea9e0d11bac74de7e730 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Wed, 15 May 2024 13:46:56 +0200 Subject: [PATCH 1/8] Disable step controls when uploading --- .../custom-wizard-composer-editor.js.es6 | 5 +++- .../components/custom-wizard-step.js.es6 | 27 ++++++++++++++++++- .../components/custom-wizard-step.hbs | 4 +-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 index 95ae56c0..0f431f3d 100644 --- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 @@ -18,6 +18,9 @@ import { inject as service } from "@ember/service"; const IMAGE_MARKDOWN_REGEX = /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g; + +export const wizardComposerEdtiorEventPrefix = "wizard-editor"; + export default ComposerEditor.extend({ modal: service(), @@ -33,7 +36,7 @@ export default ComposerEditor.extend({ draftStatus: "null", replyPlaceholder: alias("field.translatedPlaceholder"), wizardEventFieldId: null, - composerEventPrefix: "wizard-editor", + composerEventPrefix: wizardComposerEdtiorEventPrefix, @on("didInsertElement") _composerEditorInit() { diff --git a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 index 44bef872..99176259 100644 --- a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 @@ -7,8 +7,21 @@ import { cook } from "discourse/lib/text"; import CustomWizard, { updateCachedWizard, } from "discourse/plugins/discourse-custom-wizard/discourse/models/custom-wizard"; -import { alias, not } from "@ember/object/computed"; +import { alias, not, or } from "@ember/object/computed"; import discourseLater from "discourse-common/lib/later"; +import { wizardComposerEdtiorEventPrefix } from "./custom-wizard-composer-editor"; + +const uploadStartedEventKeys = [ + "upload-started" +]; +const uploadEndedEventKeys = [ + "upload-success", + "upload-error", + "upload-cancelled", + "uploads-cancelled", + "uploads-aborted", + "all-uploads-complete" +]; export default Component.extend({ classNameBindings: [":wizard-step", "step.id"], @@ -28,6 +41,17 @@ export default Component.extend({ cook(this.step.translatedDescription).then((cookedDescription) => { this.set("cookedDescription", cookedDescription); }); + + uploadStartedEventKeys.forEach(key => { + this.appEvents.on(`${wizardComposerEdtiorEventPrefix}:${key}`, () => { + this.set("uploading", true); + }); + }); + uploadEndedEventKeys.forEach(key => { + this.appEvents.on(`${wizardComposerEdtiorEventPrefix}:${key}`, () => { + this.set("uploading", false); + }); + }); }, didInsertElement() { @@ -40,6 +64,7 @@ export default Component.extend({ showNextButton: not("step.final"), showDoneButton: alias("step.final"), + btnsDisabled: or("saving", "uploading"), @discourseComputed( "step.index", diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-step.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-step.hbs index b9f0c06e..fd4e038e 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-step.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-step.hbs @@ -60,7 +60,7 @@ type="button" class="wizard-btn next primary" {{action "nextStep"}} - disabled={{saving}} + disabled={{btnsDisabled}} tabindex={{primaryButtonIndex}} > {{i18n "wizard.next"}} @@ -73,7 +73,7 @@ type="button" class="wizard-btn done" {{action "done"}} - disabled={{saving}} + disabled={{btnsDisabled}} tabindex={{primaryButtonIndex}} > {{i18n "wizard.done_custom"}} From 8e4d37bf31234b12e87d321603af7ac519f70cd4 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Thu, 23 May 2024 09:23:15 +0200 Subject: [PATCH 2/8] COMPATIBILITY: hide powered by discourse on wizards --- assets/stylesheets/common/wizard/wizard.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/stylesheets/common/wizard/wizard.scss b/assets/stylesheets/common/wizard/wizard.scss index 1bb0d086..4c8f2357 100644 --- a/assets/stylesheets/common/wizard/wizard.scss +++ b/assets/stylesheets/common/wizard/wizard.scss @@ -160,6 +160,10 @@ body.custom-wizard { display: flex; justify-content: flex-end; } + + .powered-by-discourse { + display: none; + } } /* IE11 hacks */ From 4ad6f331b37bf757fb4ed2b6e6a25ebaeeb68ae3 Mon Sep 17 00:00:00 2001 From: merefield Date: Wed, 29 May 2024 15:51:51 +0100 Subject: [PATCH 3/8] add fe test for next button disablement during upload --- test/javascripts/acceptance/field-test.js | 47 ++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/test/javascripts/acceptance/field-test.js b/test/javascripts/acceptance/field-test.js index 455d420d..8635bee1 100644 --- a/test/javascripts/acceptance/field-test.js +++ b/test/javascripts/acceptance/field-test.js @@ -1,8 +1,10 @@ -import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers"; +import { getOwner } from "@ember/application"; +import { click, fillIn, settled, triggerKeyEvent, visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance, count, + createFile, exists, query, visible, @@ -11,6 +13,8 @@ import { allFieldsWizard } from "../helpers/wizard"; import tagsJson from "../fixtures/tags"; import usersJson from "../fixtures/users"; +const wizardComposerEdtiorEventPrefix = "wizard-editor"; + acceptance("Field | Fields", function (needs) { needs.pretender((server, helper) => { server.get("/w/wizard.json", () => helper.response(allFieldsWizard)); @@ -18,6 +22,26 @@ acceptance("Field | Fields", function (needs) { helper.response({ results: tagsJson["tags"] }) ); server.get("/u/search/users", () => helper.response(usersJson)); + + server.post("/uploads.json", () => { + return helper.response({ + extension: "jpeg", + filesize: 126177, + height: 800, + human_filesize: "123 KB", + id: 202, + original_filename: "avatar.PNG.jpg", + retain_hours: null, + short_path: "/uploads/short-url/yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", + short_url: "upload://yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", + thumbnail_height: 320, + thumbnail_width: 690, + url: "/images/discourse-logo-sketch-small.png", + width: 1920, + }); + }, + 500 // this delay is important to slow down the uploads a bit so we can let elements of the interface update + ); }); test("Text", async function (assert) { @@ -54,6 +78,27 @@ acceptance("Field | Fields", function (needs) { "Input in composer" ); }); + + test("Composer - Upload Disables Next Button", async function (assert) { + await visit("/w/wizard"); + const appEvents = getOwner(this).lookup("service:app-events"); + const done = assert.async(); + + appEvents.on(`${wizardComposerEdtiorEventPrefix}:all-uploads-complete`, async () => { + await settled(); + assert.ok(!exists(".wizard-btn.next.primary:disabled")); + done(); + }); + + appEvents.on(`${wizardComposerEdtiorEventPrefix}:upload-started`, async () => { + await settled() + assert.ok(exists(".wizard-btn.next.primary:disabled")); + }); + + const image = createFile("avatar.png"); + appEvents.trigger(`${wizardComposerEdtiorEventPrefix}:add-files`, image); + }); + test("Composer - Hyperlink", async function (assert) { await visit("/w/wizard"); assert.ok( From 9ec820fce856b42c8c3695db6df207e7d8daec54 Mon Sep 17 00:00:00 2001 From: merefield Date: Wed, 29 May 2024 15:54:34 +0100 Subject: [PATCH 4/8] linting --- test/javascripts/acceptance/field-test.js | 66 ++++++++++++++--------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/test/javascripts/acceptance/field-test.js b/test/javascripts/acceptance/field-test.js index 8635bee1..fdf99da5 100644 --- a/test/javascripts/acceptance/field-test.js +++ b/test/javascripts/acceptance/field-test.js @@ -1,5 +1,11 @@ import { getOwner } from "@ember/application"; -import { click, fillIn, settled, triggerKeyEvent, visit } from "@ember/test-helpers"; +import { + click, + fillIn, + settled, + triggerKeyEvent, + visit, +} from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance, @@ -23,22 +29,24 @@ acceptance("Field | Fields", function (needs) { ); server.get("/u/search/users", () => helper.response(usersJson)); - server.post("/uploads.json", () => { - return helper.response({ - extension: "jpeg", - filesize: 126177, - height: 800, - human_filesize: "123 KB", - id: 202, - original_filename: "avatar.PNG.jpg", - retain_hours: null, - short_path: "/uploads/short-url/yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", - short_url: "upload://yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", - thumbnail_height: 320, - thumbnail_width: 690, - url: "/images/discourse-logo-sketch-small.png", - width: 1920, - }); + server.post( + "/uploads.json", + () => { + return helper.response({ + extension: "jpeg", + filesize: 126177, + height: 800, + human_filesize: "123 KB", + id: 202, + original_filename: "avatar.PNG.jpg", + retain_hours: null, + short_path: "/uploads/short-url/yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", + short_url: "upload://yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg", + thumbnail_height: 320, + thumbnail_width: 690, + url: "/images/discourse-logo-sketch-small.png", + width: 1920, + }); }, 500 // this delay is important to slow down the uploads a bit so we can let elements of the interface update ); @@ -84,16 +92,22 @@ acceptance("Field | Fields", function (needs) { const appEvents = getOwner(this).lookup("service:app-events"); const done = assert.async(); - appEvents.on(`${wizardComposerEdtiorEventPrefix}:all-uploads-complete`, async () => { - await settled(); - assert.ok(!exists(".wizard-btn.next.primary:disabled")); - done(); - }); + appEvents.on( + `${wizardComposerEdtiorEventPrefix}:all-uploads-complete`, + async () => { + await settled(); + assert.ok(!exists(".wizard-btn.next.primary:disabled")); + done(); + } + ); - appEvents.on(`${wizardComposerEdtiorEventPrefix}:upload-started`, async () => { - await settled() - assert.ok(exists(".wizard-btn.next.primary:disabled")); - }); + appEvents.on( + `${wizardComposerEdtiorEventPrefix}:upload-started`, + async () => { + await settled(); + assert.ok(exists(".wizard-btn.next.primary:disabled")); + } + ); const image = createFile("avatar.png"); appEvents.trigger(`${wizardComposerEdtiorEventPrefix}:add-files`, image); From fbf52aae3c56217038f40948a1b506be3864ddbf Mon Sep 17 00:00:00 2001 From: merefield Date: Wed, 29 May 2024 16:00:11 +0100 Subject: [PATCH 5/8] linting --- .../components/custom-wizard-composer-editor.js.es6 | 1 - .../discourse/components/custom-wizard-step.js.es6 | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 index 0f431f3d..ea26cc67 100644 --- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 @@ -18,7 +18,6 @@ import { inject as service } from "@ember/service"; const IMAGE_MARKDOWN_REGEX = /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g; - export const wizardComposerEdtiorEventPrefix = "wizard-editor"; export default ComposerEditor.extend({ diff --git a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 index 99176259..86ae1afa 100644 --- a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 @@ -11,16 +11,14 @@ import { alias, not, or } from "@ember/object/computed"; import discourseLater from "discourse-common/lib/later"; import { wizardComposerEdtiorEventPrefix } from "./custom-wizard-composer-editor"; -const uploadStartedEventKeys = [ - "upload-started" -]; +const uploadStartedEventKeys = ["upload-started"]; const uploadEndedEventKeys = [ "upload-success", "upload-error", "upload-cancelled", "uploads-cancelled", "uploads-aborted", - "all-uploads-complete" + "all-uploads-complete", ]; export default Component.extend({ @@ -42,12 +40,12 @@ export default Component.extend({ this.set("cookedDescription", cookedDescription); }); - uploadStartedEventKeys.forEach(key => { + uploadStartedEventKeys.forEach((key) => { this.appEvents.on(`${wizardComposerEdtiorEventPrefix}:${key}`, () => { this.set("uploading", true); }); }); - uploadEndedEventKeys.forEach(key => { + uploadEndedEventKeys.forEach((key) => { this.appEvents.on(`${wizardComposerEdtiorEventPrefix}:${key}`, () => { this.set("uploading", false); }); From eda0aa19b2884959e8c68628d21db69761620eb5 Mon Sep 17 00:00:00 2001 From: merefield Date: Wed, 29 May 2024 16:04:36 +0100 Subject: [PATCH 6/8] bump patch --- plugin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.rb b/plugin.rb index 15723558..c9d647cf 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # name: discourse-custom-wizard # about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more. -# version: 2.6.8 +# version: 2.6.9 # authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever, Juan Marcos Gutierrez Ramos # url: https://github.com/paviliondev/discourse-custom-wizard # contact_emails: development@pavilion.tech From 883bd6d96c2a50ee9c5a369cebea1b4826f58ccc Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 4 Jun 2024 12:04:15 +0200 Subject: [PATCH 7/8] DEV: fallback to core composerEditorInit --- .../custom-wizard-composer-editor.js.es6 | 27 +++++-------------- plugin.rb | 2 +- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 index ea26cc67..4e035236 100644 --- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 @@ -39,25 +39,11 @@ export default ComposerEditor.extend({ @on("didInsertElement") _composerEditorInit() { - const $input = $(this.element.querySelector(".d-editor-input")); + this._super(...arguments); - if (this.siteSettings.enable_mentions) { - $input.autocomplete({ - template: findRawTemplate("user-selector-autocomplete"), - dataSource: (term) => this._userSearchTerm.call(this, term), - key: "@", - transformComplete: (v) => v.username || v.name, - afterComplete: (value) => { - this.composer.set("reply", value); - scheduleOnce("afterRender", () => $input.blur().focus()); - }, - triggerRule: (textarea) => - !inCodeBlock(textarea.value, caretPosition(textarea)), - }); - } + if (this.siteSettings.mentionables_enabled) { + const $input = $(this.element.querySelector(".d-editor-input")); - const siteSettings = this.siteSettings; - if (siteSettings.mentionables_enabled) { Site.currentProp("mentionable_items", this.wizard.mentionable_items); const { SEPARATOR } = requirejs( "discourse/plugins/discourse-mentionables/discourse/lib/discourse-markdown/mentionable-items" @@ -75,15 +61,14 @@ export default ComposerEditor.extend({ }, transformComplete: (item) => item.model.slug, dataSource: (term) => - term.match(/\s/) ? null : searchMentionableItem(term, siteSettings), + term.match(/\s/) + ? null + : searchMentionableItem(term, this.siteSettings), triggerRule: (textarea) => !inCodeBlock(textarea.value, caretPosition(textarea)), }); } - $input.on("scroll", this._throttledSyncEditorAndPreviewScroll); - this._bindUploadTarget(); - const field = this.field; this.editorInputClass = `.${dasherize(field.type)}-${dasherize( field.id diff --git a/plugin.rb b/plugin.rb index c9d647cf..332285dd 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # name: discourse-custom-wizard # about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more. -# version: 2.6.9 +# version: 2.6.10 # authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever, Juan Marcos Gutierrez Ramos # url: https://github.com/paviliondev/discourse-custom-wizard # contact_emails: development@pavilion.tech From 153435950aa5b34642541d6ac1ca72cb6cc4e0fe Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Thu, 20 Jun 2024 09:38:37 +0200 Subject: [PATCH 8/8] DEV: handle add_to_serializer deprecations --- plugin.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin.rb b/plugin.rb index 332285dd..db0dd9be 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # name: discourse-custom-wizard # about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more. -# version: 2.6.10 +# version: 2.6.11 # authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever, Juan Marcos Gutierrez Ramos # url: https://github.com/paviliondev/discourse-custom-wizard # contact_emails: development@pavilion.tech @@ -185,17 +185,17 @@ after_initialize do end end - add_to_serializer(:site, :include_wizard_required?) do + add_to_class(:site_serializer, :include_wizard_required?) do scope.is_admin? && Wizard.new(scope.user).requires_completion? end - add_to_serializer(:site, :complete_custom_wizard) do + add_to_class(:site_serializer, :complete_custom_wizard) do if scope.user && requires_completion = CustomWizard::Wizard.prompt_completion(scope.user) requires_completion.map { |w| { name: w[:name], url: "/w/#{w[:id]}" } } end end - add_to_serializer(:site, :include_complete_custom_wizard?) do + add_to_class(:site_serializer, :include_complete_custom_wizard?) do complete_custom_wizard.present? end