diff --git a/.github/workflows/discourse-plugin.yml b/.github/workflows/discourse-plugin.yml index f5cf62e5..13850e3e 100644 --- a/.github/workflows/discourse-plugin.yml +++ b/.github/workflows/discourse-plugin.yml @@ -5,6 +5,8 @@ on: branches: - main pull_request: + schedule: + - cron: "0 0 * * *" jobs: ci: diff --git a/app/serializers/custom_wizard/submission_serializer.rb b/app/serializers/custom_wizard/submission_serializer.rb index 48892c21..ed9ad411 100644 --- a/app/serializers/custom_wizard/submission_serializer.rb +++ b/app/serializers/custom_wizard/submission_serializer.rb @@ -10,7 +10,7 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer end def user - ::BasicUserSerializer.new(object.wizard.user).as_json + ::BasicUserSerializer.new(object.wizard.user, root: false).as_json end def fields 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 5e2ef424..5335da81 100644 --- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 @@ -12,6 +12,7 @@ import { alias } from "@ember/object/computed"; import Site from "discourse/models/site"; import { uploadIcon } from "discourse/lib/uploads"; import { dasherize } from "@ember/string"; +import showModal from "discourse/lib/show-modal"; const IMAGE_MARKDOWN_REGEX = /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g; @@ -19,7 +20,6 @@ export default ComposerEditor.extend({ classNameBindings: ["fieldClass"], allowUpload: true, showLink: false, - showHyperlinkBox: false, topic: null, showToolbar: true, focusTarget: "reply", @@ -29,6 +29,7 @@ export default ComposerEditor.extend({ draftStatus: "null", replyPlaceholder: alias("field.translatedPlaceholder"), wizardEventFieldId: null, + composerEventPrefix: "wizard-editor", @on("didInsertElement") _composerEditorInit() { @@ -77,24 +78,13 @@ export default ComposerEditor.extend({ $input.on("scroll", this._throttledSyncEditorAndPreviewScroll); this._bindUploadTarget(); - const wizardEventNames = ["insert-text", "replace-text"]; - const eventPrefix = this.eventPrefix; - this.appEvents.reopen({ - trigger(name, ...args) { - let eventParts = name.split(":"); - let currentEventPrefix = eventParts[0]; - let currentEventName = eventParts[1]; + const field = this.field; + this.editorInputClass = `.${dasherize(field.type)}-${dasherize( + field.id + )} .d-editor-input`; - if ( - currentEventPrefix !== "wizard-editor" && - wizardEventNames.some((wen) => wen === currentEventName) - ) { - let wizardEventName = name.replace(eventPrefix, "wizard-editor"); - return this._super(wizardEventName, ...args); - } else { - return this._super(name, ...args); - } - }, + this._uppyInstance.on("file-added", () => { + this.session.set("wizardEventFieldId", field.id); }); }, @@ -116,12 +106,6 @@ export default ComposerEditor.extend({ return uploadIcon(false, this.siteSettings); }, - click(e) { - if ($(e.target).hasClass("wizard-composer-hyperlink")) { - this.set("showHyperlinkBox", false); - } - }, - @bind _handleImageDeleteButtonClick(event) { if (!event.target.classList.contains("delete-image-button")) { @@ -165,7 +149,7 @@ export default ComposerEditor.extend({ shortcut: "K", trimLeading: true, unshift: true, - sendAction: () => component.set("showHyperlinkBox", true), + sendAction: (event) => component.send("showLinkModal", event), }); if (this.siteSettings.mentionables_enabled) { @@ -206,17 +190,18 @@ export default ComposerEditor.extend({ this._super(...arguments); }, - addLink(linkName, linkUrl) { - let link = `[${linkName}](${linkUrl})`; - this.appEvents.trigger("wizard-editor:insert-text", { - fieldId: this.field.id, - text: link, - }); - this.set("showHyperlinkBox", false); - }, + showLinkModal(toolbarEvent) { + let linkText = ""; + this._lastSel = toolbarEvent.selected; - hideBox() { - this.set("showHyperlinkBox", false); + if (this._lastSel) { + linkText = this._lastSel.value; + } + + showModal("insert-hyperlink").setProperties({ + linkText, + toolbarEvent, + }); }, showUploadModal() { diff --git a/assets/javascripts/discourse/components/custom-wizard-composer-hyperlink.js.es6 b/assets/javascripts/discourse/components/custom-wizard-composer-hyperlink.js.es6 deleted file mode 100644 index a56b7aff..00000000 --- a/assets/javascripts/discourse/components/custom-wizard-composer-hyperlink.js.es6 +++ /dev/null @@ -1,15 +0,0 @@ -import Component from "@ember/component"; - -export default Component.extend({ - classNames: ["wizard-composer-hyperlink"], - - actions: { - addLink() { - this.addLink(this.linkName, this.linkUrl); - }, - - hideBox() { - this.hideBox(); - }, - }, -}); diff --git a/assets/javascripts/discourse/components/custom-wizard-date-input.js.es6 b/assets/javascripts/discourse/components/custom-wizard-date-input.js.es6 index 9c8e4bff..2805c370 100644 --- a/assets/javascripts/discourse/components/custom-wizard-date-input.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-date-input.js.es6 @@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators"; export default DateInput.extend({ useNativePicker: false, + classNameBindings: ["fieldClass"], @discourseComputed() placeholder() { diff --git a/assets/javascripts/discourse/components/custom-wizard-date-time-input.js.es6 b/assets/javascripts/discourse/components/custom-wizard-date-time-input.js.es6 index 44b675b0..1fcb62f5 100644 --- a/assets/javascripts/discourse/components/custom-wizard-date-time-input.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-date-time-input.js.es6 @@ -2,6 +2,8 @@ import DateTimeInput from "discourse/components/date-time-input"; import discourseComputed from "discourse-common/utils/decorators"; export default DateTimeInput.extend({ + classNameBindings: ["fieldClass"], + @discourseComputed("timeFirst", "tabindex") timeTabindex(timeFirst, tabindex) { return timeFirst ? tabindex : tabindex + 1; diff --git a/assets/javascripts/discourse/components/custom-wizard-field-time.js.es6 b/assets/javascripts/discourse/components/custom-wizard-field-time.js.es6 index 82f9c68b..1406d63b 100644 --- a/assets/javascripts/discourse/components/custom-wizard-field-time.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-field-time.js.es6 @@ -2,6 +2,8 @@ import Component from "@ember/component"; import { observes } from "discourse-common/utils/decorators"; export default Component.extend({ + classNameBindings: ["fieldClass"], + @observes("time") setValue() { this.set("field.value", this.time.format(this.field.format)); diff --git a/assets/javascripts/discourse/components/custom-wizard-field-upload.js.es6 b/assets/javascripts/discourse/components/custom-wizard-field-upload.js.es6 index eb5d318b..990d7daa 100644 --- a/assets/javascripts/discourse/components/custom-wizard-field-upload.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-field-upload.js.es6 @@ -4,7 +4,7 @@ import { computed } from "@ember/object"; export default Component.extend(UppyUploadMixin, { classNames: ["wizard-field-upload"], - classNameBindings: ["isImage"], + classNameBindings: ["isImage", "fieldClass"], uploading: false, type: computed(function () { return `wizard_${this.field.id}`; diff --git a/assets/javascripts/discourse/components/custom-wizard-field-user-selector.js.es6 b/assets/javascripts/discourse/components/custom-wizard-field-user-selector.js.es6 index 87d5ddb0..64741c6b 100644 --- a/assets/javascripts/discourse/components/custom-wizard-field-user-selector.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-field-user-selector.js.es6 @@ -1,3 +1,5 @@ import Component from "@ember/component"; -export default Component.extend({}); +export default Component.extend({ + classNameBindings: ["fieldClass"], +}); diff --git a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 index b98db1ab..7c933771 100644 --- a/assets/javascripts/discourse/components/custom-wizard-step.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-step.js.es6 @@ -9,6 +9,7 @@ import CustomWizard, { updateCachedWizard, } from "discourse/plugins/discourse-custom-wizard/discourse/models/custom-wizard"; import { alias, not } from "@ember/object/computed"; +import discourseLater from "discourse-common/lib/later"; const alreadyWarned = {}; @@ -110,29 +111,22 @@ export default Component.extend({ }, autoFocus() { - schedule("afterRender", () => { - const $invalid = $( - ".wizard-field.invalid:nth-of-type(1) .wizard-focusable" - ); - - if ($invalid.length) { - return $invalid.focus(); - } - - $(".wizard-focusable:first").focus(); + discourseLater(() => { + schedule("afterRender", () => { + if ($(".invalid .wizard-focusable").length) { + this.animateInvalidFields(); + } + }); }); }, animateInvalidFields() { schedule("afterRender", () => { - let $element = $( - ".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit" - ); - - if ($element.length) { + let $invalid = $(".invalid .wizard-focusable"); + if ($invalid.length) { $([document.documentElement, document.body]).animate( { - scrollTop: $element.offset().top - 200, + scrollTop: $invalid.offset().top - 200, }, 400 ); diff --git a/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 index 5cc6b17c..3a1eac9c 100644 --- a/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 +++ b/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 @@ -7,7 +7,7 @@ export default Component.extend(Subscription, { @discourseComputed("subscribed") subscribedIcon(subscribed) { - return subscribed ? "check" : "dash"; + return subscribed ? "check" : "times"; }, @discourseComputed("subscribed") diff --git a/assets/javascripts/discourse/helpers/char-counter.js.es6 b/assets/javascripts/discourse/helpers/char-counter.js.es6 deleted file mode 100644 index a700a432..00000000 --- a/assets/javascripts/discourse/helpers/char-counter.js.es6 +++ /dev/null @@ -1,22 +0,0 @@ -import { registerUnbound } from "discourse-common/lib/helpers"; -import I18n from "I18n"; -import Handlebars from "handlebars"; - -export default registerUnbound("char-counter", function (body, maxLength) { - let bodyLength = body ? body.length : 0; - let finalString; - - if (maxLength) { - let isOverMax = bodyLength > maxLength ? "true" : "false"; - finalString = `
${bodyLength} / ${I18n.t( - "wizard.x_characters", - { count: parseInt(maxLength, 10) } - )}
`; - } else { - finalString = `
${I18n.t("wizard.x_characters", { - count: parseInt(bodyLength, 10), - })}
`; - } - - return new Handlebars.SafeString(finalString); -}); diff --git a/assets/javascripts/discourse/helpers/wizard-char-counter.js.es6 b/assets/javascripts/discourse/helpers/wizard-char-counter.js.es6 new file mode 100644 index 00000000..1e194314 --- /dev/null +++ b/assets/javascripts/discourse/helpers/wizard-char-counter.js.es6 @@ -0,0 +1,25 @@ +import { registerUnbound } from "discourse-common/lib/helpers"; +import I18n from "I18n"; +import Handlebars from "handlebars"; + +export default registerUnbound( + "wizard-char-counter", + function (body, maxLength) { + let bodyLength = body ? body.length : 0; + let finalString; + + if (maxLength) { + let isOverMax = bodyLength > maxLength ? "true" : "false"; + finalString = `
${bodyLength} / ${I18n.t( + "wizard.x_characters", + { count: parseInt(maxLength, 10) } + )}
`; + } else { + finalString = `
${I18n.t("wizard.x_characters", { + count: parseInt(bodyLength, 10), + })}
`; + } + + return new Handlebars.SafeString(finalString); + } +); diff --git a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 index c398eaf4..9037bec5 100644 --- a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 @@ -35,6 +35,7 @@ function inputTypesContent(options = {}) { const connectors = { pair: [ "equal", + "not_equal", "greater", "less", "greater_or_equal", diff --git a/assets/javascripts/discourse/mixins/undo-changes.js.es6 b/assets/javascripts/discourse/mixins/undo-changes.js.es6 index b2ab322d..e98cfb0e 100644 --- a/assets/javascripts/discourse/mixins/undo-changes.js.es6 +++ b/assets/javascripts/discourse/mixins/undo-changes.js.es6 @@ -4,6 +4,8 @@ import { get, set } from "@ember/object"; import Mixin from "@ember/object/mixin"; import { deepEqual } from "discourse-common/lib/object"; +const observedCache = []; + export default Mixin.create({ didInsertElement() { this._super(...arguments); @@ -32,7 +34,13 @@ export default Mixin.create({ }; listProperties(componentType, opts).forEach((property) => { - obj.removeObserver(property, this, this.toggleUndo); + if (observedCache.includes(property)) { + obj.removeObserver(property, this, this.toggleUndo); + let index = observedCache.indexOf(property); + if (index !== -1) { + observedCache.splice(index, 1); + } + } }); }, @@ -45,6 +53,9 @@ export default Mixin.create({ }; listProperties(componentType, opts).forEach((property) => { + if (observedCache.indexOf(property) === -1) { + observedCache.push(property); + } obj.addObserver(property, this, this.toggleUndo); }); }, diff --git a/assets/javascripts/discourse/models/custom-wizard-field.js.es6 b/assets/javascripts/discourse/models/custom-wizard-field.js.es6 index a03c7c9e..2afe79d9 100644 --- a/assets/javascripts/discourse/models/custom-wizard-field.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard-field.js.es6 @@ -72,7 +72,7 @@ export default EmberObject.extend(ValidState, { valid = true; } - this.setValid(valid); + this.setValid(Boolean(valid)); return valid; }, diff --git a/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 b/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 index dd7b8be8..a882340b 100644 --- a/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 +++ b/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 @@ -1,6 +1,8 @@ import I18n from "I18n"; import { getCachedWizard } from "../models/custom-wizard"; import Route from "@ember/routing/route"; +import { scrollTop } from "discourse/mixins/scroll-top"; +import { action } from "@ember/object"; export default Route.extend({ beforeModel() { @@ -48,4 +50,10 @@ export default Route.extend({ controller.setProperties(props); }, + + @action + didTransition() { + scrollTop(); + return true; + }, }); diff --git a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs index 303b3f6d..7fe0fd21 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs @@ -32,13 +32,19 @@
- {{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}} +
{{#if api.isNew}} - {{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}} + {{else}} {{api.name}} {{/if}} @@ -104,7 +110,9 @@
- {{input value=api.authUrl}} +
{{/if}} @@ -112,21 +120,27 @@
- {{input value=api.tokenUrl}} +
- {{input value=api.clientId}} +
- {{input value=api.clientSecret}} +
@@ -135,8 +149,14 @@
{{#each api.authParams as |param|}}
- {{input value=param.key placeholder=(i18n "admin.wizard.key")}} - {{input value=param.value placeholder=(i18n "admin.wizard.value")}} + + {{d-button action=(action "removeParam") actionParam=param icon="times"}}
{{/each}} @@ -149,14 +169,18 @@
- {{input value=api.username}} +
- {{input value=api.password}} +
{{/if}} @@ -235,11 +259,15 @@
- {{input value=endpoint.name - placeholder=(i18n "admin.wizard.api.endpoint.name")}} - {{input value=endpoint.url - placeholder=(i18n "admin.wizard.api.endpoint.url") - class="endpoint-url"}} + + {{d-button action=(action "removeEndpoint") actionParam=endpoint icon="times" diff --git a/assets/javascripts/discourse/templates/admin-wizards-manager.hbs b/assets/javascripts/discourse/templates/admin-wizards-manager.hbs index 4b91bd3d..38ef54d2 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-manager.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-manager.hbs @@ -11,11 +11,12 @@
{{/if}} - {{input + {{d-button id="upload-button" label="admin.wizard.manager.upload" @@ -65,16 +66,18 @@ {{/link-to}} - {{input - type="checkbox" + - {{input - type="checkbox" + {{/each}} diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs index a81ec6db..4b04878e 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs @@ -1,9 +1,10 @@ {{#if wizard}}
- {{input +
{{#if wizard.name}} @@ -23,11 +24,12 @@
- {{input +
@@ -58,7 +60,10 @@
- {{input type="checkbox" checked=wizard.save_submissions}} + {{i18n "admin.wizard.save_submissions_label"}}
@@ -68,7 +73,10 @@
- {{input type="checkbox" checked=wizard.multiple_submissions}} + {{i18n "admin.wizard.multiple_submissions_label"}}
@@ -78,7 +86,10 @@
- {{input type="checkbox" checked=wizard.after_signup}} + {{i18n "admin.wizard.after_signup_label"}}
@@ -88,7 +99,10 @@
- {{input type="checkbox" checked=wizard.prompt_completion}} + {{i18n "admin.wizard.prompt_completion_label"}}
@@ -98,7 +112,10 @@
- {{input type="checkbox" checked=wizard.after_time}} + {{i18n "admin.wizard.after_time_label"}} {{d-button action=(action "setNextSessionScheduled") @@ -114,7 +131,10 @@
- {{input type="checkbox" checked=wizard.required}} + {{i18n "admin.wizard.required_label"}}
@@ -124,7 +144,10 @@
- {{input type="checkbox" checked=wizard.restart_on_revisit}} + {{i18n "admin.wizard.restart_on_revisit_label"}}
diff --git a/assets/javascripts/discourse/templates/components/custom-field-input.hbs b/assets/javascripts/discourse/templates/components/custom-field-input.hbs index c0bdaaff..8c532cc9 100644 --- a/assets/javascripts/discourse/templates/components/custom-field-input.hbs +++ b/assets/javascripts/discourse/templates/components/custom-field-input.hbs @@ -20,9 +20,10 @@ )}} - {{input - value=field.name - placeholder=(i18n "admin.wizard.custom_field.name.select")}} + {{multi-select diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-composer-hyperlink.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-composer-hyperlink.hbs deleted file mode 100644 index f430fb59..00000000 --- a/assets/javascripts/discourse/templates/components/custom-wizard-composer-hyperlink.hbs +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-date-input.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-date-input.hbs index 3b776215..0f798714 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-date-input.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-date-input.hbs @@ -1,11 +1,11 @@ -{{input - type=inputType +
diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs index 5c1cc45b..6350594c 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs @@ -40,7 +40,12 @@ {{conditional-loading-spinner condition=loading}} - {{textarea tabindex=tabindex value=value class="d-editor-input" placeholder=placeholder}} +