Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 01:10:28 +01:00
Add community subscription as an explicit type
Dieser Commit ist enthalten in:
Ursprung
785bd5d956
Commit
c79dee3d16
20 geänderte Dateien mit 176 neuen und 90 gelöschten Zeilen
|
@ -1,2 +1,8 @@
|
|||
inherit_gem:
|
||||
rubocop-discourse: default.yml
|
||||
|
||||
RSpec/ContextWording:
|
||||
Enabled: false
|
||||
|
||||
RSpec/DescribeClass:
|
||||
Enabled: false
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Component.extend(Subscription, {
|
|||
|
||||
@discourseComputed("subscriptionType")
|
||||
i18nKey(type) {
|
||||
return `admin.wizard.subscription_container.type.${type ? type : "none"}`;
|
||||
return `admin.wizard.subscription.type.${type ? type : "none"}`;
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey")
|
||||
|
|
|
@ -12,14 +12,14 @@ export default Component.extend(Subscription, {
|
|||
|
||||
@discourseComputed("subscribed")
|
||||
subscribedLabel(subscribed) {
|
||||
return `admin.wizard.subscription_container.${
|
||||
return `admin.wizard.subscription.${
|
||||
subscribed ? "subscribed" : "not_subscribed"
|
||||
}.label`;
|
||||
},
|
||||
|
||||
@discourseComputed("subscribed")
|
||||
subscribedTitle(subscribed) {
|
||||
return `admin.wizard.subscription_container.${
|
||||
return `admin.wizard.subscription.${
|
||||
subscribed ? "subscribed" : "not_subscribed"
|
||||
}.title`;
|
||||
},
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import Component from "@ember/component";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Subscription from "../mixins/subscription";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default Component.extend(Subscription, {
|
||||
tagName: "a",
|
||||
classNameBindings: [":btn", ":btn-pavilion-support", "subscriptionType"],
|
||||
attributeBindings: ["title"],
|
||||
|
||||
@discourseComputed("subscribed")
|
||||
i18nKey(subscribed) {
|
||||
return `admin.wizard.subscription.cta.${subscribed ? "subscribed" : "none"}`;
|
||||
},
|
||||
|
||||
@discourseComputed("subscribed")
|
||||
icon(subscribed) {
|
||||
return subscribed ? "far-life-ring" : "external-link-alt";
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey")
|
||||
title(i18nKey) {
|
||||
return I18n.t(`${i18nKey}.title`);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey")
|
||||
label(i18nKey) {
|
||||
return I18n.t(`${i18nKey}.label`);
|
||||
},
|
||||
|
||||
click() {
|
||||
window.open(this.subscriptionCtaLink, "_blank").focus();
|
||||
},
|
||||
});
|
|
@ -1,10 +1,6 @@
|
|||
import SingleSelectComponent from "select-kit/components/single-select";
|
||||
import Subscription from "../mixins/subscription";
|
||||
import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
|
||||
import {
|
||||
subscriptionTypeSufficient,
|
||||
subscriptionTypes,
|
||||
} from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-subscription";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "I18n";
|
||||
|
||||
|
@ -29,45 +25,50 @@ export default SingleSelectComponent.extend(Subscription, {
|
|||
caretDownIcon: "caret-down",
|
||||
},
|
||||
|
||||
requiredSubscriptionType(feature, attribute, value) {
|
||||
allowedSubscriptionTypes(feature, attribute, value) {
|
||||
let attributes = this.subscriptionAttributes[feature];
|
||||
if (!attributes || !attributes[attribute]) {
|
||||
return null;
|
||||
return ['none'];
|
||||
}
|
||||
|
||||
let requiredType = null;
|
||||
Object.keys(attributes[attribute]).some((subscriptionType) => {
|
||||
let allowedTypes = [];
|
||||
Object.keys(attributes[attribute]).forEach((subscriptionType) => {
|
||||
let values = attributes[attribute][subscriptionType];
|
||||
if (values[0] === "*" || values.includes(value)) {
|
||||
if (subscriptionTypes.includes(subscriptionType)) {
|
||||
requiredType = subscriptionType;
|
||||
allowedTypes.push(subscriptionType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return requiredType;
|
||||
return allowedTypes;
|
||||
},
|
||||
|
||||
@discourseComputed("feature", "attribute")
|
||||
content(feature, attribute) {
|
||||
return wizardSchema[feature][attribute]
|
||||
.map((value) => {
|
||||
let requiredSubscriptionType = this.requiredSubscriptionType(
|
||||
let allowedSubscriptionTypes = this.allowedSubscriptionTypes(
|
||||
feature,
|
||||
attribute,
|
||||
value
|
||||
);
|
||||
return {
|
||||
|
||||
let subscriptionRequired = allowedSubscriptionTypes.length &&
|
||||
!allowedSubscriptionTypes.includes('none');
|
||||
|
||||
let attrs = {
|
||||
id: value,
|
||||
name: I18n.t(nameKey(feature, attribute, value)),
|
||||
subscriptionType: requiredSubscriptionType,
|
||||
disabled: !subscriptionTypeSufficient(
|
||||
this.subscriptionType,
|
||||
requiredSubscriptionType
|
||||
),
|
||||
subscriptionRequired
|
||||
};
|
||||
|
||||
if (subscriptionRequired) {
|
||||
let subscribed = allowedSubscriptionTypes.includes(this.subscriptionType);
|
||||
let selectorKey = subscribed ? "subscribed" : "not_subscribed";
|
||||
let selectorLabel = `admin.wizard.subscription.${selectorKey}.selector`;
|
||||
|
||||
attrs.disabled = !subscribed;
|
||||
attrs.selectorLabel = selectorLabel;
|
||||
}
|
||||
|
||||
return attrs;
|
||||
})
|
||||
.sort(function (a, b) {
|
||||
if (a.subscriptionType && !b.subscriptionType) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { equal } from "@ember/object/computed";
|
||||
import { equal, or } from "@ember/object/computed";
|
||||
|
||||
export default Controller.extend({
|
||||
businessSubscription: equal("subscriptionType", "business"),
|
||||
communitySubscription: equal("subscriptionType", "community"),
|
||||
standardSubscription: equal("subscriptionType", "standard"),
|
||||
showApi: or('businessSubscription', 'communitySubscription')
|
||||
});
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
const subscriptionTypes = ["standard", "business"];
|
||||
|
||||
function subscriptionTypeSufficient(subscriptionType, requiredType) {
|
||||
if (requiredType && !subscriptionType) {
|
||||
return false;
|
||||
}
|
||||
if (requiredType === "none" || requiredType === null) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
requiredType === "standard" &&
|
||||
subscriptionTypes.includes(subscriptionType)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (requiredType === "business" && subscriptionType === "business") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export { subscriptionTypeSufficient, subscriptionTypes };
|
|
@ -3,8 +3,12 @@ import { getOwner } from "discourse-common/lib/get-owner";
|
|||
import { readOnly } from "@ember/object/computed";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
const PRODUCT_PAGE = "https://custom-wizard.pavilion.tech";
|
||||
const SUPPORT_MESSAGE = "https://coop.pavilion.tech/new-message?username=support&title=Custom%20Wizard%20Support";
|
||||
const MANAGER_CATEGORY = "https://discourse.pluginmanager.org/c/discourse-custom-wizard";
|
||||
|
||||
export default Mixin.create({
|
||||
subscriptionLandingUrl: "https://custom-wizard.pavilion.tech",
|
||||
subscriptionLandingUrl: PRODUCT_PAGE,
|
||||
subscriptionClientUrl: "/admin/plugins/subscription-client",
|
||||
|
||||
@discourseComputed
|
||||
|
@ -15,6 +19,7 @@ export default Mixin.create({
|
|||
subscribed: readOnly("adminWizards.subscribed"),
|
||||
subscriptionType: readOnly("adminWizards.subscriptionType"),
|
||||
businessSubscription: readOnly("adminWizards.businessSubscription"),
|
||||
communitySubscription: readOnly("adminWizards.communitySubscription"),
|
||||
standardSubscription: readOnly("adminWizards.standardSubscription"),
|
||||
subscriptionAttributes: readOnly("adminWizards.subscriptionAttributes"),
|
||||
subscriptionClientInstalled: readOnly(
|
||||
|
@ -27,4 +32,15 @@ export default Mixin.create({
|
|||
? this.subscriptionClientUrl
|
||||
: this.subscriptionLandingUrl;
|
||||
},
|
||||
|
||||
@discourseComputed("subscriptionType")
|
||||
subscriptionCtaLink(subscriptionType) {
|
||||
switch (subscriptionType) {
|
||||
case "none": return PRODUCT_PAGE;
|
||||
case "standard": return SUPPORT_MESSAGE;
|
||||
case "business": return SUPPORT_MESSAGE;
|
||||
case "community": return MANAGER_CATEGORY;
|
||||
default: return PRODUCT_PAGE;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ import { A } from "@ember/array";
|
|||
import EmberObject from "@ember/object";
|
||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import CustomWizard from "../models/custom-wizard";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
model(params) {
|
||||
|
|
|
@ -2,17 +2,15 @@
|
|||
{{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
|
||||
{{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}}
|
||||
{{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}}
|
||||
{{#if businessSubscription}}
|
||||
{{#if showApi}}
|
||||
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
|
||||
{{/if}}
|
||||
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
||||
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
||||
|
||||
<div class="announcement">
|
||||
<a href="https://custom-wizard.pavilion.tech/subscriptions" target="_blank" title="Click to learn more about Custom Wizard Subscriptions">
|
||||
<img src='/images/emoji/twitter/man_mage.png?v=12'>
|
||||
<span>Custom Wizard Subscriptions Are Coming!</span>
|
||||
</a>
|
||||
<div class="admin-actions">
|
||||
{{wizard-subscription-badge}}
|
||||
{{wizard-subscription-cta}}
|
||||
</div>
|
||||
{{/admin-nav}}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="subscription-header">
|
||||
<h4>{{i18n "admin.wizard.subscription_container.title"}}</h4>
|
||||
<h4>{{i18n "admin.wizard.subscription.title"}}</h4>
|
||||
|
||||
<a href={{subscriptionLink}} title={{i18n subscribedTitle}}>
|
||||
{{d-icon subscribedIcon}}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{{d-icon icon}}{{label}}
|
|
@ -7,10 +7,8 @@
|
|||
shouldDisplayClearableButton=shouldDisplayClearableButton
|
||||
}}
|
||||
|
||||
{{#if selectedContent.subscriptionType}}
|
||||
<span class="subscription-label">
|
||||
{{selectedContent.subscriptionType}}
|
||||
</span>
|
||||
{{#if subscriptionRequired}}
|
||||
<span class="subscription-label">{{i18n selectorLabel}}</span>
|
||||
{{/if}}
|
||||
|
||||
{{d-icon caretIcon class="caret-icon"}}
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
<div class="texts">
|
||||
<span class="name">{{html-safe label}}</span>
|
||||
{{#if item.subscriptionType}}
|
||||
<span class="subscription-label">
|
||||
{{item.subscriptionType}}
|
||||
</span>
|
||||
{{#if item.subscriptionRequired}}
|
||||
<span class="subscription-label">{{i18n item.selectorLabel}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -841,7 +841,7 @@ $error: #ef1700;
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn[href].btn-pavilion-support {
|
||||
.btn.btn-pavilion-support {
|
||||
background: var(--pavilion-primary);
|
||||
color: var(--pavilion-secondary);
|
||||
|
||||
|
@ -920,6 +920,12 @@ $error: #ef1700;
|
|||
color: $secondary;
|
||||
}
|
||||
|
||||
&.community {
|
||||
background-color: $subscription_community;
|
||||
border: 1.5px solid $pavilion_primary;
|
||||
color: $pavilion_primary;
|
||||
}
|
||||
|
||||
.d-icon {
|
||||
margin-right: 0.75em;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ $pavilion_warning: rgb(243, 163, 61);
|
|||
|
||||
$subscription_standard: $pavilion_primary;
|
||||
$subscription_business: #333;
|
||||
$subscription_community: #fff;
|
||||
|
||||
:root {
|
||||
--pavilion-primary: #{$pavilion_primary};
|
||||
|
@ -11,4 +12,5 @@ $subscription_business: #333;
|
|||
--pavilion-warning: #{$pavilion_warning};
|
||||
--subscription-standard: #{$subscription_standard};
|
||||
--subscription-business: #{$subscription_business};
|
||||
--subscription-community: #{$subscription_community};
|
||||
}
|
||||
|
|
|
@ -129,9 +129,6 @@ en:
|
|||
edit_columns: "Edit Columns"
|
||||
expand_text: "Read More"
|
||||
collapse_text: "Show Less"
|
||||
support_button:
|
||||
title: "Request Support"
|
||||
label: "Support"
|
||||
category_settings:
|
||||
custom_wizard:
|
||||
title: "Custom Wizard"
|
||||
|
@ -535,14 +532,16 @@ en:
|
|||
destroy: Destroy
|
||||
destroyed: destroyed
|
||||
|
||||
subscription_container:
|
||||
subscription:
|
||||
title: Subscriber Features
|
||||
subscribed:
|
||||
label: Subscribed
|
||||
title: You're subscribed and can use these features
|
||||
selector: subscribed
|
||||
not_subscribed:
|
||||
label: Not Subscribed
|
||||
title: Subscribe to use these features
|
||||
selector: not subscribed
|
||||
type:
|
||||
none:
|
||||
label: Not Subscribed
|
||||
|
@ -553,6 +552,17 @@ en:
|
|||
standard:
|
||||
label: Standard
|
||||
title: There is a Custom Wizard Standard subscription active on this forum.
|
||||
community:
|
||||
label: Community
|
||||
title: There is a Custom Wizard Community subscription active on this forum.
|
||||
cta:
|
||||
none:
|
||||
label: Get a Subscription
|
||||
title: Get a subscription for this forum.
|
||||
subscribed:
|
||||
label: Support
|
||||
title: Get support for your subscription.
|
||||
|
||||
|
||||
wizard_js:
|
||||
group:
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::Subscription
|
||||
STANDARD_PRODUCT_ID = 'prod_LNAGVAaIqDsHmB'
|
||||
BUSINESS_PRODUCT_ID = 'prod_LNABQ50maBQ1pY'
|
||||
STANDARD_PRODUCT_ID = 'prod_MH11woVoZU5AWb'
|
||||
BUSINESS_PRODUCT_ID = 'prod_MH0wT627okh3Ef'
|
||||
COMMUNITY_PRODUCT_ID = 'prod_MU7l9EjxhaukZ7'
|
||||
|
||||
def self.attributes
|
||||
{
|
||||
|
@ -9,75 +10,88 @@ class CustomWizard::Subscription
|
|||
required: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
permitted: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
}
|
||||
},
|
||||
step: {
|
||||
condition: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
index: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
required_data: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
permitted_params: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
}
|
||||
},
|
||||
field: {
|
||||
condition: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
index: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
type: {
|
||||
none: ['text', 'textarea', 'text_only', 'date', 'time', 'date_time', 'number', 'checkbox', 'dropdown', 'upload'],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
realtime_validations: {
|
||||
none: [],
|
||||
standard: ['*'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
}
|
||||
},
|
||||
action: {
|
||||
type: {
|
||||
none: ['create_topic', 'update_profile', 'open_composer', 'route_to'],
|
||||
standard: ['create_topic', 'update_profile', 'open_composer', 'route_to', 'send_message', 'watch_categories', 'add_to_group'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
}
|
||||
},
|
||||
custom_field: {
|
||||
klass: {
|
||||
none: ['topic', 'post'],
|
||||
standard: ['topic', 'post'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
},
|
||||
type: {
|
||||
none: ['string', 'boolean', 'integer'],
|
||||
standard: ['string', 'boolean', 'integer'],
|
||||
business: ['*']
|
||||
business: ['*'],
|
||||
community: ['*']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,10 +123,11 @@ class CustomWizard::Subscription
|
|||
return :none unless subscribed?
|
||||
return :standard if standard?
|
||||
return :business if business?
|
||||
return :community if community?
|
||||
end
|
||||
|
||||
def subscribed?
|
||||
standard? || business?
|
||||
standard? || business? || community?
|
||||
end
|
||||
|
||||
def standard?
|
||||
|
@ -123,6 +138,10 @@ class CustomWizard::Subscription
|
|||
@subscription.product_id === BUSINESS_PRODUCT_ID
|
||||
end
|
||||
|
||||
def community?
|
||||
@subscription.product_id === COMMUNITY_PRODUCT_ID
|
||||
end
|
||||
|
||||
def client_installed?
|
||||
defined?(SubscriptionClient) == 'constant' && SubscriptionClient.class == Module
|
||||
end
|
||||
|
@ -132,7 +151,7 @@ class CustomWizard::Subscription
|
|||
|
||||
if client_installed?
|
||||
subscription = SubscriptionClientSubscription.active
|
||||
.where(product_id: [STANDARD_PRODUCT_ID, BUSINESS_PRODUCT_ID])
|
||||
.where(product_id: [STANDARD_PRODUCT_ID, BUSINESS_PRODUCT_ID, COMMUNITY_PRODUCT_ID])
|
||||
.order("product_id = '#{BUSINESS_PRODUCT_ID}' DESC")
|
||||
.first
|
||||
end
|
||||
|
@ -152,6 +171,10 @@ class CustomWizard::Subscription
|
|||
new.business?
|
||||
end
|
||||
|
||||
def self.community?
|
||||
new.community?
|
||||
end
|
||||
|
||||
def self.standard?
|
||||
new.standard?
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ describe CustomWizard::Submission do
|
|||
).to eq("I am user submission")
|
||||
end
|
||||
|
||||
context "#list" do
|
||||
describe "#list" do
|
||||
before do
|
||||
template_json_2 = template_json.dup
|
||||
template_json_2["id"] = "super_mega_fun_wizard_2"
|
||||
|
|
|
@ -96,7 +96,21 @@ describe CustomWizard::Subscription do
|
|||
expect(described_class.type).to eq(:business)
|
||||
end
|
||||
|
||||
it "business are included" do
|
||||
it "business features are included" do
|
||||
expect(described_class.includes?(:action, :type, 'create_category')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "with community subscription" do
|
||||
before do
|
||||
SubscriptionClientSubscription.stubs(:product_id).returns(CustomWizard::Subscription::COMMUNITY_PRODUCT_ID)
|
||||
end
|
||||
|
||||
it "detects community type" do
|
||||
expect(described_class.type).to eq(:community)
|
||||
end
|
||||
|
||||
it "community features are included" do
|
||||
expect(described_class.includes?(:action, :type, 'create_category')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
|
Laden …
In neuem Issue referenzieren