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,7 +16,13 @@ en: | |||
|   js: | ||||
|     discourse_patrons: | ||||
|       title: Discourse Patrons | ||||
|       nav_item: Payment | ||||
|       navigation: | ||||
|         subscribe: Subscribe | ||||
|       subscribe: | ||||
|         title: Subscribe | ||||
|         buttons: | ||||
|           subscribe: Subscribe | ||||
|       one_time: | ||||
|         heading: | ||||
|           payment: Make a Payment | ||||
|           success: Thank you! | ||||
|  |  | |||
|  | @ -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,8 +3,7 @@ | |||
| require 'rails_helper' | ||||
| 
 | ||||
| module DiscoursePatrons | ||||
|   module Admin | ||||
|     RSpec.describe SubscriptionsController do | ||||
|   RSpec.describe Admin::SubscriptionsController do | ||||
| 
 | ||||
|     let(:admin) { Fabricate(:admin) } | ||||
| 
 | ||||
|  | @ -21,4 +20,3 @@ module DiscoursePatrons | |||
|     end | ||||
|   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