save the product

This commit is contained in:
Rimian Perkins 2019-10-16 14:15:01 +11:00
parent e2f1f0f523
commit 496f2b9706
14 changed files with 141 additions and 38 deletions

View File

@ -30,6 +30,36 @@ module DiscoursePatrons
end end
end end
def show
begin
product = ::Stripe::Product.retrieve(params[:id])
render_json_dump product
rescue ::Stripe::InvalidRequestError => e
return render_json_error e.message
end
end
def update
begin
product = ::Stripe::Product.update(
params[:id], {
name: params[:name],
active: params[:active],
metadata: {
group_name: params[:group_name]
}
}
)
render_json_dump product
rescue ::Stripe::InvalidRequestError => e
return render_json_error e.message
end
end
def destroy def destroy
begin begin
product = ::Stripe::Product.delete(params[:id]) product = ::Stripe::Product.delete(params[:id])

View File

@ -3,7 +3,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
actions: { actions: {
createPlan() { createPlan() {
this.get("model") this.get("model.plan")
.save() .save()
.then(() => { .then(() => {
this.transitionToRoute("adminPlugins.discourse-patrons.plans"); this.transitionToRoute("adminPlugins.discourse-patrons.plans");

View File

@ -17,6 +17,15 @@ export default Ember.Controller.extend({
this.transitionToRoute("adminPlugins.discourse-patrons.products"); this.transitionToRoute("adminPlugins.discourse-patrons.products");
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
},
updateProduct() {
this.get("model.product")
.update()
.then(() => {
this.transitionToRoute("adminPlugins.discourse-patrons.products");
})
.catch(popupAjaxError);
} }
} }
}); });

View File

@ -5,7 +5,7 @@ export default {
this.route("discourse-patrons", function() { this.route("discourse-patrons", function() {
this.route("dashboard"); this.route("dashboard");
this.route("products", function() { this.route("products", function() {
this.route("show", { path: "/:plan-id" }); this.route("show", { path: "/:product-id" });
}); });
this.route("plans", function() { this.route("plans", function() {
this.route("show", { path: "/:plan-id" }); this.route("show", { path: "/:plan-id" });

View File

@ -1,6 +1,8 @@
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
const AdminProduct = Discourse.Model.extend({ const AdminProduct = Discourse.Model.extend({
isNew: false,
destroy() { destroy() {
return ajax(`/patrons/admin/products/${this.id}`, { method: "delete" }); return ajax(`/patrons/admin/products/${this.id}`, { method: "delete" });
}, },
@ -13,6 +15,16 @@ const AdminProduct = Discourse.Model.extend({
}; };
return ajax("/patrons/admin/products", { method: "post", data }); return ajax("/patrons/admin/products", { method: "post", data });
},
update() {
const data = {
name: this.name,
groupName: this.groupName,
active: this.active
};
return ajax(`/patrons/admin/products/${this.id}`, { method: "patch", data });
} }
}); });
@ -21,7 +33,13 @@ AdminProduct.reopenClass({
return ajax("/patrons/admin/products", { method: "get" }).then(result => return ajax("/patrons/admin/products", { method: "get" }).then(result =>
result.map(product => AdminProduct.create(product)) result.map(product => AdminProduct.create(product))
); );
} },
find(id) {
return ajax(`/patrons/admin/products/${id}`, { method: "get" }).then(product =>
AdminProduct.create(product)
);
},
}); });
export default AdminProduct; export default AdminProduct;

View File

@ -1,7 +1,11 @@
import AdminPlan from "discourse/plugins/discourse-patrons/discourse/models/admin-plan"; import AdminPlan from "discourse/plugins/discourse-patrons/discourse/models/admin-plan";
import AdminProduct from "discourse/plugins/discourse-patrons/discourse/models/admin-product";
export default Discourse.Route.extend({ export default Discourse.Route.extend({
model() { model() {
return AdminPlan.create(); const plan = AdminPlan.create();
const products = AdminProduct.findAll();
return Ember.RSVP.hash({ plan, products });
} }
}); });

View File

@ -2,8 +2,17 @@ import AdminProduct from "discourse/plugins/discourse-patrons/discourse/models/a
import Group from "discourse/models/group"; import Group from "discourse/models/group";
export default Discourse.Route.extend({ export default Discourse.Route.extend({
model(param) { model(params) {
const product = AdminProduct.create(); const id = params['product-id'];
let product;
if(id === 'new') {
product = AdminProduct.create({ active: true, isNew: true });
}
else {
product = AdminProduct.find(id);
}
const groups = Group.findAll({ ignore_automatic: true }); const groups = Group.findAll({ ignore_automatic: true });
return Ember.RSVP.hash({ product, groups }); return Ember.RSVP.hash({ product, groups });

View File

@ -2,18 +2,22 @@
<h4>{{i18n 'discourse_patrons.admin.plans.title'}}</h4> <h4>{{i18n 'discourse_patrons.admin.plans.title'}}</h4>
<form class="form-horizontal"> <form class="form-horizontal">
<div> <p>
<label for="name">{{i18n 'discourse_patrons.admin.plans.show.name'}}</label> <label for="name">{{i18n 'discourse_patrons.admin.plans.show.name'}}</label>
{{input type="text" name="name" value=model.name}} {{input type="text" name="name" value=model.plan.name}}
</div> </p>
<div> <p>
<label for="amount">{{i18n 'discourse_patrons.admin.plans.show.amount'}}</label> <label for="amount">{{i18n 'discourse_patrons.admin.plans.show.amount'}}</label>
{{input type="text" name="name" value=model.amount}} {{input type="text" name="name" value=model.plan.amount}}
</div> </p>
<div> <p>
<label for="product">{{i18n 'discourse_patrons.admin.plans.show.product'}}</label>
{{combo-box valueAttribute="value" content=model.products value=defaultProduct}}
</p>
<p>
<label for="interval">{{i18n 'discourse_patrons.admin.plans.show.interval'}}</label> <label for="interval">{{i18n 'discourse_patrons.admin.plans.show.interval'}}</label>
{{combo-box valueAttribute="value" content=model.intervals value=model.interval}} {{combo-box valueAttribute="value" content=model.plan.intervals value=model.plan.interval}}
</div> </p>
</form> </form>
<div class="buttons"> <div class="buttons">

View File

@ -2,20 +2,24 @@
<h4>{{i18n 'discourse_patrons.admin.products.title'}}</h4> <h4>{{i18n 'discourse_patrons.admin.products.title'}}</h4>
<form class="form-horizontal"> <form class="form-horizontal">
<div> <p>
<label for="name">{{i18n 'discourse_patrons.admin.plans.show.name'}}</label> <label for="name">{{i18n 'discourse_patrons.admin.products.product.name'}}</label>
{{input type="text" name="name" value=model.product.name}} {{input type="text" name="name" value=model.product.name}}
</div> </p>
<div> <p>
<label for="interval">{{i18n 'discourse_patrons.admin.products.show.group'}}</label> <label for="interval">{{i18n 'discourse_patrons.admin.products.product.group'}}</label>
{{combo-box valueAttribute="value" content=model.groups value=model.product.groupName}} {{combo-box valueAttribute="value" content=model.groups value=model.product.groupName}}
</div> </p>
<div> <p>
<label for="interval">{{i18n 'discourse_patrons.admin.products.show.active'}}</label> <label for="interval">{{i18n 'discourse_patrons.admin.products.product.active'}}</label>
{{input type="checkbox" checked=model.product.active}} {{input type="checkbox" checked=model.product.active}}
</div> </p>
</form> </form>
<div class="buttons"> <div class="buttons">
{{d-button label="discourse_patrons.admin.products.show.create" action="createProduct" icon="plus"}} {{#if model.product.isNew}}
{{d-button label="discourse_patrons.admin.products.operations.create" action="createProduct" icon="plus"}}
{{else}}
{{d-button label="discourse_patrons.admin.products.operations.update" action="updateProduct" icon="fa-save"}}
{{/if}}
</div> </div>

View File

@ -2,7 +2,7 @@
<p class="btn-right"> <p class="btn-right">
{{#link-to 'adminPlugins.discourse-patrons.products.show' 'new' class="btn btn-primary"}} {{#link-to 'adminPlugins.discourse-patrons.products.show' 'new' class="btn btn-primary"}}
{{d-icon "plus"}} {{d-icon "plus"}}
<span>{{i18n 'discourse_patrons.admin.products.new'}}</span> <span>{{i18n 'discourse_patrons.admin.products.operations.new'}}</span>
{{/link-to}} {{/link-to}}
</p> </p>

View File

@ -61,18 +61,17 @@ en:
amount: Amount amount: Amount
products: products:
title: Products title: Products
new: New Product operations:
show: create: Create New Product
group: User Group update: Update Product
create: Create Product new: New Product
active: Active destroy:
confirm: Are you sure you want to destroy this product?
product: product:
product_id: Product ID product_id: Product ID
name: Product Name
group: User Group group: User Group
active: Active active: Active
operations:
destroy:
confirm: Are you sure you want to destroy this product?
plans: plans:
title: Plans title: Plans
new: New Plan new: New Plan

View File

@ -9,7 +9,7 @@ DiscoursePatrons::Engine.routes.draw do
namespace :admin do namespace :admin do
resources :plans resources :plans
resources :subscriptions, only: [:index] resources :subscriptions, only: [:index]
resources :products, only: [:index, :create, :destroy] resources :products
end end
resources :customers, only: [:create] resources :customers, only: [:create]

View File

@ -8,7 +8,7 @@
enabled_site_setting :discourse_patrons_enabled enabled_site_setting :discourse_patrons_enabled
gem 'stripe', '5.7.0' gem 'stripe', '5.7.1'
register_asset "stylesheets/common/discourse-patrons.scss" register_asset "stylesheets/common/discourse-patrons.scss"
register_asset "stylesheets/mobile/discourse-patrons.scss" register_asset "stylesheets/mobile/discourse-patrons.scss"

View File

@ -16,13 +16,25 @@ module DiscoursePatrons
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
it "does not create the products" do it "does not create the product" do
::Stripe::Product.expects(:create).never ::Stripe::Product.expects(:create).never
post "/patrons/admin/products.json" post "/patrons/admin/products.json"
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
it "does not delete the products" do it "does not show the product" do
::Stripe::Product.expects(:retrieve).never
get "/patrons/admin/products/prod_qwerty123.json"
expect(response.status).to eq(403)
end
it "does not update the product" do
::Stripe::Product.expects(:update).never
put "/patrons/admin/products/prod_qwerty123.json"
expect(response.status).to eq(403)
end
it "does not delete the product" do
::Stripe::Product.expects(:delete).never ::Stripe::Product.expects(:delete).never
delete "/patrons/admin/products/u2.json" delete "/patrons/admin/products/u2.json"
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -63,6 +75,20 @@ module DiscoursePatrons
end end
end end
describe 'show' do
it 'retrieves the product' do
::Stripe::Product.expects(:retrieve).with('prod_walterwhite')
get "/patrons/admin/products/prod_walterwhite.json"
end
end
describe 'update' do
it 'updates the product' do
::Stripe::Product.expects(:update)
patch "/patrons/admin/products/prod_walterwhite.json", params: {}
end
end
describe 'delete' do describe 'delete' do
it 'deletes the product' do it 'deletes the product' do
::Stripe::Product.expects(:delete).with('prod_walterwhite') ::Stripe::Product.expects(:delete).with('prod_walterwhite')