diff --git a/.github/workflows/plugin-tests.yml b/.github/workflows/plugin-tests.yml index 4b272042..f58f1b64 100644 --- a/.github/workflows/plugin-tests.yml +++ b/.github/workflows/plugin-tests.yml @@ -8,7 +8,7 @@ on: pull_request: concurrency: - group: plugin-tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }} + group: tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }} cancel-in-progress: true jobs: diff --git a/.rubocop.yml b/.rubocop.yml index d46296cf..69fcfc56 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,8 @@ inherit_gem: rubocop-discourse: default.yml + +RSpec/ContextWording: + Enabled: false + +RSpec/DescribeClass: + Enabled: false diff --git a/app/controllers/custom_wizard/admin/admin.rb b/app/controllers/custom_wizard/admin/admin.rb index c99954d6..867be56c 100644 --- a/app/controllers/custom_wizard/admin/admin.rb +++ b/app/controllers/custom_wizard/admin/admin.rb @@ -3,6 +3,13 @@ class CustomWizard::AdminController < ::Admin::AdminController before_action :ensure_admin def index + subcription = CustomWizard::Subscription.new + render_json_dump( + subscribed: subcription.subscribed?, + subscription_type: subcription.type, + subscription_attributes: CustomWizard::Subscription.attributes, + subscription_client_installed: subcription.client_installed? + ) end private diff --git a/app/controllers/custom_wizard/admin/custom_fields.rb b/app/controllers/custom_wizard/admin/custom_fields.rb index c52759c9..111e9faf 100644 --- a/app/controllers/custom_wizard/admin/custom_fields.rb +++ b/app/controllers/custom_wizard/admin/custom_fields.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController def index - render_json_dump(custom_field_list) + render_json_dump( + custom_fields: custom_field_list + ) end def update diff --git a/app/controllers/custom_wizard/admin/logs.rb b/app/controllers/custom_wizard/admin/logs.rb index 976814f8..7ca37bb2 100644 --- a/app/controllers/custom_wizard/admin/logs.rb +++ b/app/controllers/custom_wizard/admin/logs.rb @@ -1,9 +1,44 @@ # frozen_string_literal: true class CustomWizard::AdminLogsController < CustomWizard::AdminController + before_action :find_wizard, except: [:index] + def index - render_serialized( - CustomWizard::Log.list(params[:page].to_i, params[:limit].to_i), - CustomWizard::LogSerializer + render json: ActiveModel::ArraySerializer.new( + CustomWizard::Wizard.list(current_user), + each_serializer: CustomWizard::BasicWizardSerializer ) end + + def show + render_json_dump( + wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false), + logs: ActiveModel::ArraySerializer.new( + log_list.logs, + each_serializer: CustomWizard::LogSerializer + ), + total: log_list.total + ) + end + + protected + + def log_list + @log_list ||= begin + list = CustomWizard::Log.list(params[:page].to_i, params[:limit].to_i, params[:wizard_id]) + + if list.logs.any? && (usernames = list.logs.map(&:username)).present? + user_map = User.where(username: usernames) + .reduce({}) do |result, user| + result[user.username] = user + result + end + + list.logs.each do |log_item| + log_item.user = user_map[log_item.username] + end + end + + list + end + end end diff --git a/app/controllers/custom_wizard/admin/submissions.rb b/app/controllers/custom_wizard/admin/submissions.rb index 4cb2a0e4..c3bf809f 100644 --- a/app/controllers/custom_wizard/admin/submissions.rb +++ b/app/controllers/custom_wizard/admin/submissions.rb @@ -13,12 +13,16 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController def show render_json_dump( wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false), - submissions: ActiveModel::ArraySerializer.new(ordered_submissions, each_serializer: CustomWizard::SubmissionSerializer) + submissions: ActiveModel::ArraySerializer.new( + submission_list.submissions, + each_serializer: CustomWizard::SubmissionSerializer + ), + total: submission_list.total ) end def download - send_data ordered_submissions.to_json, + send_data submission_list.submissions.to_json, filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json", content_type: "application/json", disposition: "attachment" @@ -26,7 +30,7 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController protected - def ordered_submissions - CustomWizard::Submission.list(@wizard, order_by: 'id') + def submission_list + CustomWizard::Submission.list(@wizard, page: params[:page].to_i) end end diff --git a/app/jobs/refresh_api_access_token.rb b/app/jobs/regular/refresh_api_access_token.rb similarity index 100% rename from app/jobs/refresh_api_access_token.rb rename to app/jobs/regular/refresh_api_access_token.rb diff --git a/app/jobs/set_after_time_wizard.rb b/app/jobs/regular/set_after_time_wizard.rb similarity index 100% rename from app/jobs/set_after_time_wizard.rb rename to app/jobs/regular/set_after_time_wizard.rb diff --git a/app/serializers/custom_wizard/log_serializer.rb b/app/serializers/custom_wizard/log_serializer.rb index e521c573..56c5fd8f 100644 --- a/app/serializers/custom_wizard/log_serializer.rb +++ b/app/serializers/custom_wizard/log_serializer.rb @@ -1,4 +1,10 @@ # frozen_string_literal: true + class CustomWizard::LogSerializer < ApplicationSerializer - attributes :message, :date + attributes :date, + :action, + :username, + :message + + has_one :user, serializer: ::BasicUserSerializer, embed: :objects end diff --git a/app/serializers/custom_wizard/submission_serializer.rb b/app/serializers/custom_wizard/submission_serializer.rb index 52f0cb32..732d6743 100644 --- a/app/serializers/custom_wizard/submission_serializer.rb +++ b/app/serializers/custom_wizard/submission_serializer.rb @@ -1,16 +1,32 @@ # frozen_string_literal: true class CustomWizard::SubmissionSerializer < ApplicationSerializer attributes :id, - :username, :fields, - :submitted_at, - :route_to, - :redirect_on_complete, - :redirect_to + :submitted_at - def username - object.user.present? ? - object.user.username : - I18n.t('admin.wizard.submission.no_user', user_id: object.user_id) + has_one :user, serializer: ::BasicUserSerializer, embed: :objects + + def include_user? + object.user.present? + end + + def fields + @fields ||= begin + result = {} + + object.wizard.template['steps'].each do |step| + step['fields'].each do |field| + if value = object.fields[field['id']] + result[field['id']] = { + value: value, + type: field['type'], + label: field['label'] + } + end + end + end + + result + end end end diff --git a/app/serializers/custom_wizard/wizard_field_serializer.rb b/app/serializers/custom_wizard/wizard_field_serializer.rb index 70784f7f..d5f57060 100644 --- a/app/serializers/custom_wizard/wizard_field_serializer.rb +++ b/app/serializers/custom_wizard/wizard_field_serializer.rb @@ -42,13 +42,8 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer object.value end - def i18n_key - @i18n_key ||= "wizard.step.#{object.step.id}.fields.#{object.id}".underscore - end - def label - return object.label if object.label.present? - I18n.t("#{object.key || i18n_key}.label", default: '') + I18n.t("#{i18n_key}.label", default: object.label, base_url: Discourse.base_url) end def include_label? @@ -56,14 +51,21 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer end def description - return object.description if object.description.present? - I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url) + I18n.t("#{i18n_key}.description", default: object.description, base_url: Discourse.base_url) end def include_description? description.present? end + def placeholder + I18n.t("#{i18n_key}.placeholder", default: object.placeholder) + end + + def include_placeholder? + placeholder.present? + end + def image object.image end @@ -72,15 +74,6 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer object.image.present? end - def placeholder - return object.placeholder if object.placeholder.present? - I18n.t("#{object.key || i18n_key}.placeholder", default: '') - end - - def include_placeholder? - placeholder.present? - end - def file_types object.file_types end @@ -127,4 +120,14 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer def preview_template object.preview_template end + + protected + + def i18n_key + @i18n_key ||= "#{object.step.wizard.id}.#{object.step.id}.#{object.id}".underscore + end + + def subscribed? + @subscribed ||= CustomWizard::Subscription.subscribed? + end end diff --git a/app/serializers/custom_wizard/wizard_step_serializer.rb b/app/serializers/custom_wizard/wizard_step_serializer.rb index 85f527bb..a2a314a4 100644 --- a/app/serializers/custom_wizard/wizard_step_serializer.rb +++ b/app/serializers/custom_wizard/wizard_step_serializer.rb @@ -39,13 +39,8 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer object.previous.present? end - def i18n_key - @i18n_key ||= "wizard.step.#{object.id}".underscore - end - def title - return PrettyText.cook(object.title) if object.title - PrettyText.cook(I18n.t("#{object.key || i18n_key}.title", default: '')) + I18n.t("#{i18n_key}.title", default: object.title, base_url: Discourse.base_url) end def include_title? @@ -53,8 +48,7 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer end def description - return object.description if object.description - PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url)) + I18n.t("#{i18n_key}.description", default: object.description, base_url: Discourse.base_url) end def include_description? @@ -80,4 +74,10 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer def final object.final? end + + protected + + def i18n_key + @i18n_key ||= "#{object.wizard.id}.#{object.id}".underscore + end end diff --git a/app/views/layouts/qunit.html.erb b/app/views/layouts/qunit.html.erb new file mode 100644 index 00000000..c2f5fb5e --- /dev/null +++ b/app/views/layouts/qunit.html.erb @@ -0,0 +1,28 @@ + + + + Custom Wizard QUnit Test Runner + <%= discourse_stylesheet_link_tag(:test_helper, theme_id: nil) %> + <%= discourse_stylesheet_link_tag :wizard, theme_id: nil %> + <%= discourse_stylesheet_link_tag :wizard_custom %> + <%= preload_script "locales/en" %> + <%= preload_script "ember_jquery" %> + <%= preload_script "wizard-vendor" %> + <%= preload_script "wizard-custom" %> + <%= preload_script "wizard-raw-templates" %> + <%= preload_script "wizard-plugin" %> + <%= preload_script "pretty-text-bundle" %> + <%= preload_script "wizard-qunit" %> + <%= csrf_meta_tags %> + + + + <%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %> + + + + +
+
+ + diff --git a/assets/javascripts/discourse/components/custom-field-input.js.es6 b/assets/javascripts/discourse/components/custom-field-input.js.es6 index e49c6f1d..5d2d6c3b 100644 --- a/assets/javascripts/discourse/components/custom-field-input.js.es6 +++ b/assets/javascripts/discourse/components/custom-field-input.js.es6 @@ -3,27 +3,12 @@ import discourseComputed, { observes } from "discourse-common/utils/decorators"; import { alias, equal, or } from "@ember/object/computed"; import I18n from "I18n"; -const generateContent = function (array, type) { - return array.map((key) => ({ - id: key, - name: I18n.t(`admin.wizard.custom_field.${type}.${key}`), - })); -}; - export default Component.extend({ tagName: "tr", topicSerializers: ["topic_view", "topic_list_item"], postSerializers: ["post"], groupSerializers: ["basic_group"], categorySerializers: ["basic_category"], - klassContent: generateContent( - ["topic", "post", "group", "category"], - "klass" - ), - typeContent: generateContent( - ["string", "boolean", "integer", "json"], - "type" - ), showInputs: or("field.new", "field.edit"), classNames: ["custom-field-input"], loading: or("saving", "destroying"), @@ -40,9 +25,13 @@ export default Component.extend({ const serializers = this.get(`${klass}Serializers`); if (serializers) { - return generateContent(serializers, "serializers"); - } else { - return []; + return serializers.reduce((result, key) => { + result.push({ + id: key, + name: I18n.t(`admin.wizard.custom_field.serializers.${key}`), + }); + return result; + }, []); } }, diff --git a/assets/javascripts/discourse/components/wizard-advanced-toggle.js.es6 b/assets/javascripts/discourse/components/wizard-advanced-toggle.js.es6 deleted file mode 100644 index c6e1fd9c..00000000 --- a/assets/javascripts/discourse/components/wizard-advanced-toggle.js.es6 +++ /dev/null @@ -1,21 +0,0 @@ -import { default as discourseComputed } from "discourse-common/utils/decorators"; -import Component from "@ember/component"; - -export default Component.extend({ - classNames: "wizard-advanced-toggle", - - @discourseComputed("showAdvanced") - toggleClass(showAdvanced) { - let classes = "btn"; - if (showAdvanced) { - classes += " btn-primary"; - } - return classes; - }, - - actions: { - toggleAdvanced() { - this.toggleProperty("showAdvanced"); - }, - }, -}); diff --git a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 index 83baafc7..48dfef48 100644 --- a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 @@ -1,8 +1,8 @@ import { default as discourseComputed } from "discourse-common/utils/decorators"; -import { and, empty, equal, or } from "@ember/object/computed"; +import { subscriptionSelectKitContent } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-subscription"; +import { empty, equal, or } from "@ember/object/computed"; import { notificationLevels, selectKitContent } from "../lib/wizard"; import { computed } from "@ember/object"; -import wizardSchema from "../lib/wizard-schema"; import UndoChanges from "../mixins/undo-changes"; import Component from "@ember/component"; import I18n from "I18n"; @@ -25,8 +25,6 @@ export default Component.extend(UndoChanges, { createGroup: equal("action.type", "create_group"), apiEmpty: empty("action.api"), groupPropertyTypes: selectKitContent(["id", "name"]), - hasAdvanced: or("hasCustomFields", "routeTo"), - showAdvanced: and("hasAdvanced", "action.type"), hasCustomFields: or( "basicTopicFields", "updateProfile", @@ -36,12 +34,6 @@ export default Component.extend(UndoChanges, { basicTopicFields: or("createTopic", "sendMessage", "openComposer"), publicTopicFields: or("createTopic", "openComposer"), showPostAdvanced: or("createTopic", "sendMessage"), - actionTypes: Object.keys(wizardSchema.action.types).map((type) => { - return { - id: type, - name: I18n.t(`admin.wizard.action.${type}.label`), - }; - }), availableNotificationLevels: notificationLevels.map((type) => { return { id: type, @@ -102,6 +94,11 @@ export default Component.extend(UndoChanges, { return apis.find((a) => a.name === api).endpoints; }, + @discourseComputed + actionTypes() { + return subscriptionSelectKitContent("action", "types"); + }, + @discourseComputed("fieldTypes") hasEventsField(fieldTypes) { return fieldTypes.map((ft) => ft.id).includes("event"); diff --git a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 index 31c8dc66..ed66012a 100644 --- a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 @@ -1,5 +1,5 @@ import { default as discourseComputed } from "discourse-common/utils/decorators"; -import { alias, equal, or } from "@ember/object/computed"; +import { equal, or } from "@ember/object/computed"; import { computed } from "@ember/object"; import { selectKitContent } from "../lib/wizard"; import UndoChanges from "../mixins/undo-changes"; @@ -27,7 +27,6 @@ export default Component.extend(UndoChanges, { isTextType: or("isText", "isTextarea", "isComposer"), isComposerPreview: equal("field.type", "composer_preview"), categoryPropertyTypes: selectKitContent(["id", "slug"]), - showAdvanced: alias("field.type"), messageUrl: "https://discourse.pluginmanager.org/t/field-settings", @discourseComputed("field.type") diff --git a/assets/javascripts/discourse/components/wizard-message.js.es6 b/assets/javascripts/discourse/components/wizard-message.js.es6 index b273e78b..686a7254 100644 --- a/assets/javascripts/discourse/components/wizard-message.js.es6 +++ b/assets/javascripts/discourse/components/wizard-message.js.es6 @@ -6,6 +6,7 @@ import I18n from "I18n"; const icons = { error: "times-circle", success: "check-circle", + warn: "exclamation-circle", info: "info-circle", }; diff --git a/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 b/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 index 8332b86e..b1d8a0f5 100644 --- a/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 +++ b/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 @@ -6,7 +6,8 @@ import discourseComputed from "discourse-common/utils/decorators"; import I18n from "I18n"; export default Component.extend({ - classNames: ["realtime-validations"], + classNames: ["realtime-validations", "setting", "full", "subscription"], + @discourseComputed timeUnits() { return ["days", "weeks", "months", "years"].map((unit) => { diff --git a/assets/javascripts/discourse/components/wizard-subscription-badge.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-badge.js.es6 new file mode 100644 index 00000000..301c618e --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-badge.js.es6 @@ -0,0 +1,30 @@ +import Component from "@ember/component"; +import discourseComputed from "discourse-common/utils/decorators"; +import Subscription from "../mixins/subscription"; +import DiscourseURL from "discourse/lib/url"; +import I18n from "I18n"; + +export default Component.extend(Subscription, { + tagName: "a", + classNameBindings: [":wizard-subscription-badge", "subscriptionType"], + attributeBindings: ["title"], + + @discourseComputed("subscriptionType") + i18nKey(type) { + return `admin.wizard.subscription.type.${type ? type : "none"}`; + }, + + @discourseComputed("i18nKey") + title(i18nKey) { + return I18n.t(`${i18nKey}.title`); + }, + + @discourseComputed("i18nKey") + label(i18nKey) { + return I18n.t(`${i18nKey}.label`); + }, + + click() { + DiscourseURL.routeTo(this.subscriptionLink); + }, +}); diff --git a/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 new file mode 100644 index 00000000..5cc6b17c --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-container.js.es6 @@ -0,0 +1,26 @@ +import Component from "@ember/component"; +import discourseComputed from "discourse-common/utils/decorators"; +import Subscription from "../mixins/subscription"; + +export default Component.extend(Subscription, { + classNameBindings: [":wizard-subscription-container", "subscribed"], + + @discourseComputed("subscribed") + subscribedIcon(subscribed) { + return subscribed ? "check" : "dash"; + }, + + @discourseComputed("subscribed") + subscribedLabel(subscribed) { + return `admin.wizard.subscription.${ + subscribed ? "subscribed" : "not_subscribed" + }.label`; + }, + + @discourseComputed("subscribed") + subscribedTitle(subscribed) { + return `admin.wizard.subscription.${ + subscribed ? "subscribed" : "not_subscribed" + }.title`; + }, +}); diff --git a/assets/javascripts/discourse/components/wizard-subscription-cta.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-cta.js.es6 new file mode 100644 index 00000000..f483fbe8 --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-cta.js.es6 @@ -0,0 +1,36 @@ +import Component from "@ember/component"; +import discourseComputed from "discourse-common/utils/decorators"; +import Subscription from "../mixins/subscription"; +import I18n from "I18n"; + +export default Component.extend(Subscription, { + tagName: "a", + classNameBindings: [":btn", ":btn-pavilion-support", "subscriptionType"], + attributeBindings: ["title"], + + @discourseComputed("subscribed") + i18nKey(subscribed) { + return `admin.wizard.subscription.cta.${ + subscribed ? "subscribed" : "none" + }`; + }, + + @discourseComputed("subscribed") + icon(subscribed) { + return subscribed ? "far-life-ring" : "external-link-alt"; + }, + + @discourseComputed("i18nKey") + title(i18nKey) { + return I18n.t(`${i18nKey}.title`); + }, + + @discourseComputed("i18nKey") + label(i18nKey) { + return I18n.t(`${i18nKey}.label`); + }, + + click() { + window.open(this.subscriptionCtaLink, "_blank").focus(); + }, +}); diff --git a/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 new file mode 100644 index 00000000..53f7d19c --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-selector.js.es6 @@ -0,0 +1,96 @@ +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 discourseComputed from "discourse-common/utils/decorators"; +import I18n from "I18n"; + +const nameKey = function (feature, attribute, value) { + if (feature === "action") { + return `admin.wizard.action.${value}.label`; + } else { + return `admin.wizard.${feature}.${attribute}.${value}`; + } +}; + +export default SingleSelectComponent.extend(Subscription, { + classNames: ["combo-box", "wizard-subscription-selector"], + + selectKitOptions: { + autoFilterable: false, + filterable: false, + showFullTitle: true, + headerComponent: + "wizard-subscription-selector/wizard-subscription-selector-header", + caretUpIcon: "caret-up", + caretDownIcon: "caret-down", + }, + + allowedSubscriptionTypes(feature, attribute, value) { + let attributes = this.subscriptionAttributes[feature]; + if (!attributes || !attributes[attribute]) { + return ["none"]; + } + let allowedTypes = []; + Object.keys(attributes[attribute]).forEach((subscriptionType) => { + let values = attributes[attribute][subscriptionType]; + if (values[0] === "*" || values.includes(value)) { + allowedTypes.push(subscriptionType); + } + }); + return allowedTypes; + }, + + @discourseComputed("feature", "attribute") + content(feature, attribute) { + return wizardSchema[feature][attribute] + .map((value) => { + let allowedSubscriptionTypes = this.allowedSubscriptionTypes( + feature, + attribute, + value + ); + + let subscriptionRequired = + allowedSubscriptionTypes.length && + !allowedSubscriptionTypes.includes("none"); + + let attrs = { + id: value, + name: I18n.t(nameKey(feature, attribute, value)), + subscriptionRequired, + }; + + if (subscriptionRequired) { + let subscribed = allowedSubscriptionTypes.includes( + this.subscriptionType + ); + let selectorKey = subscribed ? "subscribed" : "not_subscribed"; + let selectorLabel = `admin.wizard.subscription.${selectorKey}.selector`; + + attrs.disabled = !subscribed; + attrs.selectorLabel = selectorLabel; + } + + return attrs; + }) + .sort(function (a, b) { + if (a.subscriptionType && !b.subscriptionType) { + return 1; + } + if (!a.subscriptionType && b.subscriptionType) { + return -1; + } + if (a.subscriptionType === b.subscriptionType) { + return a.subscriptionType + ? a.subscriptionType.localeCompare(b.subscriptionType) + : 0; + } else { + return a.subscriptionType === "standard" ? -1 : 0; + } + }); + }, + + modifyComponentForRow() { + return "wizard-subscription-selector/wizard-subscription-selector-row"; + }, +}); diff --git a/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-header.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-header.js.es6 new file mode 100644 index 00000000..74f29f08 --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-header.js.es6 @@ -0,0 +1,17 @@ +import SingleSelectHeaderComponent from "select-kit/components/select-kit/single-select-header"; +import { computed } from "@ember/object"; +import { reads } from "@ember/object/computed"; + +export default SingleSelectHeaderComponent.extend({ + classNames: ["combo-box-header", "wizard-subscription-selector-header"], + caretUpIcon: reads("selectKit.options.caretUpIcon"), + caretDownIcon: reads("selectKit.options.caretDownIcon"), + caretIcon: computed( + "selectKit.isExpanded", + "caretUpIcon", + "caretDownIcon", + function () { + return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon; + } + ), +}); diff --git a/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-row.js.es6 b/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-row.js.es6 new file mode 100644 index 00000000..1d43047a --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-subscription-selector/wizard-subscription-selector-row.js.es6 @@ -0,0 +1,20 @@ +import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row"; +import { default as discourseComputed } from "discourse-common/utils/decorators"; + +export default SelectKitRowComponent.extend({ + classNameBindings: ["isDisabled:disabled"], + + @discourseComputed("item") + isDisabled() { + return this.item.disabled; + }, + + click(event) { + event.preventDefault(); + event.stopPropagation(); + if (!this.item.disabled) { + this.selectKit.select(this.rowValue, this.item); + } + return false; + }, +}); diff --git a/assets/javascripts/discourse/components/wizard-table-field.js.es6 b/assets/javascripts/discourse/components/wizard-table-field.js.es6 new file mode 100644 index 00000000..049b4d40 --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-table-field.js.es6 @@ -0,0 +1,139 @@ +import Component from "@ember/component"; +import { action } from "@ember/object"; +import { equal, notEmpty } from "@ember/object/computed"; +import discourseComputed from "discourse-common/utils/decorators"; +import I18n from "I18n"; + +export default Component.extend({ + classNameBindings: ["value.type"], + isText: equal("value.type", "text"), + isComposer: equal("value.type", "composer"), + isDate: equal("value.type", "date"), + isTime: equal("value.type", "time"), + isDateTime: equal("value.type", "date_time"), + isNumber: equal("value.type", "number"), + isCheckbox: equal("value.type", "checkbox"), + isUrl: equal("value.type", "url"), + isUpload: equal("value.type", "upload"), + isDropdown: equal("value.type", "dropdown"), + isTag: equal("value.type", "tag"), + isCategory: equal("value.type", "category"), + isGroup: equal("value.type", "group"), + isUserSelector: equal("value.type", "user_selector"), + isSubmittedAt: equal("field", "submitted_at"), + isComposerPreview: equal("value.type", "composer_preview"), + textState: "text-collapsed", + toggleText: I18n.t("admin.wizard.expand_text"), + + @discourseComputed("value", "isUser") + hasValue(value, isUser) { + if (isUser) { + return value; + } + return value && value.value; + }, + + @discourseComputed("field", "value.type") + isUser(field, type) { + return field === "username" || field === "user" || type === "user"; + }, + + @discourseComputed("value.type") + isLongtext(type) { + return type === "textarea" || type === "long_text"; + }, + + @discourseComputed("value") + checkboxValue(value) { + const isCheckbox = this.get("isCheckbox"); + if (isCheckbox) { + if (value.value.includes("true")) { + return true; + } else if (value.value.includes("false")) { + return false; + } + } + }, + + @action + expandText() { + const state = this.get("textState"); + + if (state === "text-collapsed") { + this.set("textState", "text-expanded"); + this.set("toggleText", I18n.t("admin.wizard.collapse_text")); + } else if (state === "text-expanded") { + this.set("textState", "text-collapsed"); + this.set("toggleText", I18n.t("admin.wizard.expand_text")); + } + }, + + @discourseComputed("value") + file(value) { + const isUpload = this.get("isUpload"); + if (isUpload) { + return value.value; + } + }, + + @discourseComputed("value") + submittedUsers(value) { + const isUserSelector = this.get("isUserSelector"); + const users = []; + + if (isUserSelector) { + const userData = value.value; + const usernames = []; + + if (userData.indexOf(",")) { + usernames.push(...userData.split(",")); + + usernames.forEach((u) => { + const user = { + username: u, + url: `/u/${u}`, + }; + users.push(user); + }); + } + } + return users; + }, + + @discourseComputed("isUser", "field", "value") + username(isUser, field, value) { + if (isUser) { + return value.username; + } + if (field === "username") { + return value.value; + } + return null; + }, + + showUsername: notEmpty("username"), + + @discourseComputed("username") + userProfileUrl(username) { + if (username) { + return `/u/${username}`; + } + return "/"; + }, + + @discourseComputed("value") + categoryUrl(value) { + const isCategory = this.get("isCategory"); + if (isCategory) { + return `/c/${value.value}`; + } + }, + + @discourseComputed("value") + groupUrl(value) { + const isGroup = this.get("isGroup"); + if (isGroup) { + return `/g/${value.value}`; + } + }, +}); 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 f76722fc..f893d4ac 100644 --- a/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs +++ b/assets/javascripts/discourse/connectors/admin-menu/wizards-nav-button.hbs @@ -1,3 +1,7 @@ {{#if currentUser.admin}} {{nav-item route="adminWizards" label="admin.wizard.nav_label"}} + + {{#if wizardErrorNotice}} + {{d-icon "exclaimation-circle"}} + {{/if}} {{/if}} 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 4b5d673d..5ce96f2f 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 @@ -6,11 +6,11 @@
{{combo-box - value=wizardListVal - content=wizardList - onChange=(action "changeWizard") - options=(hash - none="admin.wizard.select" - )}} + value=wizardListVal + content=wizardList + onChange=(action "changeWizard") + options=(hash + none="admin.wizard.select" + )}}
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 a71557c2..b89cc447 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6 @@ -11,7 +11,7 @@ export default Controller.extend({ queryParams: ["refresh_list"], loadingSubscriptions: false, notAuthorized: not("api.authorized"), - endpointMethods: selectKitContent(["GET", "PUT", "POST", "PATCH", "DELETE"]), + endpointMethods: selectKitContent(["PUT", "POST", "PATCH", "DELETE"]), showRemove: not("isNew"), showRedirectUri: and("threeLeggedOauth", "api.name"), responseIcon: null, @@ -88,6 +88,11 @@ export default Controller.extend({ twoLeggedOauth: equal("api.authType", "oauth_2"), threeLeggedOauth: equal("api.authType", "oauth_3"), + @discourseComputed("api.isNew") + nameClass(isNew) { + return isNew ? "new" : "saved"; + }, + actions: { addParam() { this.get("api.authParams").pushObject({}); diff --git a/assets/javascripts/discourse/controllers/admin-wizards-columns.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-columns.js.es6 new file mode 100644 index 00000000..4754c577 --- /dev/null +++ b/assets/javascripts/discourse/controllers/admin-wizards-columns.js.es6 @@ -0,0 +1,14 @@ +import Controller from "@ember/controller"; +import ModalFunctionality from "discourse/mixins/modal-functionality"; + +export default Controller.extend(ModalFunctionality, { + actions: { + save() { + this.send("closeModal"); + }, + + resetToDefault() { + this.get("model.reset")(); + }, + }, +}); diff --git a/assets/javascripts/discourse/controllers/admin-wizards-logs-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-logs-show.js.es6 new file mode 100644 index 00000000..7e3fdff1 --- /dev/null +++ b/assets/javascripts/discourse/controllers/admin-wizards-logs-show.js.es6 @@ -0,0 +1,52 @@ +import discourseComputed from "discourse-common/utils/decorators"; +import { notEmpty } from "@ember/object/computed"; +import CustomWizardLogs from "../models/custom-wizard-logs"; +import Controller from "@ember/controller"; + +export default Controller.extend({ + refreshing: false, + hasLogs: notEmpty("logs"), + page: 0, + canLoadMore: true, + logs: [], + messageKey: "viewing", + + loadLogs() { + if (!this.canLoadMore) { + return; + } + const page = this.get("page"); + const wizardId = this.get("wizard.id"); + + this.set("refreshing", true); + + CustomWizardLogs.list(wizardId, page) + .then((result) => { + this.set("logs", this.logs.concat(result.logs)); + }) + .finally(() => this.set("refreshing", false)); + }, + + @discourseComputed("hasLogs", "refreshing") + noResults(hasLogs, refreshing) { + return !hasLogs && !refreshing; + }, + + actions: { + loadMore() { + if (!this.loadingMore && this.logs.length < this.total) { + this.set("page", (this.page += 1)); + this.loadLogs(); + } + }, + + refresh() { + this.setProperties({ + canLoadMore: true, + page: 0, + logs: [], + }); + this.loadLogs(); + }, + }, +}); diff --git a/assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6 index 9559b01b..7388a8d6 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6 @@ -1,50 +1,34 @@ -import discourseComputed from "discourse-common/utils/decorators"; -import { notEmpty } from "@ember/object/computed"; -import CustomWizardLogs from "../models/custom-wizard-logs"; import Controller from "@ember/controller"; +import { default as discourseComputed } from "discourse-common/utils/decorators"; export default Controller.extend({ - refreshing: false, - hasLogs: notEmpty("logs"), - page: 0, - canLoadMore: true, - logs: [], + documentationUrl: "https://thepavilion.io/t/2818", - loadLogs() { - if (!this.canLoadMore) { - return; + @discourseComputed("wizardId") + wizardName(wizardId) { + let currentWizard = this.wizardList.find( + (wizard) => wizard.id === wizardId + ); + if (currentWizard) { + return currentWizard.name; + } + }, + + @discourseComputed("wizardName") + messageOpts(wizardName) { + return { + wizardName, + }; + }, + + @discourseComputed("wizardId") + messageKey(wizardId) { + let key = "select"; + + if (wizardId) { + key = "viewing"; } - this.set("refreshing", true); - - CustomWizardLogs.list() - .then((result) => { - if (!result || result.length === 0) { - this.set("canLoadMore", false); - } - this.set("logs", this.logs.concat(result)); - }) - .finally(() => this.set("refreshing", false)); - }, - - @discourseComputed("hasLogs", "refreshing") - noResults(hasLogs, refreshing) { - return !hasLogs && !refreshing; - }, - - actions: { - loadMore() { - this.set("page", (this.page += 1)); - this.loadLogs(); - }, - - refresh() { - this.setProperties({ - canLoadMore: true, - page: 0, - logs: [], - }); - this.loadLogs(); - }, + return key; }, }); diff --git a/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 index f5f9926d..10621cd3 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 @@ -1,6 +1,69 @@ import Controller from "@ember/controller"; +import { empty } from "@ember/object/computed"; +import discourseComputed from "discourse-common/utils/decorators"; import { fmt } from "discourse/lib/computed"; +import showModal from "discourse/lib/show-modal"; +import CustomWizard from "../models/custom-wizard"; export default Controller.extend({ downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"), + noResults: empty("submissions"), + page: 0, + total: 0, + + loadMoreSubmissions() { + const page = this.get("page"); + const wizardId = this.get("wizard.id"); + + this.set("loadingMore", true); + CustomWizard.submissions(wizardId, page) + .then((result) => { + if (result.submissions) { + this.get("submissions").pushObjects(result.submissions); + } + }) + .finally(() => { + this.set("loadingMore", false); + }); + }, + + @discourseComputed("submissions", "fields.@each.enabled") + displaySubmissions(submissions, fields) { + let result = []; + + submissions.forEach((submission) => { + let sub = {}; + + Object.keys(submission).forEach((fieldId) => { + if (fields.some((f) => f.id === fieldId && f.enabled)) { + sub[fieldId] = submission[fieldId]; + } + }); + result.push(sub); + }); + + return result; + }, + + actions: { + loadMore() { + if (!this.loadingMore && this.submissions.length < this.total) { + this.set("page", this.get("page") + 1); + this.loadMoreSubmissions(); + } + }, + + showEditColumnsModal() { + return showModal("admin-wizards-columns", { + model: { + columns: this.get("fields"), + reset: () => { + this.get("fields").forEach((field) => { + field.set("enabled", true); + }); + }, + }, + }); + }, + }, }); diff --git a/assets/javascripts/discourse/controllers/admin-wizards-submissions.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-submissions.js.es6 new file mode 100644 index 00000000..7388a8d6 --- /dev/null +++ b/assets/javascripts/discourse/controllers/admin-wizards-submissions.js.es6 @@ -0,0 +1,34 @@ +import Controller from "@ember/controller"; +import { default as discourseComputed } from "discourse-common/utils/decorators"; + +export default Controller.extend({ + documentationUrl: "https://thepavilion.io/t/2818", + + @discourseComputed("wizardId") + wizardName(wizardId) { + let currentWizard = this.wizardList.find( + (wizard) => wizard.id === wizardId + ); + if (currentWizard) { + return currentWizard.name; + } + }, + + @discourseComputed("wizardName") + messageOpts(wizardName) { + return { + wizardName, + }; + }, + + @discourseComputed("wizardId") + messageKey(wizardId) { + let key = "select"; + + if (wizardId) { + key = "viewing"; + } + + return key; + }, +}); 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 1eeb62e6..e6b0ad04 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 @@ -92,7 +92,11 @@ export default Controller.extend({ wizard .save(opts) .then((result) => { - this.send("afterSave", result.wizard_id); + if (result.wizard_id) { + this.send("afterSave", result.wizard_id); + } else if (result.errors) { + this.set("error", result.errors.join(", ")); + } }) .catch((result) => { this.set("error", this.getErrorMessage(result)); @@ -118,10 +122,6 @@ export default Controller.extend({ controller.setup(); }, - toggleAdvanced() { - this.toggleProperty("wizard.showAdvanced"); - }, - copyUrl() { const $copyRange = $('

'); $copyRange.html(this.wizardUrl); diff --git a/assets/javascripts/discourse/controllers/admin-wizards.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards.js.es6 new file mode 100644 index 00000000..518893b6 --- /dev/null +++ b/assets/javascripts/discourse/controllers/admin-wizards.js.es6 @@ -0,0 +1,9 @@ +import Controller from "@ember/controller"; +import { equal, or } from "@ember/object/computed"; + +export default Controller.extend({ + businessSubscription: equal("subscriptionType", "business"), + communitySubscription: equal("subscriptionType", "community"), + standardSubscription: equal("subscriptionType", "standard"), + showApi: or("businessSubscription", "communitySubscription"), +}); diff --git a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 index 90ab5359..272e276e 100644 --- a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 +++ b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 @@ -43,7 +43,16 @@ export default { } ); - this.route("adminWizardsLogs", { path: "/logs", resetNamespace: true }); + this.route( + "adminWizardsLogs", + { path: "/logs", resetNamespace: true }, + function () { + this.route("adminWizardsLogsShow", { + path: "/:wizardId/", + resetNamespace: true, + }); + } + ); this.route("adminWizardsManager", { path: "/manager", diff --git a/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 index d4b2c57d..2d13e703 100644 --- a/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 +++ b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 @@ -20,7 +20,7 @@ export default { return existing.apply(this, [path, opts]); }; - withPluginApi("0.8.7", (api) => { + withPluginApi("0.8.36", (api) => { api.modifyClass("component:d-navigation", { pluginId: "custom-wizard", actions: { diff --git a/assets/javascripts/discourse/lib/wizard-json.js.es6 b/assets/javascripts/discourse/lib/wizard-json.js.es6 index 79da60cb..95eaba49 100644 --- a/assets/javascripts/discourse/lib/wizard-json.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-json.js.es6 @@ -97,11 +97,6 @@ function buildObjectArray(json, type) { if (present(json)) { json.forEach((objJson, objectIndex) => { let object = buildObject(objJson, type, objectIndex); - - if (hasAdvancedProperties(object, type)) { - object.set("showAdvanced", true); - } - array.pushObject(object); }); } @@ -112,21 +107,11 @@ function buildObjectArray(json, type) { function buildBasicProperties(json, type, props, objectIndex = null) { listProperties(type).forEach((p) => { props[p] = buildProperty(json, p, type, objectIndex); - - if (hasAdvancedProperties(json, type)) { - props.showAdvanced = true; - } }); return props; } -function hasAdvancedProperties(object, type) { - return Object.keys(object).some((p) => { - return wizardSchema[type].advanced.indexOf(p) > -1 && present(object[p]); - }); -} - /// to be removed: necessary due to action array being moved from step to wizard function actionPatch(json) { let actions = json.actions || []; diff --git a/assets/javascripts/discourse/lib/wizard-schema.js.es6 b/assets/javascripts/discourse/lib/wizard-schema.js.es6 index 4953e59c..e9622c45 100644 --- a/assets/javascripts/discourse/lib/wizard-schema.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-schema.js.es6 @@ -19,7 +19,6 @@ const wizard = { permitted: null, }, mapped: ["permitted"], - advanced: ["restart_on_revisit"], required: ["id"], dependent: { after_time: "after_time_scheduled", @@ -41,7 +40,6 @@ const step = { id: null, index: null, title: null, - key: null, banner: null, banner_upload_id: null, raw_description: null, @@ -52,7 +50,6 @@ const step = { force_final: false, }, mapped: ["required_data", "permitted_params", "condition", "index"], - advanced: ["required_data", "permitted_params", "condition", "index"], required: ["id"], dependent: {}, objectArrays: { @@ -71,14 +68,13 @@ const field = { image: null, image_upload_id: null, description: null, + property: null, required: null, - key: null, type: null, condition: null, }, types: {}, mapped: ["prefill", "content", "condition", "index"], - advanced: ["property", "key", "condition", "index"], required: ["id", "type"], dependent: {}, objectArrays: {}, @@ -201,22 +197,24 @@ const action = { "members_visibility_level", "add_event", ], - advanced: [ - "code", - "custom_fields", - "skip_redirect", - "suppress_notifications", - "required", - ], required: ["id", "type"], dependent: {}, objectArrays: {}, }; +const custom_field = { + klass: ["topic", "post", "group", "category"], + type: ["string", "boolean", "integer", "json"], +}; + +field.type = Object.keys(field.types); +action.type = Object.keys(action.types); + const wizardSchema = { wizard, step, field, + custom_field, action, }; diff --git a/assets/javascripts/discourse/mixins/subscription.js.es6 b/assets/javascripts/discourse/mixins/subscription.js.es6 new file mode 100644 index 00000000..34276c3f --- /dev/null +++ b/assets/javascripts/discourse/mixins/subscription.js.es6 @@ -0,0 +1,53 @@ +import Mixin from "@ember/object/mixin"; +import { getOwner } from "discourse-common/lib/get-owner"; +import { readOnly } from "@ember/object/computed"; +import discourseComputed from "discourse-common/utils/decorators"; + +const PRODUCT_PAGE = "https://custom-wizard.pavilion.tech"; +const SUPPORT_MESSAGE = + "https://coop.pavilion.tech/new-message?username=support&title=Custom%20Wizard%20Support"; +const MANAGER_CATEGORY = + "https://discourse.pluginmanager.org/c/discourse-custom-wizard"; + +export default Mixin.create({ + subscriptionLandingUrl: PRODUCT_PAGE, + subscriptionClientUrl: "/admin/plugins/subscription-client", + + @discourseComputed + adminWizards() { + return getOwner(this).lookup("controller:admin-wizards"); + }, + + subscribed: readOnly("adminWizards.subscribed"), + subscriptionType: readOnly("adminWizards.subscriptionType"), + businessSubscription: readOnly("adminWizards.businessSubscription"), + communitySubscription: readOnly("adminWizards.communitySubscription"), + standardSubscription: readOnly("adminWizards.standardSubscription"), + subscriptionAttributes: readOnly("adminWizards.subscriptionAttributes"), + subscriptionClientInstalled: readOnly( + "adminWizards.subscriptionClientInstalled" + ), + + @discourseComputed("subscriptionClientInstalled") + subscriptionLink(subscriptionClientInstalled) { + return subscriptionClientInstalled + ? this.subscriptionClientUrl + : this.subscriptionLandingUrl; + }, + + @discourseComputed("subscriptionType") + subscriptionCtaLink(subscriptionType) { + switch (subscriptionType) { + case "none": + return PRODUCT_PAGE; + case "standard": + return SUPPORT_MESSAGE; + case "business": + return SUPPORT_MESSAGE; + case "community": + return MANAGER_CATEGORY; + default: + return PRODUCT_PAGE; + } + }, +}); diff --git a/assets/javascripts/discourse/models/custom-wizard-logs.js.es6 b/assets/javascripts/discourse/models/custom-wizard-logs.js.es6 index e2de8a07..23565e2c 100644 --- a/assets/javascripts/discourse/models/custom-wizard-logs.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard-logs.js.es6 @@ -3,14 +3,54 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; import EmberObject from "@ember/object"; const CustomWizardLogs = EmberObject.extend(); +const logItemTypes = { + date: "date_time", + action: "text", + message: "long_text", + user: "user", + username: "text", +}; + +function logItem(item, attr) { + return { + value: item[attr], + type: logItemTypes[attr], + }; +} CustomWizardLogs.reopenClass({ - list(page = 0) { - return ajax("/admin/wizards/logs", { - data: { - page, - }, - }).catch(popupAjaxError); + list(wizardId, page = 0) { + let data = { + page, + }; + + return ajax(`/admin/wizards/logs/${wizardId}`, { data }) + .catch(popupAjaxError) + .then((result) => { + if (result.logs) { + result.logs = result.logs.map((item) => { + let map = {}; + + if (item.date) { + map.date = logItem(item, "date"); + } + if (item.action) { + map.action = logItem(item, "action"); + } + if (item.user) { + map.user = item.user; + } else { + map.user = logItem(item, "username"); + } + if (item.message) { + map.message = logItem(item, "message"); + } + + return map; + }); + } + return result; + }); }, }); diff --git a/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 index a1c625ad..a04d36f9 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 @@ -8,7 +8,10 @@ export default DiscourseRoute.extend({ }, setupController(controller, model) { - const customFields = A(model || []); - controller.set("customFields", customFields); + const customFields = A(model.custom_fields || []); + + controller.setProperties({ + customFields, + }); }, }); diff --git a/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 new file mode 100644 index 00000000..474360ec --- /dev/null +++ b/assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6 @@ -0,0 +1,17 @@ +import CustomWizardLogs from "../models/custom-wizard-logs"; +import DiscourseRoute from "discourse/routes/discourse"; +import { A } from "@ember/array"; + +export default DiscourseRoute.extend({ + model(params) { + return CustomWizardLogs.list(params.wizardId); + }, + + setupController(controller, model) { + controller.setProperties({ + wizard: model.wizard, + logs: A(model.logs), + total: model.total, + }); + }, +}); diff --git a/assets/javascripts/discourse/routes/admin-wizards-logs.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-logs.js.es6 index 56b91350..a1575050 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-logs.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-logs.js.es6 @@ -1,12 +1,24 @@ -import CustomWizardLogs from "../models/custom-wizard-logs"; import DiscourseRoute from "discourse/routes/discourse"; +import { ajax } from "discourse/lib/ajax"; export default DiscourseRoute.extend({ model() { - return CustomWizardLogs.list(); + return ajax(`/admin/wizards/wizard`); }, setupController(controller, model) { - controller.set("logs", model); + const showParams = this.paramsFor("adminWizardsLogsShow"); + + controller.setProperties({ + wizardId: showParams.wizardId, + wizardList: model.wizard_list, + }); + }, + + actions: { + changeWizard(wizardId) { + this.controllerFor("adminWizardsLogs").set("wizardId", wizardId); + this.transitionTo("adminWizardsLogsShow", wizardId); + }, }, }); 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 64847a9f..5a9d6046 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 @@ -1,42 +1,24 @@ +import { A } from "@ember/array"; +import EmberObject from "@ember/object"; import CustomWizardAdmin from "../models/custom-wizard-admin"; import DiscourseRoute from "discourse/routes/discourse"; -const excludedMetaFields = ["route_to", "redirect_on_complete", "redirect_to"]; - export default DiscourseRoute.extend({ model(params) { return CustomWizardAdmin.submissions(params.wizardId); }, setupController(controller, model) { - if (model && model.submissions) { - let fields = ["username"]; - model.submissions.forEach((s) => { - Object.keys(s.fields).forEach((k) => { - if (!excludedMetaFields.includes(k) && fields.indexOf(k) < 0) { - fields.push(k); - } - }); - }); - - let submissions = []; - model.submissions.forEach((s) => { - let submission = { - username: s.username, - }; - Object.keys(s.fields).forEach((f) => { - if (fields.includes(f)) { - submission[f] = s.fields[f]; - } - }); - submissions.push(submission); - }); - - controller.setProperties({ - wizard: model.wizard, - submissions, - fields, - }); - } + const fields = model.fields.map((f) => { + const fieldsObject = EmberObject.create(f); + fieldsObject.enabled = true; + return fieldsObject; + }); + controller.setProperties({ + wizard: model.wizard, + fields: A(fields), + submissions: A(model.submissions), + total: model.total, + }); }, }); diff --git a/assets/javascripts/discourse/routes/admin-wizards.js.es6 b/assets/javascripts/discourse/routes/admin-wizards.js.es6 index 5de271a8..1fa786d3 100644 --- a/assets/javascripts/discourse/routes/admin-wizards.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards.js.es6 @@ -1,7 +1,21 @@ import DiscourseRoute from "discourse/routes/discourse"; +import { ajax } from "discourse/lib/ajax"; export default DiscourseRoute.extend({ - beforeModel(transition) { + model() { + return ajax("/admin/wizards"); + }, + + setupController(controller, model) { + controller.setProperties({ + subscribed: model.subscribed, + subscriptionType: model.subscription_type, + subscriptionAttributes: model.subscription_attributes, + subscriptionClientInstalled: model.subscription_client_installed, + }); + }, + + afterModel(model, transition) { if (transition.targetName === "adminWizards.index") { this.transitionTo("adminWizardsWizard"); } diff --git a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs index 4d3def3d..303b3f6d 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs @@ -21,11 +21,11 @@ {{/if}} -
+
{{#if api.isNew}} {{i18n "admin.wizard.api.new"}} {{else}} - {{api.title}} + {{api.title}} {{/if}}
@@ -35,12 +35,12 @@ {{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}} + {{api.name}} {{/if}}
@@ -63,7 +63,7 @@ {{/if}} -
+
{{i18n "admin.wizard.api.auth.label"}}
@@ -71,7 +71,7 @@
-
+
{{i18n "admin.wizard.api.auth.settings"}}
@@ -174,7 +174,7 @@ {{/if}}
-
+
{{i18n "admin.wizard.api.status.label"}}
@@ -220,7 +220,7 @@ {{/if}}
-
+
{{i18n "admin.wizard.api.endpoint.label"}}
@@ -277,11 +277,15 @@ {{/if}}
-
+
{{i18n "admin.wizard.api.log.label"}} - {{d-button action=(action "clearLogs") - icon="trash-alt" - class="clear-logs"}} + +
+ {{d-button + action=(action "clearLogs") + class="clear-logs" + label="admin.wizard.api.log.clear"}} +
@@ -300,7 +304,7 @@ {{logentry.time}} {{logentry.status}} diff --git a/assets/javascripts/discourse/templates/admin-wizards-api.hbs b/assets/javascripts/discourse/templates/admin-wizards-api.hbs index 00d8ad60..af91d0fb 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api.hbs @@ -8,7 +8,7 @@ )}} {{d-button - action="createApi" + action=(route-action "createApi") label="admin.wizard.api.create" icon="plus"}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs index 10501498..a90f6299 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs @@ -5,7 +5,7 @@ {{d-button label="admin.wizard.custom_field.add" icon="plus" - action="addField"}} + action=(action "addField")}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs new file mode 100644 index 00000000..270d5c21 --- /dev/null +++ b/assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs @@ -0,0 +1,45 @@ +{{#if logs}} +
+ + +
+ {{d-button + label="refresh" + icon="sync" + action=(action "refresh") + class="refresh"}} +
+
+ +
+ {{#load-more selector=".wizard-table tr" action=(action "loadMore")}} + {{#if noResults}} +

{{i18n "search.no_results"}}

+ {{else}} + + + + + + + + + + + {{#each logs as |log|}} + + {{#each-in log as |field value|}} + + {{/each-in}} + + {{/each}} + +
{{i18n "admin.wizard.log.date"}}{{i18n "admin.wizard.log.action"}}{{i18n "admin.wizard.log.user"}}{{i18n "admin.wizard.log.message"}}
{{wizard-table-field field=field value=value}}
+ {{/if}} + + {{conditional-loading-spinner condition=refreshing}} + {{/load-more}} +
+{{/if}} diff --git a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs index b0dd3de6..45738a9f 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs @@ -1,34 +1,19 @@ -
-

{{i18n "admin.wizard.log.nav_label"}}

- - {{d-button - label="refresh" - icon="sync" - action="refresh" - class="refresh"}} +
+ {{combo-box + value=wizardId + content=wizardList + onChange=(route-action "changeWizard") + options=(hash + none="admin.wizard.select" + )}}
-{{#load-more selector=".log-list tr" action=(action "loadMore") class="wizard-logs"}} - {{#if noResults}} -

{{i18n "search.no_results"}}

- {{else}} - - - - - - - - - {{#each logs as |log|}} - - - - - {{/each}} - -
MessageDate
{{log.message}}{{bound-date log.date}}
- {{/if}} +{{wizard-message + key=messageKey + opts=messageOpts + url=documentationUrl + component="logs"}} - {{conditional-loading-spinner condition=refreshing}} -{{/load-more}} +
+ {{outlet}} +
diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs index 6d1f255b..72ec7c38 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs @@ -1,8 +1,24 @@ {{#if submissions}} -
- - - - {{#each fields as |f|}} - - {{/each}} - - - - {{#each submissions as |s|}} - - {{#each-in s as |k v|}} - - {{/each-in}} - - {{/each}} - -
{{f}}
{{v}}
+
+ {{#load-more selector=".wizard-table tr" action=(action "loadMore")}} + {{#if noResults}} +

{{i18n "search.no_results"}}

+ {{else}} + + + + {{#each fields as |field|}} + {{#if field.enabled}} + + {{/if}} + {{/each}} + + + + {{#each displaySubmissions as |submission|}} + + {{#each-in submission as |field value|}} + + {{/each-in}} + + {{/each}} + +
+ {{field.label}} +
{{wizard-table-field field=field value=value}}
+ {{/if}} + + {{conditional-loading-spinner condition=loadingMore}} + {{/load-more}}
{{/if}} diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs index d843485a..07dd1682 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs @@ -1,4 +1,4 @@ -
+
{{combo-box value=wizardId content=wizardList @@ -8,6 +8,12 @@ )}}
+{{wizard-message + key=messageKey + opts=messageOpts + url=documentationUrl + component="submissions"}} +
{{outlet}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs index b1281a6a..96d773cf 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs @@ -101,7 +101,7 @@ {{input type="checkbox" checked=wizard.after_time}} {{i18n "admin.wizard.after_time_label"}} {{d-button - action="setNextSessionScheduled" + action=(action "setNextSessionScheduled") translatedLabel=nextSessionScheduledLabel class="btn-after-time" icon="far-calendar"}} @@ -126,43 +126,27 @@
- {{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}} - - {{#if wizard.showAdvanced}} -
- -
-
- -
-
- {{input type="checkbox" checked=wizard.save_submissions}} - {{i18n "admin.wizard.save_submissions_label"}} -
+ {{#wizard-subscription-container}} +
+
+
- -
-
- -
-
- {{input type="checkbox" checked=wizard.restart_on_revisit}} - {{i18n "admin.wizard.restart_on_revisit_label"}} -
+
+ {{input type="checkbox" checked=wizard.save_submissions}} + {{i18n "admin.wizard.save_submissions_label"}}
- -
-
- -
-
- {{input type="checkbox" checked=wizard.resume_on_revisit}} - {{i18n "admin.wizard.resume_on_revisit_label"}} -
-
-
- {{/if}} + +
+
+ +
+
+ {{input type="checkbox" checked=wizard.restart_on_revisit}} + {{i18n "admin.wizard.restart_on_revisit_label"}} +
+
+ {{/wizard-subscription-container}}
{{wizard-links @@ -176,7 +160,8 @@ wizard=wizard currentField=currentField wizardFields=wizardFields - fieldTypes=fieldTypes}} + fieldTypes=fieldTypes + subscribed=subscribed}} {{/if}} {{wizard-links @@ -185,9 +170,9 @@ items=wizard.actions generateLabels=true}} - {{#each wizard.actions as |action|}} + {{#each wizard.actions as |wizardAction|}} {{wizard-custom-action - action=action + action=wizardAction currentActionId=currentAction.id wizard=wizard apis=apis diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs index 081cd5f3..c96f8009 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs @@ -8,7 +8,7 @@ )}} {{d-button - action="createWizard" + action=(route-action "createWizard") label="admin.wizard.create" icon="plus"}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards.hbs b/assets/javascripts/discourse/templates/admin-wizards.hbs index 21da3421..cea77942 100644 --- a/assets/javascripts/discourse/templates/admin-wizards.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards.hbs @@ -2,17 +2,15 @@ {{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"}} - {{#if siteSettings.wizard_apis_enabled}} + {{#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"}} -
- - - Custom Wizard Subscriptions Are Coming! - +
+ {{wizard-subscription-badge}} + {{wizard-subscription-cta}}
{{/admin-nav}} diff --git a/assets/javascripts/discourse/templates/components/custom-field-input.hbs b/assets/javascripts/discourse/templates/components/custom-field-input.hbs index 43a97be8..c0bdaaff 100644 --- a/assets/javascripts/discourse/templates/components/custom-field-input.hbs +++ b/assets/javascripts/discourse/templates/components/custom-field-input.hbs @@ -1,17 +1,23 @@ {{#if showInputs}} - {{combo-box + {{wizard-subscription-selector value=field.klass - content=klassContent - none="admin.wizard.custom_field.klass.select" - onChange=(action (mut field.klass))}} + feature="custom_field" + attribute="klass" + onChange=(action (mut field.klass)) + options=(hash + none="admin.wizard.custom_field.klass.select" + )}} - {{combo-box + {{wizard-subscription-selector value=field.type - content=typeContent - none="admin.wizard.custom_field.type.select" - onChange=(action (mut field.type))}} + feature="custom_field" + attribute="type" + onChange=(action (mut field.type)) + options=(hash + none="admin.wizard.custom_field.type.select" + )}} {{input @@ -22,8 +28,10 @@ {{multi-select value=field.serializers content=serializerContent - none="admin.wizard.custom_field.serializers.select" - onChange=(action (mut field.serializers))}} + onChange=(action (mut field.serializers)) + options=(hash + none="admin.wizard.custom_field.serializers.select" + )}} {{#if loading}} @@ -34,17 +42,17 @@ {{/if}} {{/if}} {{d-button - action="destroy" + action=(action "destroy") icon="trash-alt" class="destroy" disabled=destroyDisabled}} {{d-button icon="save" - action="save" + action=(action "save") disabled=saveDisabled class="save"}} {{d-button - action="close" + action=(action "close") icon="times" disabled=closeDisabled}} @@ -69,7 +77,7 @@ {{else}} - {{d-button action="edit" icon="pencil-alt"}} + {{d-button action=(action "edit") icon="pencil-alt"}} {{/if}} {{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-advanced-toggle.hbs b/assets/javascripts/discourse/templates/components/wizard-advanced-toggle.hbs deleted file mode 100644 index ec2bcb76..00000000 --- a/assets/javascripts/discourse/templates/components/wizard-advanced-toggle.hbs +++ /dev/null @@ -1,4 +0,0 @@ -{{d-button - action="toggleAdvanced" - label="admin.wizard.advanced" - class=toggleClass}} diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs index 03aee3f4..3b2222a0 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs @@ -1,6 +1,6 @@ {{#if showUndo}} {{d-button - action="undoChanges" + action=(action "undoChanges") icon=undoIcon label=undoKey class="undo-changes"}} @@ -12,13 +12,15 @@
- {{combo-box + {{wizard-subscription-selector value=action.type - content=actionTypes + feature="action" + attribute="type" onChange=(action "changeType") options=(hash none="admin.wizard.select_type" - )}} + ) + }}
@@ -733,99 +735,90 @@
{{/if}} -{{#if showAdvanced}} - {{wizard-advanced-toggle showAdvanced=action.showAdvanced}} - - {{#if action.showAdvanced}} -
- - {{#if hasCustomFields}} -
-
- -
- -
- {{wizard-mapper - inputs=action.custom_fields - property="custom_fields" - onUpdate=(action "mappedFieldUpdated") - options=(hash - inputTypes="association" - customFieldSelection="key" - wizardFieldSelection="value" - wizardActionSelection="value" - userFieldSelection="value" - keyPlaceholder="admin.wizard.action.custom_fields.key" - context=customFieldsContext - )}} -
-
- {{/if}} - - {{#if sendMessage}} -
-
- -
- -
- {{wizard-mapper - inputs=action.required - property="required" - onUpdate=(action "mappedFieldUpdated") - options=(hash - textSelection="value" - wizardFieldSelection=true - userFieldSelection=true - groupSelection=true - context="action" - )}} -
-
- {{/if}} - - {{#if showPostAdvanced}} -
-
- -
- -
- {{input type="checkbox" checked=action.skip_redirect}} - - - {{i18n "admin.wizard.action.skip_redirect.description" type="topic"}} - -
-
- -
-
- -
- -
- {{input type="checkbox" checked=action.suppress_notifications}} - - - {{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}} - -
-
- {{/if}} - - {{#if routeTo}} -
-
- -
- -
- {{input value=action.code}} -
-
- {{/if}} +{{#if hasCustomFields}} +
+
+
- {{/if}} + +
+ {{wizard-mapper + inputs=action.custom_fields + property="custom_fields" + onUpdate=(action "mappedFieldUpdated") + options=(hash + inputTypes="association" + customFieldSelection="key" + wizardFieldSelection="value" + wizardActionSelection="value" + userFieldSelection="value" + keyPlaceholder="admin.wizard.action.custom_fields.key" + context=customFieldsContext + )}} +
+
+{{/if}} + +{{#if sendMessage}} +
+
+ +
+ +
+ {{wizard-mapper + inputs=action.required + property="required" + onUpdate=(action "mappedFieldUpdated") + options=(hash + textSelection="value" + wizardFieldSelection=true + userFieldSelection=true + groupSelection=true + context="action" + )}} +
+
+{{/if}} + +{{#if showPostAdvanced}} +
+
+ +
+ +
+ {{input type="checkbox" checked=action.skip_redirect}} + + + {{i18n "admin.wizard.action.skip_redirect.description" type="topic"}} + +
+
+ +
+
+ +
+ +
+ {{input type="checkbox" checked=action.suppress_notifications}} + + + {{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}} + +
+
+{{/if}} + +{{#if routeTo}} +
+
+ +
+ +
+ {{input value=action.code}} +
+
{{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs index dbf59e32..6e524fe3 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs @@ -1,6 +1,6 @@ {{#if showUndo}} {{d-button - action="undoChanges" + action=(action "undoChanges") icon=undoIcon label=undoKey class="undo-changes"}} @@ -224,70 +224,50 @@
{{/if}} -{{#if showAdvanced}} - {{wizard-advanced-toggle showAdvanced=field.showAdvanced}} +{{#wizard-subscription-container}} +
+
+ +
- {{#if field.showAdvanced}} -
+
+ {{wizard-mapper + inputs=field.condition + options=fieldConditionOptions}} +
+
-
-
- -
+
+
+ +
-
- {{wizard-mapper - inputs=field.condition - options=fieldConditionOptions}} -
+
+ {{wizard-mapper + inputs=field.index + options=fieldIndexOptions}} +
+
+ + {{#if isCategory}} +
+
+
-
-
- -
- -
- {{wizard-mapper - inputs=field.index - options=fieldIndexOptions}} -
+
+ {{combo-box + value=field.property + content=categoryPropertyTypes + onChange=(action (mut field.property)) + options=(hash + none="admin.wizard.selector.placeholder.property" + )}}
- - {{#if isCategory}} -
-
- -
- -
- {{combo-box - value=field.property - content=categoryPropertyTypes - onChange=(action (mut field.property)) - options=(hash - none="admin.wizard.selector.placeholder.property" - )}} -
-
- {{/if}} - -
-
- -
-
- {{input - name="key" - value=field.key - class="medium" - placeholderKey="admin.wizard.translation_placeholder"}} -
-
- - {{#if validations}} - {{wizard-realtime-validations field=field validations=validations}} - {{/if}}
{{/if}} -{{/if}} + + {{#if validations}} + {{wizard-realtime-validations field=field validations=validations}} + {{/if}} +{{/wizard-subscription-container}} diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs index 9d7ae5af..40ac09e0 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs @@ -34,88 +34,72 @@
-{{wizard-advanced-toggle showAdvanced=step.showAdvanced}} - -{{#if step.showAdvanced}} -
- -
-
- -
- -
- {{wizard-mapper - inputs=step.condition - options=stepConditionOptions}} -
+{{#wizard-subscription-container}} +
+
+
-
-
-
-

{{i18n "admin.wizard.step.force_final.label"}}

- {{input type="checkbox" checked=step.force_final}} - {{i18n "admin.wizard.step.force_final.description"}} -
-
- -
-
- -
-
- {{wizard-mapper - inputs=step.required_data - options=(hash - inputTypes="validation" - inputConnector="and" - wizardFieldSelection="value" - userFieldSelection="value" - keyPlaceholder="admin.wizard.submission_key" - context="step" - )}} - {{#if step.required_data}} -
-
- {{i18n "admin.wizard.step.required_data.not_permitted_message"}} -
- {{input value=step.required_data_message}} -
- {{/if}} -
-
- -
-
- -
-
- {{wizard-mapper - inputs=step.permitted_params - options=(hash - pairConnector="set" - inputTypes="association" - keyPlaceholder="admin.wizard.param_key" - valuePlaceholder="admin.wizard.submission_key" - context="step" - )}} -
-
- -
-
- -
-
- {{input - name="key" - value=step.key - placeholderKey="admin.wizard.translation_placeholder"}} -
+
+ {{wizard-mapper + inputs=step.condition + options=stepConditionOptions}}
-{{/if}} + +
+
+
+

{{i18n "admin.wizard.step.force_final.label"}}

+ {{input type="checkbox" checked=step.force_final}} + {{i18n "admin.wizard.step.force_final.description"}} +
+
+ +
+
+ +
+ +
+ {{wizard-mapper + inputs=step.required_data + options=(hash + inputTypes="validation" + inputConnector="and" + wizardFieldSelection="value" + userFieldSelection="value" + keyPlaceholder="admin.wizard.submission_key" + context="step" + )}} + {{#if step.required_data}} +
+
+ {{i18n "admin.wizard.step.required_data.not_permitted_message"}} +
+ {{input value=step.required_data_message}} +
+ {{/if}} +
+
+ +
+
+ +
+
+ {{wizard-mapper + inputs=step.permitted_params + options=(hash + pairConnector="set" + inputTypes="association" + keyPlaceholder="admin.wizard.param_key" + valuePlaceholder="admin.wizard.submission_key" + context="step" + )}} +
+
+{{/wizard-subscription-container}} {{wizard-links itemType="field" @@ -130,5 +114,6 @@ currentFieldId=currentField.id fieldTypes=fieldTypes removeField="removeField" - wizardFields=wizardFields}} + wizardFields=wizardFields + subscribed=subscribed}} {{/each}} diff --git a/assets/javascripts/discourse/templates/components/wizard-links.hbs b/assets/javascripts/discourse/templates/components/wizard-links.hbs index a7a7662e..368acd35 100644 --- a/assets/javascripts/discourse/templates/components/wizard-links.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-links.hbs @@ -4,17 +4,16 @@ {{#if anyLinks}} {{#each links as |link|}}
- {{d-button action="change" actionParam=link.id translatedLabel=link.label class=link.classes}} + {{d-button action=(action "change") actionParam=link.id translatedLabel=link.label class=link.classes}} {{#unless link.first}} - {{d-button action="back" actionParam=link icon="arrow-left" class="back"}} + {{d-button action=(action "back") actionParam=link icon="arrow-left" class="back"}} {{/unless}} {{#unless link.last}} - {{d-button action="forward" actionParam=link icon="arrow-right" class="forward"}} + {{d-button action=(action "forward") actionParam=link icon="arrow-right" class="forward"}} {{/unless}} - {{d-button action="remove" actionParam=link.id icon="times" class="remove"}} + {{d-button action=(action "remove") actionParam=link.id icon="times" class="remove"}}
{{/each}} {{/if}} - {{d-button action="add" label="admin.wizard.add" icon="plus"}} + {{d-button action=(action "add") label="admin.wizard.add" icon="plus"}}
- diff --git a/assets/javascripts/discourse/templates/components/wizard-mapper.hbs b/assets/javascripts/discourse/templates/components/wizard-mapper.hbs index 2de35e0d..c0cc6818 100644 --- a/assets/javascripts/discourse/templates/components/wizard-mapper.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-mapper.hbs @@ -15,6 +15,6 @@ {{#if canAdd}} - {{d-button action="add" label="admin.wizard.add" icon="plus"}} + {{d-button action=(action "add") label="admin.wizard.add" icon="plus"}} {{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs b/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs index cd1298a9..8269d6ca 100644 --- a/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs @@ -1,50 +1,53 @@ -

{{i18n "admin.wizard.field.validations.header"}}

- -
    - {{#each-in field.validations as |type props|}} -
  • - -

    {{i18n (concat "admin.wizard.field.validations." type)}}

    - {{input type="checkbox" checked=props.status}} - {{i18n "admin.wizard.field.validations.enabled"}} -
    -
    -
    -
    - +
    + +
    +
    +
      + {{#each-in field.validations as |type props|}} +
    • + +

      {{i18n (concat "admin.wizard.field.validations." type)}}

      + {{input type="checkbox" checked=props.status}} + {{i18n "admin.wizard.field.validations.enabled"}} +
      +
      +
      +
      + +
      +
      + {{category-selector + categories=(get this (concat "validationBuffer." type ".categories")) + onChange=(action "updateValidationCategories" type props) + class="wizard"}} +
      -
      - {{category-selector - categories=(get this (concat "validationBuffer." type ".categories")) - onChange=(action "updateValidationCategories" type props) - class="wizard"}} +
      +
      + +
      +
      + {{input type="number" class="time-n-value" value=props.time_n_value}} + {{combo-box + value=(readonly props.time_unit) + content=timeUnits + class="time-unit-selector" + onChange=(action (mut props.time_unit))}} +
      +
      +
      +
      + +
      +
      + {{radio-button name=(concat type field.id) value="above" selection=props.position}} + {{i18n "admin.wizard.field.validations.above"}} + {{radio-button name=(concat type field.id) value="below" selection=props.position}} + {{i18n "admin.wizard.field.validations.below"}} +
      -
      -
      - -
      -
      - {{input type="number" class="time-n-value" value=props.time_n_value}} - {{combo-box - value=(readonly props.time_unit) - content=timeUnits - class="time-unit-selector" - onChange=(action (mut props.time_unit))}} -
      -
      -
      -
      - -
      -
      - {{radio-button name=(concat type field.id) value="above" selection=props.position}} - {{i18n "admin.wizard.field.validations.above"}} - {{radio-button name=(concat type field.id) value="below" selection=props.position}} - {{i18n "admin.wizard.field.validations.below"}} -
      -
      -
      -
    • - {{/each-in}} -
    +
  • + {{/each-in}} +
+
diff --git a/assets/javascripts/discourse/templates/components/wizard-subscription-badge.hbs b/assets/javascripts/discourse/templates/components/wizard-subscription-badge.hbs new file mode 100644 index 00000000..b2ce05bc5 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-subscription-badge.hbs @@ -0,0 +1,6 @@ + + + +{{label}} diff --git a/assets/javascripts/discourse/templates/components/wizard-subscription-container.hbs b/assets/javascripts/discourse/templates/components/wizard-subscription-container.hbs new file mode 100644 index 00000000..01d436f5 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-subscription-container.hbs @@ -0,0 +1,12 @@ +
+

{{i18n "admin.wizard.subscription.title"}}

+ + + {{d-icon subscribedIcon}} + {{i18n subscribedLabel}} + +
+ +
+ {{yield}} +
diff --git a/assets/javascripts/discourse/templates/components/wizard-subscription-cta.hbs b/assets/javascripts/discourse/templates/components/wizard-subscription-cta.hbs new file mode 100644 index 00000000..00569756 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-subscription-cta.hbs @@ -0,0 +1 @@ +{{d-icon icon}}{{label}} diff --git a/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-header.hbs b/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-header.hbs new file mode 100644 index 00000000..d91e90f1 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-header.hbs @@ -0,0 +1,15 @@ +
+ + {{component selectKit.options.selectedNameComponent + tabindex=tabindex + item=selectedContent + selectKit=selectKit + shouldDisplayClearableButton=shouldDisplayClearableButton + }} + + {{#if subscriptionRequired}} + {{i18n selectorLabel}} + {{/if}} + + {{d-icon caretIcon class="caret-icon"}} +
diff --git a/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-row.hbs b/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-row.hbs new file mode 100644 index 00000000..de24fd75 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-subscription-selector/wizard-subscription-selector-row.hbs @@ -0,0 +1,15 @@ +{{#if icons}} +
+ + {{#each icons as |icon|}} + {{d-icon icon translatedtitle=(dasherize title)}} + {{/each}} +
+{{/if}} + +
+ {{html-safe label}} + {{#if item.subscriptionRequired}} + {{i18n item.selectorLabel}} + {{/if}} +
diff --git a/assets/javascripts/discourse/templates/components/wizard-table-field.hbs b/assets/javascripts/discourse/templates/components/wizard-table-field.hbs new file mode 100644 index 00000000..bd7da5c4 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/wizard-table-field.hbs @@ -0,0 +1,161 @@ +{{#if hasValue}} + {{#if isText}} + {{value.value}} + {{/if}} + + {{#if isLongtext}} +
+

+ {{value.value}} +

+ + {{toggleText}} + +
+ {{/if}} + + {{#if isComposer}} +
+

+ {{value.value}} +

+ + {{toggleText}} + +
+ {{/if}} + + {{#if isComposerPreview}} + {{d-icon "comment-alt"}} + + {{i18n "admin.wizard.submissions.composer_preview"}}: {{value.value}} + + {{/if}} + + {{#if isTextOnly}} + {{value.value}} + {{/if}} + + {{#if isDate}} + + {{d-icon "calendar"}}{{value.value}} + + {{/if}} + + {{#if isTime}} + + {{d-icon "clock"}}{{value.value}} + + {{/if}} + + {{#if isDateTime}} + + {{d-icon "calendar"}}{{format-date value.value format="medium"}} + + {{/if}} + + {{#if isNumber}} + {{value.value}} + {{/if}} + + {{#if isCheckbox}} + {{#if checkboxValue}} + + {{d-icon "check"}}{{value.value}} + + {{else}} + + {{d-icon "times"}}{{value.value}} + + {{/if}} + {{/if}} + + {{#if isUrl}} + + {{d-icon "link"}} + + {{value.value}} + + + {{/if}} + + {{#if isUpload}} + + {{file.original_filename}} + + {{/if}} + + {{#if isDropdown}} + + {{d-icon "check-square"}} + {{value.value}} + + {{/if}} + + {{#if isTag}} + {{#each value.value as |tag|}} + {{discourse-tag tag}} + {{/each}} + {{/if}} + + {{#if isCategory}} + + {{i18n "admin.wizard.submissions.category_id"}}: + + + {{value.value}} + + {{/if}} + + {{#if isGroup}} + + {{i18n "admin.wizard.submissions.group_id"}}: + + {{value.value}} + {{/if}} + + {{#if isUserSelector}} + {{#each submittedUsers as |user|}} + {{d-icon "user"}} + + {{user.username}} + + {{/each}} + {{/if}} + + {{#if isUser}} + {{#link-to "user" value}} + {{avatar value imageSize="tiny"}} + {{/link-to}} + {{/if}} + + {{#if showUsername}} + + {{username}} + + {{/if}} + + {{#if isSubmittedAt}} + + {{d-icon "clock"}}{{format-date value format="tiny"}} + + {{/if}} +{{else}} + — +{{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-text-editor.hbs b/assets/javascripts/discourse/templates/components/wizard-text-editor.hbs index c657049d..37a3e549 100644 --- a/assets/javascripts/discourse/templates/components/wizard-text-editor.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-text-editor.hbs @@ -6,13 +6,13 @@
{{#if previewEnabled}} {{d-button - action="togglePreview" + action=(action "togglePreview") translatedLabel=previewLabel}} {{/if}} {{#if fieldsEnabled}} {{d-button - action="togglePopover" + action=(action "togglePopover") translatedLabel=popoverLabel}} {{#if showPopover}} diff --git a/assets/javascripts/discourse/templates/modal/admin-wizards-columns.hbs b/assets/javascripts/discourse/templates/modal/admin-wizards-columns.hbs new file mode 100644 index 00000000..eb5218b1 --- /dev/null +++ b/assets/javascripts/discourse/templates/modal/admin-wizards-columns.hbs @@ -0,0 +1,32 @@ +{{#d-modal-body title="admin.wizard.edit_columns"}} + {{#if loading}} + {{loading-spinner size="large"}} + {{else}} +
+ {{#each model.columns as |column|}} +
+
+ +
+
+ {{/each}} +
+ {{/if}} +{{/d-modal-body}} + + diff --git a/assets/javascripts/discourse/templates/modal/next-session-scheduled.hbs b/assets/javascripts/discourse/templates/modal/next-session-scheduled.hbs index 1b138360..cbc9d610 100644 --- a/assets/javascripts/discourse/templates/modal/next-session-scheduled.hbs +++ b/assets/javascripts/discourse/templates/modal/next-session-scheduled.hbs @@ -9,7 +9,7 @@