mirror of
https://github.com/TryGhost/Ghost-Admin.git
synced 2023-12-14 02:33:04 +01:00
Updated members list/detail screens base structure
no issue
This commit is contained in:
parent
6bbe7bb3d4
commit
54283b9431
14 changed files with 83 additions and 127 deletions
|
@ -16,11 +16,12 @@ export default Component.extend({
|
|||
tagName: '',
|
||||
|
||||
member: null,
|
||||
initialsClass: 'f6 fw4',
|
||||
|
||||
backgroundStyle: computed('member.name', function () {
|
||||
let name = this.member.name;
|
||||
initialsClass: computed('sizeClass', function () {
|
||||
return this.sizeClass || 'f6 fw4';
|
||||
}),
|
||||
|
||||
backgroundStyle: computed('member.{name,email}', function () {
|
||||
let name = this.member.name || this.member.email;
|
||||
if (name) {
|
||||
let color = stringToHslColor(name, 55, 55);
|
||||
return htmlSafe(`background-color: ${color}`);
|
||||
|
@ -29,11 +30,11 @@ export default Component.extend({
|
|||
return htmlSafe('');
|
||||
}),
|
||||
|
||||
initials: computed('member.name', function () {
|
||||
let name = this.member.name;
|
||||
initials: computed('member.{name,email}', function () {
|
||||
let name = this.member.name || this.member.email;
|
||||
if (name) {
|
||||
let names = name.split(' ');
|
||||
let intials = [names[0][0], names[names.length - 1][0]];
|
||||
let intials = names.length > 1 ? [names[0][0], names[names.length - 1][0]] : [names[0][0]];
|
||||
return intials.join('').toUpperCase();
|
||||
}
|
||||
return '';
|
||||
|
|
|
@ -1,31 +1,22 @@
|
|||
/* global key */
|
||||
import Component from '@ember/component';
|
||||
import Ember from 'ember';
|
||||
import boundOneWay from 'ghost-admin/utils/bound-one-way';
|
||||
import {computed} from '@ember/object';
|
||||
import {htmlSafe} from '@ember/string';
|
||||
import {reads} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
const {Handlebars} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
feature: service(),
|
||||
config: service(),
|
||||
mediaQueries: service(),
|
||||
|
||||
member: null,
|
||||
|
||||
isViewingSubview: false,
|
||||
|
||||
scratchDescription: '',
|
||||
|
||||
// Allowed actions
|
||||
setProperty: () => {},
|
||||
showDeleteTagModal: () => {},
|
||||
|
||||
scratchName: boundOneWay('member.name'),
|
||||
scratchEmail: boundOneWay('member.email'),
|
||||
scratchDescription: '',
|
||||
|
||||
actions: {
|
||||
setProperty(property, value) {
|
||||
this.setProperty(property, value);
|
||||
|
|
|
@ -20,6 +20,8 @@ export default Component.extend({
|
|||
return this.member.name || '-';
|
||||
}),
|
||||
subscribedAt: computed('member.createdAt', function () {
|
||||
return moment(this.member.createdAt).format('YYYY-MM-DD HH:mm');
|
||||
let memberSince = moment(this.member.createdAt).from(moment());
|
||||
let createdDate = moment(this.member.createdAt).format('MMM DD, YYYY');
|
||||
return `Created on ${createdDate} (${memberSince})`;
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Controller from '@ember/controller';
|
||||
import moment from 'moment';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as controller} from '@ember/controller';
|
||||
|
@ -30,9 +31,14 @@ export default Controller.extend({
|
|||
};
|
||||
}),
|
||||
|
||||
subscribedAt: computed('member.createdAt', function () {
|
||||
let createdDate = moment(this.member.createdAt).format('MMM DD, YYYY');
|
||||
return `Subscribed ${createdDate}`;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
setProperty(propKey, value) {
|
||||
// this._saveTagProperty(propKey, value);
|
||||
setProperty() {
|
||||
return;
|
||||
},
|
||||
toggleDeleteTagModal() {
|
||||
this.toggleProperty('showDeleteMemberModal');
|
||||
|
@ -44,17 +50,9 @@ export default Controller.extend({
|
|||
this.members.decrementProperty('meta.pagination.total');
|
||||
}
|
||||
this.router.transitionTo('members');
|
||||
},
|
||||
save() {
|
||||
return this.save.perform();
|
||||
}
|
||||
},
|
||||
|
||||
save: task(function* () {
|
||||
// DO NOTHING ATM
|
||||
return;
|
||||
}),
|
||||
|
||||
fetchMember: task(function* (memberId) {
|
||||
yield this.store.findRecord('member', memberId, {
|
||||
reload: true
|
||||
|
|
|
@ -32,63 +32,7 @@ export default Controller.extend({
|
|||
|
||||
return filtered;
|
||||
}),
|
||||
|
||||
chartData: computed('members.@each', function () {
|
||||
let {members} = this;
|
||||
let dateFormat = 'DD-MM-YYYY';
|
||||
let monthData = [];
|
||||
let dateLabel = [];
|
||||
let startDate = moment().subtract(29, 'days');
|
||||
for (let i = 0; i < 30; i++) {
|
||||
let m = moment(startDate).add(i, 'days');
|
||||
dateLabel.push(m.format(dateFormat));
|
||||
let membersTillDate = members.filter((member) => {
|
||||
let isValid = moment(member.createdAt).isSameOrBefore(m, 'day');
|
||||
return isValid;
|
||||
}).length;
|
||||
monthData.push(membersTillDate);
|
||||
}
|
||||
return {
|
||||
data: {
|
||||
labels: dateLabel,
|
||||
datasets: [
|
||||
{
|
||||
label: 'Total Members',
|
||||
data: monthData,
|
||||
fill: false,
|
||||
strokeColor: 'rgba(151,187,205,1)',
|
||||
pointColor: 'rgba(151,187,205,1)',
|
||||
pointStrokeColor: '#fff',
|
||||
pointHighlightFill: '#fff',
|
||||
pointHighlightStroke: 'rgba(151,187,205,1)'
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Total members in last 30 days'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
format: dateFormat,
|
||||
tooltipFormat: 'll'
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
},
|
||||
display: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
}),
|
||||
|
||||
|
||||
fetchMembers: task(function* () {
|
||||
let newFetchDate = new Date();
|
||||
let results;
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
@import "layouts/user.css";
|
||||
@import "layouts/about.css";
|
||||
@import "layouts/tags.css";
|
||||
@import "layouts/member.css";
|
||||
@import "layouts/members.css";
|
||||
@import "layouts/error.css";
|
||||
@import "layouts/apps.css";
|
||||
@import "layouts/packages.css";
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
@import "layouts/user.css";
|
||||
@import "layouts/about.css";
|
||||
@import "layouts/tags.css";
|
||||
@import "layouts/member.css";
|
||||
@import "layouts/members.css";
|
||||
@import "layouts/error.css";
|
||||
@import "layouts/apps.css";
|
||||
@import "layouts/packages.css";
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
}
|
||||
|
||||
.gh-list-row:nth-of-type(2) .gh-list-data {
|
||||
border: none;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.gh-list-data.show-on-hover > *,
|
||||
|
|
13
app/styles/layouts/member.css
Normal file
13
app/styles/layouts/member.css
Normal file
|
@ -0,0 +1,13 @@
|
|||
.member-detail-main-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.member-basic-info-form input:disabled {
|
||||
background: var(--lightgrey);
|
||||
}
|
||||
|
||||
.member-basic-info-form textarea:disabled {
|
||||
background: var(--lightgrey);
|
||||
}
|
3
app/styles/layouts/members.css
Normal file
3
app/styles/layouts/members.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
.members-list .gh-list-row:nth-of-type(2) .gh-list-data {
|
||||
border-top: var(--whitegrey) 1px solid;
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
<h4 class="midlightgrey f-small fw5 ttu">Basic settings</h4>
|
||||
<h4 class="midlightgrey f-small fw5 ttu">Basic info</h4>
|
||||
<div class="pa5 pt4 br4 shadow-1 bg-grouped-table mt2 flex flex-column flex-row-ns items-start justify-between gh-tag-basic-settings-form">
|
||||
<div class="order-1 flex flex-column items-start mr5 w-100 w-50-m w-two-thirds-l">
|
||||
{{#gh-form-group errors=member.errors hasValidated=member.hasValidated property="name"}}
|
||||
<label for="member-name">Name</label>
|
||||
{{gh-text-input
|
||||
disabled=true
|
||||
id="member-name"
|
||||
name="name"
|
||||
value=(readonly scratchName)
|
||||
|
@ -16,27 +17,31 @@
|
|||
{{#gh-form-group errors=member.errors hasValidated=member.hasValidated property="email"}}
|
||||
<label for="member-email">Email</label>
|
||||
{{gh-text-input
|
||||
value=(readonly scratchSlug)
|
||||
id="member-email"
|
||||
name="email"
|
||||
tabindex="2"
|
||||
focus-out=(action 'setProperty' 'email' scratchEmail)
|
||||
input=(action (mut scratchSlug) value="target.value")}}
|
||||
disabled=true
|
||||
value=(readonly scratchEmail)
|
||||
id="member-email"
|
||||
name="email"
|
||||
tabindex="2"
|
||||
focus-out=(action 'setProperty' 'email' scratchEmail)
|
||||
input=(action (mut scratchEmail) value="target.value")}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
</div>
|
||||
<div class="order-0 mb6 mb0-ns order-2-ns w-100 w-50-m w-third-l">
|
||||
{{#gh-form-group errors=member.errors hasValidated=tag.hasValidated property="note"}}
|
||||
<label for="member-description">Note</label>
|
||||
{{gh-textarea
|
||||
id="member-description"
|
||||
name="description"
|
||||
class="gh-tag-details-textarea"
|
||||
tabindex="3"
|
||||
value=(readonly scratchDescription)
|
||||
input=(action (mut scratchDescription) value="target.value")
|
||||
focus-out=(action 'setProperty' 'description' scratchDescription)
|
||||
}}
|
||||
{{gh-error-message errors=tag.errors property="description"}}
|
||||
<p>Maximum: <b>500</b> characters. You’ve used {{gh-count-down-characters scratchDescription 500}}</p>
|
||||
<label for="member-description">Note</label>
|
||||
{{gh-textarea
|
||||
disabled=true
|
||||
id="member-description"
|
||||
name="description"
|
||||
class="gh-tag-details-textarea"
|
||||
tabindex="3"
|
||||
value=(readonly scratchDescription)
|
||||
input=(action (mut scratchDescription) value="target.value")
|
||||
focus-out=(action 'setProperty' 'description' scratchDescription)
|
||||
}}
|
||||
{{gh-error-message errors=tag.errors property="description"}}
|
||||
<p>Maximum: <b>500</b> characters. You’ve used {{gh-count-down-characters scratchDescription 500}}</p>
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
</div>
|
|
@ -1,11 +1,11 @@
|
|||
{{#link-to "member" member class="gh-list-data" title="Edit Member"}}
|
||||
<h3 class="gh-tag-list-name">
|
||||
{{this.email}}
|
||||
</h3>
|
||||
{{/link-to}}
|
||||
|
||||
{{#link-to "member" member class="gh-list-data middarkgrey f8 gh-tag-list-slug" title="Edit Member"}}
|
||||
<span class="gh-tag-list-slug" title="Created at">{{this.name}}</span>
|
||||
<div class="apps-card-left">
|
||||
<GhMemberAvatar @member={{member}} class="w9 h9 mr4" />
|
||||
<div class="apps-card-meta">
|
||||
<h3 class="apps-card-app-title">{{this.name}}</h3>
|
||||
<p class="apps-card-app-desc">{{this.email}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{/link-to}}
|
||||
|
||||
{{#link-to "member" member class="gh-list-data middarkgrey f8 gh-tag-list-slug" title="Subscribed At" }}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
<section class="gh-canvas">
|
||||
<form class="mb15" {{action (perform "save") on="submit"}}>
|
||||
<form class="mb15 member-basic-info-form" {{action (perform "save") on="submit"}}>
|
||||
<GhCanvasHeader class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>
|
||||
{{#link-to "members" data-test-link="members-back"}}Members{{/link-to}}
|
||||
<span>{{svg-jar "arrow-right"}}</span>
|
||||
{{member.email}}
|
||||
</h2>
|
||||
<section class="view-actions">
|
||||
{{gh-task-button task=save class="gh-btn gh-btn-blue gh-btn-icon" data-test-button="save"}}
|
||||
</section>
|
||||
</GhCanvasHeader>
|
||||
<div class="member-detail-main-info">
|
||||
<GhMemberAvatar @member={{member}} @sizeClass={{'f-headline fw6'}} class="w16 h16 mr4" />
|
||||
<div class="apps-card-meta">
|
||||
<h3 class="apps-card-app-title">{{member.email}}</h3>
|
||||
<p class="apps-card-app-desc">{{this.subscribedAt}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{gh-member-settings-form member=member
|
||||
setProperty=(action "setProperty")
|
||||
showDeleteTagModal=(action "toggleDeleteTagModal")}}
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
@input={{action (mut this.searchText) value="target.value"}} />
|
||||
</div>
|
||||
</GhCanvasHeader>
|
||||
<div style="width:100%">
|
||||
{{ember-chart type='line' options=chartOptions.options data=chartData.data height=70}}
|
||||
</div>
|
||||
<section class="view-container h-100">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
|
@ -27,14 +24,8 @@
|
|||
</div>
|
||||
|
||||
<section class="content-list">
|
||||
<ol class="tags-list gh-list">
|
||||
<ol class="members-list gh-list">
|
||||
{{#if filteredMembers}}
|
||||
<li class="gh-list-row header">
|
||||
<div class="gh-list-header gh-list-cellwidth-1-2">Member Email</div>
|
||||
<div class="gh-list-header">Member Name</div>
|
||||
<div class="gh-list-header">Subscribed on</div>
|
||||
<div class="gh-list-header"></div>
|
||||
</li>
|
||||
{{#vertical-collection
|
||||
items=filteredMembers
|
||||
key="id"
|
||||
|
|
Loading…
Reference in a new issue