mirror of
https://github.com/TryGhost/Ghost-Admin.git
synced 2023-12-14 02:33:04 +01:00
Added csv import/export for members
no issue - Adds action view with import/export csv options
This commit is contained in:
parent
b01bb02534
commit
6cd12401c1
9 changed files with 169 additions and 2 deletions
43
app/components/modal-import-members.js
Normal file
43
app/components/modal-import-members.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import ModalComponent from 'ghost-admin/components/modal-base';
|
||||
import ghostPaths from 'ghost-admin/utils/ghost-paths';
|
||||
import {computed} from '@ember/object';
|
||||
|
||||
export default ModalComponent.extend({
|
||||
labelText: 'Select or drag-and-drop a CSV File',
|
||||
|
||||
response: null,
|
||||
closeDisabled: false,
|
||||
|
||||
// Allowed actions
|
||||
confirm: () => {},
|
||||
|
||||
uploadUrl: computed(function () {
|
||||
return `${ghostPaths().apiRoot}/members/csv/`;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
uploadStarted() {
|
||||
this.set('closeDisabled', true);
|
||||
},
|
||||
|
||||
uploadFinished() {
|
||||
this.set('closeDisabled', false);
|
||||
},
|
||||
|
||||
uploadSuccess(response) {
|
||||
this.set('response', response.meta.stats);
|
||||
// invoke the passed in confirm action
|
||||
this.confirm();
|
||||
},
|
||||
|
||||
confirm() {
|
||||
// noop - we don't want the enter key doing anything
|
||||
},
|
||||
|
||||
closeModal() {
|
||||
if (!this.closeDisabled) {
|
||||
this._super(...arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,4 +1,5 @@
|
|||
import Controller from '@ember/controller';
|
||||
import ghostPaths from 'ghost-admin/utils/ghost-paths';
|
||||
import moment from 'moment';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
@ -33,6 +34,22 @@ export default Controller.extend({
|
|||
return filtered;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
exportData() {
|
||||
let exportUrl = ghostPaths().url.api('members/csv');
|
||||
let downloadURL = `${exportUrl}`;
|
||||
let iframe = document.getElementById('iframeDownload');
|
||||
|
||||
if (!iframe) {
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.id = 'iframeDownload';
|
||||
iframe.style.display = 'none';
|
||||
document.body.append(iframe);
|
||||
}
|
||||
iframe.setAttribute('src', downloadURL);
|
||||
}
|
||||
},
|
||||
|
||||
fetchMembers: task(function* () {
|
||||
let newFetchDate = new Date();
|
||||
let results;
|
||||
|
|
19
app/controllers/members/import.js
Normal file
19
app/controllers/members/import.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Controller from '@ember/controller';
|
||||
import {inject as controller} from '@ember/controller';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
export default Controller.extend({
|
||||
members: controller(),
|
||||
router: service(),
|
||||
|
||||
actions: {
|
||||
fetchNewMembers() {
|
||||
this.members.fetchMembers.perform();
|
||||
},
|
||||
|
||||
close() {
|
||||
this.router.transitionTo('members');
|
||||
}
|
||||
}
|
||||
});
|
|
@ -58,7 +58,9 @@ Router.map(function () {
|
|||
this.route('settings.integrations.unsplash', {path: '/settings/integrations/unsplash'});
|
||||
this.route('settings.integrations.zapier', {path: '/settings/integrations/zapier'});
|
||||
|
||||
this.route('members');
|
||||
this.route('members', function () {
|
||||
this.route('import');
|
||||
});
|
||||
this.route('member', {path: '/members/:member_id'});
|
||||
|
||||
this.route('subscribers', function () {
|
||||
|
|
4
app/routes/members/import.js
Normal file
4
app/routes/members/import.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import Route from '@ember/routing/route';
|
||||
|
||||
export default Route.extend({
|
||||
});
|
|
@ -28,3 +28,11 @@ textarea.gh-member-details-textarea {
|
|||
max-width: 100%;
|
||||
height: 123px;
|
||||
}
|
||||
|
||||
/* Import modal
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
.members-import-results {
|
||||
margin: 0;
|
||||
width: auto;
|
||||
}
|
47
app/templates/components/modal-import-members.hbs
Normal file
47
app/templates/components/modal-import-members.hbs
Normal file
|
@ -0,0 +1,47 @@
|
|||
<header class="modal-header" data-test-modal="import-members">
|
||||
<h1>
|
||||
{{#if response}}
|
||||
Import Successful
|
||||
{{else}}
|
||||
Import Members
|
||||
{{/if}}
|
||||
</h1>
|
||||
</header>
|
||||
<a class="close" href="" title="Close" {{action "closeModal"}}>{{svg-jar "close"}}<span class="hidden">Close</span></a>
|
||||
|
||||
<div class="modal-body">
|
||||
{{#if response}}
|
||||
<table class="members-import-results">
|
||||
<tr>
|
||||
<td>Imported:</td>
|
||||
<td align="left" data-test-text="import-members-imported">{{response.imported}}</td>
|
||||
</tr>
|
||||
{{#if response.duplicates}}
|
||||
<tr>
|
||||
<td>Duplicates:</td>
|
||||
<td align="left" data-test-text="import-members-duplicates">{{response.duplicates}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if response.invalid}}
|
||||
<tr>
|
||||
<td>Invalid:</td>
|
||||
<td align="left" data-test-text="import-members-invalid">{{response.invalid}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
</table>
|
||||
{{else}}
|
||||
{{gh-file-uploader
|
||||
url=uploadUrl
|
||||
paramName="membersfile"
|
||||
labelText="Select or drag-and-drop a CSV file."
|
||||
uploadStarted=(action "uploadStarted")
|
||||
uploadFinished=(action "uploadFinished")
|
||||
uploadSuccess=(action "uploadSuccess")}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button {{action "closeModal"}} disabled={{closeDisabled}} class="gh-btn" data-test-button="close-import-members">
|
||||
<span>{{#if response}}Close{{else}}Cancel{{/if}}</span>
|
||||
</button>
|
||||
</div>
|
|
@ -6,6 +6,28 @@
|
|||
{{svg-jar "search" class="absolute top-2 left-2 w4 h4 fill-midlightgrey-l2"}}
|
||||
<GhTextInput placeholder="Search members..." @value={{this.searchText}} @input={{action (mut this.searchText) value="target.value"}} class="gh-members-list-searchfield" />
|
||||
</div>
|
||||
<section class="view-actions">
|
||||
<span class="dropdown">
|
||||
{{#gh-dropdown-button dropdownName="members-actions-menu" classNames="gh-btn gh-btn-white gh-btn-icon only-has-icon user-actions-cog" title="Members Actions" data-test-user-actions=true}}
|
||||
<span>
|
||||
{{svg-jar "settings"}}
|
||||
<span class="hidden">Members Actions</span>
|
||||
</span>
|
||||
{{/gh-dropdown-button}}
|
||||
{{#gh-dropdown name="members-actions-menu" tagName="ul" classNames="user-actions-menu dropdown-menu dropdown-triangle-top-right"}}
|
||||
<li>
|
||||
{{#link-to "members.import" class="mr2" data-test-link="import-csv"}}
|
||||
<span>Import CSV </span>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" {{action 'exportData'}} class="mr2">
|
||||
<span>Export CSV </span>
|
||||
</a>
|
||||
</li>
|
||||
{{/gh-dropdown}}
|
||||
</span>
|
||||
</section>
|
||||
</section>
|
||||
</GhCanvasHeader>
|
||||
<section class="view-container">
|
||||
|
@ -65,3 +87,4 @@
|
|||
</section>
|
||||
</section>
|
||||
</section>
|
||||
{{outlet}}
|
4
app/templates/members/import.hbs
Normal file
4
app/templates/members/import.hbs
Normal file
|
@ -0,0 +1,4 @@
|
|||
{{gh-fullscreen-modal "import-members"
|
||||
close=(action "close")
|
||||
confirm=(action "fetchNewMembers")
|
||||
modifier="action wide"}}
|
Loading…
Reference in a new issue