Author SHA1 Message Date
Blake Erickson 7fe7be7ef8 add nonce to pricing-table.js 2024-04-24 11:38:56 -06:00
Blake Erickson d6c4ec21ae add pricing table to csp 2024-04-24 11:18:47 -06:00
Blake Erickson c48cbc7071 fix spec still linking to /s 2024-04-24 11:12:48 -06:00
spirobel 66cf05943c DEV: Change add_admin_route from products to plans 2024-04-24 11:11:38 -06:00
Blake Erickson e46693b94e linting 2024-04-24 10:09:53 -06:00
spirobel fcc414dbbe DEV: fix backend tests
After the engine url got moved to /subscriptions, the tests had to be adapted.

The subscribe controller does not return products anymore after moving to the stripe pricing table, so the respective tests were removed.
2024-04-23 16:24:34 -06:00
spirobel 411ac6ec80 DEV: add frontend tests to make sure pricing-table works
We test three conditions:
1. Make sure the customer email is prefilled, if there is a logged in discourse user
2. The pricing table also displays, if there is no logged in discourse user
3. If the pricing table is not configured, the pricing table element does not show up.
2024-04-23 15:32:19 -06:00
spirobel ce988c9512 DEV: continue to use subscribe_controller instead of introducting a new controller 2024-04-23 15:30:28 -06:00
spirobel bf7079928e DEV: fix linter issues 2024-04-23 15:26:52 -06:00
spirobel ff981f76e8 DEV: Remove the old product / pricing table display routes 2024-04-23 15:24:58 -06:00
spirobel 13d23dc3fa FEATURE: Add new stripe based pricing table
This commit adds the new stripe based pricing table.
If the user is logged in, the email field will be prepopulated with the users email.

The pricing table can be configured in the stripe dashboard.

Once the discourse_subscriptions_pricing_table setting is filled with the pricing table embed code from the stripe dashboard,
the pricing table will be displayed on /subscriptions

