mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Updated delete member UI to add toggle to cancel subscriptions (#1647)
no-issue * Supported cancellation of subscriptions on delete This makes the cancellation of subscriptions much more obvious to the user, and we err on the side of caution by *not* cancelling by default. * Updated base adapter to handle urls with query params After creating the member adapter and overriding the urlForDeleteRecord method the flow would take the url from that and it would get passed into the buildUrl method of the base adapter. At this point it would append a "/" _after_ the query param. It would ouput http://admin.com/ghost/api?query=blah/ rather than http://admin.com/ghost/api/?query=blah
This commit is contained in:
parent
a0cd857da1
commit
28a2caec98
@ -28,11 +28,12 @@ export default RESTAdapter.extend(DataAdapterMixin, AjaxServiceSupport, {
|
||||
buildURL() {
|
||||
// Ensure trailing slashes
|
||||
let url = this._super(...arguments);
|
||||
let parsedUrl = new URL(url);
|
||||
|
||||
if (url.slice(-1) !== '/') {
|
||||
url += '/';
|
||||
if (!parsedUrl.pathname.endsWith('/')) {
|
||||
parsedUrl.pathname += '/';
|
||||
}
|
||||
|
||||
return url;
|
||||
return parsedUrl.toString();
|
||||
}
|
||||
});
|
||||
|
14
ghost/admin/app/adapters/member.js
Normal file
14
ghost/admin/app/adapters/member.js
Normal file
@ -0,0 +1,14 @@
|
||||
import ApplicationAdapter from 'ghost-admin/adapters/application';
|
||||
|
||||
export default ApplicationAdapter.extend({
|
||||
urlForDeleteRecord(id, modelName, snapshot) {
|
||||
let url = this._super(...arguments);
|
||||
let parsedUrl = new URL(url);
|
||||
|
||||
if (snapshot && snapshot.adapterOptions && snapshot.adapterOptions.cancel) {
|
||||
parsedUrl.searchParams.set('cancel', 'true');
|
||||
}
|
||||
|
||||
return parsedUrl.toString();
|
||||
}
|
||||
});
|
@ -7,6 +7,26 @@
|
||||
<p>
|
||||
You're about to delete "<strong>{{or this.member.name this.member.email}}</strong>". This is permanent! We warned you, k?
|
||||
</p>
|
||||
|
||||
{{#if this.hasActiveStripeSubscriptions}}
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<h4>Cancel Stripe subscription</h4>
|
||||
<p class="pa0 ma0">If disabled, member's Stripe subscription will continue</p>
|
||||
</div>
|
||||
<div class="for-switch">
|
||||
<label class="switch">
|
||||
<input
|
||||
class="gh-input"
|
||||
type="checkbox"
|
||||
checked={{this.shouldCancelSubscriptions}}
|
||||
{{on "click" (action "toggleShouldCancelSubscriptions")}}
|
||||
/>
|
||||
<span class="input-toggle-component mt1"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
|
@ -1,25 +1,46 @@
|
||||
import ModalComponent from 'ghost-admin/components/modal-base';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default ModalComponent.extend({
|
||||
membersStats: service(),
|
||||
|
||||
shouldCancelSubscriptions: false,
|
||||
|
||||
// Allowed actions
|
||||
confirm: () => {},
|
||||
|
||||
member: alias('model'),
|
||||
|
||||
hasActiveStripeSubscriptions: computed('member', function () {
|
||||
let subscriptions = this.member.get('stripe');
|
||||
|
||||
if (!subscriptions || subscriptions.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let firstActiveStripeSubscription = subscriptions.find((subscription) => {
|
||||
return subscription.status === 'active' || subscription.status === 'trialing';
|
||||
});
|
||||
|
||||
return firstActiveStripeSubscription !== undefined;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
confirm() {
|
||||
this.deleteMember.perform();
|
||||
},
|
||||
|
||||
toggleShouldCancelSubscriptions() {
|
||||
this.shouldCancelSubscriptions = !this.shouldCancelSubscriptions;
|
||||
}
|
||||
},
|
||||
|
||||
deleteMember: task(function* () {
|
||||
try {
|
||||
yield this.confirm();
|
||||
yield this.confirm(this.shouldCancelSubscriptions);
|
||||
this.membersStats.invalidate();
|
||||
} finally {
|
||||
this.send('closeModal');
|
||||
|
@ -65,8 +65,13 @@ export default class MemberController extends Controller {
|
||||
}
|
||||
|
||||
@action
|
||||
deleteMember() {
|
||||
return this.member.destroyRecord().then(() => {
|
||||
deleteMember(cancelSubscriptions = false) {
|
||||
let options = {
|
||||
adapterOptions: {
|
||||
cancel: cancelSubscriptions
|
||||
}
|
||||
};
|
||||
return this.member.destroyRecord(options).then(() => {
|
||||
this.members.refreshData();
|
||||
return this.transitionToRoute('members');
|
||||
}, (error) => {
|
||||
|
Loading…
Reference in New Issue
Block a user