mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Implemented first pass of member details screen
This commit is contained in:
parent
ac321fa62a
commit
6ac2569f24
@ -16,6 +16,7 @@ export default Component.extend({
|
||||
tagName: '',
|
||||
|
||||
member: null,
|
||||
initialsClass: 'f6 fw3',
|
||||
|
||||
backgroundStyle: computed('member.name', function () {
|
||||
let name = this.member.name;
|
||||
|
42
ghost/admin/app/components/modal-delete-member.js
Normal file
42
ghost/admin/app/components/modal-delete-member.js
Normal file
@ -0,0 +1,42 @@
|
||||
import ModalComponent from 'ghost-admin/components/modal-base';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default ModalComponent.extend({
|
||||
notifications: service(),
|
||||
|
||||
member: alias('model.member'),
|
||||
onSuccess: alias('model.onSuccess'),
|
||||
|
||||
actions: {
|
||||
confirm() {
|
||||
this.deleteMember.perform();
|
||||
}
|
||||
},
|
||||
|
||||
_success() {
|
||||
// clear any previous error messages
|
||||
this.notifications.closeAlerts('post.delete');
|
||||
|
||||
// trigger the success action
|
||||
if (this.onSuccess) {
|
||||
this.onSuccess();
|
||||
}
|
||||
},
|
||||
|
||||
_failure(error) {
|
||||
this.notifications.showAPIError(error, {key: 'post.delete.failed'});
|
||||
},
|
||||
|
||||
deleteMember: task(function* () {
|
||||
try {
|
||||
yield this.member.destroyRecord();
|
||||
this._success();
|
||||
} catch (e) {
|
||||
this._failure(e);
|
||||
} finally {
|
||||
this.send('closeModal');
|
||||
}
|
||||
}).drop()
|
||||
});
|
@ -1,6 +1,22 @@
|
||||
import Controller from '@ember/controller';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {inject as controller} from '@ember/controller';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default Controller.extend({
|
||||
member: alias('model')
|
||||
members: controller(),
|
||||
router: service(),
|
||||
|
||||
member: alias('model'),
|
||||
|
||||
actions: {
|
||||
finaliseDeletion() {
|
||||
// decrememnt the total member count manually so there's no flash
|
||||
// when transitioning back to the members list
|
||||
if (this.members.meta) {
|
||||
this.members.decrementProperty('meta.pagination.total');
|
||||
}
|
||||
this.router.transitionTo('members');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,3 +1,3 @@
|
||||
<div class="flex items-center justify-center br-100" style={{this.backgroundStyle}} ...attributes>
|
||||
<span class="block white f6 fw3">{{this.initials}}</span>
|
||||
<span class="db white {{this.initialsClass}}">{{this.initials}}</span>
|
||||
</div>
|
15
ghost/admin/app/templates/components/modal-delete-member.hbs
Normal file
15
ghost/admin/app/templates/components/modal-delete-member.hbs
Normal file
@ -0,0 +1,15 @@
|
||||
<header class="modal-header">
|
||||
<h1>Are you sure you want to delete this member?</h1>
|
||||
</header>
|
||||
<a class="close" href="" title="Close" {{action "closeModal"}}>{{svg-jar "close"}}<span class="hidden">Close</span></a>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
You're about to delete "<strong>{{or member.name member.email}}</strong>". This is permanent! We warned you, k?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button {{action "closeModal"}} class="gh-btn"><span>Cancel</span></button>
|
||||
{{gh-task-button "Delete" successText="Deleted" task=deleteMember class="gh-btn gh-btn-red gh-btn-icon"}}
|
||||
</div>
|
@ -8,6 +8,52 @@
|
||||
</header>
|
||||
|
||||
<section class="view-container">
|
||||
<div class="pt1">
|
||||
<h2 class="f7 fw4 midgrey">Overview</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-column mb10 ba br3 b--whitegrey">
|
||||
<div class="flex flex-row pa5">
|
||||
<GhMemberAvatar class="w20 h20 mr4" @initialsClass="f-subheadline" @member={{member}} />
|
||||
<div class="flex flex-column justify-center">
|
||||
<h3 class="ma0 pa0">{{member.name}}</h3>
|
||||
<span class="db">
|
||||
<a class="midlightgrey" href="mailto:{{member.email}}">
|
||||
{{member.email}}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row bt b--whitegrey bg-whitegrey-l2">
|
||||
<div class="flex flex-column flex-grow-1 pa5 br b--whitegrey">
|
||||
<span class="db ttu f8 midlightgrey">Member since</span>
|
||||
<span class="db f5">{{moment-format member.createdAt "MMMM Do"}}</span>
|
||||
<span class="db f8 midlightgrey">({{moment-to-now member.createdAt hideAffix=true}})</span>
|
||||
</div>
|
||||
<div class="flex flex-column flex-grow-1 pa5">
|
||||
<span class="db ttu f8 midlightgrey">Current plan</span>
|
||||
<span class="db f5">-</span>
|
||||
<span class="db f8 midlightgrey"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="pb1 bb b--whitegrey f7 fw4 midgrey">Danger zone</h2>
|
||||
<button
|
||||
type="button"
|
||||
class="gh-btn gh-btn-red gh-btn-icon"
|
||||
{{action (toggle "showDeleteMemberModal" this)}}
|
||||
data-test-button="delete-member"
|
||||
>
|
||||
<span>Delete member</span>
|
||||
</button>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
{{#if showDeleteMemberModal}}
|
||||
{{gh-fullscreen-modal "delete-member"
|
||||
model=(hash member=member onSuccess=(action "finaliseDeletion"))
|
||||
close=(action (toggle "showDeleteMemberModal" this))
|
||||
modifier="action wide"}}
|
||||
{{/if}}
|
@ -5,7 +5,14 @@
|
||||
|
||||
<section class="view-container h-100">
|
||||
<div class="flex justify-between items-center pt1">
|
||||
<h2 class="f7 fw4 midgrey">All members ({{this.meta.pagination.total}})</h2>
|
||||
<h2 class="f7 fw4 midgrey">
|
||||
All members
|
||||
{{#if this.fetchMembers.lastSuccessful}}
|
||||
({{this.meta.pagination.total}})
|
||||
{{else}}
|
||||
(...)
|
||||
{{/if}}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{{#if this.members}}
|
||||
|
@ -2,4 +2,18 @@ import {paginatedResponse} from '../utils';
|
||||
|
||||
export default function mockMembers(server) {
|
||||
server.get('/members/', paginatedResponse('members'));
|
||||
|
||||
server.get('/members/:id/', function ({members}, {params}) {
|
||||
let {id} = params;
|
||||
let member = members.find(id);
|
||||
|
||||
return member || new Response(404, {}, {
|
||||
errors: [{
|
||||
errorType: 'NotFoundError',
|
||||
message: 'Member not found.'
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
server.del('/members/:id/');
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { expect } from 'chai';
|
||||
import { describe, it } from 'mocha';
|
||||
import { setupComponentTest } from 'ember-mocha';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
describe('Integration | Component | modal-delete-member', function() {
|
||||
setupComponentTest('modal-delete-member', {
|
||||
integration: true
|
||||
});
|
||||
|
||||
it('renders', function() {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.on('myAction', function(val) { ... });
|
||||
// Template block usage:
|
||||
// this.render(hbs`
|
||||
// {{#modal-delete-member}}
|
||||
// template content
|
||||
// {{/modal-delete-member}}
|
||||
// `);
|
||||
|
||||
this.render(hbs`{{modal-delete-member}}`);
|
||||
expect(this.$()).to.have.length(1);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user