For more details see https://stripe.com/docs/payments/checkout/pricing-table
2024-04-23 15:18:31 -06:00
Blake Erickson dcde03d7c4 DEV: Bump stripe gem (#200)
Upgrading to the latest stripe gem and api version.
2024-04-16 11:28:07 -06:00
Michelle Bueno Saquetim Vendrame d63f241e0d FEATURE: add ZAR currency support (#199) 2024-04-15 21:26:26 +02:00
Discourse Translator Bot 8f1b332f9e Update translations (#198) 2024-04-02 18:20:05 +02:00
Blake Erickson 9190001a3c FIX: Translation missing for Norway (#196)
Turns out in YAML `NO` is interpreted as a boolean value, so we need to
wrap it in quotes.
2024-03-27 15:50:15 -06:00
Natalie Tay 0d28c9a56d FIX: Ensure deletion of product upon confirmation (#195)
Ensure deletion of product upon confirmation
2024-03-13 17:16:07 +08:00
David Taylor 7361721ec0 DEV: Update for strict-dynamic CSP (#194) 2024-03-06 16:45:55 +00:00
Loïc Guitaut 87659e237b DEV: Fix new Rubocop offenses 2024-03-06 15:23:55 +01:00
Selase Krakani 7b8a41ad0d DEV: Pin plugin for Discourse < 3.3.0.beta1-dev (#192) 2024-02-29 13:59:04 -07:00
Discourse Translator Bot 0dcf17de59 Update translations (#191) 2024-01-30 17:04:52 +01:00
Discourse Translator Bot 2cfded9a77 Update translations (#190) 2024-01-23 18:30:34 +01:00
Jarek Radosz d33cf2921e DEV: Update linting (#189) 2024-01-16 17:51:44 +01:00
David Taylor a3883d2a9a DEV: Resolve registerUnbound deprecation (#188) 2024-01-15 11:52:19 +00:00
104 changed files with 2784 additions and 2425 deletions
+1
View File
@@ -1,2 +1,3 @@
< 3.3.0.beta1-dev: 0dcf17de59bdf82c0233bb630dad0ce407d1ae76
3.1.999: c4f8220a5572ef9a42a9a71500e001d0df206c43
2.9.0.beta9: 39b7253c082270e33839f4b0821fbf75abfdd826
-6
View File
@@ -1,6 +0,0 @@
{
"globals": {
"Stripe": true
},
"extends": "eslint-config-discourse"
}
+1
View File
@@ -0,0 +1 @@
module.exports = require("@discourse/lint-configs/eslint");
-1
View File
@@ -1 +0,0 @@
{}
+1
View File
@@ -0,0 +1 @@
module.exports = require("@discourse/lint-configs/prettier");
+1
View File
@@ -0,0 +1 @@
module.exports = require("@discourse/lint-configs/template-lint");
-4
View File
@@ -1,4 +0,0 @@
module.exports = {
plugins: ["ember-template-lint-plugin-discourse"],
extends: "discourse:recommended",
};
+56 -21
View File
@@ -7,36 +7,71 @@ GIT
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.2)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
ast (2.4.2)
json (2.6.2)
parallel (1.22.1)
parser (3.1.2.1)
base64 (0.2.0)
bigdecimal (3.1.6)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.3)
concurrent-ruby (~> 1.0)
racc (~> 1.7)
json (2.7.1)
language_server-protocol (3.17.0.3)
minitest (5.22.2)
mutex_m (0.2.0)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
prettier_print (1.2.0)
racc
prettier_print (1.2.1)
racc (1.7.3)
rainbow (3.1.1)
regexp_parser (2.6.0)
rexml (3.2.5)
rubocop (1.36.0)
regexp_parser (2.9.0)
rexml (3.2.6)
rubocop (1.62.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.1.2.1)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.20.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.21.0)
parser (>= 3.1.1.0)
rubocop-discourse (3.0)
rubocop (>= 1.1.0)
rubocop-rspec (>= 2.0.0)
rubocop-rspec (2.13.2)
rubocop (~> 1.33)
ruby-progressbar (1.11.0)
syntax_tree (5.1.0)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.31.1)
parser (>= 3.3.0.4)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-discourse (3.7.1)
activesupport (>= 6.1)
rubocop (>= 1.59.0)
rubocop-capybara (>= 2.0.0)
rubocop-factory_bot (>= 2.0.0)
rubocop-rspec (>= 2.25.0)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-rspec (2.27.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
unicode-display_width (2.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
PLATFORMS
ruby
@@ -47,4 +82,4 @@ DEPENDENCIES
translations-manager!
BUNDLED WITH
2.3.4
2.5.4
@@ -5,6 +5,9 @@ module DiscourseSubscriptions
class CouponsController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
def index
@@ -5,6 +5,8 @@ module DiscourseSubscriptions
class PlansController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
def index
@@ -5,6 +5,8 @@ module DiscourseSubscriptions
class ProductsController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
def index
@@ -3,6 +3,8 @@
module DiscourseSubscriptions
module Admin
class SubscriptionsController < ::Admin::AdminController
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group
before_action :set_api_key
@@ -2,6 +2,8 @@
module DiscourseSubscriptions
class AdminController < ::Admin::AdminController
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
def index
head 200
end
@@ -5,6 +5,8 @@ module DiscourseSubscriptions
include DiscourseSubscriptions::Group
include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
layout false
skip_before_action :check_xhr
@@ -4,24 +4,14 @@ module DiscourseSubscriptions
class SubscribeController < ::ApplicationController
include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
requires_login except: %i[index contributors show]
def index
begin
product_ids = Product.all.pluck(:external_id)
products = []
if product_ids.present? && is_stripe_configured?
response = ::Stripe::Product.list({ ids: product_ids, active: true })
products = response[:data].map { |p| serialize_product(p) }
end
render_json_dump products
rescue ::Stripe::InvalidRequestError => e
render_json_error e.message
end
head 200
end
def contributors
@@ -4,6 +4,9 @@ module DiscourseSubscriptions
module User
class PaymentsController < ::ApplicationController
include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
requires_login
@@ -5,6 +5,9 @@ module DiscourseSubscriptions
class SubscriptionsController < ::ApplicationController
include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key
requires_login
@@ -51,6 +51,8 @@ module DiscourseSubscriptions
"KR"
when "sgd"
"S$"
when "zar"
"R"
else
"$"
end
@@ -1,11 +1,11 @@
import { action } from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { equal } from "@ember/object/computed";
import { setting } from "discourse/lib/computed";
import Component from "@ember/component";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { action } from "@ember/object";
import { equal } from "@ember/object/computed";
import { later } from "@ember/runloop";
import { inject as service } from "@ember/service";
import { ajax } from "discourse/lib/ajax";
import { setting } from "discourse/lib/computed";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
const SIDEBAR_BODY_CLASS = "subscription-campaign-sidebar";
@@ -58,12 +58,14 @@ export default Component.extend({
}
if (this.currentUser && this.showContributors) {
return ajax("/s/contributors", { method: "get" }).then((result) => {
this.setProperties({
contributors: result,
loading: false,
});
});
return ajax("/subscriptions/contributors", { method: "get" }).then(
(result) => {
this.setProperties({
contributors: result,
loading: false,
});
}
);
}
},
@@ -96,6 +98,7 @@ export default Component.extend({
},
willDestroyElement() {
this._super(...arguments);
document.body.classList.remove(SIDEBAR_BODY_CLASS);
},
@@ -1,10 +1,10 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { fn, hash } from "@ember/helper";
import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal";
import Component from "@glimmer/component";
import { fn, hash } from "@ember/helper";
import i18n from "discourse-common/helpers/i18n";
import { Input } from "@ember/component";
import { tracked } from "@glimmer/tracking";
export default class AdminCancelSubscription extends Component {
@tracked refund;
@@ -1,6 +1,6 @@
import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils";
import Component from "@ember/component";
import { isEmpty } from "@ember/utils";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["product-list"],
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object";
import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-ca-province-select"],
@@ -24,5 +24,8 @@ export default Component.extend({
},
});
},
didDestroyElement() {},
didDestroyElement() {
this._super(...arguments);
},
});
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object";
import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-country-select"],
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object";
import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-us-state-select"],
@@ -1,6 +1,6 @@
import Controller from "@ember/controller";
import AdminCoupon from "discourse/plugins/discourse-subscriptions/discourse/models/admin-coupon";
import { popupAjaxError } from "discourse/lib/ajax-error";
import AdminCoupon from "discourse/plugins/discourse-subscriptions/discourse/models/admin-coupon";
export default Controller.extend({
creating: null,
@@ -1,6 +1,6 @@
import Controller from "@ember/controller";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
router: service(),
@@ -1,8 +1,8 @@
import discourseComputed from "discourse-common/utils/decorators";
import DiscourseURL from "discourse/lib/url";
import Controller from "@ember/controller";
import { alias } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error";
import DiscourseURL from "discourse/lib/url";
import discourseComputed from "discourse-common/utils/decorators";
const RECURRING = "recurring";
const ONE_TIME = "one_time";
@@ -41,6 +41,7 @@ export default Controller.extend({
{ id: "DKK", name: "DKK" },
{ id: "SGD", name: "SGD" },
{ id: "JPY", name: "JPY" },
{ id: "ZAR", name: "ZAR" },
];
},
@@ -1,6 +1,6 @@
import { popupAjaxError } from "discourse/lib/ajax-error";
import Controller from "@ember/controller";
import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
router: service(),
@@ -1,9 +1,9 @@
import AdminCancelSubscription from "../components/modal/admin-cancel-subscription";
import AdminSubscription from "../models/admin-subscription";
import Controller from "@ember/controller";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import I18n from "discourse-i18n";
import AdminCancelSubscription from "../components/modal/admin-cancel-subscription";
import AdminSubscription from "../models/admin-subscription";
export default Controller.extend({
modal: service(),

Some files were not shown because too many files have changed in this diff Show More