diff --git a/.github/workflows/discourse-plugin.yml b/.github/workflows/discourse-plugin.yml new file mode 100644 index 00000000..13850e3e --- /dev/null +++ b/.github/workflows/discourse-plugin.yml @@ -0,0 +1,13 @@ +name: Discourse Plugin + +on: + push: + branches: + - main + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + ci: + uses: discourse/.github/.github/workflows/discourse-plugin.yml@v1 diff --git a/.github/workflows/plugin-linting.yml b/.github/workflows/plugin-linting.yml deleted file mode 100644 index acb85230..00000000 --- a/.github/workflows/plugin-linting.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Linting - -on: - push: - branches: - - main - - stable - pull_request: - -concurrency: - group: plugin-linting-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 16 - cache: yarn - - - name: Yarn install - run: yarn install - - - name: Set up ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - bundler-cache: true - - - name: ESLint - if: ${{ always() }} - run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern {test,assets}/javascripts - - - name: Prettier - if: ${{ always() }} - shell: bash - run: | - yarn prettier -v - if [ 0 -lt $(find assets -type f \( -name "*.scss" -or -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then - yarn prettier --list-different "assets/**/*.{scss,js,es6}" - fi - if [ 0 -lt $(find test -type f \( -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then - yarn prettier --list-different "test/**/*.{js,es6}" - fi - - - name: Rubocop - if: ${{ always() }} - run: bundle exec rubocop . diff --git a/.github/workflows/plugin-tests.yml b/.github/workflows/plugin-tests.yml deleted file mode 100644 index f58f1b64..00000000 --- a/.github/workflows/plugin-tests.yml +++ /dev/null @@ -1,136 +0,0 @@ -name: Plugin Tests - -on: - push: - branches: - - main - - stable - pull_request: - -concurrency: - group: tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.build_type }} - runs-on: ubuntu-latest - container: discourse/discourse_test:slim${{ startsWith(matrix.build_type, 'frontend') && '-browsers' || '' }} - timeout-minutes: 30 - - env: - DISCOURSE_HOSTNAME: www.example.com - RUBY_GLOBAL_METHOD_CACHE_SIZE: 131072 - RAILS_ENV: test - PGUSER: discourse - PGPASSWORD: discourse - - strategy: - fail-fast: false - - matrix: - build_type: ["backend", "frontend"] - - steps: - - uses: actions/checkout@v3 - with: - repository: discourse/discourse - fetch-depth: 1 - - - name: Install plugin - uses: actions/checkout@v3 - with: - path: plugins/${{ github.event.repository.name }} - fetch-depth: 1 - - - name: Setup Git - run: | - git config --global user.email "ci@ci.invalid" - git config --global user.name "Discourse CI" - - - name: Start redis - run: | - redis-server /etc/redis/redis.conf & - - - name: Start Postgres - run: | - chown -R postgres /var/run/postgresql - sudo -E -u postgres script/start_test_db.rb - sudo -u postgres psql -c "CREATE ROLE $PGUSER LOGIN SUPERUSER PASSWORD '$PGPASSWORD';" - - - name: Bundler cache - uses: actions/cache@v3 - with: - path: vendor/bundle - key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }} - restore-keys: | - ${{ runner.os }}-gem- - - - name: Setup gems - run: | - gem install bundler --conservative -v $(awk '/BUNDLED WITH/ { getline; gsub(/ /,""); print $0 }' Gemfile.lock) - bundle config --local path vendor/bundle - bundle config --local deployment true - bundle config --local without development - bundle install --jobs 4 - bundle clean - - - name: Lint English locale - if: matrix.build_type == 'backend' - run: bundle exec ruby script/i18n_lint.rb "plugins/${{ github.event.repository.name }}/locales/{client,server}.en.yml" - - - name: Get yarn cache directory - id: yarn-cache-dir - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: Yarn cache - uses: actions/cache@v3 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Yarn install - run: yarn install - - - name: Fetch app state cache - uses: actions/cache@v3 - id: app-cache - with: - path: tmp/app-cache - key: >- - ${{ hashFiles('.github/workflows/tests.yml') }}- - ${{ hashFiles('db/**/*', 'plugins/**/db/**/*') }}- - - - name: Restore database from cache - if: steps.app-cache.outputs.cache-hit == 'true' - run: psql -f tmp/app-cache/cache.sql postgres - - - name: Restore uploads from cache - if: steps.app-cache.outputs.cache-hit == 'true' - run: rm -rf public/uploads && cp -r tmp/app-cache/uploads public/uploads - - - name: Create and migrate database - if: steps.app-cache.outputs.cache-hit != 'true' - run: | - bin/rake db:create - bin/rake db:migrate - - - name: Dump database for cache - if: steps.app-cache.outputs.cache-hit != 'true' - run: mkdir -p tmp/app-cache && pg_dumpall > tmp/app-cache/cache.sql - - - name: Dump uploads for cache - if: steps.app-cache.outputs.cache-hit != 'true' - run: rm -rf tmp/app-cache/uploads && cp -r public/uploads tmp/app-cache/uploads - - - name: Plugin RSpec - if: matrix.build_type == 'backend' - run: bin/rake plugin:spec[${{ github.event.repository.name }}] - - - name: Plugin QUnit - if: matrix.build_type == 'frontend' - run: QUNIT_EMBER_CLI=1 bundle exec rake plugin:qunit['${{ github.event.repository.name }}','1200000'] - timeout-minutes: 10 diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 48cea364..66b401ac 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -1,4 +1,4 @@ -All code in this repository is Copyright 2018 by Angus McLeod. +All code in this repository is Copyright 2023 by Angus McLeod. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/README.md b/README.md index 0190f16e..0c454685 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,24 @@ The Custom Wizard Plugin lets you make forms for your Discourse forum. Better us +👋 Looking to report an issue? We're managing issues for this plugin using our [bug report wizard](https://coop.pavilion.tech/w/bug-report). + ## Install If you're not sure how to install a plugin in Discourse, please follow the [plugin installation guide](https://meta.discourse.org/t/install-a-plugin/19157) or contact your Discourse hosting provider. ## Documentation -[Read the full documentation here](https://discourse.pluginmanager.org/c/discourse-custom-wizard/documentation), or go directly to the relevant section +[Read the full documentation here](https://coop.pavilion.tech/c/82), or go directly to the relevant section -- [Wizard Administration](https://discourse.pluginmanager.org/t/wizard-administration) -- [Wizard Settings](https://discourse.pluginmanager.org/t/wizard-settings) -- [Step Settings](https://discourse.pluginmanager.org/t/step-settings) -- [Field Settings](https://discourse.pluginmanager.org/t/field-settings) -- [Conditional Settings](https://discourse.pluginmanager.org/t/conditional-settings) -- [Field Interpolation](https://discourse.pluginmanager.org/t/field-interpolation) -- [Wizard Examples and Templates](https://discourse.pluginmanager.org/t/wizard-examples-and-templates) +- [Wizard Administration](https://coop.pavilion.tech/t/1602) +- [Wizard Settings](https://coop.pavilion.tech/t/1614) +- [Step Settings](https://coop.pavilion.tech/t/1735) +- [Field Settings](https://coop.pavilion.tech/t/1580) +- [Conditional Settings](https://coop.pavilion.tech/t/1673) +- [Field Interpolation](https://coop.pavilion.tech/t/1557) +- [Handling Dates and Times](https://coop.pavilion.tech/t/1708) ## Support -- [Report a bug](https://discourse.pluginmanager.org/w/bug-report) +- [Report an issue](https://coop.pavilion.tech/w/bug-report) diff --git a/app/controllers/custom_wizard/admin/admin.rb b/app/controllers/custom_wizard/admin/admin.rb index 867be56c..aa8862b6 100644 --- a/app/controllers/custom_wizard/admin/admin.rb +++ b/app/controllers/custom_wizard/admin/admin.rb @@ -8,7 +8,7 @@ class CustomWizard::AdminController < ::Admin::AdminController subscribed: subcription.subscribed?, subscription_type: subcription.type, subscription_attributes: CustomWizard::Subscription.attributes, - subscription_client_installed: subcription.client_installed? + subscription_client_installed: CustomWizard::Subscription.client_installed? ) end diff --git a/app/controllers/custom_wizard/steps.rb b/app/controllers/custom_wizard/steps.rb index df3c2cb3..2a4305c7 100644 --- a/app/controllers/custom_wizard/steps.rb +++ b/app/controllers/custom_wizard/steps.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -class CustomWizard::StepsController < ::ApplicationController - before_action :ensure_logged_in +class CustomWizard::StepsController < ::CustomWizard::WizardClientController before_action :ensure_can_update def update @@ -22,7 +21,7 @@ class CustomWizard::StepsController < ::ApplicationController if updater.success? wizard_id = update_params[:wizard_id] - builder = CustomWizard::Builder.new(wizard_id, current_user) + builder = CustomWizard::Builder.new(wizard_id, current_user, guest_id) @wizard = builder.build(force: true) current_step = @wizard.find_step(update[:step_id]) @@ -85,7 +84,6 @@ class CustomWizard::StepsController < ::ApplicationController private def ensure_can_update - @builder = CustomWizard::Builder.new(update_params[:wizard_id], current_user) raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil? raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access? diff --git a/app/controllers/custom_wizard/wizard.rb b/app/controllers/custom_wizard/wizard.rb index 7aafdd3b..dd4ea4ca 100644 --- a/app/controllers/custom_wizard/wizard.rb +++ b/app/controllers/custom_wizard/wizard.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true -class CustomWizard::WizardController < ::ApplicationController - before_action :ensure_plugin_enabled - before_action :ensure_logged_in, only: [:skip] - +class CustomWizard::WizardController < ::CustomWizard::WizardClientController def show if wizard.present? render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200 @@ -35,19 +32,8 @@ class CustomWizard::WizardController < ::ApplicationController def wizard @wizard ||= begin - builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user) - return nil unless builder.present? - opts = {} - opts[:reset] = params[:reset] - builder.build(opts, params) - end - end - - private - - def ensure_plugin_enabled - unless SiteSetting.custom_wizard_enabled - redirect_to path("/") + return nil unless @builder.present? + @builder.build({ reset: params[:reset] }, params) end end end diff --git a/app/controllers/custom_wizard/wizard_client.rb b/app/controllers/custom_wizard/wizard_client.rb new file mode 100644 index 00000000..e898852a --- /dev/null +++ b/app/controllers/custom_wizard/wizard_client.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +class CustomWizard::WizardClientController < ::ApplicationController + before_action :ensure_plugin_enabled + before_action :set_builder + + private + + def ensure_plugin_enabled + unless SiteSetting.custom_wizard_enabled + redirect_to path("/") + end + end + + def guest_id + return nil if current_user.present? + cookies[:custom_wizard_guest_id] ||= CustomWizard::Wizard.generate_guest_id + cookies[:custom_wizard_guest_id] + end + + def set_builder + @builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user, guest_id) + end +end diff --git a/app/serializers/custom_wizard/submission_serializer.rb b/app/serializers/custom_wizard/submission_serializer.rb index 732d6743..ed9ad411 100644 --- a/app/serializers/custom_wizard/submission_serializer.rb +++ b/app/serializers/custom_wizard/submission_serializer.rb @@ -2,12 +2,15 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer attributes :id, :fields, - :submitted_at - - has_one :user, serializer: ::BasicUserSerializer, embed: :objects + :submitted_at, + :user def include_user? - object.user.present? + object.wizard.user.present? + end + + def user + ::BasicUserSerializer.new(object.wizard.user, root: false).as_json end def fields diff --git a/assets/javascripts/discourse/components/custom-user-selector.js.es6 b/assets/javascripts/discourse/components/custom-user-selector.js.es6 index 3bb1fb3d..59711ec2 100644 --- a/assets/javascripts/discourse/components/custom-user-selector.js.es6 +++ b/assets/javascripts/discourse/components/custom-user-selector.js.es6 @@ -7,7 +7,7 @@ import userSearch from "discourse/lib/user-search"; import I18n from "I18n"; import Handlebars from "handlebars"; import { isEmpty } from "@ember/utils"; -import TextField from "@ember/component/text-field"; +import TextField from "discourse/components/text-field"; const template = function (params) { const options = params.options; 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..5560a126 100644 --- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 @@ -12,14 +12,15 @@ 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; +const IMAGE_MARKDOWN_REGEX = + /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g; export default ComposerEditor.extend({ classNameBindings: ["fieldClass"], allowUpload: true, showLink: false, - showHyperlinkBox: false, topic: null, showToolbar: true, focusTarget: "reply", @@ -29,6 +30,7 @@ export default ComposerEditor.extend({ draftStatus: "null", replyPlaceholder: alias("field.translatedPlaceholder"), wizardEventFieldId: null, + composerEventPrefix: "wizard-editor", @on("didInsertElement") _composerEditorInit() { @@ -77,24 +79,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 +107,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")) { @@ -132,9 +117,8 @@ export default ComposerEditor.extend({ event.target.closest(".button-wrapper").dataset.imageIndex, 10 ); - const matchingPlaceholder = this.get("composer.reply").match( - IMAGE_MARKDOWN_REGEX - ); + const matchingPlaceholder = + this.get("composer.reply").match(IMAGE_MARKDOWN_REGEX); this.session.set("wizardEventFieldId", this.field.id); this.appEvents.trigger( @@ -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/custom-wizard-tag-chooser.js.es6 b/assets/javascripts/discourse/components/custom-wizard-tag-chooser.js.es6 index 32a1fd6a..8d439aa4 100644 --- a/assets/javascripts/discourse/components/custom-wizard-tag-chooser.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-tag-chooser.js.es6 @@ -4,7 +4,10 @@ export default TagChooser.extend({ searchTags(url, data, callback) { if (this.tagGroups) { let tagGroupsString = this.tagGroups.join(","); - data.tag_groups = tagGroupsString; + data.filterForInput = { + name: "custom-wizard-tag-chooser", + groups: tagGroupsString, + }; } return this._super(url, data, callback); diff --git a/assets/javascripts/discourse/components/custom-wizard-text-field.js.es6 b/assets/javascripts/discourse/components/custom-wizard-text-field.js.es6 index e8c22e93..d2832282 100644 --- a/assets/javascripts/discourse/components/custom-wizard-text-field.js.es6 +++ b/assets/javascripts/discourse/components/custom-wizard-text-field.js.es6 @@ -1,7 +1,7 @@ import computed from "discourse-common/utils/decorators"; import { isLTR, isRTL, siteDir } from "discourse/lib/text-direction"; import I18n from "I18n"; -import TextField from "@ember/component/text-field"; +import TextField from "discourse/components/text-field"; export default TextField.extend({ attributeBindings: [ diff --git a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 index a257ed12..e19e4917 100644 --- a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 @@ -15,6 +15,7 @@ import { import Component from "@ember/component"; import { bind, later } from "@ember/runloop"; import I18n from "I18n"; +import Subscription from "../mixins/subscription"; const customFieldActionMap = { topic: ["create_topic", "send_message"], @@ -26,7 +27,7 @@ const customFieldActionMap = { const values = ["present", "true", "false"]; -export default Component.extend({ +export default Component.extend(Subscription, { classNameBindings: [":mapper-selector", "activeType"], showText: computed("activeType", function () { @@ -116,6 +117,9 @@ export default Component.extend({ groupEnabled: computed("options.groupSelection", "inputType", function () { return this.optionEnabled("groupSelection"); }), + guestGroup: computed("options.guestGroup", "inputType", function () { + return this.optionEnabled("guestGroup"); + }), userEnabled: computed("options.userSelection", "inputType", function () { return this.optionEnabled("userSelection"); }), @@ -126,7 +130,29 @@ export default Component.extend({ return this.connector === "is"; }), - groups: alias("site.groups"), + @discourseComputed("site.groups", "guestGroup", "subscriptionType") + groups(groups, guestGroup, subscriptionType) { + let result = groups; + if (!guestGroup) { + return result; + } + + if (["standard", "business"].includes(subscriptionType)) { + let guestIndex; + result.forEach((r, index) => { + if (r.id === 0) { + r.name = I18n.t("admin.wizard.selector.label.users"); + guestIndex = index; + } + }); + result.splice(guestIndex, 0, { + id: -1, + name: I18n.t("admin.wizard.selector.label.guests"), + }); + } + + return result; + }, categories: alias("site.categories"), showComboBox: or( "showWizardField", diff --git a/assets/javascripts/discourse/components/wizard-mapper.js.es6 b/assets/javascripts/discourse/components/wizard-mapper.js.es6 index 95aabb1c..ec58e3f2 100644 --- a/assets/javascripts/discourse/components/wizard-mapper.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper.js.es6 @@ -32,6 +32,7 @@ export default Component.extend({ pairConnector: options.pairConnector || null, outputConnector: options.outputConnector || null, context: options.context || null, + guestGroup: options.guestGroup || false, }; let inputTypes = ["key", "value", "output"]; 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/components/wizard-subscription-selector.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 index 53f7d19c..351b5782 100644 --- a/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 @@ -1,6 +1,6 @@ import SingleSelectComponent from "select-kit/components/single-select"; import Subscription from "../mixins/subscription"; -import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema"; +import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema"; import discourseComputed from "discourse-common/utils/decorators"; import I18n from "I18n"; @@ -40,9 +40,9 @@ export default SingleSelectComponent.extend(Subscription, { return allowedTypes; }, - @discourseComputed("feature", "attribute") + @discourseComputed("feature", "attribute", "wizard.allowGuests") content(feature, attribute) { - return wizardSchema[feature][attribute] + return filterValues(this.wizard, feature, attribute) .map((value) => { let allowedSubscriptionTypes = this.allowedSubscriptionTypes( feature, diff --git a/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs b/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs index f893d4ac..0aef2dcb 100644 --- a/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs +++ b/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs @@ -4,4 +4,4 @@ {{#if wizardErrorNotice}} {{d-icon "exclaimation-circle"}} {{/if}} -{{/if}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/connectors/category-custom-settings/custom-wizard-category-settings.hbs b/assets/javascripts/discourse/connectors/category-custom-settings/custom-wizard-category-settings.hbs index 5ce96f2f..2c6a6975 100644 --- a/assets/javascripts/discourse/connectors/category-custom-settings/custom-wizard-category-settings.hbs +++ b/assets/javascripts/discourse/connectors/category-custom-settings/custom-wizard-category-settings.hbs @@ -9,8 +9,7 @@ value=wizardListVal content=wizardList onChange=(action "changeWizard") - options=(hash - none="admin.wizard.select" - )}} + options=(hash none="admin.wizard.select") + }} - + \ No newline at end of file diff --git a/assets/javascripts/discourse/connectors/top-notices/prompt-completion.hbs b/assets/javascripts/discourse/connectors/top-notices/prompt-completion.hbs index 70c0b7c4..10057345 100644 --- a/assets/javascripts/discourse/connectors/top-notices/prompt-completion.hbs +++ b/assets/javascripts/discourse/connectors/top-notices/prompt-completion.hbs @@ -1,7 +1,10 @@ {{#each site.complete_custom_wizard as |wizard|}}
- {{i18n "wizard.complete_custom" name=wizard.name}} + {{i18n + "wizard.complete_custom" + name=wizard.name + }}
-{{/each}} +{{/each}} \ No newline at end of file diff --git a/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 index b89cc447..c08e820c 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 @@ -4,6 +4,7 @@ import CustomWizardApi from "../models/custom-wizard-api"; import { default as discourseComputed } from "discourse-common/utils/decorators"; import { and, equal, not } from "@ember/object/computed"; import { selectKitContent } from "../lib/wizard"; +import { underscore } from "@ember/string"; import Controller from "@ember/controller"; import I18n from "I18n"; @@ -20,29 +21,8 @@ export default Controller.extend({ "application/x-www-form-urlencoded", ]), successCodes: selectKitContent([ - 100, - 101, - 102, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 226, - 300, - 301, - 302, - 303, - 303, - 304, - 305, - 306, - 307, - 308, + 100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, + 302, 303, 303, 304, 305, 306, 307, 308, ]), @discourseComputed( @@ -118,7 +98,7 @@ export default Controller.extend({ if (authType === "oauth_2") { this.set("authorizing", true); - ajax(`/admin/wizards/apis/${name.underscore()}/authorize`) + ajax(`/admin/wizards/apis/${underscore(name)}/authorize`) .catch(popupAjaxError) .then((result) => { if (result.success) { @@ -187,11 +167,11 @@ export default Controller.extend({ if (!api[rp]) { let key = rp.replace("auth", ""); error = `${I18n.t( - `admin.wizard.api.auth.${key.underscore()}` + `admin.wizard.api.auth.${underscore(key)}` )} is required for ${authType}`; break; } - data[rp.underscore()] = api[rp]; + data[underscore(rp)] = api[rp]; } } @@ -221,7 +201,7 @@ export default Controller.extend({ this.set("updating", true); - ajax(`/admin/wizards/api/${name.underscore()}`, { + ajax(`/admin/wizards/api/${underscore(name)}`, { type: "PUT", data, }) @@ -244,7 +224,7 @@ export default Controller.extend({ this.set("updating", true); - ajax(`/admin/wizards/api/${name.underscore()}`, { + ajax(`/admin/wizards/api/${underscore(name)}`, { type: "DELETE", }) .catch(popupAjaxError) @@ -262,7 +242,7 @@ export default Controller.extend({ return; } - ajax(`/admin/wizards/api/${name.underscore()}/logs`, { + ajax(`/admin/wizards/api/${underscore(name)}/logs`, { type: "DELETE", }) .catch(popupAjaxError) diff --git a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 index c9a80e0e..75ea0ff7 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 @@ -10,6 +10,7 @@ import { later, scheduleOnce } from "@ember/runloop"; import Controller from "@ember/controller"; import copyText from "discourse/lib/copy-text"; import I18n from "I18n"; +import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema"; export default Controller.extend({ hasName: notEmpty("wizard.name"), @@ -59,6 +60,19 @@ export default Controller.extend({ } return wizardFieldList(steps); }, + + @discourseComputed("fieldTypes", "wizard.allowGuests") + filteredFieldTypes(fieldTypes) { + const fieldTypeIds = fieldTypes.map((f) => f.id); + const allowedTypeIds = filterValues( + this.wizard, + "field", + "type", + fieldTypeIds + ); + return fieldTypes.filter((f) => allowedTypeIds.includes(f.id)); + }, + getErrorMessage(result) { if (result.backend_validation_error) { return result.backend_validation_error; diff --git a/assets/javascripts/discourse/controllers/next-session-scheduled.js.es6 b/assets/javascripts/discourse/controllers/next-session-scheduled.js.es6 index 4ea22d38..b8f51d1f 100644 --- a/assets/javascripts/discourse/controllers/next-session-scheduled.js.es6 +++ b/assets/javascripts/discourse/controllers/next-session-scheduled.js.es6 @@ -5,7 +5,10 @@ export default Controller.extend({ title: "admin.wizard.after_time_modal.title", setup() { - this.set("bufferedDateTime", moment(this.model.dateTime)); + this.set( + "bufferedDateTime", + this.model.dateTime ? moment(this.model.dateTime) : moment(Date.now()) + ); }, @discourseComputed("bufferedDateTime") 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/initializers/custom-wizard-edits.js.es6 b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 index 7eed8faf..c974fafb 100644 --- a/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 +++ b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 @@ -69,7 +69,10 @@ export default { }, _wizardInsertText(text, options) { - if (this.session.wizardEventFieldId === this.fieldId && this.element) { + if ( + this.session.wizardEventFieldId === this.fieldId && + this.element + ) { this.insertText(text, options); } }, diff --git a/assets/javascripts/discourse/initializers/custom-wizard-redirect.js.es6 b/assets/javascripts/discourse/initializers/custom-wizard-redirect.js.es6 index 5667bdf8..70676bb0 100644 --- a/assets/javascripts/discourse/initializers/custom-wizard-redirect.js.es6 +++ b/assets/javascripts/discourse/initializers/custom-wizard-redirect.js.es6 @@ -1,14 +1,16 @@ -import ApplicationRoute from "discourse/routes/application"; +import DiscourseURL from "discourse/lib/url"; +import { withPluginApi } from "discourse/lib/plugin-api"; +import { dasherize } from "@ember/string"; export default { name: "custom-wizard-redirect", after: "message-bus", - initialize: function (container) { + initialize(container) { const messageBus = container.lookup("service:message-bus"); const siteSettings = container.lookup("service:site-settings"); - if (!siteSettings.custom_wizard_enabled || !messageBus) { + if (!siteSettings.custom_wizard_enabled) { return; } @@ -17,28 +19,26 @@ export default { window.location.href = wizardUrl; }); - ApplicationRoute.reopen({ - actions: { - willTransition(transition) { - const redirectToWizard = this.get("currentUser.redirect_to_wizard"); - const excludedPaths = this.siteSettings.wizard_redirect_exclude_paths + withPluginApi("0.8.36", (api) => { + api.onAppEvent("page:changed", (data) => { + const currentUser = api.getCurrentUser(); + + if (currentUser) { + const redirectToWizard = currentUser.redirect_to_wizard; + const excludedPaths = siteSettings.wizard_redirect_exclude_paths .split("|") .concat(["loading"]); - if ( redirectToWizard && - (!transition.intent.name || - !excludedPaths.find((p) => { - return transition.intent.name.indexOf(p) > -1; - })) + data.currentRouteName !== "customWizardStep" && + !excludedPaths.find((p) => { + return data.currentRouteName.indexOf(p) > -1; + }) ) { - transition.abort(); - window.location = "/w/" + redirectToWizard.dasherize(); + DiscourseURL.routeTo(`/w/${dasherize(redirectToWizard)}`); } - - return this._super(transition); - }, - }, + } + }); }); }, }; 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/lib/wizard-schema.js.es6 b/assets/javascripts/discourse/lib/wizard-schema.js.es6 index 8c3323ff..47257d82 100644 --- a/assets/javascripts/discourse/lib/wizard-schema.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-schema.js.es6 @@ -72,6 +72,7 @@ const field = { required: null, type: null, condition: null, + tag_groups: null, }, types: {}, mapped: ["prefill", "content", "condition", "index"], @@ -210,11 +211,42 @@ const action = { objectArrays: {}, }; +const filters = { + allow_guests: { + field: { + type: [ + "text", + "textarea", + "text_only", + "date", + "time", + "date_time", + "number", + "checkbox", + "url", + "dropdown", + "tag", + "category", + "group", + "user_selector", + ], + }, + action: { + type: ["route_to", "send_message"], + }, + }, +}; + const custom_field = { klass: ["topic", "post", "group", "category"], type: ["string", "boolean", "integer", "json"], }; +export function buildFieldTypes(types) { + wizardSchema.field.types = types; + wizardSchema.field.type = Object.keys(types); +} + field.type = Object.keys(field.types); action.type = Object.keys(action.types); @@ -224,16 +256,29 @@ const wizardSchema = { field, custom_field, action, + filters, }; -export function buildFieldTypes(types) { - wizardSchema.field.types = types; -} - export function buildFieldValidations(validations) { wizardSchema.field.validations = validations; } +export function filterValues(currentWizard, feature, attribute, values = null) { + values = values || wizardSchema[feature][attribute]; + + if (currentWizard && currentWizard.allowGuests) { + const filteredFeature = wizardSchema.filters.allow_guests[feature]; + if (filteredFeature) { + const filtered = filteredFeature[attribute]; + if (filtered) { + values = values.filter((v) => filtered.includes(v)); + } + } + } + + return values; +} + const siteSettings = getOwner(this).lookup("service:site-settings"); if (siteSettings.wizard_apis_enabled) { wizardSchema.action.types.send_to_api = { 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-admin.js.es6 b/assets/javascripts/discourse/models/custom-wizard-admin.js.es6 index 65c7aa7f..afca4833 100644 --- a/assets/javascripts/discourse/models/custom-wizard-admin.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard-admin.js.es6 @@ -5,8 +5,20 @@ import wizardSchema from "../lib/wizard-schema"; import { Promise } from "rsvp"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; +import discourseComputed from "discourse-common/utils/decorators"; + +const GUEST_GROUP_ID = -1; const CustomWizardAdmin = EmberObject.extend({ + @discourseComputed("permitted.@each.output") + allowGuests(permitted) { + return ( + permitted && + permitted.filter((p) => p.output && p.output.includes(GUEST_GROUP_ID)) + .length + ); + }, + save(opts) { return new Promise((resolve, reject) => { let wizard = this.buildJson(this, "wizard"); 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/admin-wizards-api-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6 index 6c0ed7a8..bfe90f72 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6 @@ -10,6 +10,12 @@ export default DiscourseRoute.extend({ } }, + afterModel(model) { + if (model === null) { + return this.transitionTo("adminWizardsApi"); + } + }, + setupController(controller, model) { controller.set("api", model); }, diff --git a/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 index 474360ec..e1f53c8f 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 @@ -7,6 +7,12 @@ export default DiscourseRoute.extend({ return CustomWizardLogs.list(params.wizardId); }, + afterModel(model) { + if (model === null) { + return this.transitionTo("adminWizardsLogs"); + } + }, + setupController(controller, model) { controller.setProperties({ wizard: model.wizard, diff --git a/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 index b616b5be..b9dbd90f 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 @@ -8,6 +8,12 @@ export default DiscourseRoute.extend({ return CustomWizardAdmin.submissions(params.wizardId); }, + afterModel(model) { + if (model === null) { + return this.transitionTo("adminWizardsSubmissions"); + } + }, + setupController(controller, model) { const { fields, submissions } = formatModel(model); diff --git a/assets/javascripts/discourse/routes/custom-wizard-index.js.es6 b/assets/javascripts/discourse/routes/custom-wizard-index.js.es6 index 1d5a71c7..5ffe83c6 100644 --- a/assets/javascripts/discourse/routes/custom-wizard-index.js.es6 +++ b/assets/javascripts/discourse/routes/custom-wizard-index.js.es6 @@ -4,13 +4,7 @@ import Route from "@ember/routing/route"; export default Route.extend({ beforeModel() { const wizard = getCachedWizard(); - if ( - wizard && - wizard.user && - wizard.permitted && - !wizard.completed && - wizard.start - ) { + if (wizard && wizard.permitted && !wizard.completed && wizard.start) { this.replaceWith("customWizardStep", wizard.start); } }, @@ -26,7 +20,7 @@ export default Route.extend({ const wizardId = model.get("id"); const user = model.get("user"); const name = model.get("name"); - const requiresLogin = !user; + const requiresLogin = !user && !permitted; const notPermitted = !permitted; const props = { diff --git a/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 b/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 index 969df1eb..a882340b 100644 --- a/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 +++ b/assets/javascripts/discourse/routes/custom-wizard-step.js.es6 @@ -1,13 +1,15 @@ 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() { const wizard = getCachedWizard(); this.set("wizard", wizard); - if (!wizard || !wizard.user || !wizard.permitted || wizard.completed) { + if (!wizard || !wizard.permitted || wizard.completed) { this.replaceWith("customWizard"); } }, @@ -48,4 +50,10 @@ export default Route.extend({ controller.setProperties(props); }, + + @action + didTransition() { + scrollTop(); + return true; + }, }); diff --git a/assets/javascripts/discourse/routes/custom-wizard.js.es6 b/assets/javascripts/discourse/routes/custom-wizard.js.es6 index d03714a2..1a214a2d 100644 --- a/assets/javascripts/discourse/routes/custom-wizard.js.es6 +++ b/assets/javascripts/discourse/routes/custom-wizard.js.es6 @@ -1,6 +1,7 @@ import { findCustomWizard, updateCachedWizard } from "../models/custom-wizard"; import I18n from "I18n"; import DiscourseRoute from "discourse/routes/discourse"; +import bootbox from "bootbox"; export default DiscourseRoute.extend({ titleToken() { diff --git a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs index 303b3f6d..5270aa28 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs @@ -8,7 +8,12 @@ {{/if}} {{/if}} - {{d-button label="admin.wizard.api.save" action=(action "save") class="btn-primary" disabled=saveDisabled}} + {{d-button + label="admin.wizard.api.save" + action=(action "save") + class="btn-primary" + disabled=saveDisabled + }} {{#if showRemove}} {{d-button action=(action "remove") label="admin.wizard.api.remove"}} @@ -32,13 +37,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}} @@ -56,10 +67,12 @@ {{authErrorMessage}} {{/if}} {{/if}} - {{d-button label="admin.wizard.api.auth.btn" - action=(action "authorize") - disabled=authDisabled - class="btn-primary"}} + {{d-button + label="admin.wizard.api.auth.btn" + action=(action "authorize") + disabled=authDisabled + class="btn-primary" + }} {{/if}}
@@ -93,9 +106,8 @@ value=api.authType content=authorizationTypes onChange=(action (mut api.authType)) - options=(hash - none="admin.wizard.api.auth.type_none" - )}} + options=(hash none="admin.wizard.api.auth.type_none") + }}
@@ -104,7 +116,7 @@
- {{input value=api.authUrl}} +
{{/if}} @@ -112,21 +124,21 @@
- {{input value=api.tokenUrl}} +
- {{input value=api.clientId}} +
- {{input value=api.clientSecret}} +
@@ -135,12 +147,26 @@
{{#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"}} + + + {{d-button + action=(action "removeParam") + actionParam=param + icon="times" + }}
{{/each}} - {{d-button label="admin.wizard.api.auth.params.new" icon="plus" action=(action "addParam")}} + {{d-button + label="admin.wizard.api.auth.params.new" + icon="plus" + action=(action "addParam") + }}
{{/if}} @@ -149,14 +175,14 @@
- {{input value=api.username}} +
- {{input value=api.password}} +
{{/if}} @@ -225,7 +251,11 @@
- {{d-button action=(action "addEndpoint") label="admin.wizard.api.endpoint.add" icon="plus"}} + {{d-button + action=(action "addEndpoint") + label="admin.wizard.api.endpoint.add" + icon="plus" + }} {{#if api.endpoints}}
@@ -235,38 +265,43 @@
- {{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" - class="remove-endpoint"}} + + + {{d-button + action=(action "removeEndpoint") + actionParam=endpoint + icon="times" + class="remove-endpoint" + }}
{{combo-box content=endpointMethods value=endpoint.method onChange=(action (mut endpoint.method)) - options=(hash - none="admin.wizard.api.endpoint.method" - )}} + options=(hash none="admin.wizard.api.endpoint.method") + }} {{combo-box content=contentTypes value=endpoint.content_type onChange=(action (mut endpoint.content_type)) - options=(hash - none="admin.wizard.api.endpoint.content_type" - )}} + options=(hash none="admin.wizard.api.endpoint.content_type") + }} {{multi-select value=endpoint.success_codes content=successCodes onChange=(action (mut endpoint.success_codes)) options=(hash none="admin.wizard.api.endpoint.success_codes" - )}} + ) + }}
@@ -284,7 +319,8 @@ {{d-button action=(action "clearLogs") class="clear-logs" - label="admin.wizard.api.log.clear"}} + label="admin.wizard.api.log.clear" + }}
@@ -304,7 +340,10 @@ {{logentry.time}}
- {{avatar logentry imageSize="medium"}} + {{avatar logentry imageSize="medium"}}
{{logentry.status}} @@ -315,4 +354,4 @@ - + \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-api.hbs b/assets/javascripts/discourse/templates/admin-wizards-api.hbs index af91d0fb..6a6c5832 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api.hbs @@ -3,16 +3,16 @@ value=apiName content=apiList onChange=(route-action "changeApi") - options=(hash - none="admin.wizard.api.select" - )}} + options=(hash none="admin.wizard.api.select") + }} {{d-button action=(route-action "createApi") label="admin.wizard.api.create" - icon="plus"}} + icon="plus" + }}
{{outlet}} -
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs index a90f6299..4dda0ac8 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs @@ -5,7 +5,8 @@ {{d-button label="admin.wizard.custom_field.add" icon="plus" - action=(action "addField")}} + action=(action "addField") + }} @@ -14,7 +15,8 @@ opts=messageOpts type=messageType url=documentationUrl - component="custom_fields"}} + component="custom_fields" +}}
{{#if customFields}} @@ -32,9 +34,10 @@ {{custom-field-input field=field removeField=(action "removeField") - saveField=(action "saveField")}} + saveField=(action "saveField") + }} {{/each}} {{/if}} -
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs index 270d5c21..deb7ed8b 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs @@ -9,7 +9,8 @@ label="refresh" icon="sync" action=(action "refresh") - class="refresh"}} + class="refresh" + }} @@ -31,7 +32,10 @@ {{#each logs as |log|}} {{#each-in log as |field value|}} - {{wizard-table-field field=field value=value}} + {{wizard-table-field + field=field + value=value + }} {{/each-in}} {{/each}} @@ -42,4 +46,4 @@ {{conditional-loading-spinner condition=refreshing}} {{/load-more}} -{{/if}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs index 45738a9f..703f4fa3 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs @@ -3,17 +3,17 @@ value=wizardId content=wizardList onChange=(route-action "changeWizard") - options=(hash - none="admin.wizard.select" - )}} + options=(hash none="admin.wizard.select") + }} {{wizard-message key=messageKey opts=messageOpts url=documentationUrl - component="logs"}} + component="logs" +}}
{{outlet}} -
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-manager.hbs b/assets/javascripts/discourse/templates/admin-wizards-manager.hbs index 4b91bd3d..f2de0783 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-manager.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-manager.hbs @@ -11,30 +11,35 @@ {{/if}} - {{input + {{d-button id="upload-button" label="admin.wizard.manager.upload" - action=(action "upload")}} + action=(action "upload") + }} {{d-button id="import-button" label="admin.wizard.manager.import" action=(action "import") - disabled=importDisabled}} + disabled=importDisabled + }} {{d-button id="export-button" label="admin.wizard.manager.export" action=(action "export") - disabled=exportDisabled}} + disabled=exportDisabled + }} {{d-button id="destroy-button" label="admin.wizard.manager.destroy" action=(action "destroy") - disabled=destoryDisabled}} + disabled=destoryDisabled + }} @@ -45,7 +50,8 @@ opts=messageOpts items=messageItems loading=loading - component="manager"}} + component="manager" +}}
@@ -65,19 +71,21 @@ {{/link-to}} {{/each}}
- {{input - type="checkbox" + - {{input - type="checkbox" +
-
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs index 72ec7c38..96a24a9d 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs @@ -58,4 +58,4 @@ {{conditional-loading-spinner condition=loadingMore}} {{/load-more}} -{{/if}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs index 07dd1682..1ccaa3b8 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs @@ -3,17 +3,17 @@ value=wizardId content=wizardList onChange=(route-action "changeWizard") - options=(hash - none="admin.wizard.select" - )}} + options=(hash none="admin.wizard.select") + }} {{wizard-message key=messageKey opts=messageOpts url=documentationUrl - component="submissions"}} + component="submissions" +}}
{{outlet}} -
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs index 11a2b415..053deb73 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs @@ -1,18 +1,31 @@ {{#if wizard}}
- {{input +
{{#if wizard.name}} {{#if copiedUrl}} - {{d-button class="btn-hover pull-right" icon="copy" label="ip_lookup.copied"}} + {{d-button + class="btn-hover pull-right" + icon="copy" + label="ip_lookup.copied" + }} {{else}} - {{d-button action=(action "copyUrl") class="pull-right no-text" icon="copy"}} + {{d-button + action=(action "copyUrl") + class="pull-right no-text" + icon="copy" + }} {{/if}} - {{wizardUrl}} + {{wizardUrl}} {{/if}}
@@ -23,11 +36,12 @@
- {{input +
@@ -41,9 +55,8 @@ valueProperty="id" value=wizard.theme_id onChange=(action (mut wizard.theme_id)) - options=(hash - none="admin.wizard.no_theme" - )}} + options=(hash none="admin.wizard.no_theme") + }} @@ -58,7 +71,7 @@
- {{input type="checkbox" checked=wizard.save_submissions}} + {{i18n "admin.wizard.save_submissions_label"}}
@@ -68,7 +81,7 @@
- {{input type="checkbox" checked=wizard.multiple_submissions}} + {{i18n "admin.wizard.multiple_submissions_label"}}
@@ -78,7 +91,7 @@
- {{input type="checkbox" checked=wizard.after_signup}} + {{i18n "admin.wizard.after_signup_label"}}
@@ -88,7 +101,7 @@
- {{input type="checkbox" checked=wizard.prompt_completion}} + {{i18n "admin.wizard.prompt_completion_label"}}
@@ -98,13 +111,14 @@
- {{input type="checkbox" checked=wizard.after_time}} + {{i18n "admin.wizard.after_time_label"}} {{d-button action=(action "setNextSessionScheduled") translatedLabel=nextSessionScheduledLabel class="btn-after-time" - icon="far-calendar"}} + icon="far-calendar" + }}
@@ -114,7 +128,7 @@
- {{input type="checkbox" checked=wizard.required}} + {{i18n "admin.wizard.required_label"}}
@@ -124,7 +138,7 @@
- {{input type="checkbox" checked=wizard.restart_on_revisit}} + {{i18n "admin.wizard.restart_on_revisit_label"}}
@@ -140,19 +154,18 @@ context="wizard" inputTypes="assignment,validation" groupSelection="output" + guestGroup=true userFieldSelection="key" textSelection="value" inputConnector="and" - )}} + ) + }} {{/wizard-subscription-container}} - {{wizard-links - itemType="step" - current=currentStep - items=wizard.steps}} + {{wizard-links itemType="step" current=currentStep items=wizard.steps}} {{#if currentStep}} {{wizard-custom-step @@ -160,15 +173,17 @@ wizard=wizard currentField=currentField wizardFields=wizardFields - fieldTypes=fieldTypes - subscribed=subscribed}} + fieldTypes=filteredFieldTypes + subscribed=subscribed + }} {{/if}} {{wizard-links itemType="action" current=currentAction items=wizard.actions - generateLabels=true}} + generateLabels=true + }} {{#each wizard.actions as |wizardAction|}} {{wizard-custom-action @@ -178,11 +193,17 @@ apis=apis removeAction="removeAction" wizardFields=wizardFields - fieldTypes=fieldTypes}} + fieldTypes=filteredFieldTypes + }} {{/each}}
- @@ -198,4 +219,4 @@ {{d-icon "times"}}{{error}} {{/if}}
-{{/if}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs index c96f8009..7a33dac1 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs @@ -3,21 +3,18 @@ value=wizardListVal content=wizardList onChange=(route-action "changeWizard") - options=(hash - none="admin.wizard.select" - )}} + options=(hash none="admin.wizard.select") + }} {{d-button action=(route-action "createWizard") label="admin.wizard.create" - icon="plus"}} + icon="plus" + }} -{{wizard-message - key=messageKey - url=messageUrl - component="wizard"}} +{{wizard-message key=messageKey url=messageUrl component="wizard"}}
{{outlet}} -
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards.hbs b/assets/javascripts/discourse/templates/admin-wizards.hbs index cea77942..452193b1 100644 --- a/assets/javascripts/discourse/templates/admin-wizards.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards.hbs @@ -1,12 +1,21 @@ {{#admin-nav}} {{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}} - {{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}} - {{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}} + {{nav-item + route="adminWizardsCustomFields" + label="admin.wizard.custom_field.nav_label" + }} + {{nav-item + route="adminWizardsSubmissions" + label="admin.wizard.submissions.nav_label" + }} {{#if showApi}} {{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}} {{/if}} {{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}} - {{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}} + {{nav-item + route="adminWizardsManager" + label="admin.wizard.manager.nav_label" + }}
{{wizard-subscription-badge}} @@ -16,4 +25,4 @@
{{outlet}} -
+
\ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/custom-field-input.hbs b/assets/javascripts/discourse/templates/components/custom-field-input.hbs index c0bdaaff..4e3fa2f0 100644 --- a/assets/javascripts/discourse/templates/components/custom-field-input.hbs +++ b/assets/javascripts/discourse/templates/components/custom-field-input.hbs @@ -5,9 +5,8 @@ feature="custom_field" attribute="klass" onChange=(action (mut field.klass)) - options=(hash - none="admin.wizard.custom_field.klass.select" - )}} + options=(hash none="admin.wizard.custom_field.klass.select") + }} {{wizard-subscription-selector @@ -15,23 +14,22 @@ feature="custom_field" attribute="type" onChange=(action (mut field.type)) - options=(hash - none="admin.wizard.custom_field.type.select" - )}} + options=(hash none="admin.wizard.custom_field.type.select") + }} - {{input - value=field.name - placeholder=(i18n "admin.wizard.custom_field.name.select")}} + {{multi-select value=field.serializers content=serializerContent onChange=(action (mut field.serializers)) - options=(hash - none="admin.wizard.custom_field.serializers.select" - )}} + options=(hash none="admin.wizard.custom_field.serializers.select") + }} {{#if loading}} @@ -45,16 +43,15 @@ action=(action "destroy") icon="trash-alt" class="destroy" - disabled=destroyDisabled}} + disabled=destroyDisabled + }} {{d-button icon="save" action=(action "save") disabled=saveDisabled - class="save"}} - {{d-button - action=(action "close") - icon="times" - disabled=closeDisabled}} + class="save" + }} + {{d-button action=(action "close") icon="times" disabled=closeDisabled}} {{else}} @@ -80,4 +77,4 @@ {{d-button action=(action "edit") icon="pencil-alt"}} {{/if}} -{{/if}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-composer-editor.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-composer-editor.hbs index baa6a17a..70286603 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-composer-editor.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-composer-editor.hbs @@ -14,7 +14,8 @@ wizardComposer=true fieldId=field.id disabled=disableTextarea - outletArgs=(hash composer=composer editorType="composer")}} + outletArgs=(hash composer=composer editorType="composer") +}} +/> \ No newline at end of file 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..3f1cc4c6 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 + -
+
\ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-date-time-input.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-date-time-input.hbs index 4fed9c95..051ce6f8 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-date-time-input.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-date-time-input.hbs @@ -26,9 +26,5 @@ {{/if}} {{#if clearable}} - {{d-button - class="clear-date-time" - icon="times" - action=(action "onClear") - }} -{{/if}} + {{d-button class="clear-date-time" icon="times" action=(action "onClear")}} +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs index 5c1cc45b..fd10299c 100644 --- a/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs +++ b/assets/javascripts/discourse/templates/components/custom-wizard-editor.hbs @@ -2,7 +2,7 @@
{{#if showPreview}} -
+
{{html-safe preview}}
@@ -18,13 +18,16 @@ onExpand=(action b.action b) class=b.className content=popupMenuOptions - options=(hash - popupTitle=b.title - icon=b.icon - )}} + options=(hash popupTitle=b.title icon=b.icon) + }} {{else}}
{{d.icon}}
-
{{conditional-loading-spinner condition=loading}} - {{textarea tabindex=tabindex value=value class="d-editor-input" placeholder=placeholder}} +