From 733f76d5718c78f2b18e9c25dd848ebd1c7b6c9a Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 8 Apr 2021 16:06:00 +0100 Subject: [PATCH] Added automatic CSV export when bulk deleting members refs https://github.com/TryGhost/Team/issues/585 - updated bulk destroy task to first use the current query params to fetch from the appropriate CSV export endpoint and trigger a download - fetches via JS and triggers download from a blob URL link instead of an iframe so that we can be sure the download is successful before we hit the bulk delete endpoint - works differently to user deletion download because the server is not generating an export file and saving it meaning the client has to be sure we don't delete data before it's exported - updated copy in the confirmation modal to reflect the download behaviour --- .../app/components/modal-delete-members.hbs | 5 ++- ghost/admin/app/controllers/members.js | 35 +++++++++++++++++-- ghost/admin/mirage/config/members.js | 8 +++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/ghost/admin/app/components/modal-delete-members.hbs b/ghost/admin/app/components/modal-delete-members.hbs index 1a772107e0..2020af0220 100644 --- a/ghost/admin/app/components/modal-delete-members.hbs +++ b/ghost/admin/app/components/modal-delete-members.hbs @@ -10,6 +10,9 @@ {{gh-pluralize this.model.memberCount "member"}}. This is permanent! All Ghost data will be deleted, this will have no effect on subscriptions in Stripe.

+

+ A backup of your selection will be automatically downloaded to your device before deletion. +

{{else}}
@@ -52,7 +55,7 @@ res.blob()) + .then((blob) => { + const blobUrl = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = blobUrl; + a.download = `members.${moment().format('YYYY-MM-DD')}.csv`; + document.body.appendChild(a); + if (!this.isTesting) { + a.click(); + } + a.remove(); + URL.revokeObjectURL(blobUrl); + }); + + // backup downloaded, continue with deletion + + const deleteUrl = `${this.ghostPaths.url.api('members')}?${query}`; // response contains details of which members failed to be deleted - let response = yield this.ajax.del(url); + const response = yield this.ajax.del(deleteUrl); // reset and reload this.store.unloadAll('member'); diff --git a/ghost/admin/mirage/config/members.js b/ghost/admin/mirage/config/members.js index 8fdf0c5544..abbdb10055 100644 --- a/ghost/admin/mirage/config/members.js +++ b/ghost/admin/mirage/config/members.js @@ -146,5 +146,13 @@ export default function mockMembers(server) { server.del('/members/:id/'); + server.get('/members/upload/', function () { + return new Response(200, { + 'Content-Disposition': 'attachment', + filename: `members.${moment().format('YYYY-MM-DD')}.csv`, + 'Content-Type': 'text/csv' + }, ''); + }); + mockMembersStats(server); }