Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 09:20:29 +01:00
wip
Dieser Commit ist enthalten in:
Ursprung
270d3bccf5
Commit
084c6f4a7a
94 geänderte Dateien mit 1228 neuen und 413 gelöschten Zeilen
|
@ -6,20 +6,20 @@ import I18n from "I18n";
|
||||||
|
|
||||||
const klasses = ["topic", "post", "group", "category"];
|
const klasses = ["topic", "post", "group", "category"];
|
||||||
const types = ["string", "boolean", "integer", "json"];
|
const types = ["string", "boolean", "integer", "json"];
|
||||||
const proTypes = {
|
const subscriptionTypes = {
|
||||||
klass: ["group", "category"],
|
klass: ["group", "category"],
|
||||||
type: ["json"],
|
type: ["json"],
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateContent = function (array, type, proSubscribed = false) {
|
const generateContent = function (array, type, subscribed = false) {
|
||||||
return array.reduce((result, key) => {
|
return array.reduce((result, key) => {
|
||||||
let proArr = proTypes[type];
|
let subArr = subscriptionTypes[type];
|
||||||
let pro = proArr && proArr.includes(key);
|
let subscription = subArr && subArr.includes(key);
|
||||||
if (!pro || proSubscribed) {
|
if (!subscription || subscribed) {
|
||||||
result.push({
|
result.push({
|
||||||
id: key,
|
id: key,
|
||||||
name: I18n.t(`admin.wizard.custom_field.${type}.${key}`),
|
name: I18n.t(`admin.wizard.custom_field.${type}.${key}`),
|
||||||
pro,
|
subscription,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -32,11 +32,11 @@ export default Component.extend({
|
||||||
postSerializers: ["post"],
|
postSerializers: ["post"],
|
||||||
groupSerializers: ["basic_group"],
|
groupSerializers: ["basic_group"],
|
||||||
categorySerializers: ["basic_category"],
|
categorySerializers: ["basic_category"],
|
||||||
klassContent: computed("proSubscribed", function () {
|
klassContent: computed("subscribed", function () {
|
||||||
return generateContent(klasses, "klass", this.proSubscribed);
|
return generateContent(klasses, "klass", this.subscribed);
|
||||||
}),
|
}),
|
||||||
typeContent: computed("proSubscribed", function () {
|
typeContent: computed("subscribed", function () {
|
||||||
return generateContent(types, "type", this.proSubscribed);
|
return generateContent(types, "type", this.subscribed);
|
||||||
}),
|
}),
|
||||||
showInputs: or("field.new", "field.edit"),
|
showInputs: or("field.new", "field.edit"),
|
||||||
classNames: ["custom-field-input"],
|
classNames: ["custom-field-input"],
|
||||||
|
@ -54,7 +54,7 @@ export default Component.extend({
|
||||||
const serializers = this.get(`${klass}Serializers`);
|
const serializers = this.get(`${klass}Serializers`);
|
||||||
|
|
||||||
if (serializers) {
|
if (serializers) {
|
||||||
return generateContent(serializers, "serializers", this.proSubscribed);
|
return generateContent(serializers, "serializers", this.subscribed);
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
classNameBindings: [":subscription-container", "subscribed"],
|
||||||
|
|
||||||
|
@discourseComputed('subscribed')
|
||||||
|
subscribedIcon(subscribed) {
|
||||||
|
return subscribed ? 'check' : 'dash';
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed('subscribed')
|
||||||
|
subscribedLabel(subscribed) {
|
||||||
|
return `admin.wizard.subscription_container.${subscribed ? 'subscribed' : 'not_subscribed'}.label`;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed('subscribed')
|
||||||
|
subscribedTitle(subscribed) {
|
||||||
|
return `admin.wizard.subscription_container.${subscribed ? 'subscribed' : 'not_subscribed'}.title`;
|
||||||
|
}
|
||||||
|
})
|
|
@ -94,15 +94,15 @@ export default Component.extend(UndoChanges, {
|
||||||
return apis.find((a) => a.name === api).endpoints;
|
return apis.find((a) => a.name === api).endpoints;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("proSubscribed")
|
@discourseComputed("subscribed")
|
||||||
actionTypes(proSubscribed) {
|
actionTypes(subscribed) {
|
||||||
return Object.keys(wizardSchema.action.types).reduce((result, type) => {
|
return Object.keys(wizardSchema.action.types).reduce((result, type) => {
|
||||||
let pro = wizardSchema.action.proTypes.includes(type);
|
let subscription = wizardSchema.action.subscriptionTypes.includes(type);
|
||||||
if (proSubscribed || !pro) {
|
if (subscribed || !subscription) {
|
||||||
result.push({
|
result.push({
|
||||||
id: type,
|
id: type,
|
||||||
name: I18n.t(`admin.wizard.action.${type}.label`),
|
name: I18n.t(`admin.wizard.action.${type}.label`),
|
||||||
pro,
|
subscription,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
34
assets/javascripts/discourse/components/wizard-notice.js.es6
Normale Datei
34
assets/javascripts/discourse/components/wizard-notice.js.es6
Normale Datei
|
@ -0,0 +1,34 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import { notEmpty, not } from "@ember/object/computed";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
classNameBindings: [':wizard-notice', 'notice.type', 'dismissed', 'expired'],
|
||||||
|
showFull: false,
|
||||||
|
resolved: notEmpty('notice.expired_at'),
|
||||||
|
dismissed: notEmpty('notice.dismissed_at'),
|
||||||
|
canDismiss: not('dismissed'),
|
||||||
|
|
||||||
|
@discourseComputed('notice.type')
|
||||||
|
title(type) {
|
||||||
|
return I18n.t(`admin.wizard.notice.title.${type}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed('notice.type')
|
||||||
|
icon(type) {
|
||||||
|
return {
|
||||||
|
warning: 'exclamation-circle',
|
||||||
|
info: 'info-circle'
|
||||||
|
}[type];
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
dismiss() {
|
||||||
|
this.set('dismissing', true)
|
||||||
|
this.notice.dismiss().then(() => {
|
||||||
|
this.set('dismissing', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -6,7 +6,7 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: ["realtime-validations", "setting", "full", "pro"],
|
classNames: ["realtime-validations", "setting", "full", "subscription"],
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
timeUnits() {
|
timeUnits() {
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import SingleSelectComponent from "select-kit/components/single-select";
|
import SingleSelectComponent from "select-kit/components/single-select";
|
||||||
|
|
||||||
export default SingleSelectComponent.extend({
|
export default SingleSelectComponent.extend({
|
||||||
classNames: ["combo-box", "wizard-pro-selector"],
|
classNames: ["combo-box", "wizard-subscription-selector"],
|
||||||
|
|
||||||
selectKitOptions: {
|
selectKitOptions: {
|
||||||
autoFilterable: false,
|
autoFilterable: false,
|
||||||
filterable: false,
|
filterable: false,
|
||||||
showFullTitle: true,
|
showFullTitle: true,
|
||||||
headerComponent: "wizard-pro-selector/wizard-pro-selector-header",
|
headerComponent: "wizard-subscription-selector/wizard-subscription-selector-header",
|
||||||
caretUpIcon: "caret-up",
|
caretUpIcon: "caret-up",
|
||||||
caretDownIcon: "caret-down",
|
caretDownIcon: "caret-down",
|
||||||
},
|
},
|
||||||
|
|
||||||
modifyComponentForRow() {
|
modifyComponentForRow() {
|
||||||
return "wizard-pro-selector/wizard-pro-selector-row";
|
return "wizard-subscription-selector/wizard-subscription-selector-row";
|
||||||
},
|
},
|
||||||
});
|
});
|
|
@ -3,7 +3,7 @@ import { computed } from "@ember/object";
|
||||||
import { reads } from "@ember/object/computed";
|
import { reads } from "@ember/object/computed";
|
||||||
|
|
||||||
export default SingleSelectHeaderComponent.extend({
|
export default SingleSelectHeaderComponent.extend({
|
||||||
classNames: ["combo-box-header", "wizard-pro-selector-header"],
|
classNames: ["combo-box-header", "wizard-subscription-selector-header"],
|
||||||
caretUpIcon: reads("selectKit.options.caretUpIcon"),
|
caretUpIcon: reads("selectKit.options.caretUpIcon"),
|
||||||
caretDownIcon: reads("selectKit.options.caretDownIcon"),
|
caretDownIcon: reads("selectKit.options.caretDownIcon"),
|
||||||
caretIcon: computed(
|
caretIcon: computed(
|
|
@ -1,12 +1,12 @@
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import CustomWizardPro from "../models/custom-wizard-pro";
|
import CustomWizardSubscription from "../models/custom-wizard-subscription";
|
||||||
import { notEmpty } from "@ember/object/computed";
|
import { notEmpty } from "@ember/object/computed";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNameBindings: [
|
classNameBindings: [
|
||||||
":custom-wizard-pro-subscription",
|
":custom-wizard-subscription",
|
||||||
"subscription.active:active:inactive",
|
"subscription.active:active:inactive",
|
||||||
],
|
],
|
||||||
subscribed: notEmpty("subscription"),
|
subscribed: notEmpty("subscription"),
|
||||||
|
@ -14,8 +14,8 @@ export default Component.extend({
|
||||||
@discourseComputed("subscription.type")
|
@discourseComputed("subscription.type")
|
||||||
title(type) {
|
title(type) {
|
||||||
return type
|
return type
|
||||||
? I18n.t(`admin.wizard.pro.subscription.title.${type}`)
|
? I18n.t(`admin.wizard.subscription.subscription.title.${type}`)
|
||||||
: I18n.t("admin.wizard.pro.not_subscribed");
|
: I18n.t("admin.wizard.subscription.not_subscribed");
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("subscription.active")
|
@discourseComputed("subscription.active")
|
||||||
|
@ -25,13 +25,13 @@ export default Component.extend({
|
||||||
|
|
||||||
@discourseComputed("stateClass")
|
@discourseComputed("stateClass")
|
||||||
stateLabel(stateClass) {
|
stateLabel(stateClass) {
|
||||||
return I18n.t(`admin.wizard.pro.subscription.status.${stateClass}`);
|
return I18n.t(`admin.wizard.subscription.subscription.status.${stateClass}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
update() {
|
update() {
|
||||||
this.set("updating", true);
|
this.set("updating", true);
|
||||||
CustomWizardPro.update_subscription()
|
CustomWizardSubscription.update()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
this.setProperties({
|
this.setProperties({
|
|
@ -0,0 +1,3 @@
|
||||||
|
{{#if wizardWarningNotice}}
|
||||||
|
{{wizard-notice notice=wizardWarningNotice}}
|
||||||
|
{{/if}}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setupComponent() {
|
||||||
|
const controller = getOwner(this).lookup('controller:admin-dashboard')
|
||||||
|
const wizardWarningNotice = controller.get('wizardWarningNotice');
|
||||||
|
|
||||||
|
if (wizardWarningNotice) {
|
||||||
|
this.set('wizardWarningNotice', wizardWarningNotice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
{{#if currentUser.admin}}
|
{{#if currentUser.admin}}
|
||||||
{{nav-item route="adminWizards" label="admin.wizard.nav_label"}}
|
{{nav-item route="adminWizards" label="admin.wizard.nav_label"}}
|
||||||
|
|
||||||
|
{{#if wizardErrorNotice}}
|
||||||
|
{{d-icon "exclaimation-circle"}}
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import CustomWizardPro from "../models/custom-wizard-pro";
|
import CustomWizardSubscription from "../models/custom-wizard-subscription";
|
||||||
import { alias } from "@ember/object/computed";
|
import { alias } from "@ember/object/computed";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
20
assets/javascripts/discourse/controllers/admin-wizards.js.es6
Normale Datei
20
assets/javascripts/discourse/controllers/admin-wizards.js.es6
Normale Datei
|
@ -0,0 +1,20 @@
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
actions: {
|
||||||
|
dismissNotice(noticeId) {
|
||||||
|
ajax(`/admin/wizards/notice/${this.id}`, {
|
||||||
|
type: "DELETE",
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
const notices = this.notices;
|
||||||
|
notices.removeObject(notices.findBy('id', noticeId));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -59,8 +59,8 @@ export default {
|
||||||
resetNamespace: true,
|
resetNamespace: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route("adminWizardsPro", {
|
this.route("adminWizardsSubscription", {
|
||||||
path: "/pro",
|
path: "/subscription",
|
||||||
resetNamespace: true,
|
resetNamespace: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import DiscourseURL from "discourse/lib/url";
|
||||||
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import CustomWizardNotice from "../models/custom-wizard-notice";
|
||||||
|
import { A } from "@ember/array";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "custom-wizard-edits",
|
name: "custom-wizard-edits",
|
||||||
|
@ -16,5 +20,29 @@ export default {
|
||||||
}
|
}
|
||||||
return existing.apply(this, [path, opts]);
|
return existing.apply(this, [path, opts]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
withPluginApi("0.8.36", (api) => {
|
||||||
|
api.modifyClass('route:admin-dashboard', {
|
||||||
|
afterModel() {
|
||||||
|
return CustomWizardNotice.list().then(result => {
|
||||||
|
if (result && result.length) {
|
||||||
|
this.set('notices', A(result.map(n => CustomWizardNotice.create(n))));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
if (this.notices) {
|
||||||
|
let warningNotices = this.notices.filter(n => n.type === 'warning');
|
||||||
|
|
||||||
|
if (warningNotices.length) {
|
||||||
|
controller.set('wizardWarningNotice', warningNotices[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super(...arguments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -193,6 +193,14 @@ const action = {
|
||||||
"members_visibility_level",
|
"members_visibility_level",
|
||||||
],
|
],
|
||||||
required: ["id", "type"],
|
required: ["id", "type"],
|
||||||
|
subscriptionTypes: [
|
||||||
|
"send_message",
|
||||||
|
"add_to_group",
|
||||||
|
"create_category",
|
||||||
|
"create_group",
|
||||||
|
"send_to_api",
|
||||||
|
],
|
||||||
|
required: ["id", "type"],
|
||||||
proTypes: [
|
proTypes: [
|
||||||
"send_message",
|
"send_message",
|
||||||
"add_to_group",
|
"add_to_group",
|
||||||
|
|
23
assets/javascripts/discourse/models/custom-wizard-notice.js.es6
Normale Datei
23
assets/javascripts/discourse/models/custom-wizard-notice.js.es6
Normale Datei
|
@ -0,0 +1,23 @@
|
||||||
|
import EmberObject from "@ember/object";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
|
const CustomWizardNotice = EmberObject.extend();
|
||||||
|
|
||||||
|
CustomWizardNotice.reopen({
|
||||||
|
dismiss() {
|
||||||
|
return ajax(`/admin/wizards/notice/${this.id}`, { type: 'PUT' }).then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
this.set('dismissed_at', result.dismissed_at);
|
||||||
|
}
|
||||||
|
}).catch(popupAjaxError)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CustomWizardNotice.reopenClass({
|
||||||
|
list() {
|
||||||
|
return ajax('/admin/wizards/notice').catch(popupAjaxError)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CustomWizardNotice;
|
|
@ -2,11 +2,11 @@ import { ajax } from "discourse/lib/ajax";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
|
|
||||||
const CustomWizardPro = EmberObject.extend();
|
const CustomWizardSubscription = EmberObject.extend();
|
||||||
|
|
||||||
const basePath = "/admin/wizards/pro";
|
const basePath = "/admin/wizards/subscription";
|
||||||
|
|
||||||
CustomWizardPro.reopenClass({
|
CustomWizardSubscription.reopenClass({
|
||||||
status() {
|
status() {
|
||||||
return ajax(basePath, {
|
return ajax(basePath, {
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
@ -23,11 +23,11 @@ CustomWizardPro.reopenClass({
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
update_subscription() {
|
update() {
|
||||||
return ajax(`${basePath}/subscription`, {
|
return ajax(basePath, {
|
||||||
type: "POST",
|
type: "POST",
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default CustomWizardPro;
|
export default CustomWizardSubscription;
|
|
@ -9,11 +9,11 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
const customFields = A(model.custom_fields || []);
|
const customFields = A(model.custom_fields || []);
|
||||||
const proSubscribed = model.pro_subscribed;
|
const subscribed = model.subscribed;
|
||||||
|
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
customFields,
|
customFields,
|
||||||
proSubscribed,
|
subscribed,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import CustomWizardPro from "../models/custom-wizard-pro";
|
import CustomWizardSubscription from "../models/custom-wizard-subscription";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
model() {
|
model() {
|
||||||
return CustomWizardPro.status();
|
return CustomWizardSubscription.status();
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
|
@ -13,7 +13,7 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
authorize() {
|
authorize() {
|
||||||
CustomWizardPro.authorize();
|
CustomWizardSubscription.authorize();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
|
@ -39,7 +39,7 @@ export default DiscourseRoute.extend({
|
||||||
currentStep: wizard.steps[0],
|
currentStep: wizard.steps[0],
|
||||||
currentAction: wizard.actions[0],
|
currentAction: wizard.actions[0],
|
||||||
creating: model.create,
|
creating: model.create,
|
||||||
proSubscribed: parentModel.pro_subscribed,
|
subscribed: parentModel.subscribed,
|
||||||
};
|
};
|
||||||
|
|
||||||
controller.setProperties(props);
|
controller.setProperties(props);
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { A } from "@ember/array";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
beforeModel(transition) {
|
model() {
|
||||||
|
return ajax('/admin/wizards');
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
controller.set('notices', A(model.notices));
|
||||||
|
},
|
||||||
|
|
||||||
|
afterModel(model, transition) {
|
||||||
if (transition.targetName === "adminWizards.index") {
|
if (transition.targetName === "adminWizards.index") {
|
||||||
this.transitionTo("adminWizardsWizard");
|
this.transitionTo("adminWizardsWizard");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
field=field
|
field=field
|
||||||
removeField=(action "removeField")
|
removeField=(action "removeField")
|
||||||
saveField=(action "saveField")
|
saveField=(action "saveField")
|
||||||
proSubscribed=proSubscribed}}
|
subscribed=subscribed}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
<div class="admin-wizard-controls">
|
|
||||||
<h3>{{i18n "admin.wizard.pro.title"}}</h3>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
{{#if model.authentication.active}}
|
|
||||||
{{conditional-loading-spinner size="small" condition=unauthorizing}}
|
|
||||||
<a {{action "unauthorize"}} title={{i18n "admin.wizard.pro.unauthorize"}} role="button">
|
|
||||||
{{i18n "admin.wizard.pro.unauthorize"}}
|
|
||||||
</a>
|
|
||||||
<label title={{i18n "admin.wizard.pro.authorized"}}>
|
|
||||||
{{i18n "admin.wizard.pro.authorized"}}
|
|
||||||
</label>
|
|
||||||
{{else}}
|
|
||||||
{{d-button
|
|
||||||
icon="id-card"
|
|
||||||
label="admin.wizard.pro.authorize"
|
|
||||||
title="admin.wizard.pro.authorize"
|
|
||||||
action=(route-action "authorize")}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{wizard-message
|
|
||||||
key=messageKey
|
|
||||||
url=messageUrl
|
|
||||||
type=messageType
|
|
||||||
opts=messageOpts
|
|
||||||
component="pro"}}
|
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
|
||||||
{{#if showSubscription}}
|
|
||||||
{{wizard-pro-subscription subscription=model.subscription}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<div class="admin-wizard-controls">
|
||||||
|
<h3>{{i18n "admin.wizard.subscription.title"}}</h3>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
{{#if model.authentication.active}}
|
||||||
|
{{conditional-loading-spinner size="small" condition=unauthorizing}}
|
||||||
|
<a {{action "unauthorize"}} title={{i18n "admin.wizard.subscription.unauthorize"}} role="button">
|
||||||
|
{{i18n "admin.wizard.subscription.unauthorize"}}
|
||||||
|
</a>
|
||||||
|
<label title={{i18n "admin.wizard.subscription.authorized"}}>
|
||||||
|
{{i18n "admin.wizard.subscription.authorized"}}
|
||||||
|
</label>
|
||||||
|
{{else}}
|
||||||
|
{{d-button
|
||||||
|
icon="id-card"
|
||||||
|
class="btn-primary"
|
||||||
|
label="admin.wizard.subscription.authorize"
|
||||||
|
title="admin.wizard.subscription.authorize"
|
||||||
|
action=(route-action "authorize")}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{wizard-message
|
||||||
|
key=messageKey
|
||||||
|
url=messageUrl
|
||||||
|
type=messageType
|
||||||
|
opts=messageOpts
|
||||||
|
component="subscription"}}
|
||||||
|
|
||||||
|
<div class="admin-wizard-container">
|
||||||
|
{{#if showSubscription}}
|
||||||
|
{{wizard-subscription subscription=model.subscription}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
|
@ -126,11 +126,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if proSubscribed}}
|
{{#subscription-container subscribed=subscribed}}
|
||||||
<div class="setting pro">
|
<div class="setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.save_submissions}}
|
{{input type="checkbox" checked=wizard.save_submissions}}
|
||||||
|
@ -138,17 +137,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting pro">
|
<div class="setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.restart_on_revisit}}
|
{{input type="checkbox" checked=wizard.restart_on_revisit}}
|
||||||
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/subscription-container}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
|
@ -163,7 +161,7 @@
|
||||||
currentField=currentField
|
currentField=currentField
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields
|
||||||
fieldTypes=fieldTypes
|
fieldTypes=fieldTypes
|
||||||
proSubscribed=proSubscribed}}
|
subscribed=subscribed}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
|
@ -180,7 +178,7 @@
|
||||||
apis=apis
|
apis=apis
|
||||||
removeAction="removeAction"
|
removeAction="removeAction"
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields
|
||||||
proSubscribed=proSubscribed}}
|
subscribed=subscribed}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
<div class="admin-wizard-buttons">
|
<div class="admin-wizard-buttons">
|
||||||
|
|
|
@ -7,13 +7,18 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
||||||
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
||||||
{{nav-item route="adminWizardsPro" label="admin.wizard.pro.nav_label"}}
|
{{nav-item route="adminWizardsSubscription" label="admin.wizard.subscription.nav_label"}}
|
||||||
|
|
||||||
<div class="admin-actions">
|
<div class="admin-actions">
|
||||||
<a target="_blank" class="btn btn-pavilion-pro" rel="noreferrer noopener" href="https://thepavilion.io/w/support" title={{i18n "admin.wizard.pro_support_button.title"}}>{{d-icon "far-life-ring"}}{{i18n "admin.wizard.pro_support_button.label"}}</a>
|
<a target="_blank" class="btn btn-pavilion-support" rel="noreferrer noopener" href="https://thepavilion.io/w/support" title={{i18n "admin.wizard.support_button.title"}}>
|
||||||
|
{{d-icon "far-life-ring"}}{{i18n "admin.wizard.support_button.label"}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{/admin-nav}}
|
{{/admin-nav}}
|
||||||
|
|
||||||
<div class="admin-container">
|
<div class="admin-container">
|
||||||
|
{{#each notices as |notice|}}
|
||||||
|
{{wizard-notice notice=notice}}
|
||||||
|
{{/each}}
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{{#if showInputs}}
|
{{#if showInputs}}
|
||||||
<td>
|
<td>
|
||||||
{{wizard-pro-selector
|
{{wizard-subscription-selector
|
||||||
value=field.klass
|
value=field.klass
|
||||||
content=klassContent
|
content=klassContent
|
||||||
none="admin.wizard.custom_field.klass.select"
|
none="admin.wizard.custom_field.klass.select"
|
||||||
onChange=(action (mut field.klass))}}
|
onChange=(action (mut field.klass))}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{wizard-pro-selector
|
{{wizard-subscription-selector
|
||||||
value=field.type
|
value=field.type
|
||||||
content=typeContent
|
content=typeContent
|
||||||
none="admin.wizard.custom_field.type.select"
|
none="admin.wizard.custom_field.type.select"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class=subscription-header>
|
||||||
|
<h3>{{i18n 'admin.wizard.subscription_container.title'}}</h3>
|
||||||
|
|
||||||
|
<a href="/admin/wizards/subscription" title={{i18n subscribedTitle}}>
|
||||||
|
{{d-icon subscribedIcon}}
|
||||||
|
{{i18n subscribedLabel}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subscription-settings">
|
||||||
|
{{yield}}
|
||||||
|
</div>
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{wizard-pro-selector
|
{{wizard-subscription-selector
|
||||||
value=action.type
|
value=action.type
|
||||||
content=actionTypes
|
content=actionTypes
|
||||||
onChange=(action "changeType")
|
onChange=(action "changeType")
|
||||||
|
|
|
@ -207,11 +207,10 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if proSubscribed}}
|
{{#subscription-container subscribed=subscribed}}
|
||||||
<div class="setting full field-mapper-setting pro">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.condition"}}</label>
|
<label>{{i18n "admin.wizard.condition"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
|
@ -221,10 +220,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting full field-mapper-setting pro">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.index"}}</label>
|
<label>{{i18n "admin.wizard.index"}}</label>>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
|
@ -256,4 +254,4 @@
|
||||||
{{#if validations}}
|
{{#if validations}}
|
||||||
{{wizard-realtime-validations field=field validations=validations}}
|
{{wizard-realtime-validations field=field validations=validations}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/subscription-container}}
|
||||||
|
|
|
@ -33,11 +33,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if proSubscribed}}
|
{{#subscription-container subscribed=subscribed}}
|
||||||
<div class="setting full field-mapper-setting pro">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.condition"}}</label>
|
<label>{{i18n "admin.wizard.condition"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
|
@ -83,10 +82,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting full field-mapper-setting pro">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
|
<label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{wizard-mapper
|
{{wizard-mapper
|
||||||
|
@ -100,7 +98,7 @@
|
||||||
)}}
|
)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/subscription-container}}
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
itemType="field"
|
itemType="field"
|
||||||
|
@ -116,5 +114,5 @@
|
||||||
fieldTypes=fieldTypes
|
fieldTypes=fieldTypes
|
||||||
removeField="removeField"
|
removeField="removeField"
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields
|
||||||
proSubscribed=proSubscribed}}
|
subscribed=subscribed}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
37
assets/javascripts/discourse/templates/components/wizard-notice.hbs
Normale Datei
37
assets/javascripts/discourse/templates/components/wizard-notice.hbs
Normale Datei
|
@ -0,0 +1,37 @@
|
||||||
|
<div class="notice-header">
|
||||||
|
{{#if resolved}}
|
||||||
|
<div class="notice-expired-at notice-badge" title={{notice.expired_at}}>
|
||||||
|
{{d-icon "check"}}
|
||||||
|
<span class="notice-resolved">{{i18n "admin.wizard.notice.resolved"}}</span>
|
||||||
|
{{format-date notice.expired_at leaveAgo="true"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="notice-title notice-badge" title={{title}}>
|
||||||
|
{{d-icon icon}}
|
||||||
|
<span>{{title}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="notice-created-at notice-badge" title={{notice.created_at}}>
|
||||||
|
{{d-icon "calendar-alt"}}
|
||||||
|
<span class="notice-issued">{{i18n "admin.wizard.notice.issued"}}</span>
|
||||||
|
{{format-date notice.created_at leaveAgo="true"}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="notice-plugin notice-badge" title={{i18n "admin.wizard.notice.plugin"}}>
|
||||||
|
{{d-icon "plug"}}
|
||||||
|
<span>{{i18n "admin.wizard.notice.plugin"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="notice-message">
|
||||||
|
{{{notice.message}}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if canDismiss}}
|
||||||
|
{{#if dismissing}}
|
||||||
|
{{loading-spinner size="small"}}
|
||||||
|
{{else}}
|
||||||
|
<a {{action "dismiss"}} role="button" class="dismiss-notice">{{d-icon "times"}}</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
|
@ -1,6 +1,5 @@
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.field.validations.header"}}</label>
|
<label>{{i18n "admin.wizard.field.validations.header"}}</label>
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value full">
|
<div class="setting-value full">
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
shouldDisplayClearableButton=shouldDisplayClearableButton
|
shouldDisplayClearableButton=shouldDisplayClearableButton
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{{#if selectedContent.pro}}
|
{{#if selectedContent.subscription}}
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
<span class="subscription-label">{{i18n "admin.wizard.subscription.label"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{d-icon caretIcon class="caret-icon"}}
|
{{d-icon caretIcon class="caret-icon"}}
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<div class="texts">
|
<div class="texts">
|
||||||
<span class="name">{{html-safe label}}</span>
|
<span class="name">{{html-safe label}}</span>
|
||||||
{{#if item.pro}}
|
{{#if item.subscription}}
|
||||||
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
|
<span class="subscription-label">{{i18n "admin.wizard.subscription.label"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
|
@ -13,8 +13,8 @@
|
||||||
icon="sync"
|
icon="sync"
|
||||||
action=(action "update")
|
action=(action "update")
|
||||||
disabled=updating
|
disabled=updating
|
||||||
title="admin.wizard.pro.subscription.update"
|
title="admin.wizard.subscription.subscription.update"
|
||||||
label="admin.wizard.pro.subscription.update"}}
|
label="admin.wizard.subscription.subscription.update"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
{{#if subscription.updated_at}}
|
{{#if subscription.updated_at}}
|
||||||
<div class="subscription-updated-at" title={{subscription.updated_at}}>
|
<div class="subscription-updated-at" title={{subscription.updated_at}}>
|
||||||
{{i18n "admin.wizard.pro.subscription.last_updated"}} {{format-date subscription.updated_at leaveAgo="true"}}
|
{{i18n "admin.wizard.subscription.subscription.last_updated"}} {{format-date subscription.updated_at leaveAgo="true"}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
|
@ -1,8 +1,8 @@
|
||||||
@import "wizard-mapper";
|
@import "wizard/mapper";
|
||||||
@import "wizard-manager";
|
@import "wizard/manager";
|
||||||
@import "wizard-api";
|
@import "wizard/api";
|
||||||
@import "common/components/buttons";
|
@import "common/components/buttons";
|
||||||
@import "wizard-variables";
|
@import "wizard/variables";
|
||||||
|
|
||||||
.admin-wizard-controls {
|
.admin-wizard-controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-settings-parent {
|
.wizard-settings-parent {
|
||||||
padding: 20px;
|
padding: 1em;
|
||||||
border: 1px solid var(--primary-low);
|
border: 1px solid var(--primary-low);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
|
|
||||||
.wizard-basic-details,
|
.wizard-basic-details,
|
||||||
.wizard-custom-field,
|
.wizard-custom-field,
|
||||||
.advanced-settings {
|
.subscription-settings {
|
||||||
@extend .wizard-settings-group;
|
@extend .wizard-settings-group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.pro {
|
&.subscription {
|
||||||
.setting-label {
|
.setting-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -423,15 +423,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.advanced-settings {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 30px;
|
|
||||||
|
|
||||||
[class~="setting"]:first-of-type {
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-custom-action > [class~="setting"]:first-of-type {
|
.wizard-custom-action > [class~="setting"]:first-of-type {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -735,7 +726,7 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
background-color: var(--primary-low);
|
border: 1px solid var(--primary);
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin: 0 0 1em 0;
|
margin: 0 0 1em 0;
|
||||||
|
|
||||||
|
@ -797,12 +788,12 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pro-label {
|
.subscription-label {
|
||||||
color: var(--tertiary);
|
color: var(--tertiary);
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-wizards-pro {
|
.admin-wizards-subscription {
|
||||||
.admin-wizard-controls {
|
.admin-wizard-controls {
|
||||||
h3,
|
h3,
|
||||||
label {
|
label {
|
||||||
|
@ -826,7 +817,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-wizard-pro-subscription {
|
.custom-wizard-subscription {
|
||||||
.title-container {
|
.title-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -861,19 +852,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-pro-selector.select-kit.single-select {
|
.wizard-subscription-selector.select-kit.single-select {
|
||||||
.select-kit-row .texts {
|
.select-kit-row .texts {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pro-label {
|
.subscription-label {
|
||||||
margin-left: 0.75em;
|
margin-left: 0.75em;
|
||||||
padding-top: 0.25em;
|
padding-top: 0.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn.btn-pavilion-pro {
|
.btn.btn-pavilion-support {
|
||||||
background: var(--pavilion-primary);
|
background: var(--pavilion-primary);
|
||||||
color: var(--pavilion-secondary);
|
color: var(--pavilion-secondary);
|
||||||
|
|
||||||
|
@ -883,11 +874,108 @@
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: darken($pavilionPrimary, 5%);
|
background: darken($pavilion_primary, 5%);
|
||||||
|
|
||||||
&[href],
|
&[href],
|
||||||
svg.d-icon {
|
svg.d-icon {
|
||||||
color: darken($pavilionSecondary, 10%);
|
color: darken($pavilion_secondary, 10%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subscription-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: rgba($pavilion_primary, 0.1);
|
||||||
|
|
||||||
|
.subscription-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--pavilion-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.subscribed) .subscription-settings {
|
||||||
|
filter: blur(1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-notice {
|
||||||
|
padding: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.dismissed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d-icon {
|
||||||
|
margin-right: .4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-badge {
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 .5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 1em;
|
||||||
|
font-size: .9em;
|
||||||
|
line-height: 25px;
|
||||||
|
min-height: 25px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
.notice-expired-at {
|
||||||
|
border: 1px solid var(--success);
|
||||||
|
background-color: rgba($success, 0.1);
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-title {
|
||||||
|
border: 1px solid var(--pavilion-warning);
|
||||||
|
background-color: rgba($pavilion_warning, 0.1);
|
||||||
|
color: var(--pavilion-warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-issued {
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-message {
|
||||||
|
p {
|
||||||
|
margin: .5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-of-type {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dismiss-notice,
|
||||||
|
.spinner {
|
||||||
|
position: absolute;
|
||||||
|
top: 1em;
|
||||||
|
right: 1em;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
}
|
9
assets/stylesheets/admin/wizard/variables.scss
Normale Datei
9
assets/stylesheets/admin/wizard/variables.scss
Normale Datei
|
@ -0,0 +1,9 @@
|
||||||
|
$pavilion_primary: #3c1c8c;
|
||||||
|
$pavilion_secondary: #ffffff;
|
||||||
|
$pavilion_warning: rgb(243, 163, 61);
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--pavilion-primary: #{$pavilion_primary};
|
||||||
|
--pavilion-secondary: #{$pavilion_secondary};
|
||||||
|
--pavilion-warning: #{$pavilion_warning};
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
$pavilionPrimary: #3c1c8c;
|
|
||||||
$pavilionSecondary: #ffffff;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--pavilion-primary: #3c1c8c;
|
|
||||||
--pavilion-secondary: #ffffff;
|
|
||||||
}
|
|
|
@ -60,9 +60,9 @@ en:
|
||||||
expand_text: "Read More"
|
expand_text: "Read More"
|
||||||
collapse_text: "Show Less"
|
collapse_text: "Show Less"
|
||||||
|
|
||||||
pro_support_button:
|
support_button:
|
||||||
title: "Request Pro Support"
|
title: "Request Support"
|
||||||
label: "Pro Support"
|
label: "Support"
|
||||||
|
|
||||||
message:
|
message:
|
||||||
wizard:
|
wizard:
|
||||||
|
@ -95,10 +95,10 @@ en:
|
||||||
destroying: Destroying wizards...
|
destroying: Destroying wizards...
|
||||||
import_complete: Import complete
|
import_complete: Import complete
|
||||||
destroy_complete: Destruction complete
|
destroy_complete: Destruction complete
|
||||||
pro:
|
subscription:
|
||||||
documentation: Check out the PRO documentation
|
documentation: Check out the subscription documentation
|
||||||
authorize: "Authorize this forum to use your PRO subscription plan on %{server}."
|
authorize: "Authorize this forum to use your Custom Wizard subscription plan on %{server}."
|
||||||
not_subscribed: "You've authorized, but are not currently subscribed to a PRO plan on %{server}."
|
not_subscribed: "You've authorized, but are not currently subscribed to a Custom Wizard plan on %{server}."
|
||||||
subscription_expiring: "Your subscription is active, but will expire in the next 48 hours."
|
subscription_expiring: "Your subscription is active, but will expire in the next 48 hours."
|
||||||
subscription_active: "Your subscription is active."
|
subscription_active: "Your subscription is active."
|
||||||
subscription_inactive: "Your subscription is inactive on this forum. Read more in <a href='https://thepavilion.io/t/3652'>the documentation</a>."
|
subscription_inactive: "Your subscription is inactive on this forum. Read more in <a href='https://thepavilion.io/t/3652'>the documentation</a>."
|
||||||
|
@ -455,10 +455,19 @@ en:
|
||||||
destroy: Destroy
|
destroy: Destroy
|
||||||
destroyed: destroyed
|
destroyed: destroyed
|
||||||
|
|
||||||
pro:
|
subscription_container:
|
||||||
nav_label: PRO
|
title: Subscriber Features
|
||||||
label: PRO
|
subscribed:
|
||||||
title: Custom Wizard PRO
|
label: Subscribed
|
||||||
|
title: You're subscribed and can use these features
|
||||||
|
not_subscribed:
|
||||||
|
label: Not Subscribed
|
||||||
|
title: Subscribe to use these features
|
||||||
|
|
||||||
|
subscription:
|
||||||
|
nav_label: Subscription
|
||||||
|
label: Subscription
|
||||||
|
title: Custom Wizard Subscription
|
||||||
authorize: Authorize
|
authorize: Authorize
|
||||||
authorized: Authorized
|
authorized: Authorized
|
||||||
unauthorize: cancel
|
unauthorize: cancel
|
||||||
|
@ -473,6 +482,13 @@ en:
|
||||||
update: Update
|
update: Update
|
||||||
last_updated: Last updated
|
last_updated: Last updated
|
||||||
|
|
||||||
|
notice:
|
||||||
|
plugin: Custom Wizard Plugin
|
||||||
|
issued: Issued
|
||||||
|
resolved: Resolved
|
||||||
|
title:
|
||||||
|
warning: Warning Notice
|
||||||
|
|
||||||
wizard_js:
|
wizard_js:
|
||||||
group:
|
group:
|
||||||
select: "Select a group"
|
select: "Select a group"
|
||||||
|
|
|
@ -17,7 +17,7 @@ en:
|
||||||
name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})"
|
name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})"
|
||||||
name_already_taken: "'%{name}' is already taken as a custom field name"
|
name_already_taken: "'%{name}' is already taken as a custom field name"
|
||||||
save_default: "Failed to save custom field '%{name}'"
|
save_default: "Failed to save custom field '%{name}'"
|
||||||
pro_type: "%{type} custom fields require PRO Subscription"
|
subscription_type: "%{type} custom fields require a subscription"
|
||||||
|
|
||||||
field:
|
field:
|
||||||
too_short: "%{label} must be at least %{min} characters"
|
too_short: "%{label} must be at least %{min} characters"
|
||||||
|
@ -50,7 +50,16 @@ en:
|
||||||
required: "%{property} is required"
|
required: "%{property} is required"
|
||||||
conflict: "Wizard with id '%{wizard_id}' already exists"
|
conflict: "Wizard with id '%{wizard_id}' already exists"
|
||||||
after_time: "After time setting is invalid"
|
after_time: "After time setting is invalid"
|
||||||
pro: "%{type} %{property} is PRO only"
|
subscription: "%{type} %{property} is subscription only"
|
||||||
|
|
||||||
|
notice:
|
||||||
|
connection_error: "Failed to connect to [%{server}](http://%{server})"
|
||||||
|
compatibility_issue: >
|
||||||
|
The Custom Wizard Plugin may have a compatibility issue with the latest version of Discourse.
|
||||||
|
Please check the Custom Wizard Plugin status on [%{server}](http://%{server}) before updating Discourse.
|
||||||
|
plugin_status_connection_error_limit: >
|
||||||
|
We're unable to connect to the plugin status server to determine whether there are any compatibility issues with the latest version of Discourse.
|
||||||
|
Please contact <a href="mailto:support@thepavilion.io">support@thepavilion.io</a> for further assistance.
|
||||||
|
|
||||||
site_settings:
|
site_settings:
|
||||||
custom_wizard_enabled: "Enable custom wizards."
|
custom_wizard_enabled: "Enable custom wizards."
|
||||||
|
|
|
@ -45,10 +45,13 @@ Discourse::Application.routes.append do
|
||||||
post 'admin/wizards/manager/import' => 'admin_manager#import'
|
post 'admin/wizards/manager/import' => 'admin_manager#import'
|
||||||
delete 'admin/wizards/manager/destroy' => 'admin_manager#destroy'
|
delete 'admin/wizards/manager/destroy' => 'admin_manager#destroy'
|
||||||
|
|
||||||
get 'admin/wizards/pro' => 'admin_pro#index'
|
get 'admin/wizards/subscription' => 'admin_subscription#index'
|
||||||
get 'admin/wizards/pro/authorize' => 'admin_pro#authorize'
|
post 'admin/wizards/subscription' => 'admin_subscription#update_subscription'
|
||||||
get 'admin/wizards/pro/authorize/callback' => 'admin_pro#authorize_callback'
|
get 'admin/wizards/subscription/authorize' => 'admin_subscription#authorize'
|
||||||
delete 'admin/wizards/pro/authorize' => 'admin_pro#destroy_authentication'
|
get 'admin/wizards/subscription/authorize/callback' => 'admin_subscription#authorize_callback'
|
||||||
post 'admin/wizards/pro/subscription' => 'admin_pro#update_subscription'
|
delete 'admin/wizards/subscription/authorize' => 'admin_subscription#destroy_authentication'
|
||||||
|
|
||||||
|
get 'admin/wizards/notice' => 'admin_notice#index'
|
||||||
|
put 'admin/wizards/notice/:notice_id' => 'admin_notice#dismiss'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,12 @@ class CustomWizard::AdminController < ::Admin::AdminController
|
||||||
before_action :ensure_admin
|
before_action :ensure_admin
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
render_json_dump(
|
||||||
|
notices: ActiveModel::ArraySerializer.new(
|
||||||
|
CustomWizard::Notice.list,
|
||||||
|
each_serializer: CustomWizard::NoticeSerializer
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -3,7 +3,7 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
|
||||||
def index
|
def index
|
||||||
render_json_dump(
|
render_json_dump(
|
||||||
custom_fields: custom_field_list,
|
custom_fields: custom_field_list,
|
||||||
pro_subscribed: CustomWizard::Pro.subscribed?
|
subscribed: CustomWizard::Subscription.subscribed?
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
22
controllers/custom_wizard/admin/notice.rb
Normale Datei
22
controllers/custom_wizard/admin/notice.rb
Normale Datei
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CustomWizard::AdminNoticeController < CustomWizard::AdminController
|
||||||
|
before_action :find_notice, only: [:dismiss]
|
||||||
|
|
||||||
|
def index
|
||||||
|
render_serialized(CustomWizard::Notice.list, CustomWizard::NoticeSerializer)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismiss
|
||||||
|
if @notice.dismissable? && @notice.dismiss
|
||||||
|
render json: success_json.merge(dismissed_at: @notice.dismissed_at)
|
||||||
|
else
|
||||||
|
render json: failed_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_notice
|
||||||
|
@notice = CustomWizard::Notice.find(params[:notice_id])
|
||||||
|
raise Discourse::InvalidParameters.new(:notice_id) unless @notice
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,48 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class CustomWizard::AdminProController < CustomWizard::AdminController
|
|
||||||
skip_before_action :check_xhr, :preload_json, :verify_authenticity_token, only: [:authorize, :authorize_callback]
|
|
||||||
|
|
||||||
def index
|
|
||||||
render_serialized(pro, CustomWizard::ProSerializer, root: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize
|
|
||||||
request_id = SecureRandom.hex(32)
|
|
||||||
cookies[:user_api_request_id] = request_id
|
|
||||||
redirect_to pro.authentication_url(current_user.id, request_id).to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize_callback
|
|
||||||
payload = params[:payload]
|
|
||||||
request_id = cookies[:user_api_request_id]
|
|
||||||
|
|
||||||
pro.authentication_response(request_id, payload)
|
|
||||||
pro.update_subscription
|
|
||||||
|
|
||||||
redirect_to '/admin/wizards/pro'
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_authentication
|
|
||||||
if pro.destroy_authentication
|
|
||||||
render json: success_json
|
|
||||||
else
|
|
||||||
render json: failed_json
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_subscription
|
|
||||||
if pro.update_subscription
|
|
||||||
subscription = CustomWizard::ProSubscriptionSerializer.new(pro.subscription, root: false)
|
|
||||||
render json: success_json.merge(subscription: subscription)
|
|
||||||
else
|
|
||||||
render json: failed_json
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def pro
|
|
||||||
@pro ||= CustomWizard::Pro.new
|
|
||||||
end
|
|
||||||
end
|
|
48
controllers/custom_wizard/admin/subscription.rb
Normale Datei
48
controllers/custom_wizard/admin/subscription.rb
Normale Datei
|
@ -0,0 +1,48 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CustomWizard::AdminSubscriptionController < CustomWizard::AdminController
|
||||||
|
skip_before_action :check_xhr, :preload_json, :verify_authenticity_token, only: [:authorize, :authorize_callback]
|
||||||
|
|
||||||
|
def index
|
||||||
|
render_serialized(subscription, CustomWizard::SubscriptionSerializer, root: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize
|
||||||
|
request_id = SecureRandom.hex(32)
|
||||||
|
cookies[:user_api_request_id] = request_id
|
||||||
|
redirect_to subscription.authentication_url(current_user.id, request_id).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_callback
|
||||||
|
payload = params[:payload]
|
||||||
|
request_id = cookies[:user_api_request_id]
|
||||||
|
|
||||||
|
subscription.authentication_response(request_id, payload)
|
||||||
|
subscription.update
|
||||||
|
|
||||||
|
redirect_to '/admin/wizards/subscription'
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_authentication
|
||||||
|
if subscription.destroy_authentication
|
||||||
|
render json: success_json
|
||||||
|
else
|
||||||
|
render json: failed_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_subscription
|
||||||
|
if subscription.update
|
||||||
|
serialized_subscription = CustomWizard::Subscription::SubscriptionSerializer.new(subscription.subscription, root: false)
|
||||||
|
render json: success_json.merge(subscription: serialized_subscription)
|
||||||
|
else
|
||||||
|
render json: failed_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def subscription
|
||||||
|
@subscription ||= CustomWizard::Subscription.new
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,7 +11,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
field_types: CustomWizard::Field.types,
|
field_types: CustomWizard::Field.types,
|
||||||
realtime_validations: CustomWizard::RealtimeValidation.types,
|
realtime_validations: CustomWizard::RealtimeValidation.types,
|
||||||
custom_fields: custom_field_list,
|
custom_fields: custom_field_list,
|
||||||
pro_subscribed: CustomWizard::Pro.subscribed?
|
subscribed: CustomWizard::Subscription.subscribed?
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
layout 'wizard'
|
layout 'wizard'
|
||||||
|
|
||||||
before_action :ensure_plugin_enabled
|
before_action :ensure_plugin_enabled
|
||||||
before_action :update_pro_subscription, only: [:index]
|
before_action :update_subscription, only: [:index]
|
||||||
helper_method :wizard_page_title
|
helper_method :wizard_page_title
|
||||||
helper_method :wizard_theme_id
|
helper_method :wizard_theme_id
|
||||||
helper_method :wizard_theme_lookup
|
helper_method :wizard_theme_lookup
|
||||||
|
@ -84,7 +84,7 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_pro_subscription
|
def update_subscription
|
||||||
CustomWizard::Pro.update_subscription
|
CustomWizard::Subscription.update
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"result": {
|
"result": {
|
||||||
"line": 92.14
|
"line": 92.3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
jobs/scheduled/custom_wizard/update_notices.rb
Normale Datei
9
jobs/scheduled/custom_wizard/update_notices.rb
Normale Datei
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Jobs::CustomWizardUpdateNotices < ::Jobs::Scheduled
|
||||||
|
every 5.minutes
|
||||||
|
|
||||||
|
def execute(args = {})
|
||||||
|
CustomWizard::Notice.update
|
||||||
|
end
|
||||||
|
end
|
9
jobs/scheduled/custom_wizard/update_subscription.rb
Normale Datei
9
jobs/scheduled/custom_wizard/update_subscription.rb
Normale Datei
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Jobs::CustomWizardUpdateSubscription < ::Jobs::Scheduled
|
||||||
|
every 1.hour
|
||||||
|
|
||||||
|
def execute(args = {})
|
||||||
|
CustomWizard::Subscription.update
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,9 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class CustomWizard::UpdateProSubscription < ::Jobs::Scheduled
|
|
||||||
every 1.hour
|
|
||||||
|
|
||||||
def execute(args = {})
|
|
||||||
CustomWizard::Pro.update_subscription
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -749,8 +749,4 @@ class CustomWizard::Action
|
||||||
@log.join('; ')
|
@log.join('; ')
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pro_actions
|
|
||||||
%w[send_message watch_categories send_to_api create_group create_category]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,9 +17,9 @@ class ::CustomWizard::CustomField
|
||||||
category: ["basic_category"],
|
category: ["basic_category"],
|
||||||
post: ["post"]
|
post: ["post"]
|
||||||
}
|
}
|
||||||
PRO_CLASSES ||= ['category', 'group']
|
SUBSCRIPTION_CLASSES ||= ['category', 'group']
|
||||||
TYPES ||= ["string", "boolean", "integer", "json"]
|
TYPES ||= ["string", "boolean", "integer", "json"]
|
||||||
PRO_TYPES ||= ["json"]
|
SUBSCRIPTION_TYPES ||= ["json"]
|
||||||
LIST_CACHE_KEY ||= 'custom_field_list'
|
LIST_CACHE_KEY ||= 'custom_field_list'
|
||||||
|
|
||||||
def self.serializers
|
def self.serializers
|
||||||
|
@ -40,7 +40,7 @@ class ::CustomWizard::CustomField
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@pro = CustomWizard::Pro.new
|
@subscription = CustomWizard::Subscription.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
|
@ -85,8 +85,8 @@ class ::CustomWizard::CustomField
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
if attr == 'klass' && PRO_CLASSES.include?(value) && !@pro.subscribed?
|
if attr == 'klass' && SUBSCRIPTION_CLASSES.include?(value) && !@subscription.subscribed?
|
||||||
add_error(I18n.t("wizard.custom_field.error.pro_type", type: value))
|
add_error(I18n.t("wizard.custom_field.error.subscription_type", type: value))
|
||||||
end
|
end
|
||||||
|
|
||||||
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
|
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
|
||||||
|
@ -100,8 +100,8 @@ class ::CustomWizard::CustomField
|
||||||
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
|
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
|
||||||
end
|
end
|
||||||
|
|
||||||
if attr == 'type' && PRO_TYPES.include?(value) && !@pro.subscribed?
|
if attr == 'type' && SUBSCRIPTION_TYPES.include?(value) && !@subscription.subscribed?
|
||||||
add_error(I18n.t("wizard.custom_field.error.pro_type", type: value))
|
add_error(I18n.t("wizard.custom_field.error.subscription_type", type: value))
|
||||||
end
|
end
|
||||||
|
|
||||||
if attr == 'name'
|
if attr == 'name'
|
||||||
|
|
|
@ -47,7 +47,7 @@ class CustomWizard::Mapper
|
||||||
@data = params[:data] || {}
|
@data = params[:data] || {}
|
||||||
@user = params[:user]
|
@user = params[:user]
|
||||||
@opts = params[:opts] || {}
|
@opts = params[:opts] || {}
|
||||||
@pro = CustomWizard::Pro.new
|
@subscription = CustomWizard::Subscription.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
|
@ -252,7 +252,7 @@ class CustomWizard::Mapper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if opts[:template] && @pro.subscribed?
|
if opts[:template] && @subscription.subscribed?
|
||||||
template = Liquid::Template.parse(string)
|
template = Liquid::Template.parse(string)
|
||||||
string = template.render(data)
|
string = template.render(data)
|
||||||
end
|
end
|
||||||
|
|
234
lib/custom_wizard/notice.rb
Normale Datei
234
lib/custom_wizard/notice.rb
Normale Datei
|
@ -0,0 +1,234 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CustomWizard::Notice
|
||||||
|
include ActiveModel::Serialization
|
||||||
|
|
||||||
|
PLUGIN_STATUSES_TO_WARN = %w(incompatible tests_failing)
|
||||||
|
|
||||||
|
attr_reader :id,
|
||||||
|
:message,
|
||||||
|
:type,
|
||||||
|
:created_at
|
||||||
|
|
||||||
|
attr_accessor :retrieved_at,
|
||||||
|
:dismissed_at,
|
||||||
|
:expired_at
|
||||||
|
|
||||||
|
def initialize(attrs)
|
||||||
|
@id = Digest::SHA1.hexdigest(attrs[:message])
|
||||||
|
@message = attrs[:message]
|
||||||
|
@type = attrs[:type].to_i
|
||||||
|
@created_at = attrs[:created_at]
|
||||||
|
@retrieved_at = attrs[:retrieved_at]
|
||||||
|
@dismissed_at = attrs[:dismissed_at]
|
||||||
|
@expired_at = attrs[:expired_at]
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismiss
|
||||||
|
if dismissable?
|
||||||
|
self.dismissed_at = Time.now
|
||||||
|
self.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def expire
|
||||||
|
self.expired_at = Time.now
|
||||||
|
self.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def expired?
|
||||||
|
expired_at.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismissed?
|
||||||
|
dismissed_at.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismissable?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
attrs = {
|
||||||
|
expired_at: expired_at,
|
||||||
|
created_at: created_at,
|
||||||
|
expired_at: expired_at,
|
||||||
|
message: message,
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
|
||||||
|
if current = self.class.find(self.id)
|
||||||
|
attrs[:dismissed_at] = current.dismissed_at || self.dismissed_at
|
||||||
|
end
|
||||||
|
|
||||||
|
self.class.store(id, attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.types
|
||||||
|
@types ||= Enum.new(
|
||||||
|
info: 0,
|
||||||
|
warning: 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.connection_types
|
||||||
|
@connection_types ||= Enum.new(
|
||||||
|
plugin_status: 0,
|
||||||
|
subscription: 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.update(skip_subscription: false, skip_plugin: false)
|
||||||
|
notices = []
|
||||||
|
|
||||||
|
if !skip_subscription
|
||||||
|
subscription_messages = request(subscription_messages_url)
|
||||||
|
if subscription_messages.present?
|
||||||
|
subscription_notices = convert_subscription_messages_to_notices(subscription_messages[:messages])
|
||||||
|
notices.push(*subscription_notices)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !skip_plugin && (Discourse.git_branch === 'tests-passed' || (Rails.env.test? || Rails.env.development?))
|
||||||
|
plugin_status = request(plugin_status_url)
|
||||||
|
|
||||||
|
if plugin_status.present? && plugin_status[:status].present? && plugin_status[:status].is_a?(Hash)
|
||||||
|
plugin_notice = convert_plugin_status_to_notice(plugin_status[:status])
|
||||||
|
notices.push(plugin_notice) if plugin_notice
|
||||||
|
|
||||||
|
expire_connection_errors(connection_types[:plugin_status])
|
||||||
|
else
|
||||||
|
create_connection_error(connection_types[:plugin_status])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
notices.each do |notice_data|
|
||||||
|
notice = new(notice_data)
|
||||||
|
notice.retrieved_at = Time.now
|
||||||
|
notice.save
|
||||||
|
end
|
||||||
|
|
||||||
|
if reached_connection_error_limit(connection_types[:plugin_status])
|
||||||
|
new(
|
||||||
|
message: I18n.t("wizard.notice.plugin_status_connection_error_limit"),
|
||||||
|
type: types[:warning],
|
||||||
|
created_at: Time.now
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.convert_subscription_messages_to_notices(messages)
|
||||||
|
messages.map do |message|
|
||||||
|
{
|
||||||
|
message: message[:message],
|
||||||
|
type: types[message[:type].to_sym],
|
||||||
|
created_at: message[:created_at],
|
||||||
|
expired_at: message[:expired_at]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.convert_plugin_status_to_notice(plugin_status)
|
||||||
|
notice = nil
|
||||||
|
|
||||||
|
if PLUGIN_STATUSES_TO_WARN.include?(plugin_status[:status])
|
||||||
|
notice = {
|
||||||
|
message: PrettyText.cook(I18n.t('wizard.notice.compatibility_issue', server: plugin_status_domain)),
|
||||||
|
type: types[:warning],
|
||||||
|
created_at: plugin_status[:status_changed_at]
|
||||||
|
}
|
||||||
|
else
|
||||||
|
list(types[:warning]).each(&:expire)
|
||||||
|
end
|
||||||
|
|
||||||
|
notice
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.subscription_messages_domain
|
||||||
|
"localhost:3000"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.subscription_messages_url
|
||||||
|
"http://#{subscription_messages_domain}/subscription-server/messages.json"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.plugin_status_domain
|
||||||
|
"localhost:4200"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.plugin_status_url
|
||||||
|
"http://#{plugin_status_domain}/plugin-manager/status/discourse-custom-wizard"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.request(url)
|
||||||
|
response = Excon.get(url)
|
||||||
|
|
||||||
|
if response.status == 200
|
||||||
|
begin
|
||||||
|
data = JSON.parse(response.body).deep_symbolize_keys
|
||||||
|
rescue JSON::ParserError
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
data
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.namespace
|
||||||
|
"#{CustomWizard::PLUGIN_NAME}_notice"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.namespace_connection
|
||||||
|
"#{CustomWizard::PLUGIN_NAME}_notice_connection"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find(id)
|
||||||
|
raw = PluginStore.get(namespace, id)
|
||||||
|
new(raw.symbolize_keys) if raw.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.store(id, raw_notice)
|
||||||
|
PluginStore.set(namespace, id, raw_notice)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.plugin_status_connection_error_limit
|
||||||
|
5
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.list_connection_query(type)
|
||||||
|
query = PluginStoreRow.where(plugin_name: namespace_connection)
|
||||||
|
query.where("(value::json->>'type')::integer = ?", type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.expire_connection_errors(type)
|
||||||
|
list_connection_query(type).update_all("value = jsonb_set(value::jsonb, '{ expired_at }', (to_char(current_timestamp, 'HH12:MI:SS'))::jsonb)")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_connection_error(type)
|
||||||
|
id = SecureRandom.hex(16)
|
||||||
|
attrs = {
|
||||||
|
message: I18n.t("wizard.notice.connection_error", domain: self.send("#{type}_domain")),
|
||||||
|
type: type,
|
||||||
|
created_at: Time.now
|
||||||
|
}
|
||||||
|
PluginStore.set(namespace_connection, id, attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.reached_connection_error_limit(type)
|
||||||
|
list_connection_query(type).size >= self.send("#{connection_types.key(type)}_connection_error_limit")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.list_query(type = nil)
|
||||||
|
query = PluginStoreRow.where(plugin_name: namespace)
|
||||||
|
query = query.where("(value::json->>'expired_at') IS NULL OR (value::json->>'expired_at')::date > now()::date - 1")
|
||||||
|
query = query.where("(value::json->>'type')::integer = ?", type) if type
|
||||||
|
query.order("value::json->>'created_at' DESC")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.list(type = nil)
|
||||||
|
list_query(type)
|
||||||
|
.map { |r| self.new(JSON.parse(r.value).symbolize_keys) }
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,14 +1,14 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CustomWizard::Pro
|
class CustomWizard::Subscription
|
||||||
include ActiveModel::Serialization
|
include ActiveModel::Serialization
|
||||||
|
|
||||||
attr_accessor :authentication,
|
attr_accessor :authentication,
|
||||||
:subscription
|
:subscription
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@authentication = CustomWizard::ProAuthentication.new(get_authentication)
|
@authentication = CustomWizard::Subscription::Authentication.new(get_authentication)
|
||||||
@subscription = CustomWizard::ProSubscription.new(get_subscription)
|
@subscription = CustomWizard::Subscription::Subscription.new(get_subscription)
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?
|
def authorized?
|
||||||
|
@ -35,7 +35,7 @@ class CustomWizard::Pro
|
||||||
"discourse-subscription-server:user_subscription"
|
"discourse-subscription-server:user_subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_subscription
|
def update
|
||||||
if @authentication.active?
|
if @authentication.active?
|
||||||
response = Excon.get(
|
response = Excon.get(
|
||||||
"https://#{server}/subscription-server/user-subscriptions/#{subscription_type}/#{client_name}",
|
"https://#{server}/subscription-server/user-subscriptions/#{subscription_type}/#{client_name}",
|
||||||
|
@ -67,7 +67,7 @@ class CustomWizard::Pro
|
||||||
|
|
||||||
def destroy_subscription
|
def destroy_subscription
|
||||||
if remove_subscription
|
if remove_subscription
|
||||||
@subscription = CustomWizard::ProSubscription.new(get_subscription)
|
@subscription = CustomWizard::Subscription::Subscription.new(get_subscription)
|
||||||
!@subscription.active?
|
!@subscription.active?
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
@ -80,7 +80,7 @@ class CustomWizard::Pro
|
||||||
public_key: keys.public_key,
|
public_key: keys.public_key,
|
||||||
nonce: keys.nonce,
|
nonce: keys.nonce,
|
||||||
client_id: @authentication.client_id,
|
client_id: @authentication.client_id,
|
||||||
auth_redirect: "#{Discourse.base_url}/admin/wizards/pro/authorize/callback",
|
auth_redirect: "#{Discourse.base_url}/admin/wizards/subscription/authorize/callback",
|
||||||
application_name: SiteSetting.title,
|
application_name: SiteSetting.title,
|
||||||
scopes: scope
|
scopes: scope
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ class CustomWizard::Pro
|
||||||
|
|
||||||
def destroy_authentication
|
def destroy_authentication
|
||||||
if remove_authentication
|
if remove_authentication
|
||||||
@authentication = CustomWizard::ProAuthentication.new(get_authentication)
|
@authentication = CustomWizard::Subscription::Authentication.new(get_authentication)
|
||||||
!@authentication.active?
|
!@authentication.active?
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
@ -123,12 +123,12 @@ class CustomWizard::Pro
|
||||||
self.new.authorized?
|
self.new.authorized?
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.update_subscription
|
def self.update
|
||||||
self.new.update_subscription
|
self.new.update
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.namespace
|
def self.namespace
|
||||||
"custom_wizard_pro"
|
"custom_wizard_subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -157,8 +157,8 @@ class CustomWizard::Pro
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_subscription(type)
|
def set_subscription(type)
|
||||||
PluginStore.set(CustomWizard::Pro.namespace, subscription_db_key, type: type, updated_at: Time.now)
|
PluginStore.set(CustomWizard::Subscription.namespace, subscription_db_key, type: type, updated_at: Time.now)
|
||||||
CustomWizard::ProSubscription.new(get_subscription)
|
CustomWizard::Subscription::Subscription.new(get_subscription)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_authentication
|
def get_authentication
|
||||||
|
@ -176,7 +176,7 @@ class CustomWizard::Pro
|
||||||
auth_by: user_id,
|
auth_by: user_id,
|
||||||
auth_at: Time.now
|
auth_at: Time.now
|
||||||
)
|
)
|
||||||
CustomWizard::ProAuthentication.new(get_authentication)
|
CustomWizard::Subscription::Authentication.new(get_authentication)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_authentication
|
def remove_authentication
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::ProAuthentication
|
class CustomWizard::Subscription::Authentication
|
||||||
include ActiveModel::Serialization
|
include ActiveModel::Serialization
|
||||||
|
|
||||||
attr_reader :client_id,
|
attr_reader :client_id,
|
||||||
|
@ -53,7 +53,7 @@ class CustomWizard::ProAuthentication
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_keys(request_id)
|
def get_keys(request_id)
|
||||||
raw = PluginStore.get(CustomWizard::Pro.namespace, "#{keys_db_key}_#{request_id}")
|
raw = PluginStore.get(CustomWizard::Subscription.namespace, "#{keys_db_key}_#{request_id}")
|
||||||
OpenStruct.new(
|
OpenStruct.new(
|
||||||
user_id: raw && raw['user_id'],
|
user_id: raw && raw['user_id'],
|
||||||
pem: raw && raw['pem'],
|
pem: raw && raw['pem'],
|
||||||
|
@ -72,7 +72,7 @@ class CustomWizard::ProAuthentication
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_keys(request_id, user_id, rsa, nonce)
|
def set_keys(request_id, user_id, rsa, nonce)
|
||||||
PluginStore.set(CustomWizard::Pro.namespace, "#{keys_db_key}_#{request_id}",
|
PluginStore.set(CustomWizard::Subscription.namespace, "#{keys_db_key}_#{request_id}",
|
||||||
user_id: user_id,
|
user_id: user_id,
|
||||||
pem: rsa.export,
|
pem: rsa.export,
|
||||||
nonce: nonce
|
nonce: nonce
|
||||||
|
@ -80,16 +80,16 @@ class CustomWizard::ProAuthentication
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_keys(request_id)
|
def delete_keys(request_id)
|
||||||
PluginStore.remove(CustomWizard::Pro.namespace, "#{keys_db_key}_#{request_id}")
|
PluginStore.remove(CustomWizard::Subscription.namespace, "#{keys_db_key}_#{request_id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_client_id
|
def get_client_id
|
||||||
PluginStore.get(CustomWizard::Pro.namespace, client_id_db_key)
|
PluginStore.get(CustomWizard::Subscription.namespace, client_id_db_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_client_id
|
def set_client_id
|
||||||
client_id = SecureRandom.hex(32)
|
client_id = SecureRandom.hex(32)
|
||||||
PluginStore.set(CustomWizard::Pro.namespace, client_id_db_key, client_id)
|
PluginStore.set(CustomWizard::Subscription.namespace, client_id_db_key, client_id)
|
||||||
client_id
|
client_id
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::ProSubscription
|
class CustomWizard::Subscription::Subscription
|
||||||
include ActiveModel::Serialization
|
include ActiveModel::Serialization
|
||||||
|
|
||||||
attr_reader :type,
|
attr_reader :type,
|
|
@ -6,7 +6,7 @@ class CustomWizard::TemplateValidator
|
||||||
def initialize(data, opts = {})
|
def initialize(data, opts = {})
|
||||||
@data = data
|
@data = data
|
||||||
@opts = opts
|
@opts = opts
|
||||||
@pro = CustomWizard::Pro.new
|
@subscription = CustomWizard::Subscription.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
|
@ -15,15 +15,15 @@ class CustomWizard::TemplateValidator
|
||||||
check_id(data, :wizard)
|
check_id(data, :wizard)
|
||||||
check_required(data, :wizard)
|
check_required(data, :wizard)
|
||||||
validate_after_time
|
validate_after_time
|
||||||
validate_pro(data, :wizard)
|
validate_subscription(data, :wizard)
|
||||||
|
|
||||||
data[:steps].each do |step|
|
data[:steps].each do |step|
|
||||||
check_required(step, :step)
|
check_required(step, :step)
|
||||||
validate_pro(step, :step)
|
validate_subscription(step, :step)
|
||||||
|
|
||||||
if step[:fields].present?
|
if step[:fields].present?
|
||||||
step[:fields].each do |field|
|
step[:fields].each do |field|
|
||||||
validate_pro(field, :field)
|
validate_subscription(field, :field)
|
||||||
check_required(field, :field)
|
check_required(field, :field)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -31,7 +31,7 @@ class CustomWizard::TemplateValidator
|
||||||
|
|
||||||
if data[:actions].present?
|
if data[:actions].present?
|
||||||
data[:actions].each do |action|
|
data[:actions].each do |action|
|
||||||
validate_pro(action, :action)
|
validate_subscription(action, :action)
|
||||||
check_required(action, :action)
|
check_required(action, :action)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@ class CustomWizard::TemplateValidator
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.pro
|
def self.subscription
|
||||||
{
|
{
|
||||||
wizard: {
|
wizard: {
|
||||||
save_submissions: 'false',
|
save_submissions: 'false',
|
||||||
|
@ -90,18 +90,18 @@ class CustomWizard::TemplateValidator
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_pro(object, type)
|
def validate_subscription(object, type)
|
||||||
self.class.pro[type].each do |property, pro_type|
|
self.class.subscription[type].each do |property, subscription_type|
|
||||||
val = object[property.to_s]
|
val = object[property.to_s]
|
||||||
is_pro = (val != nil) && (
|
is_subscription = (val != nil) && (
|
||||||
pro_type === 'present' && val.present? ||
|
subscription_type === 'present' && val.present? ||
|
||||||
(['true', 'false'].include?(pro_type) && cast_bool(val) == cast_bool(pro_type)) ||
|
(['true', 'false'].include?(subscription_type) && cast_bool(val) == cast_bool(subscription_type)) ||
|
||||||
(pro_type === 'conditional' && val.is_a?(Hash)) ||
|
(subscription_type === 'conditional' && val.is_a?(Hash)) ||
|
||||||
(pro_type.is_a?(Array) && pro_type.include?(val))
|
(subscription_type.is_a?(Array) && subscription_type.include?(val))
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_pro && !@pro.subscribed?
|
if is_subscription && !@subscription.subscribed?
|
||||||
errors.add :base, I18n.t("wizard.validation.pro", type: type.to_s, property: property)
|
errors.add :base, I18n.t("wizard.validation.subscription", type: type.to_s, property: property)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
31
plugin.rb
31
plugin.rb
|
@ -7,9 +7,7 @@
|
||||||
# contact emails: angus@thepavilion.io
|
# contact emails: angus@thepavilion.io
|
||||||
|
|
||||||
gem 'liquid', '5.0.1', require: true
|
gem 'liquid', '5.0.1', require: true
|
||||||
register_asset 'stylesheets/common/wizard-admin.scss'
|
register_asset 'stylesheets/admin/admin.scss', :desktop
|
||||||
register_asset 'stylesheets/common/wizard-mapper.scss'
|
|
||||||
|
|
||||||
enabled_site_setting :custom_wizard_enabled
|
enabled_site_setting :custom_wizard_enabled
|
||||||
|
|
||||||
config = Rails.application.config
|
config = Rails.application.config
|
||||||
|
@ -42,6 +40,7 @@ if respond_to?(:register_svg_icon)
|
||||||
register_svg_icon "comment-alt"
|
register_svg_icon "comment-alt"
|
||||||
register_svg_icon "far-life-ring"
|
register_svg_icon "far-life-ring"
|
||||||
register_svg_icon "arrow-right"
|
register_svg_icon "arrow-right"
|
||||||
|
register_svg_icon "shield-virus"
|
||||||
end
|
end
|
||||||
|
|
||||||
class ::Sprockets::DirectiveProcessor
|
class ::Sprockets::DirectiveProcessor
|
||||||
|
@ -71,13 +70,15 @@ after_initialize do
|
||||||
../controllers/custom_wizard/admin/logs.rb
|
../controllers/custom_wizard/admin/logs.rb
|
||||||
../controllers/custom_wizard/admin/manager.rb
|
../controllers/custom_wizard/admin/manager.rb
|
||||||
../controllers/custom_wizard/admin/custom_fields.rb
|
../controllers/custom_wizard/admin/custom_fields.rb
|
||||||
../controllers/custom_wizard/admin/pro.rb
|
../controllers/custom_wizard/admin/subscription.rb
|
||||||
|
../controllers/custom_wizard/admin/notice.rb
|
||||||
../controllers/custom_wizard/wizard.rb
|
../controllers/custom_wizard/wizard.rb
|
||||||
../controllers/custom_wizard/steps.rb
|
../controllers/custom_wizard/steps.rb
|
||||||
../controllers/custom_wizard/realtime_validations.rb
|
../controllers/custom_wizard/realtime_validations.rb
|
||||||
../jobs/regular/refresh_api_access_token.rb
|
../jobs/regular/refresh_api_access_token.rb
|
||||||
../jobs/regular/set_after_time_wizard.rb
|
../jobs/regular/set_after_time_wizard.rb
|
||||||
../jobs/scheduled/update_pro_subscription.rb
|
../jobs/scheduled/custom_wizard/update_subscription.rb
|
||||||
|
../jobs/scheduled/custom_wizard/update_notices.rb
|
||||||
../lib/custom_wizard/validators/template.rb
|
../lib/custom_wizard/validators/template.rb
|
||||||
../lib/custom_wizard/validators/update.rb
|
../lib/custom_wizard/validators/update.rb
|
||||||
../lib/custom_wizard/action_result.rb
|
../lib/custom_wizard/action_result.rb
|
||||||
|
@ -96,9 +97,10 @@ after_initialize do
|
||||||
../lib/custom_wizard/submission.rb
|
../lib/custom_wizard/submission.rb
|
||||||
../lib/custom_wizard/template.rb
|
../lib/custom_wizard/template.rb
|
||||||
../lib/custom_wizard/wizard.rb
|
../lib/custom_wizard/wizard.rb
|
||||||
../lib/custom_wizard/pro.rb
|
../lib/custom_wizard/notice.rb
|
||||||
../lib/custom_wizard/pro/subscription.rb
|
../lib/custom_wizard/subscription.rb
|
||||||
../lib/custom_wizard/pro/authentication.rb
|
../lib/custom_wizard/subscription/subscription.rb
|
||||||
|
../lib/custom_wizard/subscription/authentication.rb
|
||||||
../lib/custom_wizard/api/api.rb
|
../lib/custom_wizard/api/api.rb
|
||||||
../lib/custom_wizard/api/authorization.rb
|
../lib/custom_wizard/api/authorization.rb
|
||||||
../lib/custom_wizard/api/endpoint.rb
|
../lib/custom_wizard/api/endpoint.rb
|
||||||
|
@ -119,9 +121,10 @@ after_initialize do
|
||||||
../serializers/custom_wizard/log_serializer.rb
|
../serializers/custom_wizard/log_serializer.rb
|
||||||
../serializers/custom_wizard/submission_serializer.rb
|
../serializers/custom_wizard/submission_serializer.rb
|
||||||
../serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb
|
../serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb
|
||||||
../serializers/custom_wizard/pro/authentication_serializer.rb
|
../serializers/custom_wizard/subscription/authentication_serializer.rb
|
||||||
../serializers/custom_wizard/pro/subscription_serializer.rb
|
../serializers/custom_wizard/subscription/subscription_serializer.rb
|
||||||
../serializers/custom_wizard/pro_serializer.rb
|
../serializers/custom_wizard/subscription_serializer.rb
|
||||||
|
../serializers/custom_wizard/notice_serializer.rb
|
||||||
../extensions/extra_locales_controller.rb
|
../extensions/extra_locales_controller.rb
|
||||||
../extensions/invites_controller.rb
|
../extensions/invites_controller.rb
|
||||||
../extensions/users_controller.rb
|
../extensions/users_controller.rb
|
||||||
|
@ -238,5 +241,11 @@ after_initialize do
|
||||||
"#{serializer_klass}_serializer".classify.constantize.prepend CustomWizardCustomFieldSerializer
|
"#{serializer_klass}_serializer".classify.constantize.prepend CustomWizardCustomFieldSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
AdminDashboardData.add_problem_check do
|
||||||
|
warning_notices = CustomWizard::Notice.list(CustomWizard::Notice.types[:warning])
|
||||||
|
warning_notices.any? ? ActionView::Base.full_sanitizer.sanitize(warning_notices.first.message, tags: %w(a)) : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
Jobs.enqueue(:custom_wizard_update_notices)
|
||||||
DiscourseEvent.trigger(:custom_wizard_ready)
|
DiscourseEvent.trigger(:custom_wizard_ready)
|
||||||
end
|
end
|
||||||
|
|
20
serializers/custom_wizard/notice_serializer.rb
Normale Datei
20
serializers/custom_wizard/notice_serializer.rb
Normale Datei
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CustomWizard::NoticeSerializer < ApplicationSerializer
|
||||||
|
attributes :id,
|
||||||
|
:message,
|
||||||
|
:type,
|
||||||
|
:created_at,
|
||||||
|
:expired_at,
|
||||||
|
:dismissed_at,
|
||||||
|
:retrieved_at,
|
||||||
|
:dismissable
|
||||||
|
|
||||||
|
def dismissable
|
||||||
|
object.dismissable?
|
||||||
|
end
|
||||||
|
|
||||||
|
def type
|
||||||
|
CustomWizard::Notice.types.key(object.type)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
class CustomWizard::ProSerializer < ApplicationSerializer
|
|
||||||
attributes :server
|
|
||||||
has_one :authentication, serializer: CustomWizard::ProAuthenticationSerializer, embed: :objects
|
|
||||||
has_one :subscription, serializer: CustomWizard::ProSubscriptionSerializer, embed: :objects
|
|
||||||
end
|
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::ProAuthenticationSerializer < ApplicationSerializer
|
class CustomWizard::Subscription::AuthenticationSerializer < ApplicationSerializer
|
||||||
attributes :active,
|
attributes :active,
|
||||||
:client_id,
|
:client_id,
|
||||||
:auth_by,
|
:auth_by,
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::ProSubscriptionSerializer < ApplicationSerializer
|
class CustomWizard::Subscription::SubscriptionSerializer < ApplicationSerializer
|
||||||
attributes :type,
|
attributes :type,
|
||||||
:active,
|
:active,
|
||||||
:updated_at
|
:updated_at
|
6
serializers/custom_wizard/subscription_serializer.rb
Normale Datei
6
serializers/custom_wizard/subscription_serializer.rb
Normale Datei
|
@ -0,0 +1,6 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
class CustomWizard::SubscriptionSerializer < ApplicationSerializer
|
||||||
|
attributes :server
|
||||||
|
has_one :authentication, serializer: CustomWizard::Subscription::AuthenticationSerializer, embed: :objects
|
||||||
|
has_one :subscription, serializer: CustomWizard::Subscription::SubscriptionSerializer, embed: :objects
|
||||||
|
end
|
|
@ -123,6 +123,6 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribed?
|
def subscribed?
|
||||||
@subscribed ||= CustomWizard::Pro.subscribed?
|
@subscribed ||= CustomWizard::Subscription.subscribed?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
|
||||||
:permitted,
|
:permitted,
|
||||||
:uncategorized_category_id,
|
:uncategorized_category_id,
|
||||||
:categories,
|
:categories,
|
||||||
:pro_subscribed
|
:subscribed
|
||||||
|
|
||||||
has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects
|
has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects
|
||||||
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
||||||
|
@ -62,7 +62,7 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
|
||||||
object.categories.map { |c| c.to_h }
|
object.categories.map { |c| c.to_h }
|
||||||
end
|
end
|
||||||
|
|
||||||
def pro_subscribed
|
def subscribed
|
||||||
CustomWizard::Pro.subscribed?
|
CustomWizard::Subscription.subscribed?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,8 +80,4 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer
|
||||||
def i18n_key
|
def i18n_key
|
||||||
@i18n_key ||= "#{object.wizard.id}.#{object.id}".underscore
|
@i18n_key ||= "#{object.wizard.id}.#{object.id}".underscore
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribed?
|
|
||||||
@subscribed ||= CustomWizard::Pro.subscribed?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -174,7 +174,7 @@ describe CustomWizard::Action do
|
||||||
expect(updater.result[:redirect_on_next]).to eq("https://google.com")
|
expect(updater.result[:redirect_on_next]).to eq("https://google.com")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "pro actions" do
|
context "subscription actions" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ require_relative '../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::CustomField do
|
describe CustomWizard::CustomField do
|
||||||
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
||||||
let(:custom_field_pro_json) { get_wizard_fixture("custom_field/pro_custom_fields") }
|
let(:custom_field_subscription_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
CustomWizard::CustomField.invalidate_cache
|
CustomWizard::CustomField.invalidate_cache
|
||||||
|
@ -193,44 +193,44 @@ describe CustomWizard::CustomField do
|
||||||
).to eq(false)
|
).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not save pro field types without a pro subscription" do
|
it "does not save subscription field types without a subscription" do
|
||||||
pro_field_json = custom_field_pro_json['custom_fields'].first
|
subscription_field_json = custom_field_subscription_json['custom_fields'].first
|
||||||
custom_field = CustomWizard::CustomField.new(nil, pro_field_json)
|
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
|
||||||
|
|
||||||
expect(custom_field.save).to eq(false)
|
expect(custom_field.save).to eq(false)
|
||||||
expect(custom_field.valid?).to eq(false)
|
expect(custom_field.valid?).to eq(false)
|
||||||
expect(custom_field.errors.full_messages.first).to eq(
|
expect(custom_field.errors.full_messages.first).to eq(
|
||||||
I18n.t("wizard.custom_field.error.pro_type", type: "json")
|
I18n.t("wizard.custom_field.error.subscription_type", type: "json")
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not save pro field classes without a pro subscription" do
|
it "does not save subscription field classes without a subscription" do
|
||||||
pro_field_json = custom_field_pro_json['custom_fields'].second
|
subscription_field_json = custom_field_subscription_json['custom_fields'].second
|
||||||
custom_field = CustomWizard::CustomField.new(nil, pro_field_json)
|
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
|
||||||
|
|
||||||
expect(custom_field.save).to eq(false)
|
expect(custom_field.save).to eq(false)
|
||||||
expect(custom_field.valid?).to eq(false)
|
expect(custom_field.valid?).to eq(false)
|
||||||
expect(custom_field.errors.full_messages.first).to eq(
|
expect(custom_field.errors.full_messages.first).to eq(
|
||||||
I18n.t("wizard.custom_field.error.pro_type", type: "category")
|
I18n.t("wizard.custom_field.error.subscription_type", type: "category")
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a pro subscription" do
|
context "with a subscription" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
end
|
end
|
||||||
|
|
||||||
it "saves pro field types" do
|
it "saves subscription field types" do
|
||||||
pro_field_json = custom_field_pro_json['custom_fields'].first
|
subscription_field_json = custom_field_subscription_json['custom_fields'].first
|
||||||
custom_field = CustomWizard::CustomField.new(nil, pro_field_json)
|
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
|
||||||
|
|
||||||
expect(custom_field.save).to eq(true)
|
expect(custom_field.save).to eq(true)
|
||||||
expect(custom_field.valid?).to eq(true)
|
expect(custom_field.valid?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "saves pro field classes" do
|
it "saves subscription field classes" do
|
||||||
pro_field_json = custom_field_pro_json['custom_fields'].second
|
subscription_field_json = custom_field_subscription_json['custom_fields'].second
|
||||||
custom_field = CustomWizard::CustomField.new(nil, pro_field_json)
|
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
|
||||||
|
|
||||||
expect(custom_field.save).to eq(true)
|
expect(custom_field.save).to eq(true)
|
||||||
expect(custom_field.valid?).to eq(true)
|
expect(custom_field.valid?).to eq(true)
|
||||||
|
|
|
@ -344,7 +344,7 @@ describe CustomWizard::Mapper do
|
||||||
expect(result).to eq(template_params["step_1_field_1"])
|
expect(result).to eq(template_params["step_1_field_1"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "requires a pro subscription" do
|
it "requires a subscription" do
|
||||||
template = '{{ "w{step_1_field_1}" | size }}'
|
template = '{{ "w{step_1_field_1}" | size }}'
|
||||||
mapper = create_template_mapper(template_params, user1)
|
mapper = create_template_mapper(template_params, user1)
|
||||||
result = mapper.interpolate(
|
result = mapper.interpolate(
|
||||||
|
@ -357,7 +357,7 @@ describe CustomWizard::Mapper do
|
||||||
expect(result).to eq("{{ \"#{template_params["step_1_field_1"]}\" | size }}")
|
expect(result).to eq("{{ \"#{template_params["step_1_field_1"]}\" | size }}")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a pro subscription" do
|
context "with a subscription" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
end
|
end
|
||||||
|
|
80
spec/components/custom_wizard/notice_spec.rb
Normale Datei
80
spec/components/custom_wizard/notice_spec.rb
Normale Datei
|
@ -0,0 +1,80 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../../plugin_helper'
|
||||||
|
|
||||||
|
describe CustomWizard::Notice do
|
||||||
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
let(:subscription_message) {
|
||||||
|
{
|
||||||
|
message: "Message about subscription",
|
||||||
|
type: "info",
|
||||||
|
created_at: Time.now - 3.day,
|
||||||
|
expired_at: nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let(:plugin_status) {
|
||||||
|
{
|
||||||
|
name: 'discourse-custom-wizard',
|
||||||
|
status: 'incompatible',
|
||||||
|
status_changed_at: Time.now - 3.day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context "subscription message" do
|
||||||
|
before do
|
||||||
|
freeze_time
|
||||||
|
stub_request(:get, described_class.subscription_messages_url).to_return(status: 200, body: { messages: [subscription_message] }.to_json)
|
||||||
|
described_class.update(skip_plugin: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts subscription messages into notices" do
|
||||||
|
notice = described_class.list.first
|
||||||
|
expect(notice.type).to eq(described_class.types[:info])
|
||||||
|
expect(notice.message).to eq(subscription_message[:message])
|
||||||
|
expect(notice.created_at.to_datetime).to be_within(1.second).of (subscription_message[:created_at].to_datetime)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "expires notice if subscription message is expired" do
|
||||||
|
subscription_message[:expired_at] = Time.now
|
||||||
|
stub_request(:get, described_class.subscription_messages_url).to_return(status: 200, body: { messages: [subscription_message] }.to_json)
|
||||||
|
described_class.update(skip_plugin: true)
|
||||||
|
|
||||||
|
notice = described_class.list.first
|
||||||
|
expect(notice.expired?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "plugin status" do
|
||||||
|
before do
|
||||||
|
freeze_time
|
||||||
|
stub_request(:get, described_class.plugin_status_url).to_return(status: 200, body: { status: plugin_status }.to_json)
|
||||||
|
described_class.update(skip_subscription: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts plugin statuses to warn into notices" do
|
||||||
|
notice = described_class.list.first
|
||||||
|
expect(notice.type).to eq(described_class.types[:warning])
|
||||||
|
expect(notice.message).to eq(PrettyText.cook(I18n.t("wizard.notice.compatibility_issue", server: described_class.plugin_status_domain)))
|
||||||
|
expect(notice.created_at.to_datetime).to be_within(1.second).of (plugin_status[:status_changed_at].to_datetime)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "expires unexpired warning notices if status is recommended or compatible" do
|
||||||
|
plugin_status[:status] = 'compatible'
|
||||||
|
plugin_status[:status_changed_at] = Time.now
|
||||||
|
stub_request(:get, described_class.plugin_status_url).to_return(status: 200, body: { status: plugin_status }.to_json)
|
||||||
|
described_class.update(skip_subscription: true)
|
||||||
|
|
||||||
|
notice = described_class.list(described_class.types[:warning]).first
|
||||||
|
expect(notice.expired?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "lists notices not expired more than a day ago" do
|
||||||
|
subscription_message[:expired_at] = Time.now - 8.hours
|
||||||
|
stub_request(:get, described_class.subscription_messages_url).to_return(status: 200, body: { messages: [subscription_message] }.to_json)
|
||||||
|
stub_request(:get, described_class.plugin_status_url).to_return(status: 200, body: { status: plugin_status }.to_json)
|
||||||
|
|
||||||
|
described_class.update
|
||||||
|
expect(described_class.list.length).to eq(2)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,69 +2,69 @@
|
||||||
|
|
||||||
require_relative '../../plugin_helper'
|
require_relative '../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::Pro do
|
describe CustomWizard::Subscription do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
it "initializes pro authentication and subscription" do
|
it "initializes subscription authentication and subscription" do
|
||||||
pro = described_class.new
|
subscription = described_class.new
|
||||||
expect(pro.authentication.class).to eq(CustomWizard::ProAuthentication)
|
expect(subscription.authentication.class).to eq(CustomWizard::Subscription::Authentication)
|
||||||
expect(pro.subscription.class).to eq(CustomWizard::ProSubscription)
|
expect(subscription.subscription.class).to eq(CustomWizard::Subscription::Subscription)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns authorized and subscribed states" do
|
it "returns authorized and subscribed states" do
|
||||||
pro = described_class.new
|
subscription = described_class.new
|
||||||
expect(pro.authorized?).to eq(false)
|
expect(subscription.authorized?).to eq(false)
|
||||||
expect(pro.subscribed?).to eq(false)
|
expect(subscription.subscribed?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "subscription" do
|
context "subscription" do
|
||||||
before do
|
before do
|
||||||
@pro = described_class.new
|
@subscription = described_class.new
|
||||||
end
|
end
|
||||||
|
|
||||||
it "updates valid subscriptions" do
|
it "updates valid subscriptions" do
|
||||||
stub_subscription_request(200, valid_subscription)
|
stub_subscription_request(200, valid_subscription)
|
||||||
expect(@pro.update_subscription).to eq(true)
|
expect(@subscription.update).to eq(true)
|
||||||
expect(@pro.subscribed?).to eq(true)
|
expect(@subscription.subscribed?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles invalid subscriptions" do
|
it "handles invalid subscriptions" do
|
||||||
stub_subscription_request(200, invalid_subscription)
|
stub_subscription_request(200, invalid_subscription)
|
||||||
expect(@pro.update_subscription).to eq(false)
|
expect(@subscription.update).to eq(false)
|
||||||
expect(@pro.subscribed?).to eq(false)
|
expect(@subscription.subscribed?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles subscription http errors" do
|
it "handles subscription http errors" do
|
||||||
stub_subscription_request(404, {})
|
stub_subscription_request(404, {})
|
||||||
expect(@pro.update_subscription).to eq(false)
|
expect(@subscription.update).to eq(false)
|
||||||
expect(@pro.subscribed?).to eq(false)
|
expect(@subscription.subscribed?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "destroys subscriptions" do
|
it "destroys subscriptions" do
|
||||||
stub_subscription_request(200, valid_subscription)
|
stub_subscription_request(200, valid_subscription)
|
||||||
expect(@pro.update_subscription).to eq(true)
|
expect(@subscription.update).to eq(true)
|
||||||
expect(@pro.destroy_subscription).to eq(true)
|
expect(@subscription.destroy_subscription).to eq(true)
|
||||||
expect(@pro.subscribed?).to eq(false)
|
expect(@subscription.subscribed?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "has class aliases" do
|
it "has class aliases" do
|
||||||
authenticate_pro
|
authenticate_subscription
|
||||||
stub_subscription_request(200, valid_subscription)
|
stub_subscription_request(200, valid_subscription)
|
||||||
expect(described_class.update_subscription).to eq(true)
|
expect(described_class.update).to eq(true)
|
||||||
expect(described_class.subscribed?).to eq(true)
|
expect(described_class.subscribed?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "authentication" do
|
context "authentication" do
|
||||||
before do
|
before do
|
||||||
@pro = described_class.new
|
@subscription = described_class.new
|
||||||
user.update!(admin: true)
|
user.update!(admin: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "generates a valid authentication request url" do
|
it "generates a valid authentication request url" do
|
||||||
request_id = SecureRandom.hex(32)
|
request_id = SecureRandom.hex(32)
|
||||||
uri = URI(@pro.authentication_url(user.id, request_id))
|
uri = URI(@subscription.authentication_url(user.id, request_id))
|
||||||
expect(uri.host).to eq(@pro.server)
|
expect(uri.host).to eq(@subscription.server)
|
||||||
|
|
||||||
parsed_query = Rack::Utils.parse_query uri.query
|
parsed_query = Rack::Utils.parse_query uri.query
|
||||||
expect(parsed_query['public_key'].present?).to eq(true)
|
expect(parsed_query['public_key'].present?).to eq(true)
|
||||||
|
@ -72,12 +72,12 @@ describe CustomWizard::Pro do
|
||||||
expect(parsed_query['client_id'].present?).to eq(true)
|
expect(parsed_query['client_id'].present?).to eq(true)
|
||||||
expect(parsed_query['auth_redirect'].present?).to eq(true)
|
expect(parsed_query['auth_redirect'].present?).to eq(true)
|
||||||
expect(parsed_query['application_name']).to eq(SiteSetting.title)
|
expect(parsed_query['application_name']).to eq(SiteSetting.title)
|
||||||
expect(parsed_query['scopes']).to eq(@pro.scope)
|
expect(parsed_query['scopes']).to eq(@subscription.scope)
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_payload(request_id, user_id)
|
def generate_payload(request_id, user_id)
|
||||||
uri = URI(@pro.authentication_url(user_id, request_id))
|
uri = URI(@subscription.authentication_url(user_id, request_id))
|
||||||
keys = @pro.authentication.get_keys(request_id)
|
keys = @subscription.authentication.get_keys(request_id)
|
||||||
raw_payload = {
|
raw_payload = {
|
||||||
key: "12345",
|
key: "12345",
|
||||||
nonce: keys.nonce,
|
nonce: keys.nonce,
|
||||||
|
@ -92,8 +92,8 @@ describe CustomWizard::Pro do
|
||||||
request_id = SecureRandom.hex(32)
|
request_id = SecureRandom.hex(32)
|
||||||
payload = generate_payload(request_id, user.id)
|
payload = generate_payload(request_id, user.id)
|
||||||
|
|
||||||
expect(@pro.authentication_response(request_id, payload)).to eq(true)
|
expect(@subscription.authentication_response(request_id, payload)).to eq(true)
|
||||||
expect(@pro.authorized?).to eq(true)
|
expect(@subscription.authorized?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "discards authentication response if user who made request as not an admin" do
|
it "discards authentication response if user who made request as not an admin" do
|
||||||
|
@ -102,24 +102,24 @@ describe CustomWizard::Pro do
|
||||||
request_id = SecureRandom.hex(32)
|
request_id = SecureRandom.hex(32)
|
||||||
payload = generate_payload(request_id, user.id)
|
payload = generate_payload(request_id, user.id)
|
||||||
|
|
||||||
expect(@pro.authentication_response(request_id, payload)).to eq(false)
|
expect(@subscription.authentication_response(request_id, payload)).to eq(false)
|
||||||
expect(@pro.authorized?).to eq(false)
|
expect(@subscription.authorized?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "discards authentication response if request_id is invalid" do
|
it "discards authentication response if request_id is invalid" do
|
||||||
payload = generate_payload(SecureRandom.hex(32), user.id)
|
payload = generate_payload(SecureRandom.hex(32), user.id)
|
||||||
|
|
||||||
expect(@pro.authentication_response(SecureRandom.hex(32), payload)).to eq(false)
|
expect(@subscription.authentication_response(SecureRandom.hex(32), payload)).to eq(false)
|
||||||
expect(@pro.authorized?).to eq(false)
|
expect(@subscription.authorized?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "destroys authentication" do
|
it "destroys authentication" do
|
||||||
request_id = SecureRandom.hex(32)
|
request_id = SecureRandom.hex(32)
|
||||||
payload = generate_payload(request_id, user.id)
|
payload = generate_payload(request_id, user.id)
|
||||||
@pro.authentication_response(request_id, payload)
|
@subscription.authentication_response(request_id, payload)
|
||||||
|
|
||||||
expect(@pro.destroy_authentication).to eq(true)
|
expect(@subscription.destroy_authentication).to eq(true)
|
||||||
expect(@pro.authorized?).to eq(false)
|
expect(@subscription.authorized?).to eq(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -10,7 +10,7 @@ describe "custom field extensions" do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
||||||
let(:pro_custom_field_json) { get_wizard_fixture("custom_field/pro_custom_fields") }
|
let(:subscription_custom_field_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
custom_field_json['custom_fields'].each do |field_json|
|
custom_field_json['custom_fields'].each do |field_json|
|
||||||
|
@ -72,11 +72,11 @@ describe "custom field extensions" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "pro custom fields" do
|
context "subscription custom fields" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
|
|
||||||
pro_custom_field_json['custom_fields'].each do |field_json|
|
subscription_custom_field_json['custom_fields'].each do |field_json|
|
||||||
custom_field = CustomWizard::CustomField.new(nil, field_json)
|
custom_field = CustomWizard::CustomField.new(nil, field_json)
|
||||||
custom_field.save
|
custom_field.save
|
||||||
end
|
end
|
||||||
|
|
29
spec/jobs/update_notices_spec.rb
Normale Datei
29
spec/jobs/update_notices_spec.rb
Normale Datei
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../plugin_helper'
|
||||||
|
|
||||||
|
describe Jobs::CustomWizardUpdateNotices do
|
||||||
|
let(:subscription_message) {
|
||||||
|
{
|
||||||
|
message: "Message about subscription",
|
||||||
|
type: "info",
|
||||||
|
created_at: Time.now - 3.day,
|
||||||
|
expired_at: nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let(:plugin_status) {
|
||||||
|
{
|
||||||
|
name: 'discourse-custom-wizard',
|
||||||
|
status: 'incompatible',
|
||||||
|
status_changed_at: Time.now - 3.day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "updates the notices" do
|
||||||
|
stub_request(:get, CustomWizard::Notice.subscription_messages_url).to_return(status: 200, body: { messages: [subscription_message] }.to_json)
|
||||||
|
stub_request(:get, CustomWizard::Notice.plugin_status_url).to_return(status: 200, body: { status: plugin_status }.to_json)
|
||||||
|
|
||||||
|
described_class.new.execute
|
||||||
|
expect(CustomWizard::Notice.list.length).to eq(2)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
require_relative '../plugin_helper'
|
require_relative '../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::UpdateProSubscription do
|
describe Jobs::CustomWizardUpdateSubscription do
|
||||||
it "updates the pro subscription" do
|
it "updates the subscription" do
|
||||||
stub_subscription_request(200, valid_subscription)
|
stub_subscription_request(200, valid_subscription)
|
||||||
described_class.new.execute
|
described_class.new.execute
|
||||||
expect(CustomWizard::Pro.subscribed?).to eq(true)
|
expect(CustomWizard::Subscription.subscribed?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -24,16 +24,16 @@ def get_wizard_fixture(path)
|
||||||
).with_indifferent_access
|
).with_indifferent_access
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_pro
|
def authenticate_subscription
|
||||||
CustomWizard::ProAuthentication.any_instance.stubs(:active?).returns(true)
|
CustomWizard::Subscription::Authentication.any_instance.stubs(:active?).returns(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable_subscription
|
def enable_subscription
|
||||||
CustomWizard::Pro.any_instance.stubs(:subscribed?).returns(true)
|
CustomWizard::Subscription.any_instance.stubs(:subscribed?).returns(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_pro
|
def disable_subscription
|
||||||
CustomWizard::Pro.any_instance.stubs(:subscribed?).returns(false)
|
CustomWizard::Subscription.any_instance.stubs(:subscribed?).returns(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_subscription
|
def valid_subscription
|
||||||
|
@ -52,7 +52,7 @@ def invalid_subscription
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_subscription_request(status, subscription)
|
def stub_subscription_request(status, subscription)
|
||||||
authenticate_pro
|
authenticate_subscription
|
||||||
pro = CustomWizard::Pro.new
|
sub = CustomWizard::Subscription.new
|
||||||
stub_request(:get, "https://#{pro.server}/subscription-server/user-subscriptions/#{pro.subscription_type}/#{pro.client_name}").to_return(status: status, body: { subscriptions: [subscription] }.to_json)
|
stub_request(:get, "https://#{sub.server}/subscription-server/user-subscriptions/#{sub.subscription_type}/#{sub.client_name}").to_return(status: status, body: { subscriptions: [subscription] }.to_json)
|
||||||
end
|
end
|
||||||
|
|
31
spec/requests/custom_wizard/admin/notice_controller_spec.rb
Normale Datei
31
spec/requests/custom_wizard/admin/notice_controller_spec.rb
Normale Datei
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
require_relative '../../../plugin_helper'
|
||||||
|
|
||||||
|
describe CustomWizard::AdminNoticeController do
|
||||||
|
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(admin_user)
|
||||||
|
@notice = CustomWizard::Notice.new(
|
||||||
|
message: "Message about subscription",
|
||||||
|
type: "info",
|
||||||
|
created_at: Time.now - 3.day,
|
||||||
|
expired_at: nil
|
||||||
|
)
|
||||||
|
@notice.save
|
||||||
|
end
|
||||||
|
|
||||||
|
it "lists notices" do
|
||||||
|
get "/admin/wizards/notice.json"
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.parsed_body.length).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "dismisses notices" do
|
||||||
|
put "/admin/wizards/notice/#{@notice.id}.json"
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
|
updated = CustomWizard::Notice.find(@notice.id)
|
||||||
|
expect(updated.dismissed?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,12 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
require_relative '../../../plugin_helper'
|
require_relative '../../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::AdminProController do
|
describe CustomWizard::AdminSubscriptionController do
|
||||||
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
||||||
|
|
||||||
def generate_payload(request_id, user_id)
|
def generate_payload(request_id, user_id)
|
||||||
uri = URI(@pro.authentication_url(user_id, request_id))
|
uri = URI(@subscription.authentication_url(user_id, request_id))
|
||||||
keys = @pro.authentication.get_keys(request_id)
|
keys = @subscription.authentication.get_keys(request_id)
|
||||||
raw_payload = {
|
raw_payload = {
|
||||||
key: "12345",
|
key: "12345",
|
||||||
nonce: keys.nonce,
|
nonce: keys.nonce,
|
||||||
|
@ -18,19 +18,19 @@ describe CustomWizard::AdminProController do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@pro = CustomWizard::Pro.new
|
@subscription = CustomWizard::Subscription.new
|
||||||
sign_in(admin_user)
|
sign_in(admin_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#index" do
|
it "#index" do
|
||||||
get "/admin/wizards/pro.json"
|
get "/admin/wizards/subscription.json"
|
||||||
expect(response.parsed_body['server']).to eq(@pro.server)
|
expect(response.parsed_body['server']).to eq(@subscription.server)
|
||||||
expect(response.parsed_body['authentication'].deep_symbolize_keys).to eq(CustomWizard::ProAuthenticationSerializer.new(@pro.authentication, root: false).as_json)
|
expect(response.parsed_body['authentication'].deep_symbolize_keys).to eq(CustomWizard::Subscription::AuthenticationSerializer.new(@subscription.authentication, root: false).as_json)
|
||||||
expect(response.parsed_body['subscription'].deep_symbolize_keys).to eq(CustomWizard::ProSubscriptionSerializer.new(@pro.subscription, root: false).as_json)
|
expect(response.parsed_body['subscription'].deep_symbolize_keys).to eq(CustomWizard::Subscription::SubscriptionSerializer.new(@subscription.subscription, root: false).as_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "#authorize" do
|
it "#authorize" do
|
||||||
get "/admin/wizards/pro/authorize"
|
get "/admin/wizards/subscription/authorize"
|
||||||
expect(response.status).to eq(302)
|
expect(response.status).to eq(302)
|
||||||
expect(cookies[:user_api_request_id].present?).to eq(true)
|
expect(cookies[:user_api_request_id].present?).to eq(true)
|
||||||
end
|
end
|
||||||
|
@ -38,12 +38,12 @@ describe CustomWizard::AdminProController do
|
||||||
it "#destroy_authentication" do
|
it "#destroy_authentication" do
|
||||||
request_id = SecureRandom.hex(32)
|
request_id = SecureRandom.hex(32)
|
||||||
payload = generate_payload(request_id, admin_user.id)
|
payload = generate_payload(request_id, admin_user.id)
|
||||||
@pro.authentication_response(request_id, payload)
|
@subscription.authentication_response(request_id, payload)
|
||||||
|
|
||||||
delete "/admin/wizards/pro/authorize.json"
|
delete "/admin/wizards/subscription/authorize.json"
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(CustomWizard::Pro.authorized?).to eq(false)
|
expect(CustomWizard::Subscription.authorized?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "subscription" do
|
context "subscription" do
|
||||||
|
@ -54,18 +54,18 @@ describe CustomWizard::AdminProController do
|
||||||
it "handles authentication response and the updates subscription" do
|
it "handles authentication response and the updates subscription" do
|
||||||
request_id = cookies[:user_api_request_id] = SecureRandom.hex(32)
|
request_id = cookies[:user_api_request_id] = SecureRandom.hex(32)
|
||||||
payload = generate_payload(request_id, admin_user.id)
|
payload = generate_payload(request_id, admin_user.id)
|
||||||
get "/admin/wizards/pro/authorize/callback", params: { payload: payload }
|
get "/admin/wizards/subscription/authorize/callback", params: { payload: payload }
|
||||||
|
|
||||||
expect(response).to redirect_to("/admin/wizards/pro")
|
expect(response).to redirect_to("/admin/wizards/subscription")
|
||||||
expect(CustomWizard::Pro.subscribed?).to eq(true)
|
expect(CustomWizard::Subscription.subscribed?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "updates the subscription" do
|
it "updates the subscription" do
|
||||||
authenticate_pro
|
authenticate_subscription
|
||||||
post "/admin/wizards/pro/subscription.json"
|
post "/admin/wizards/subscription.json"
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(CustomWizard::Pro.subscribed?).to eq(true)
|
expect(CustomWizard::Subscription.subscribed?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -9,7 +9,7 @@ describe "custom field extensions" do
|
||||||
let!(:user) { Fabricate(:user) }
|
let!(:user) { Fabricate(:user) }
|
||||||
let!(:group) { Fabricate(:group, users: [user]) }
|
let!(:group) { Fabricate(:group, users: [user]) }
|
||||||
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
|
||||||
let(:pro_custom_field_json) { get_wizard_fixture("custom_field/pro_custom_fields") }
|
let(:subscription_custom_field_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
custom_field_json['custom_fields'].each do |field_json|
|
custom_field_json['custom_fields'].each do |field_json|
|
||||||
|
@ -38,11 +38,11 @@ describe "custom field extensions" do
|
||||||
expect(response.parsed_body['post_field_1']).to eq(7)
|
expect(response.parsed_body['post_field_1']).to eq(7)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a pro subscription" do
|
context "with a subscription" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
|
|
||||||
pro_custom_field_json['custom_fields'].each do |field_json|
|
subscription_custom_field_json['custom_fields'].each do |field_json|
|
||||||
custom_field = CustomWizard::CustomField.new(nil, field_json)
|
custom_field = CustomWizard::CustomField.new(nil, field_json)
|
||||||
custom_field.save
|
custom_field.save
|
||||||
end
|
end
|
||||||
|
|
|
@ -119,7 +119,7 @@ describe CustomWizard::StepsController do
|
||||||
expect(response.parsed_body['final']).to eq(true)
|
expect(response.parsed_body['final']).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "pro" do
|
context "subscription" do
|
||||||
before do
|
before do
|
||||||
enable_subscription
|
enable_subscription
|
||||||
end
|
end
|
||||||
|
@ -149,6 +149,38 @@ describe CustomWizard::StepsController do
|
||||||
expect(response.parsed_body['wizard']['start']).to eq("step_3")
|
expect(response.parsed_body['wizard']['start']).to eq("step_3")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns the correct final step when the conditional final step and last step are the same" do
|
||||||
|
new_template = wizard_template.dup
|
||||||
|
new_template['steps'][0]['condition'] = user_condition_template['condition']
|
||||||
|
new_template['steps'][2]['condition'] = wizard_field_condition_template['condition']
|
||||||
|
CustomWizard::Template.save(new_template, skip_jobs: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error when user cant see the step due to conditions" do
|
||||||
|
sign_in(user2)
|
||||||
|
|
||||||
|
new_wizard_template = wizard_template.dup
|
||||||
|
new_wizard_template['steps'][0]['condition'] = user_condition_template['condition']
|
||||||
|
CustomWizard::Template.save(new_wizard_template, skip_jobs: true)
|
||||||
|
|
||||||
|
put '/w/super-mega-fun-wizard/steps/step_1.json'
|
||||||
|
expect(response.status).to eq(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns an updated wizard when condition doesnt pass" do
|
||||||
|
new_template = wizard_template.dup
|
||||||
|
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
|
||||||
|
CustomWizard::Template.save(new_template, skip_jobs: true)
|
||||||
|
|
||||||
|
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
|
||||||
|
fields: {
|
||||||
|
step_1_field_1: "Condition wont pass"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.parsed_body['wizard']['start']).to eq("step_3")
|
||||||
|
end
|
||||||
|
|
||||||
it "returns the correct final step when the conditional final step and last step are the same" do
|
it "returns the correct final step when the conditional final step and last step are the same" do
|
||||||
new_template = wizard_template.dup
|
new_template = wizard_template.dup
|
||||||
new_template['steps'][0]['condition'] = user_condition_template['condition']
|
new_template['steps'][0]['condition'] = user_condition_template['condition']
|
||||||
|
|
22
spec/serializers/custom_wizard/notice_serializer_spec.rb
Normale Datei
22
spec/serializers/custom_wizard/notice_serializer_spec.rb
Normale Datei
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../../plugin_helper'
|
||||||
|
|
||||||
|
describe CustomWizard::NoticeSerializer do
|
||||||
|
before do
|
||||||
|
@notice = CustomWizard::Notice.new(
|
||||||
|
message: "Message about subscription",
|
||||||
|
type: "info",
|
||||||
|
created_at: Time.now - 3.day,
|
||||||
|
expired_at: nil
|
||||||
|
)
|
||||||
|
@notice.save
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return notice attributes' do
|
||||||
|
serialized_notice = described_class.new(@notice)
|
||||||
|
expect(serialized_notice.message).to eq(@notice.message)
|
||||||
|
expect(serialized_notice.type).to eq(CustomWizard::Notice.types.key(@notice.type))
|
||||||
|
expect(serialized_notice.dismissable).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,14 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require_relative '../../plugin_helper'
|
|
||||||
|
|
||||||
describe CustomWizard::ProSerializer do
|
|
||||||
it 'should return pro attributes' do
|
|
||||||
pro = CustomWizard::Pro.new
|
|
||||||
serialized = described_class.new(pro, root: false)
|
|
||||||
|
|
||||||
expect(serialized.server).to eq(pro.server)
|
|
||||||
expect(serialized.authentication.class).to eq(CustomWizard::ProAuthentication)
|
|
||||||
expect(serialized.subscription.class).to eq(CustomWizard::ProSubscription)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
require_relative '../../../plugin_helper'
|
require_relative '../../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::ProAuthenticationSerializer do
|
describe CustomWizard::Subscription::AuthenticationSerializer do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
it 'should return pro authentication attributes' do
|
it 'should return subscription authentication attributes' do
|
||||||
auth = CustomWizard::ProAuthentication.new(OpenStruct.new(key: '1234', auth_at: Time.now, auth_by: user.id))
|
auth = CustomWizard::Subscription::Authentication.new(OpenStruct.new(key: '1234', auth_at: Time.now, auth_by: user.id))
|
||||||
serialized = described_class.new(auth, root: false).as_json
|
serialized = described_class.new(auth, root: false).as_json
|
||||||
|
|
||||||
expect(serialized[:active]).to eq(true)
|
expect(serialized[:active]).to eq(true)
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
require_relative '../../../plugin_helper'
|
require_relative '../../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::ProSubscriptionSerializer do
|
describe CustomWizard::Subscription::SubscriptionSerializer do
|
||||||
it 'should return pro subscription attributes' do
|
it 'should return subscription attributes' do
|
||||||
sub = CustomWizard::ProSubscription.new(OpenStruct.new(type: 'community', updated_at: Time.now))
|
sub = CustomWizard::Subscription::Subscription.new(OpenStruct.new(type: 'community', updated_at: Time.now))
|
||||||
serialized = described_class.new(sub, root: false).as_json
|
serialized = described_class.new(sub, root: false).as_json
|
||||||
|
|
||||||
expect(serialized[:active]).to eq(true)
|
expect(serialized[:active]).to eq(true)
|
14
spec/serializers/custom_wizard/subscription_serializer_spec.rb
Normale Datei
14
spec/serializers/custom_wizard/subscription_serializer_spec.rb
Normale Datei
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../../plugin_helper'
|
||||||
|
|
||||||
|
describe CustomWizard::SubscriptionSerializer do
|
||||||
|
it 'should return subscription attributes' do
|
||||||
|
subscription = CustomWizard::Subscription.new
|
||||||
|
serialized = described_class.new(subscription, root: false)
|
||||||
|
|
||||||
|
expect(serialized.server).to eq(subscription.server)
|
||||||
|
expect(serialized.authentication.class).to eq(CustomWizard::Subscription::Authentication)
|
||||||
|
expect(serialized.subscription.class).to eq(CustomWizard::Subscription::Subscription)
|
||||||
|
end
|
||||||
|
end
|
Laden …
In neuem Issue referenzieren