mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
8cc4c6c4a1
no issue - since `ember-concurrency@2.0` it's possible to use the standard imports as decorators removing the need for the extra `ember-concurrency-decorators` dependency and imports
110 lines
2.9 KiB
JavaScript
110 lines
2.9 KiB
JavaScript
import ModalComponent from 'ghost-admin/components/modal-base';
|
|
import {action} from '@ember/object';
|
|
import {inject as service} from '@ember/service';
|
|
import {task} from 'ember-concurrency';
|
|
import {tracked} from '@glimmer/tracking';
|
|
|
|
export default class ModalMemberProduct extends ModalComponent {
|
|
@service store;
|
|
@service ghostPaths;
|
|
@service ajax;
|
|
|
|
@tracked price;
|
|
@tracked product;
|
|
@tracked products = [];
|
|
@tracked selectedProduct = null;
|
|
@tracked loadingProducts = false;
|
|
|
|
@task({drop: true})
|
|
*fetchProducts() {
|
|
this.products = yield this.store.query('product', {filter: 'type:paid+active:true', include: 'monthly_price,yearly_price,benefits'});
|
|
|
|
this.loadingProducts = false;
|
|
if (this.products.length > 0) {
|
|
this.selectedProduct = this.products.firstObject.id;
|
|
}
|
|
}
|
|
|
|
get activeSubscriptions() {
|
|
const subscriptions = this.member.get('subscriptions') || [];
|
|
return subscriptions.filter((sub) => {
|
|
return ['active', 'trialing', 'unpaid', 'past_due'].includes(sub.status);
|
|
});
|
|
}
|
|
|
|
get member() {
|
|
return this.model;
|
|
}
|
|
|
|
get cannotAddPrice() {
|
|
return !this.price || this.price.amount !== 0;
|
|
}
|
|
|
|
@action
|
|
setup() {
|
|
this.loadingProducts = true;
|
|
this.fetchProducts.perform();
|
|
}
|
|
|
|
@action
|
|
setProduct(productId) {
|
|
this.selectedProduct = productId;
|
|
}
|
|
|
|
@action
|
|
setPrice(price) {
|
|
this.price = price;
|
|
}
|
|
|
|
@action
|
|
confirmAction() {
|
|
return this.addProduct.perform();
|
|
}
|
|
|
|
@action
|
|
close(event) {
|
|
event?.preventDefault?.();
|
|
this.closeModal();
|
|
}
|
|
|
|
@task({drop: true})
|
|
*addProduct() {
|
|
let url = this.ghostPaths.url.api(`members/${this.member.get('id')}`);
|
|
// Cancel existing active subscriptions for member
|
|
for (let i = 0; i < this.activeSubscriptions.length; i++) {
|
|
const subscription = this.activeSubscriptions[i];
|
|
const cancelUrl = this.ghostPaths.url.api(`members/${this.member.get('id')}/subscriptions/${subscription.id}`);
|
|
yield this.ajax.put(cancelUrl, {
|
|
data: {
|
|
status: 'canceled'
|
|
}
|
|
});
|
|
}
|
|
let response = yield this.ajax.put(url, {
|
|
data: {
|
|
members: [{
|
|
id: this.member.get('id'),
|
|
email: this.member.get('email'),
|
|
products: [{
|
|
id: this.selectedProduct
|
|
}]
|
|
}]
|
|
}
|
|
});
|
|
|
|
this.store.pushPayload('member', response);
|
|
this.closeModal();
|
|
return response;
|
|
}
|
|
|
|
actions = {
|
|
confirm() {
|
|
this.confirmAction(...arguments);
|
|
},
|
|
// needed because ModalBase uses .send() for keyboard events
|
|
closeModal() {
|
|
this.close();
|
|
}
|
|
}
|
|
}
|