basic subscribe page
This commit is contained in:
parent
91045583ad
commit
bb31deae89
|
@ -11,13 +11,10 @@ This is a newer version of https://github.com/rimian/discourse-donations.
|
|||
* Be sure your site is enforcing https.
|
||||
* Follow the install instructions here: https://meta.discourse.org/t/install-a-plugin/19157
|
||||
* Add your Stripe public and private keys in settings and set the currency to your local value.
|
||||
* Enable the plugin and wait for people to donate money.
|
||||
|
||||
## Usage
|
||||
## Creating Subscription Plans
|
||||
|
||||
Enable the plugin and enter your Stripe API keys in the settings. You can also configure amounts and the default currency.
|
||||
|
||||
Visit `/patrons`
|
||||
When users subscribe to your Discourse application, they are added to a user group. You can create new user groups or use existing ones. Of course, you should be careful what permissions you apply to the user group.
|
||||
|
||||
## Testing
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class PlansController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
plans = ::Stripe::Plan.list
|
||||
render json: plans.data
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@ export default Ember.Component.extend({
|
|||
this._super(...arguments);
|
||||
|
||||
const settings = Discourse.SiteSettings;
|
||||
const amounts = Discourse.SiteSettings.discourse_patrons_amounts.split("|");
|
||||
const amounts = settings.discourse_patrons_amounts.split("|");
|
||||
|
||||
this.setProperties({
|
||||
confirmation: false,
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
stripePaymentHandler(/* data */) {
|
||||
// console.log('stripePaymentHandler', data);
|
||||
},
|
||||
|
||||
paymentSuccessHandler(/* paymentIntentId */) {
|
||||
// console.log('paymentSuccessHandler');
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
const AdminPlan = Discourse.Model.extend({
|
||||
destroy() {}
|
||||
});
|
||||
|
||||
AdminPlan.reopenClass({
|
||||
find() {
|
||||
return ajax("/patrons/admin/plans", { method: "get" }).then(result =>
|
||||
result.plans.map(plan => AdminPlan.create(plan))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default AdminPlan;
|
|
@ -0,0 +1,18 @@
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
const Group = Discourse.Model.extend({});
|
||||
|
||||
Group.reopenClass({
|
||||
subscriptionGroup:
|
||||
Discourse.SiteSettings.discourse_patrons_subscription_group,
|
||||
|
||||
find() {
|
||||
return ajax(`/groups/${this.subscriptionGroup}`, { method: "get" }).then(
|
||||
result => {
|
||||
return Group.create(result.group);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Group;
|
|
@ -1,12 +1,10 @@
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
const Plan = Discourse.Model.extend({
|
||||
destroy() {}
|
||||
});
|
||||
const Plan = Discourse.Model.extend({});
|
||||
|
||||
Plan.reopenClass({
|
||||
find() {
|
||||
return ajax("/patrons/admin/plans", { method: "get" }).then(result =>
|
||||
return ajax("/patrons/plans", { method: "get" }).then(result =>
|
||||
result.plans.map(plan => Plan.create(plan))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export default function() {
|
||||
this.route("patrons", function() {
|
||||
this.route("subscribe");
|
||||
this.route("show", { path: ":pid" });
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Plan from "discourse/plugins/discourse-patrons/discourse/models/plan";
|
||||
import AdminPlan from "discourse/plugins/discourse-patrons/discourse/models/admin-plan";
|
||||
|
||||
export default Discourse.Route.extend({
|
||||
model() {
|
||||
return Plan.find();
|
||||
return AdminPlan.find();
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import Group from "discourse/plugins/discourse-patrons/discourse/models/group";
|
||||
import Plan from "discourse/plugins/discourse-patrons/discourse/models/plan";
|
||||
|
||||
export default Discourse.Route.extend({
|
||||
model() {
|
||||
const group = Group.find();
|
||||
const plans = Plan.find().then(results => results.map(p => p.id));
|
||||
|
||||
return Ember.RSVP.hash({ group, plans });
|
||||
}
|
||||
});
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
{{#link-to 'patrons.subscribe' class='discourse-patrons-subscribe'}}
|
||||
{{i18n 'discourse_patrons.navigation.subscribe'}}
|
||||
{{/link-to}}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
<h3>
|
||||
{{i18n 'discourse_patrons.subscribe.title'}}
|
||||
</h3>
|
||||
|
||||
<div class="discourse-patrons-section-columns">
|
||||
<div class="section-column discourse-patrons-confirmation-billing">
|
||||
<h4>{{model.group.full_name}}</h4>
|
||||
<p>
|
||||
{{{model.group.bio_cooked}}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="section-column">
|
||||
{{combo-box valueAttribute="id" content=model.plans value=model.plan}}
|
||||
|
||||
{{#d-button class="btn btn-primary btn-payment btn-discourse-patrons"}}
|
||||
{{i18n 'discourse_patrons.subscribe.buttons.subscribe'}}
|
||||
{{/d-button}}
|
||||
</div>
|
||||
</div>
|
|
@ -3,6 +3,7 @@ en:
|
|||
discourse_patrons_enabled: "Enable the Discourse Patrons plugin."
|
||||
discourse_patrons_secret_key: "Stripe Secret Key"
|
||||
discourse_patrons_public_key: "Stripe Public Key"
|
||||
discourse_patrons_subscription_group: The name of the group the user is added to when successfully subscribed
|
||||
discourse_patrons_currency: "Currency Code"
|
||||
discourse_patrons_zip_code: "Show Zip Code"
|
||||
discourse_patrons_billing_address: "Collect billing address"
|
||||
|
@ -15,18 +16,24 @@ en:
|
|||
js:
|
||||
discourse_patrons:
|
||||
title: Discourse Patrons
|
||||
nav_item: Payment
|
||||
heading:
|
||||
payment: Make a Payment
|
||||
success: Thank you!
|
||||
payment:
|
||||
optional: Optional
|
||||
receipt_info: A receipt is sent to this email address
|
||||
your_information: Your information
|
||||
payment_information: Payment information
|
||||
payment_confirmation: Confirm information
|
||||
amount: Amount
|
||||
payment_intent_id: Payment ID
|
||||
navigation:
|
||||
subscribe: Subscribe
|
||||
subscribe:
|
||||
title: Subscribe
|
||||
buttons:
|
||||
subscribe: Subscribe
|
||||
one_time:
|
||||
heading:
|
||||
payment: Make a Payment
|
||||
success: Thank you!
|
||||
payment:
|
||||
optional: Optional
|
||||
receipt_info: A receipt is sent to this email address
|
||||
your_information: Your information
|
||||
payment_information: Payment information
|
||||
payment_confirmation: Confirm information
|
||||
amount: Amount
|
||||
payment_intent_id: Payment ID
|
||||
billing:
|
||||
name: Full name
|
||||
email: Email
|
||||
|
|
|
@ -11,8 +11,9 @@ DiscoursePatrons::Engine.routes.draw do
|
|||
resources :subscriptions, only: [:index]
|
||||
end
|
||||
|
||||
resources :plans, only: [:index]
|
||||
resources :patrons, only: [:index, :create]
|
||||
|
||||
get '/' => 'patrons#index'
|
||||
get '/:pid' => 'patrons#show'
|
||||
|
||||
resources :patrons, only: [:index, :create]
|
||||
end
|
||||
|
|
|
@ -7,6 +7,9 @@ plugins:
|
|||
discourse_patrons_secret_key:
|
||||
default: ''
|
||||
client: false
|
||||
discourse_patrons_subscription_group:
|
||||
default: ''
|
||||
client: true
|
||||
discourse_patrons_payment_page:
|
||||
client: true
|
||||
default: ''
|
||||
|
|
|
@ -42,6 +42,7 @@ after_initialize do
|
|||
"../app/controllers/admin/plans_controller",
|
||||
"../app/controllers/admin/subscriptions_controller",
|
||||
"../app/controllers/patrons_controller",
|
||||
"../app/controllers/plans_controller",
|
||||
"../app/models/payment",
|
||||
"../app/serializers/payment_serializer",
|
||||
].each { |path| require File.expand_path(path, __FILE__) }
|
||||
|
|
|
@ -53,7 +53,7 @@ module DiscoursePatrons
|
|||
before { sign_in(admin) }
|
||||
|
||||
describe "index" do
|
||||
it "is ok" do
|
||||
it "lists the plans" do
|
||||
::Stripe::Plan.expects(:list)
|
||||
get "/patrons/admin/plans.json"
|
||||
end
|
||||
|
|
|
@ -3,22 +3,20 @@
|
|||
require 'rails_helper'
|
||||
|
||||
module DiscoursePatrons
|
||||
module Admin
|
||||
RSpec.describe SubscriptionsController do
|
||||
RSpec.describe Admin::SubscriptionsController do
|
||||
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
|
||||
before { sign_in(admin) }
|
||||
before { sign_in(admin) }
|
||||
|
||||
it 'is a subclass of AdminController' do
|
||||
expect(DiscoursePatrons::Admin::SubscriptionsController < ::Admin::AdminController).to eq(true)
|
||||
end
|
||||
it 'is a subclass of AdminController' do
|
||||
expect(DiscoursePatrons::Admin::SubscriptionsController < ::Admin::AdminController).to eq(true)
|
||||
end
|
||||
|
||||
it "gets the empty subscriptions" do
|
||||
::Stripe::Subscription.expects(:list)
|
||||
get "/patrons/admin/subscriptions.json"
|
||||
expect(response.status).to eq(204)
|
||||
end
|
||||
it "gets the empty subscriptions" do
|
||||
::Stripe::Subscription.expects(:list)
|
||||
get "/patrons/admin/subscriptions.json"
|
||||
expect(response.status).to eq(204)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
module DiscoursePatrons
|
||||
RSpec.describe PlansController do
|
||||
describe "index" do
|
||||
it "lists the plans" do
|
||||
::Stripe::Plan.expects(:list)
|
||||
get "/patrons/plans.json"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@ acceptance("Discourse Patrons", {
|
|||
}
|
||||
});
|
||||
|
||||
QUnit.test("viewing", async assert => {
|
||||
QUnit.test("viewing the one-off payment page", async assert => {
|
||||
await visit("/patrons");
|
||||
|
||||
assert.ok($(".donations-page-payment").length, "has payment form class");
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
|
||||
acceptance("Discourse Patrons");
|
||||
|
||||
QUnit.test("plugin outlets", async assert => {
|
||||
await visit("/");
|
||||
|
||||
assert.ok(
|
||||
$("#navigation-bar .discourse-patrons-subscribe").length,
|
||||
"has a subscribe button"
|
||||
);
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
|
||||
acceptance("Discourse Patrons", {
|
||||
settings: {
|
||||
discourse_patrons_subscription_group: "plan-id"
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test("subscribing", async assert => {
|
||||
await visit("/patrons/subscribe");
|
||||
|
||||
assert.ok($("h3").length, "has a heading");
|
||||
});
|
|
@ -2,4 +2,8 @@ export default function(helpers) {
|
|||
const { response } = helpers;
|
||||
|
||||
this.get("/patrons", () => response({ email: "hello@example.com" }));
|
||||
|
||||
this.get("/groups/:plan", id => {
|
||||
return response({ full_name: "Saboo", bio_cooked: "This is the plan" });
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue