diff --git a/.github/workflows/plugin-tests.yml b/.github/workflows/plugin-tests.yml index 855bdfec49..6fe55cf46c 100644 --- a/.github/workflows/plugin-tests.yml +++ b/.github/workflows/plugin-tests.yml @@ -52,7 +52,7 @@ jobs: - uses: actions/checkout@v2 with: repository: discourse/discourse - ref: "${{ (github.base_ref || github.ref) }}" + ref: "tests-passed" fetch-depth: 1 - name: Fetch Repo Name diff --git a/assets/javascripts/discourse/components/custom-field-input.js.es6 b/assets/javascripts/discourse/components/custom-field-input.js.es6 index 7ee707162d..9f739eba04 100644 --- a/assets/javascripts/discourse/components/custom-field-input.js.es6 +++ b/assets/javascripts/discourse/components/custom-field-input.js.es6 @@ -2,29 +2,7 @@ import Component from "@ember/component"; import discourseComputed, { observes } from "discourse-common/utils/decorators"; import { alias, equal, or } from "@ember/object/computed"; import I18n from "I18n"; - -import wizardSchema, { - requiringAdditionalSubscription, - subscriptionLevel, -} from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema"; - -const generateContent = function (kategory, subscription) { - let unsubscribedCustomFields = requiringAdditionalSubscription( - subscription, - "custom_fields", - kategory - ); - return wizardSchema.custom_field[kategory].reduce((result, item) => { - let disabled = unsubscribedCustomFields.includes(item); - result.push({ - id: item, - name: I18n.t(`admin.wizard.custom_field.${kategory}.${item}`), - subscription: subscriptionLevel(item, "custom_fields", kategory), - disabled, - }); - return result; - }, []); -}; +import { buildSubscriptionContent } from "../lib/wizard"; export default Component.extend({ tagName: "tr", @@ -60,12 +38,12 @@ export default Component.extend({ @discourseComputed("subscription") customFieldTypes(subscription) { - return generateContent("type", subscription); + return buildSubscriptionContent("custom_fields", "types", subscription); }, @discourseComputed("subscription") customFieldKlasses(subscription) { - return generateContent("klass", subscription); + return buildSubscriptionContent("custom_fields", "klass", subscription); }, @observes("field.klass") diff --git a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 index 6cf2294217..7d17b62bd2 100644 --- a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 @@ -1,10 +1,10 @@ import { default as discourseComputed } from "discourse-common/utils/decorators"; -import wizardSchema, { - requiringAdditionalSubscription, - subscriptionLevel, -} from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema"; import { empty, equal, or } from "@ember/object/computed"; -import { notificationLevels, selectKitContent } from "../lib/wizard"; +import { + buildSubscriptionContent, + notificationLevels, + selectKitContent, +} from "../lib/wizard"; import { computed } from "@ember/object"; import UndoChanges from "../mixins/undo-changes"; import Component from "@ember/component"; @@ -99,20 +99,6 @@ export default Component.extend(UndoChanges, { @discourseComputed("subscription") actionTypes(subscription) { - let unsubscribedActions = requiringAdditionalSubscription( - subscription, - "actions", - "" - ); - return Object.keys(wizardSchema.action.types).reduce((result, type) => { - let disabled = unsubscribedActions.includes(type); - result.push({ - id: type, - name: I18n.t(`admin.wizard.action.${type}.label`), - subscription: subscriptionLevel(type, "actions", ""), - disabled, - }); - return result; - }, []); + return buildSubscriptionContent("action", "type", subscription); }, }); diff --git a/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 index 035fa6f2c8..6a027dee2c 100644 --- a/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 +++ b/assets/javascripts/discourse/initializers/custom-wizard-edits.js.es6 @@ -64,7 +64,7 @@ export default { this.set("customWizardCriticalNotices", criticalNotices); } }); - } + }, }); api.modifyClass("component:d-navigation", { diff --git a/assets/javascripts/discourse/lib/wizard-schema.js.es6 b/assets/javascripts/discourse/lib/wizard-schema.js.es6 index 26c21bd28d..ec8f81c40e 100644 --- a/assets/javascripts/discourse/lib/wizard-schema.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-schema.js.es6 @@ -71,7 +71,7 @@ const field = { type: null, condition: null, }, - types: {}, + type: {}, mapped: ["prefill", "content", "condition", "index"], required: ["id", "type"], dependent: {}, @@ -84,7 +84,7 @@ const action = { run_after: "wizard_completion", type: null, }, - types: { + type: { create_topic: { title: null, post: null, @@ -203,107 +203,46 @@ const custom_field = { type: ["string", "boolean", "integer", "json"], }; -const subscription_levels = { - standard: { - actions: ["send_message", "add_to_group", "watch_categories"], - custom_fields: { - klass: [], - type: ["json"], - }, - }, - - business: { - actions: ["create_category", "create_group", "send_to_api"], - custom_fields: { - klass: ["group", "category"], - type: [], - }, - }, -}; - const wizardSchema = { wizard, step, field, custom_field, action, - subscription_levels, }; -export function requiringAdditionalSubscription( - currentSubscription, - category, - subCategory +export function hasRequiredSubscription( + currentSubscriptionType, + featureSubscriptionType ) { - switch (category) { - case "actions": - switch (currentSubscription) { - case "business": - return []; - case "standard": - return subscription_levels["business"][category]; - default: - return subscription_levels["standard"][category].concat( - subscription_levels["business"][category] - ); - } - case "custom_fields": - switch (currentSubscription) { - case "business": - return []; - case "standard": - return subscription_levels["business"][category][subCategory]; - default: - return subscription_levels["standard"][category][subCategory].concat( - subscription_levels["business"][category][subCategory] - ); - } - default: - return []; - } + const types = wizardSchema.subscription.types; + return ( + types.indexOf(currentSubscriptionType) >= + types.indexOf(featureSubscriptionType) + ); } -export function subscriptionLevel(type, category, subCategory) { - switch (category) { - case "actions": - if (subscription_levels["business"].actions.includes(type)) { - return "business"; - } else { - if (subscription_levels["standard"].actions.includes(type)) { - return "standard"; - } else { - return ""; - } - } - case "custom_fields": - if ( - subscription_levels["business"].custom_fields[subCategory].includes( - type - ) - ) { - return "business"; - } else { - if ( - subscription_levels["standard"].custom_fields[subCategory].includes( - type - ) - ) { - return "standard"; - } else { - return ""; - } - } - default: - return ""; +export function subscriptionType(klass, attribute, value) { + let attributes = wizardSchema.subscription.features[klass]; + + if (!attributes || !attributes[attribute] || !attributes[attribute][value]) { + return wizardSchema.subscription.types[0]; + } else { + return attributes[attribute][value]; } } -export function buildFieldTypes(types) { - wizardSchema.field.types = types; -} +export function buildSchema(model) { + wizardSchema.subscription = {}; + + let features = model.subscription_features; + features["field"]["types"] = features["field"]["type"]; + features["action"]["types"] = features["action"]["type"]; -export function buildFieldValidations(validations) { - wizardSchema.field.validations = validations; + wizardSchema.subscription.features = features; + wizardSchema.subscription.types = model.subscription_types; + wizardSchema.field.types = model.field_types; + wizardSchema.field.validations = model.realtime_validations; } const siteSettings = getOwner(this).lookup("site-settings:main"); diff --git a/assets/javascripts/discourse/lib/wizard.js.es6 b/assets/javascripts/discourse/lib/wizard.js.es6 index 98bdbfdde6..3499102986 100644 --- a/assets/javascripts/discourse/lib/wizard.js.es6 +++ b/assets/javascripts/discourse/lib/wizard.js.es6 @@ -1,5 +1,9 @@ import EmberObject from "@ember/object"; -import wizardSchema from "./wizard-schema"; +import wizardSchema, { + hasRequiredSubscription, + subscriptionType, +} from "./wizard-schema"; +import I18n from "I18n"; function selectKitContent(content) { return content.map((i) => ({ id: i, name: i })); @@ -110,6 +114,25 @@ function wizardFieldList(steps = [], opts = {}) { }, []); } +function buildSubscriptionContent(klass, attribute, currentSubscription) { + let attributes = wizardSchema[klass]; + let values = attributes[attribute]; + + if (typeof values === "object") { + values = Object.keys(values); + } + + return values.map((value) => { + let type = subscriptionType(klass, attribute, value); + return { + id: value, + name: I18n.t(`admin.wizard.${klass}.${attribute}.${value}.label`), + subscription: type, + disabled: hasRequiredSubscription(currentSubscription, type), + }; + }); +} + export { selectKitContent, generateName, @@ -121,4 +144,5 @@ export { notificationLevels, wizardFieldList, sentenceCase, + buildSubscriptionContent, }; diff --git a/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 index b23b63f6a2..33822b0551 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 @@ -1,5 +1,5 @@ import DiscourseRoute from "discourse/routes/discourse"; -import { buildFieldTypes, buildFieldValidations } from "../lib/wizard-schema"; +import { buildSchema } from "../lib/wizard-schema"; import EmberObject, { set } from "@ember/object"; import { A } from "@ember/array"; import { all } from "rsvp"; @@ -11,8 +11,7 @@ export default DiscourseRoute.extend({ }, afterModel(model) { - buildFieldTypes(model.field_types); - buildFieldValidations(model.realtime_validations); + buildSchema(model); return all([ this._getThemes(model), diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs index abf06ba9bc..0886c51944 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs @@ -55,31 +55,41 @@
Text
") expect(json_array[0][:description]).to eq("Text field description.") - expect(json_array[3][:index]).to eq(3) + expect(json_array[2][:index]).to eq(2) end it "should return optional field attributes" do diff --git a/spec/serializers/custom_wizard/wizard_serializer_spec.rb b/spec/serializers/custom_wizard/wizard_serializer_spec.rb index fe36d5a269..6136ffe056 100644 --- a/spec/serializers/custom_wizard/wizard_serializer_spec.rb +++ b/spec/serializers/custom_wizard/wizard_serializer_spec.rb @@ -42,55 +42,73 @@ ).to eq(BasicUserSerializer.new(user, root: false).as_json) end - it "should not return categories if there are no category fields" do - @template[:steps][2][:fields].delete_at(2) - CustomWizard::Template.save(@template) + context "with subscription" do + before do + enable_subscription("standard") + end - json = CustomWizard::WizardSerializer.new( - CustomWizard::Builder.new(@template[:id], user).build, - scope: Guardian.new(user) - ).as_json - expect(json[:wizard][:categories].present?).to eq(false) - expect(json[:wizard][:uncategorized_category_id].present?).to eq(false) - end + it "should not return categories if there are no category fields" do + @template[:steps][2][:fields].delete_at(2) + CustomWizard::Template.save(@template) - it "should return categories if there is a category selector field" do - json = CustomWizard::WizardSerializer.new( - CustomWizard::Builder.new(@template[:id], user).build, - scope: Guardian.new(user) - ).as_json - expect(json[:wizard][:categories].present?).to eq(true) - expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) - end + json = CustomWizard::WizardSerializer.new( + CustomWizard::Builder.new(@template[:id], user).build, + scope: Guardian.new(user) + ).as_json - it "should return categories if there is a similar topics validation scoped to category(s)" do - @template[:steps][0][:fields][0][:validations] = similar_topics_validation[:validations] - CustomWizard::Template.save(@template) + expect(json[:wizard][:categories].present?).to eq(false) + expect(json[:wizard][:uncategorized_category_id].present?).to eq(false) + end - json = CustomWizard::WizardSerializer.new( - CustomWizard::Builder.new(@template[:id], user).build, - scope: Guardian.new(user) - ).as_json - expect(json[:wizard][:categories].present?).to eq(true) - expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) - end + it "should return categories if there is a category selector field" do + @template[:steps][0][:fields] << { "id": "step_1_field_5", "label": "Category", "type": "category" }.as_json + CustomWizard::Template.save(@template) - it 'should return groups if there is a group selector field' do - json = CustomWizard::WizardSerializer.new( - CustomWizard::Builder.new(@template[:id], user).build, - scope: Guardian.new(user) - ).as_json - expect(json[:wizard][:groups].length).to eq(8) - end + json = CustomWizard::WizardSerializer.new( + CustomWizard::Builder.new(@template[:id], user).build, + scope: Guardian.new(user) + ).as_json - it 'should not return groups if there is not a group selector field' do - @template[:steps][2][:fields].delete_at(3) - CustomWizard::Template.save(@template) + expect(json[:wizard][:categories].present?).to eq(true) + expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) + end - json = CustomWizard::WizardSerializer.new( - CustomWizard::Builder.new(@template[:id], user).build, - scope: Guardian.new(user) - ).as_json - expect(json[:wizard][:groups].present?).to eq(false) + it "should return categories if there is a similar topics validation scoped to category(s)" do + @template[:steps][0][:fields][0][:validations] = similar_topics_validation + CustomWizard::Template.save(@template) + + json = CustomWizard::WizardSerializer.new( + CustomWizard::Builder.new(@template[:id], user).build, + scope: Guardian.new(user) + ).as_json + + expect(json[:wizard][:categories].present?).to eq(true) + expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) + end + + it 'should return groups if there is a group selector field' do + @template[:steps][0][:fields] << { "id": "step_1_field_5", "label": "Group", "type": "group" }.as_json + CustomWizard::Template.save(@template) + + json = CustomWizard::WizardSerializer.new( + CustomWizard::Builder.new(@template[:id], user).build, + scope: Guardian.new(user) + ).as_json + + expect(json[:wizard][:groups].present?).to eq(true) + expect(json[:wizard][:groups].length).to eq(8) + end + + it 'should not return groups if there is not a group selector field' do + @template[:steps][2][:fields].delete_at(3) + CustomWizard::Template.save(@template) + + json = CustomWizard::WizardSerializer.new( + CustomWizard::Builder.new(@template[:id], user).build, + scope: Guardian.new(user) + ).as_json + + expect(json[:wizard][:groups].present?).to eq(false) + end end end diff --git a/spec/serializers/custom_wizard/wizard_step_serializer_spec.rb b/spec/serializers/custom_wizard/wizard_step_serializer_spec.rb index f01287651e..57ef8ae3aa 100644 --- a/spec/serializers/custom_wizard/wizard_step_serializer_spec.rb +++ b/spec/serializers/custom_wizard/wizard_step_serializer_spec.rb @@ -29,12 +29,12 @@ each_serializer: described_class, scope: Guardian.new(user) ).as_json - expect(json_array[0][:fields].length).to eq(4) + expect(json_array[0][:fields].length).to eq(3) end context 'with required data' do before do - enable_subscription("standard") + enable_subscription("business") wizard_template['steps'][0]['required_data'] = required_data_json['required_data'] wizard_template['steps'][0]['required_data_message'] = required_data_json['required_data_message'] CustomWizard::Template.save(wizard_template)