DEV: Update linting config and run gjs-codemod (#277)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
< 3.5.0.beta5-dev: 7309c937dddb1933ac66aa2d3e13d071060d30ff
|
||||
< 3.5.0.beta1-dev: b4f7be4274ada9400238f8692e705669034c1709
|
||||
< 3.4.0.beta2-dev: 692f410ab59e329d0aaf537cd772698f83c32a8a
|
||||
< 3.4.0.beta1-dev: bb96d77056a9ef842e01e46fd980320d427073ad
|
||||
|
||||
+23
-21
@@ -20,30 +20,31 @@ GEM
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
ast (2.4.2)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.9)
|
||||
ast (2.4.3)
|
||||
base64 (0.3.0)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
drb (2.2.1)
|
||||
connection_pool (2.5.3)
|
||||
drb (2.2.3)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.10.2)
|
||||
language_server-protocol (3.17.0.4)
|
||||
json (2.12.2)
|
||||
language_server-protocol (3.17.0.5)
|
||||
lint_roller (1.1.0)
|
||||
logger (1.6.6)
|
||||
logger (1.7.0)
|
||||
minitest (5.25.5)
|
||||
parallel (1.26.3)
|
||||
parser (3.3.7.1)
|
||||
parallel (1.27.0)
|
||||
parser (3.3.8.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
prettier_print (1.2.1)
|
||||
prism (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (3.1.12)
|
||||
rack (3.1.15)
|
||||
rainbow (3.1.1)
|
||||
regexp_parser (2.10.0)
|
||||
rubocop (1.74.0)
|
||||
rubocop (1.75.8)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
@@ -51,11 +52,12 @@ GEM
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.38.0, < 2.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.38.1)
|
||||
parser (>= 3.3.1.0)
|
||||
rubocop-ast (1.44.1)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.4)
|
||||
rubocop-capybara (2.22.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
@@ -71,13 +73,13 @@ GEM
|
||||
rubocop-factory_bot (2.27.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rails (2.30.3)
|
||||
rubocop-rails (2.32.0)
|
||||
activesupport (>= 4.2.0)
|
||||
lint_roller (~> 1.1)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.72.1, < 2.0)
|
||||
rubocop-ast (>= 1.38.0, < 2.0)
|
||||
rubocop-rspec (3.5.0)
|
||||
rubocop (>= 1.75.0, < 2.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
rubocop-rspec (3.6.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec_rails (2.31.0)
|
||||
@@ -104,4 +106,4 @@ DEPENDENCIES
|
||||
translations-manager!
|
||||
|
||||
BUNDLED WITH
|
||||
2.6.6
|
||||
2.6.9
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,176 +0,0 @@
|
||||
{{#if this.shouldShow}}
|
||||
<div
|
||||
class="campaign-banner"
|
||||
style={{html-safe (concat "box-shadow: 5px 5px #" this.dropShadowColor)}}
|
||||
>
|
||||
<DButton @icon="xmark" @action={{this.dismissBanner}} class="close" />
|
||||
|
||||
<div class="campaign-banner-info" style={{html-safe this.bannerInfoStyle}}>
|
||||
{{#if this.isGoalMet}}
|
||||
<h2 class="campaign-banner-info-header">
|
||||
{{i18n "discourse_subscriptions.campaign.success_title"}}
|
||||
</h2>
|
||||
|
||||
<p class="campaign-banner-info-description">
|
||||
{{i18n "discourse_subscriptions.campaign.success_body"}}
|
||||
</p>
|
||||
{{else}}
|
||||
<h2 class="campaign-banner-info-header">
|
||||
{{i18n "discourse_subscriptions.campaign.title"}}
|
||||
</h2>
|
||||
|
||||
<p class="campaign-banner-info-description">
|
||||
{{i18n "discourse_subscriptions.campaign.body"}}
|
||||
</p>
|
||||
|
||||
{{#if this.product}}
|
||||
<LinkTo
|
||||
@route="subscribe.show"
|
||||
@model={{this.product}}
|
||||
@disabled={{this.product.subscribed}}
|
||||
class="btn btn-primary campaign-banner-info-button"
|
||||
>
|
||||
{{d-icon "far-heart"}}
|
||||
{{d-icon "heart" class="hover-heart"}}
|
||||
{{i18n "discourse_subscriptions.campaign.button"}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
<LinkTo
|
||||
@route={{this.subscribeRoute}}
|
||||
class="btn btn-primary campaign-banner-info-button"
|
||||
>
|
||||
{{d-icon "far-heart"}}
|
||||
{{d-icon "heart" class="hover-heart"}}
|
||||
{{i18n "discourse_subscriptions.campaign.button"}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="campaign-banner-progress">
|
||||
{{#if this.isGoalMet}}
|
||||
<div class="fireworks">
|
||||
<div class="before"></div>
|
||||
<div class="after"></div>
|
||||
</div>
|
||||
|
||||
<div class="campaign-banner-progress-success"></div>
|
||||
|
||||
{{#if this.subscriberGoal}}
|
||||
<p class="campaign-banner-progress-description">
|
||||
{{html-safe
|
||||
(i18n
|
||||
"discourse_subscriptions.campaign.goal_comparison"
|
||||
current=this.subscribers
|
||||
goal=this.goalTarget
|
||||
)
|
||||
}}
|
||||
{{i18n "discourse_subscriptions.campaign.subscribers"}}
|
||||
</p>
|
||||
{{else}}
|
||||
<p class="campaign-banner-progress-description">
|
||||
{{html-safe
|
||||
(i18n
|
||||
"discourse_subscriptions.campaign.goal_comparison"
|
||||
current=(format-currency this.currency this.amountRaised)
|
||||
goal=(format-currency this.currency this.goalTarget)
|
||||
)
|
||||
}}
|
||||
{{i18n "discourse_subscriptions.campaign.raised"}}
|
||||
</p>
|
||||
|
||||
{{#if this.showContributors}}
|
||||
<ConditionalLoadingSpinner
|
||||
@condition={{this.loading}}
|
||||
@size="small"
|
||||
>
|
||||
<div class="campaign-banner-progress-users">
|
||||
<p class="campaign-banner-progress-users-title">
|
||||
<strong>
|
||||
{{i18n
|
||||
"discourse_subscriptions.campaign.recent_contributors"
|
||||
}}
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<div class="campaign-banner-progress-users-avatars">
|
||||
{{#each this.contributors as |contributor|}}
|
||||
{{avatar
|
||||
contributor
|
||||
avatarTemplatePath="avatar_template"
|
||||
usernamePath="username"
|
||||
namePath="name"
|
||||
imageSize="small"
|
||||
}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</ConditionalLoadingSpinner>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if this.subscriberGoal}}
|
||||
<progress
|
||||
class="campaign-banner-progress-bar"
|
||||
value={{this.subscribers}}
|
||||
max={{this.siteSettings.discourse_subscriptions_campaign_goal}}
|
||||
></progress>
|
||||
|
||||
<p class="campaign-banner-progress-description">
|
||||
{{html-safe
|
||||
(i18n
|
||||
"discourse_subscriptions.campaign.goal_comparison"
|
||||
current=this.subscribers
|
||||
goal=this.goalTarget
|
||||
)
|
||||
}}
|
||||
{{i18n "discourse_subscriptions.campaign.subscribers"}}
|
||||
</p>
|
||||
{{else}}
|
||||
<progress
|
||||
class="campaign-banner-progress-bar"
|
||||
value={{this.amountRaised}}
|
||||
max={{this.siteSettings.discourse_subscriptions_campaign_goal}}
|
||||
></progress>
|
||||
|
||||
<p class="campaign-banner-progress-description">
|
||||
{{html-safe
|
||||
(i18n
|
||||
"discourse_subscriptions.campaign.goal_comparison"
|
||||
current=(format-currency this.currency this.amountRaised)
|
||||
goal=(format-currency this.currency this.goalTarget)
|
||||
)
|
||||
}}
|
||||
{{i18n "discourse_subscriptions.campaign.raised"}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.showContributors}}
|
||||
<ConditionalLoadingSpinner @condition={{this.loading}} @size="small">
|
||||
<div class="campaign-banner-progress-users">
|
||||
<p class="campaign-banner-progress-users-title">
|
||||
<strong>
|
||||
{{i18n
|
||||
"discourse_subscriptions.campaign.recent_contributors"
|
||||
}}
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<div class="campaign-banner-progress-users-avatars">
|
||||
{{#each this.contributors as |contributor|}}
|
||||
{{avatar
|
||||
contributor
|
||||
avatarTemplatePath="avatar_template"
|
||||
usernamePath="username"
|
||||
namePath="name"
|
||||
imageSize="small"
|
||||
}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</ConditionalLoadingSpinner>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
@@ -1,205 +0,0 @@
|
||||
import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
import { equal } from "@ember/object/computed";
|
||||
import { later } from "@ember/runloop";
|
||||
import { service } from "@ember/service";
|
||||
import { classNameBindings } from "@ember-decorators/component";
|
||||
import { observes } from "@ember-decorators/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
|
||||
const SIDEBAR_BODY_CLASS = "subscription-campaign-sidebar";
|
||||
|
||||
@classNameBindings("isGoalMet:goal-met")
|
||||
export default class CampaignBanner extends Component {
|
||||
@service router;
|
||||
|
||||
dismissed = false;
|
||||
loading = false;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_banner_shadow_color")
|
||||
dropShadowColor;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_banner_bg_image")
|
||||
backgroundImageUrl;
|
||||
|
||||
@equal(
|
||||
"siteSettings.discourse_subscriptions_campaign_banner_location",
|
||||
"Sidebar"
|
||||
)
|
||||
isSidebar;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_subscribers") subscribers;
|
||||
|
||||
@equal("siteSettings.discourse_subscriptions_campaign_type", "Subscribers")
|
||||
subscriberGoal;
|
||||
|
||||
@setting("discourse_subscriptions_currency") currency;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_amount_raised") amountRaised;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_goal") goalTarget;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_product") product;
|
||||
|
||||
@setting("discourse_subscriptions_pricing_table_enabled") pricingTableEnabled;
|
||||
|
||||
@setting("discourse_subscriptions_campaign_show_contributors")
|
||||
showContributors;
|
||||
|
||||
init() {
|
||||
super.init(...arguments);
|
||||
|
||||
this.set("contributors", []);
|
||||
|
||||
// add background-image url to stylesheet
|
||||
if (this.backgroundImageUrl) {
|
||||
const backgroundUrl = `url(${this.backgroundImageUrl}`.replace(/\\/g, "");
|
||||
if (
|
||||
document.documentElement.style.getPropertyValue(
|
||||
"--campaign-background-image"
|
||||
) !== backgroundUrl
|
||||
) {
|
||||
document.documentElement.style.setProperty(
|
||||
"--campaign-background-image",
|
||||
backgroundUrl
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentUser && this.showContributors) {
|
||||
return ajax("/s/contributors", { method: "get" }).then((result) => {
|
||||
this.setProperties({
|
||||
contributors: result,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
didInsertElement() {
|
||||
super.didInsertElement(...arguments);
|
||||
if (this.isSidebar && this.shouldShow && !this.site.mobileView) {
|
||||
document.body.classList.add(SIDEBAR_BODY_CLASS);
|
||||
} else {
|
||||
document.body.classList.remove(SIDEBAR_BODY_CLASS);
|
||||
}
|
||||
|
||||
// makes sure to only play animation once, & not repeat on reload
|
||||
if (this.isGoalMet) {
|
||||
const successAnimationKey = this.keyValueStore.get(
|
||||
"campaign_success_animation"
|
||||
);
|
||||
|
||||
if (!successAnimationKey) {
|
||||
later(() => {
|
||||
this.keyValueStore.set({
|
||||
key: "campaign_success_animation",
|
||||
value: Date.now(),
|
||||
});
|
||||
document.body.classList.add("success-animation-off");
|
||||
}, 7000);
|
||||
} else {
|
||||
document.body.classList.add("success-animation-off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
willDestroyElement() {
|
||||
super.willDestroyElement(...arguments);
|
||||
document.body.classList.remove(SIDEBAR_BODY_CLASS);
|
||||
}
|
||||
|
||||
@discourseComputed("backgroundImageUrl")
|
||||
bannerInfoStyle(backgroundImageUrl) {
|
||||
if (!backgroundImageUrl) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `background-image: linear-gradient(
|
||||
0deg,
|
||||
rgba(var(--secondary-rgb), 0.75) 0%,
|
||||
rgba(var(--secondary-rgb), 0.75) 100%),
|
||||
var(--campaign-background-image);
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;`;
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"router.currentRouteName",
|
||||
"currentUser",
|
||||
"siteSettings.discourse_subscriptions_campaign_enabled",
|
||||
"visible"
|
||||
)
|
||||
shouldShow(currentRoute, currentUser, enabled, visible) {
|
||||
// do not show on admin or subscriptions pages
|
||||
const showOnRoute =
|
||||
currentRoute !== "discovery.s" &&
|
||||
!currentRoute.split(".")[0].includes("admin") &&
|
||||
currentRoute.split(".")[0] !== "subscribe" &&
|
||||
currentRoute.split(".")[0] !== "subscriptions";
|
||||
|
||||
if (!this.site.show_campaign_banner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure not to render above main container when inside a topic
|
||||
if (
|
||||
this.connectorName === "above-main-container" &&
|
||||
currentRoute.includes("topic")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return showOnRoute && currentUser && enabled && visible;
|
||||
}
|
||||
|
||||
@observes("dismissed")
|
||||
_updateBodyClasses() {
|
||||
if (this.dismissed) {
|
||||
document.body.classList.remove(SIDEBAR_BODY_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
@discourseComputed("dismissed")
|
||||
visible(dismissed) {
|
||||
const dismissedBannerKey = this.keyValueStore.get(
|
||||
"dismissed_campaign_banner"
|
||||
);
|
||||
const threeMonths = 2628000000 * 3;
|
||||
|
||||
const bannerDismissedTime = new Date(dismissedBannerKey);
|
||||
const now = Date.now();
|
||||
|
||||
return (
|
||||
(!dismissedBannerKey || now - bannerDismissedTime > threeMonths) &&
|
||||
!dismissed
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
subscribeRoute() {
|
||||
if (this.pricingTableEnabled) {
|
||||
return "subscriptions";
|
||||
}
|
||||
return "subscribe";
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
isGoalMet() {
|
||||
const currentVolume = this.subscriberGoal
|
||||
? this.subscribers
|
||||
: this.amountRaised;
|
||||
return currentVolume >= this.goalTarget;
|
||||
}
|
||||
|
||||
@action
|
||||
dismissBanner() {
|
||||
this.set("dismissed", true);
|
||||
this.keyValueStore.set({
|
||||
key: "dismissed_campaign_banner",
|
||||
value: Date.now(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import Component, { Input } from "@ember/component";
|
||||
import { fn } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import ComboBox from "select-kit/components/combo-box";
|
||||
|
||||
export default class CreateCouponForm extends Component {
|
||||
discountType = "amount";
|
||||
discount = null;
|
||||
promoCode = null;
|
||||
active = false;
|
||||
|
||||
@discourseComputed
|
||||
discountTypes() {
|
||||
return [
|
||||
{ id: "amount", name: "Amount" },
|
||||
{ id: "percent", name: "Percent" },
|
||||
];
|
||||
}
|
||||
|
||||
@action
|
||||
createNewCoupon() {
|
||||
const createParams = {
|
||||
promo: this.promoCode,
|
||||
discount_type: this.discountType,
|
||||
discount: this.discount,
|
||||
active: this.active,
|
||||
};
|
||||
|
||||
this.create(createParams);
|
||||
}
|
||||
|
||||
@action
|
||||
cancelCreate() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="create-coupon-form">
|
||||
<form class="form-horizontal">
|
||||
<p>
|
||||
<label for="promo_code">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.promo_code"}}
|
||||
</label>
|
||||
<Input @type="text" name="promo_code" @value={{this.promoCode}} />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="amount">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.discount"}}
|
||||
</label>
|
||||
<ComboBox
|
||||
@content={{this.discountTypes}}
|
||||
@value={{this.discountType}}
|
||||
@onChange={{fn (mut this.discountType)}}
|
||||
/>
|
||||
<Input
|
||||
class="discount-amount"
|
||||
@type="text"
|
||||
name="amount"
|
||||
@value={{this.discount}}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="active">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.active"}}
|
||||
</label>
|
||||
<Input @type="checkbox" name="active" @checked={{this.active}} />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<DButton
|
||||
@action={{this.createNewCoupon}}
|
||||
@label="discourse_subscriptions.admin.coupons.create"
|
||||
@title="discourse_subscriptions.admin.coupons.create"
|
||||
@icon="plus"
|
||||
class="btn-primary btn btn-icon"
|
||||
/>
|
||||
|
||||
<DButton
|
||||
@action={{this.cancelCreate}}
|
||||
label="cancel"
|
||||
@title="cancel"
|
||||
@icon="xmark"
|
||||
class="btn btn-icon"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<div class="create-coupon-form">
|
||||
<form class="form-horizontal">
|
||||
<p>
|
||||
<label for="promo_code">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.promo_code"}}
|
||||
</label>
|
||||
<Input @type="text" name="promo_code" @value={{this.promoCode}} />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="amount">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.discount"}}
|
||||
</label>
|
||||
<ComboBox
|
||||
@content={{this.discountTypes}}
|
||||
@value={{this.discountType}}
|
||||
@onChange={{action (mut this.discountType)}}
|
||||
/>
|
||||
<Input
|
||||
class="discount-amount"
|
||||
@type="text"
|
||||
name="amount"
|
||||
@value={{this.discount}}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="active">
|
||||
{{i18n "discourse_subscriptions.admin.coupons.active"}}
|
||||
</label>
|
||||
<Input @type="checkbox" name="active" @checked={{this.active}} />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<DButton
|
||||
@action={{action "createNewCoupon"}}
|
||||
@label="discourse_subscriptions.admin.coupons.create"
|
||||
@title="discourse_subscriptions.admin.coupons.create"
|
||||
@icon="plus"
|
||||
class="btn-primary btn btn-icon"
|
||||
/>
|
||||
|
||||
<DButton
|
||||
@action={{action "cancelCreate"}}
|
||||
label="cancel"
|
||||
@title="cancel"
|
||||
@icon="xmark"
|
||||
class="btn btn-icon"
|
||||
/>
|
||||
</div>
|
||||
@@ -1,35 +0,0 @@
|
||||
import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
|
||||
export default class CreateCouponForm extends Component {
|
||||
discountType = "amount";
|
||||
discount = null;
|
||||
promoCode = null;
|
||||
active = false;
|
||||
|
||||
@discourseComputed
|
||||
discountTypes() {
|
||||
return [
|
||||
{ id: "amount", name: "Amount" },
|
||||
{ id: "percent", name: "Percent" },
|
||||
];
|
||||
}
|
||||
|
||||
@action
|
||||
createNewCoupon() {
|
||||
const createParams = {
|
||||
promo: this.promoCode,
|
||||
discount_type: this.discountType,
|
||||
discount: this.discount,
|
||||
active: this.active,
|
||||
};
|
||||
|
||||
this.create(createParams);
|
||||
}
|
||||
|
||||
@action
|
||||
cancelCreate() {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import DButton from "discourse/components/d-button";
|
||||
import routeAction from "discourse/helpers/route-action";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
const LoginRequired = <template>
|
||||
<h3>{{i18n "discourse_subscriptions.subscribe.unauthenticated"}}</h3>
|
||||
|
||||
<DButton
|
||||
@label="log_in"
|
||||
@action={{routeAction "showLogin"}}
|
||||
@icon="user"
|
||||
class="btn btn-primary login-required subscriptions"
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export default LoginRequired;
|
||||
@@ -1,8 +0,0 @@
|
||||
<h3>{{i18n "discourse_subscriptions.subscribe.unauthenticated"}}</h3>
|
||||
|
||||
<DButton
|
||||
@label="log_in"
|
||||
@action={{route-action "showLogin"}}
|
||||
@icon="user"
|
||||
class="btn btn-primary login-required subscriptions"
|
||||
/>
|
||||
+18
@@ -1,6 +1,8 @@
|
||||
import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import PaymentPlan from "./payment-plan";
|
||||
|
||||
export default class PaymentOptions extends Component {
|
||||
@discourseComputed("plans")
|
||||
@@ -21,4 +23,20 @@ export default class PaymentOptions extends Component {
|
||||
clickPlan(plan) {
|
||||
this.set("selectedPlan", plan.id);
|
||||
}
|
||||
|
||||
<template>
|
||||
<p>
|
||||
{{i18n "discourse_subscriptions.plans.select"}}
|
||||
</p>
|
||||
|
||||
<div class="subscribe-buttons">
|
||||
{{#each this.orderedPlans as |plan|}}
|
||||
<PaymentPlan
|
||||
@plan={{plan}}
|
||||
@selectedPlan={{this.selectedPlan}}
|
||||
@clickPlan={{this.clickPlan}}
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<p>
|
||||
{{i18n "discourse_subscriptions.plans.select"}}
|
||||
</p>
|
||||
|
||||
<div class="subscribe-buttons">
|
||||
{{#each this.orderedPlans as |plan|}}
|
||||
<PaymentPlan
|
||||
@plan={{plan}}
|
||||
@selectedPlan={{this.selectedPlan}}
|
||||
@clickPlan={{action "clickPlan"}}
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -0,0 +1,57 @@
|
||||
import Component from "@ember/component";
|
||||
import { concat } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import formatCurrency from "../helpers/format-currency";
|
||||
|
||||
const RECURRING = "recurring";
|
||||
|
||||
@tagName("")
|
||||
export default class PaymentPlan extends Component {
|
||||
@discourseComputed("selectedPlan")
|
||||
selectedClass(planId) {
|
||||
return planId === this.plan.id ? "btn-primary" : "";
|
||||
}
|
||||
|
||||
@discourseComputed("plan.type")
|
||||
recurringPlan(type) {
|
||||
return type === RECURRING;
|
||||
}
|
||||
|
||||
@action
|
||||
planClick() {
|
||||
this.clickPlan(this.plan);
|
||||
return false;
|
||||
}
|
||||
|
||||
<template>
|
||||
<DButton
|
||||
@action={{this.planClick}}
|
||||
class={{concatClass
|
||||
"btn-discourse-subscriptions-subscribe"
|
||||
this.selectedClass
|
||||
}}
|
||||
>
|
||||
<span class="interval">
|
||||
{{#if this.recurringPlan}}
|
||||
{{i18n
|
||||
(concat
|
||||
"discourse_subscriptions.plans.interval.adverb."
|
||||
this.plan.recurring.interval
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
{{i18n "discourse_subscriptions.one_time_payment"}}
|
||||
{{/if}}
|
||||
</span>
|
||||
|
||||
<span class="amount">
|
||||
{{formatCurrency this.plan.currency this.plan.amountDollars}}
|
||||
</span>
|
||||
</DButton>
|
||||
</template>
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<DButton
|
||||
@action={{action "planClick"}}
|
||||
class={{concat-class
|
||||
"btn-discourse-subscriptions-subscribe"
|
||||
this.selectedClass
|
||||
}}
|
||||
>
|
||||
<span class="interval">
|
||||
{{#if this.recurringPlan}}
|
||||
{{i18n
|
||||
(concat
|
||||
"discourse_subscriptions.plans.interval.adverb."
|
||||
this.plan.recurring.interval
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
{{i18n "discourse_subscriptions.one_time_payment"}}
|
||||
{{/if}}
|
||||
</span>
|
||||
|
||||
<span class="amount">
|
||||
{{format-currency this.plan.currency this.plan.amountDollars}}
|
||||
</span>
|
||||
</DButton>
|
||||
@@ -1,25 +0,0 @@
|
||||
import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
|
||||
const RECURRING = "recurring";
|
||||
|
||||
@tagName("")
|
||||
export default class PaymentPlan extends Component {
|
||||
@discourseComputed("selectedPlan")
|
||||
selectedClass(planId) {
|
||||
return planId === this.plan.id ? "btn-primary" : "";
|
||||
}
|
||||
|
||||
@discourseComputed("plan.type")
|
||||
recurringPlan(type) {
|
||||
return type === RECURRING;
|
||||
}
|
||||
|
||||
@action
|
||||
planClick() {
|
||||
this.clickPlan(this.plan);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import Component from "@ember/component";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import { classNames } from "@ember-decorators/component";
|
||||
import htmlSafe from "discourse/helpers/html-safe";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
@classNames("product")
|
||||
export default class ProductItem extends Component {
|
||||
<template>
|
||||
<h2>{{this.product.name}}</h2>
|
||||
|
||||
<p class="product-description">
|
||||
{{htmlSafe this.product.description}}
|
||||
</p>
|
||||
|
||||
{{#if this.isLoggedIn}}
|
||||
<div class="product-purchase">
|
||||
{{#if this.product.repurchaseable}}
|
||||
<LinkTo
|
||||
@route="subscribe.show"
|
||||
@model={{this.product.id}}
|
||||
class="btn btn-primary"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.title"}}
|
||||
</LinkTo>
|
||||
|
||||
{{#if this.product.subscribed}}
|
||||
<LinkTo
|
||||
@route="user.billing.subscriptions"
|
||||
@model={{this.currentUser.username}}
|
||||
class="billing-link"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.view_past"}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if this.product.subscribed}}
|
||||
<span class="purchased">
|
||||
✓
|
||||
{{i18n "discourse_subscriptions.subscribe.purchased"}}
|
||||
</span>
|
||||
|
||||
<LinkTo
|
||||
@route="user.billing.subscriptions"
|
||||
@model={{this.currentUser.username}}
|
||||
class="billing-link"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.go_to_billing"}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
<LinkTo
|
||||
@route="subscribe.show"
|
||||
@model={{this.product.id}}
|
||||
@disabled={{this.product.subscribed}}
|
||||
class="btn btn-primary"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.title"}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<h2>{{this.product.name}}</h2>
|
||||
|
||||
<p class="product-description">
|
||||
{{html-safe this.product.description}}
|
||||
</p>
|
||||
|
||||
{{#if this.isLoggedIn}}
|
||||
<div class="product-purchase">
|
||||
{{#if this.product.repurchaseable}}
|
||||
<LinkTo
|
||||
@route="subscribe.show"
|
||||
@model={{this.product.id}}
|
||||
class="btn btn-primary"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.title"}}
|
||||
</LinkTo>
|
||||
|
||||
{{#if this.product.subscribed}}
|
||||
<LinkTo
|
||||
@route="user.billing.subscriptions"
|
||||
@model={{this.currentUser.username}}
|
||||
class="billing-link"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.view_past"}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if this.product.subscribed}}
|
||||
<span class="purchased">
|
||||
✓
|
||||
{{i18n "discourse_subscriptions.subscribe.purchased"}}
|
||||
</span>
|
||||
|
||||
<LinkTo
|
||||
@route="user.billing.subscriptions"
|
||||
@model={{this.currentUser.username}}
|
||||
class="billing-link"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.go_to_billing"}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
<LinkTo
|
||||
@route="subscribe.show"
|
||||
@model={{this.product.id}}
|
||||
@disabled={{this.product.subscribed}}
|
||||
class="btn btn-primary"
|
||||
>
|
||||
{{i18n "discourse_subscriptions.subscribe.title"}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
@@ -1,5 +0,0 @@
|
||||
import Component from "@ember/component";
|
||||
import { classNames } from "@ember-decorators/component";
|
||||
|
||||
@classNames("product")
|
||||
export default class ProductItem extends Component {}
|
||||
+12
@@ -2,6 +2,8 @@ import Component from "@ember/component";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { classNames } from "@ember-decorators/component";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import ProductItem from "./product-item";
|
||||
|
||||
@classNames("product-list")
|
||||
export default class ProductList extends Component {
|
||||
@@ -9,4 +11,14 @@ export default class ProductList extends Component {
|
||||
emptyProducts(products) {
|
||||
return isEmpty(products);
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.emptyProducts}}
|
||||
<p>{{i18n "discourse_subscriptions.subscribe.no_products"}}</p>
|
||||
{{else}}
|
||||
{{#each this.products as |product|}}
|
||||
<ProductItem @product={{product}} @isLoggedIn={{this.isLoggedIn}} />
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{{#if this.emptyProducts}}
|
||||
<p>{{i18n "discourse_subscriptions.subscribe.no_products"}}</p>
|
||||
{{else}}
|
||||
{{#each this.products as |product|}}
|
||||
<ProductItem @product={{product}} @isLoggedIn={{this.isLoggedIn}} />
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
+4
@@ -28,4 +28,8 @@ export default class SubscribeCard extends Component {
|
||||
didDestroyElement() {
|
||||
super.didDestroyElement(...arguments);
|
||||
}
|
||||
|
||||
<template>
|
||||
<div id="card-element"></div>
|
||||
</template>
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<div id="card-element"></div>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import Component from "@ember/component";
|
||||
import { classNames, tagName } from "@ember-decorators/component";
|
||||
import CampaignBanner from "../../components/campaign-banner";
|
||||
|
||||
@tagName("div")
|
||||
@classNames("above-main-container-outlet", "subscriptions-campaign")
|
||||
export default class SubscriptionsCampaign extends Component {
|
||||
static shouldRender(args, context) {
|
||||
const { siteSettings } = context;
|
||||
const mobileView = context.site.mobileView;
|
||||
const bannerLocation =
|
||||
siteSettings.discourse_subscriptions_campaign_banner_location;
|
||||
return (
|
||||
bannerLocation === "Top" || (bannerLocation === "Sidebar" && mobileView)
|
||||
);
|
||||
}
|
||||
|
||||
<template><CampaignBanner @connectorName="above-main-container" /></template>
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
<CampaignBanner @connectorName="above-main-container" />
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
export default {
|
||||
shouldRender(args, component) {
|
||||
const { siteSettings } = component;
|
||||
const mobileView = component.site.mobileView;
|
||||
const bannerLocation =
|
||||
siteSettings.discourse_subscriptions_campaign_banner_location;
|
||||
|
||||
return (
|
||||
bannerLocation === "Top" || (bannerLocation === "Sidebar" && mobileView)
|
||||
);
|
||||
},
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import Component from "@ember/component";
|
||||
import { classNames, tagName } from "@ember-decorators/component";
|
||||
import CampaignBanner from "../../components/campaign-banner";
|
||||
|
||||
@tagName("span")
|
||||
@classNames(
|
||||
"after-topic-footer-buttons-outlet",
|
||||
"subscriptions-campaign-topic-footer"
|
||||
)
|
||||
export default class SubscriptionsCampaignTopicFooter extends Component {
|
||||
static shouldRender(args, context) {
|
||||
const { siteSettings } = context;
|
||||
const bannerLocation =
|
||||
siteSettings.discourse_subscriptions_campaign_banner_location;
|
||||
return bannerLocation === "Top" || bannerLocation === "Sidebar";
|
||||
}
|
||||
|
||||
<template>
|
||||
<CampaignBanner @connectorName="after-topic-footer-buttons" />
|
||||
</template>
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
<CampaignBanner @connectorName="after-topic-footer-buttons" />
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
export default {
|
||||
shouldRender(args, component) {
|
||||
const { siteSettings } = component;
|
||||
const bannerLocation =
|
||||
siteSettings.discourse_subscriptions_campaign_banner_location;
|
||||
|
||||
return bannerLocation === "Top" || bannerLocation === "Sidebar";
|
||||
},
|
||||
};
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import Component from "@ember/component";
|
||||
import { classNames, tagName } from "@ember-decorators/component";
|
||||
import CampaignBanner from "../../components/campaign-banner";
|
||||
|
||||
@tagName("div")
|
||||
@classNames("before-topic-list-outlet", "subscriptions-campaign-sidebar")
|
||||
export default class SubscriptionsCampaignSidebar extends Component {
|
||||
static shouldRender(args, context) {
|
||||
const { siteSettings } = context;
|
||||
const mobileView = context.site.mobileView;
|
||||
const bannerLocation =
|
||||
siteSettings.discourse_subscriptions_campaign_banner_location;
|
||||
return bannerLocation === "Sidebar" && !mobileView;
|
||||
}
|
||||
|
||||
<template><CampaignBanner @connectorName="before-topic-list" /></template>
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
<CampaignBanner @connectorName="before-topic-list" />
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user