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}}
{{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
{{else}}
- {{api.name}}
+ {{api.name}}
{{/if}}
@@ -63,7 +63,7 @@
{{/if}}
-
@@ -71,7 +71,7 @@
-
-
-
-
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}}
+
+
+
+ {{#load-more selector=".wizard-table tr" action=(action "loadMore")}}
+ {{#if noResults}}
+
{{i18n "search.no_results"}}
+ {{else}}
+
+
+
+ {{i18n "admin.wizard.log.date"}} |
+ {{i18n "admin.wizard.log.action"}} |
+ {{i18n "admin.wizard.log.user"}} |
+ {{i18n "admin.wizard.log.message"}} |
+
+
+
+ {{#each logs as |log|}}
+
+ {{#each-in log as |field value|}}
+ {{wizard-table-field field=field value=value}} |
+ {{/each-in}}
+
+ {{/each}}
+
+
+ {{/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}}
-
-
-
- Message |
- Date |
-
-
-
- {{#each logs as |log|}}
-
- {{log.message}} |
- {{bound-date log.date}} |
-
- {{/each}}
-
-
- {{/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|}}
- {{f}} |
- {{/each}}
-
-
-
- {{#each submissions as |s|}}
-
- {{#each-in s as |k v|}}
- {{v}} |
- {{/each-in}}
-
- {{/each}}
-
-
+
+ {{#load-more selector=".wizard-table tr" action=(action "loadMore")}}
+ {{#if noResults}}
+
{{i18n "search.no_results"}}
+ {{else}}
+
+
+
+ {{#each fields as |field|}}
+ {{#if field.enabled}}
+
+ {{field.label}}
+ |
+ {{/if}}
+ {{/each}}
+
+
+
+ {{#each displaySubmissions as |submission|}}
+
+ {{#each-in submission as |field value|}}
+ {{wizard-table-field field=field value=value}} |
+ {{/each-in}}
+
+ {{/each}}
+
+
+ {{/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 @@
+
+
+
+ {{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 @@
+
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 @@