mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
Wired bulk action operations on filtered members list
closes https://github.com/TryGhost/Team/issues/969 Wires the bulk action operation UI to Ghost API to perform operations on filtered member list - unsubscribe filtered members, add label to filtered members or remove label from filtered members
This commit is contained in:
parent
0afa2aa2c0
commit
6d9b8175a2
@ -1,9 +1,9 @@
|
||||
<span class="gh-select">
|
||||
<OneWaySelect
|
||||
@options={{this.availableLabels}}
|
||||
@optionValuePath="slug"
|
||||
@optionValuePath="id"
|
||||
@optionLabelPath="name"
|
||||
@optionTargetPath="slug"
|
||||
@optionTargetPath="id"
|
||||
@update={{this.updateLabel}}
|
||||
/>
|
||||
{{svg-jar "arrow-down-small"}}
|
||||
|
@ -25,7 +25,8 @@ export default class GhMemberLabelInput extends Component {
|
||||
// store and be updated when the above query returns
|
||||
this.store.query('label', {limit: 'all'});
|
||||
this._availableLabels = this.store.peekAll('label');
|
||||
this.selectedLabel = this.args.label || null;
|
||||
this.selectedLabel = this.args.label || this.availableLabels[0].get('id');
|
||||
this.args.onChange(this.selectedLabel);
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -24,7 +24,7 @@
|
||||
<GhTaskButton
|
||||
@buttonText="Add Label"
|
||||
@successText="Added"
|
||||
@task={{this.deleteMembersTask}}
|
||||
@task={{this.addLabelTask}}
|
||||
@class="gh-btn gh-btn-green gh-btn-icon"
|
||||
data-test-button="confirm"
|
||||
/>
|
||||
|
@ -14,7 +14,7 @@ export default ModalComponent.extend({
|
||||
|
||||
actions: {
|
||||
confirm() {
|
||||
this.deleteMember.perform();
|
||||
this.addLabelTask.perform();
|
||||
},
|
||||
|
||||
setLabel(label) {
|
||||
@ -22,9 +22,9 @@ export default ModalComponent.extend({
|
||||
}
|
||||
},
|
||||
|
||||
deleteMember: task(function* () {
|
||||
addLabelTask: task(function* () {
|
||||
try {
|
||||
yield this.confirm(this.shouldCancelSubscriptions);
|
||||
yield this.confirm(this.selectedLabel);
|
||||
this.membersStats.invalidate();
|
||||
} finally {
|
||||
this.send('closeModal');
|
||||
|
@ -24,7 +24,7 @@
|
||||
<GhTaskButton
|
||||
@buttonText="Remove Label"
|
||||
@successText="Removed"
|
||||
@task={{this.deleteMembersTask}}
|
||||
@task={{this.removeLabelTask}}
|
||||
@class="gh-btn gh-btn-red gh-btn-icon"
|
||||
data-test-button="confirm"
|
||||
/>
|
||||
|
@ -14,7 +14,7 @@ export default ModalComponent.extend({
|
||||
|
||||
actions: {
|
||||
confirm() {
|
||||
this.deleteMember.perform();
|
||||
this.removeLabelTask.perform();
|
||||
},
|
||||
|
||||
setLabel(label) {
|
||||
@ -22,9 +22,9 @@ export default ModalComponent.extend({
|
||||
}
|
||||
},
|
||||
|
||||
deleteMember: task(function* () {
|
||||
removeLabelTask: task(function* () {
|
||||
try {
|
||||
yield this.confirm(this.shouldCancelSubscriptions);
|
||||
yield this.confirm(this.selectedLabel);
|
||||
this.membersStats.invalidate();
|
||||
} finally {
|
||||
this.send('closeModal');
|
||||
|
@ -54,7 +54,7 @@
|
||||
<GhTaskButton
|
||||
@buttonText="Unsubscribe members"
|
||||
@successText="Unsubscribed"
|
||||
@task={{this.deleteMembersTask}}
|
||||
@task={{this.unsubscribeMemberTask}}
|
||||
@class="gh-btn gh-btn-red gh-btn-icon"
|
||||
data-test-button="confirm"
|
||||
/>
|
||||
|
@ -1,7 +1,5 @@
|
||||
import ModalComponent from 'ghost-admin/components/modal-base';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {reads} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
@ -15,35 +13,15 @@ export default ModalComponent.extend({
|
||||
|
||||
member: alias('model'),
|
||||
|
||||
cancelSubscriptions: reads('shouldCancelSubscriptions'),
|
||||
|
||||
hasActiveStripeSubscriptions: computed('member', function () {
|
||||
let subscriptions = this.member.get('subscriptions');
|
||||
|
||||
if (!subscriptions || subscriptions.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let firstActiveStripeSubscription = subscriptions.find((subscription) => {
|
||||
return ['active', 'trialing', 'unpaid', 'past_due'].includes(subscription.status);
|
||||
});
|
||||
|
||||
return firstActiveStripeSubscription !== undefined;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
confirm() {
|
||||
this.deleteMember.perform();
|
||||
},
|
||||
|
||||
toggleShouldCancelSubscriptions() {
|
||||
this.set('shouldCancelSubscriptions', !this.shouldCancelSubscriptions);
|
||||
this.unsubscribeMember.perform();
|
||||
}
|
||||
},
|
||||
|
||||
deleteMember: task(function* () {
|
||||
unsubscribeMemberTask: task(function* () {
|
||||
try {
|
||||
yield this.confirm(this.shouldCancelSubscriptions);
|
||||
yield this.confirm();
|
||||
this.membersStats.invalidate();
|
||||
} finally {
|
||||
this.send('closeModal');
|
||||
|
@ -325,13 +325,13 @@ export default class MembersController extends Controller {
|
||||
}
|
||||
|
||||
@action
|
||||
addLabelsToMembers() {
|
||||
return this.addLabelToMembersTask.perform();
|
||||
addLabelToMembers(selectedLabel) {
|
||||
return this.addLabelToMembersTask.perform(selectedLabel);
|
||||
}
|
||||
|
||||
@action
|
||||
removeLabelsFromMembers() {
|
||||
return this.removeLabelFromMembersTask.perform();
|
||||
removeLabelFromMembers(selectedLabel) {
|
||||
return this.removeLabelFromMembersTask.perform(selectedLabel);
|
||||
}
|
||||
|
||||
// Tasks -------------------------------------------------------------------
|
||||
@ -449,7 +449,15 @@ export default class MembersController extends Controller {
|
||||
|
||||
@task({drop: true})
|
||||
*unsubscribeMembersTask() {
|
||||
yield Promise.resolve();
|
||||
const query = new URLSearchParams(this.getApiQueryObject());
|
||||
const unsubscribeUrl = `${this.ghostPaths.url.api('members/bulk')}?${query}`;
|
||||
// response contains details of which members failed to be unsubscribe
|
||||
const response = yield this.ajax.put(unsubscribeUrl, {
|
||||
data: {
|
||||
action: 'unsubscribe',
|
||||
meta: {}
|
||||
}
|
||||
});
|
||||
|
||||
// reset and reload
|
||||
this.store.unloadAll('member');
|
||||
@ -457,12 +465,23 @@ export default class MembersController extends Controller {
|
||||
this.membersStats.invalidate();
|
||||
this.membersStats.fetchCounts();
|
||||
|
||||
return {};
|
||||
return response.meta;
|
||||
}
|
||||
|
||||
@task({drop: true})
|
||||
*addLabelToMembersTask() {
|
||||
yield Promise.resolve();
|
||||
*addLabelToMembersTask(selectedLabel) {
|
||||
const query = new URLSearchParams(this.getApiQueryObject());
|
||||
const addLabelUrl = `${this.ghostPaths.url.api('members/bulk')}?${query}`;
|
||||
const response = yield this.ajax.put(addLabelUrl, {
|
||||
data: {
|
||||
action: 'addLabel',
|
||||
meta: {
|
||||
label: {
|
||||
id: selectedLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// reset and reload
|
||||
this.store.unloadAll('member');
|
||||
@ -470,12 +489,23 @@ export default class MembersController extends Controller {
|
||||
this.membersStats.invalidate();
|
||||
this.membersStats.fetchCounts();
|
||||
|
||||
return {};
|
||||
return response.meta;
|
||||
}
|
||||
|
||||
@task({drop: true})
|
||||
*removeLabelFromMembersTask() {
|
||||
yield Promise.resolve();
|
||||
*removeLabelFromMembersTask(selectedLabel) {
|
||||
const query = new URLSearchParams(this.getApiQueryObject());
|
||||
const removeLabelUrl = `${this.ghostPaths.url.api('members/bulk')}?${query}`;
|
||||
const response = yield this.ajax.put(removeLabelUrl, {
|
||||
data: {
|
||||
action: 'removeLabel',
|
||||
meta: {
|
||||
label: {
|
||||
id: selectedLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// reset and reload
|
||||
this.store.unloadAll('member');
|
||||
@ -483,7 +513,7 @@ export default class MembersController extends Controller {
|
||||
this.membersStats.invalidate();
|
||||
this.membersStats.fetchCounts();
|
||||
|
||||
return {};
|
||||
return response.meta;
|
||||
}
|
||||
// Internal ----------------------------------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user