Further refinements to the new empty state for 0 members in new Dashboard

refs: https://github.com/TryGhost/Team/issues/1594

- this much more matches the style of the design
- it now covers the anchor and engagement charts
- has better fake data for all charts under the notice
- tweaked things for this in dark mode
This commit is contained in:
James Morris 2022-05-06 17:33:19 +01:00
parent 8af605babe
commit f9231afa2a
12 changed files with 377 additions and 46 deletions

View File

@ -6,11 +6,18 @@
{{#if this.hasPaidTiers}}
<Dashboard::V5::Charts::Overview />
{{/if}}
<Dashboard::V5::Charts::Anchor />
{{#if this.areNewslettersEnabled}}
<Dashboard::V5::Charts::Engagement />
{{/if}}
<div class="gh-dashboard5-group">
<Dashboard::V5::Charts::Anchor />
{{#if this.areNewslettersEnabled}}
<Dashboard::V5::Charts::Engagement />
{{/if}}
{{#if this.isTotalMembersZero}}
<Dashboard::V5::Parts::Zero />
{{/if}}
</div>
{{/if}}
<Dashboard::V5::Charts::Recents />

View File

@ -18,6 +18,10 @@ export default class DashboardDashboardV5Component extends Component {
return this.dashboardStats.memberCounts?.total ?? 0;
}
get isTotalMembersZero() {
return this.dashboardStats.memberCounts && this.totalMembers === 0;
}
get hasPaidTiers() {
return this.dashboardStats.siteStatus?.hasPaidTiers;
}

View File

@ -82,14 +82,4 @@
</div>
</article>
{{#if this.isTotalMembersZero}}
<div class="gh-dashboard5-anchor-empty">
<div class="gh-dashboard5-anchor-empty-message">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>graph-stats-ascend</title><polyline class="a" points="23.25 12.75 23.25 6 16.5 6"/><path class="a" d="M23.25,6l-7.939,7.939a1.5,1.5,0,0,1-2.122,0l-3.128-3.128a1.5,1.5,0,0,0-2.122,0L.75,18"/></svg>
<h4>Get your first member to unlock analytics!</h4>
<p>Analytics will appear here as soon as someone subscribes to your site.</p>
</div>
</div>
{{/if}}
</section>

View File

@ -210,11 +210,6 @@ export default class Anchor extends Component {
const gradientFill = ctxFill.createLinearGradient(0, 0, 1000, 0);
gradientFill.addColorStop(0, 'rgba(250, 45, 142, 0.2');
gradientFill.addColorStop(1, 'rgba(143, 66, 255, 0.02');
// fake data
console.log('stats', stats);
console.log('labels', labels);
console.log('data', data);
return {
labels: labels,

View File

@ -48,6 +48,11 @@ export default class Engagement extends Component {
}
get data30Days() {
// fake empty data
if (this.isTotalMembersZero) {
return '30%';
}
if (this.loading) {
return '- %';
}
@ -63,6 +68,11 @@ export default class Engagement extends Component {
}
get data7Days() {
// fake empty data
if (this.isTotalMembersZero) {
return '60%';
}
if (this.loading) {
return '- %';
}
@ -78,6 +88,11 @@ export default class Engagement extends Component {
}
get dataSubscribers() {
// fake empty data
if (this.isTotalMembersZero) {
return '123';
}
if (!this.dashboardStats.newsletterSubscribers) {
return '-';
}
@ -92,4 +107,12 @@ export default class Engagement extends Component {
get hasPaidTiers() {
return this.dashboardStats.siteStatus?.hasPaidTiers;
}
get totalMembers() {
return this.dashboardStats.memberCounts?.total ?? 0;
}
get isTotalMembersZero() {
return this.dashboardStats.memberCounts && this.totalMembers === 0;
}
}

View File

@ -64,6 +64,14 @@ export default class Mrr extends Component {
return 'hoverLine'; // uses custom ChartJS draw function
}
get totalMembers() {
return this.dashboardStats.memberCounts?.total ?? 0;
}
get isTotalMembersZero() {
return this.dashboardStats.memberCounts && this.totalMembers === 0;
}
get mrrCurrencySymbol() {
if (this.dashboardStats.mrrStats === null) {
return '';
@ -74,6 +82,11 @@ export default class Mrr extends Component {
}
get currentMRRFormatted() {
// fake empty data
if (this.isTotalMembersZero) {
return '$123';
}
if (this.dashboardStats.mrrStats === null) {
return '-';
}
@ -83,9 +96,18 @@ export default class Mrr extends Component {
}
get chartData() {
const stats = this.dashboardStats.filledMrrStats;
const labels = stats.map(stat => stat.date);
const data = stats.map(stat => stat.mrr);
let stats = this.dashboardStats.filledMrrStats;
let labels = stats.map(stat => stat.date);
let data = stats.map(stat => stat.mrr);
console.log('this.isTotalMembersZero', this.isTotalMembersZero);
// with no members yet, let's show empty state with dummy data
if (this.isTotalMembersZero) {
stats = this.emptyData.stats;
labels = this.emptyData.labels;
data = this.emptyData.data;
}
// gradient for fill
const canvas = document.createElement('canvas');
@ -218,6 +240,228 @@ export default class Mrr extends Component {
};
}
// used for empty state
get emptyData() {
return {
stats: [
{
"date": "2022-04-07",
"mrr": 0,
"currency": "usd"
},
{
"date": "2022-04-08",
"mrr": 0,
"currency": "usd"
},
{
"date": "2022-04-09",
"mrr": 1500,
"currency": "usd"
},
{
"date": "2022-04-10",
"mrr": 2000,
"currency": "usd"
},
{
"date": "2022-04-11",
"mrr": 4500,
"currency": "usd"
},
{
"date": "2022-04-12",
"mrr": 7500,
"currency": "usd"
},
{
"date": "2022-04-13",
"mrr": 11000,
"currency": "usd"
},
{
"date": "2022-04-14",
"mrr": 12500,
"currency": "usd"
},
{
"date": "2022-04-15",
"mrr": 14500,
"currency": "usd"
},
{
"date": "2022-04-16",
"mrr": 18000,
"currency": "usd"
},
{
"date": "2022-04-17",
"mrr": 21500,
"currency": "usd"
},
{
"date": "2022-04-18",
"mrr": 25000,
"currency": "usd"
},
{
"date": "2022-04-19",
"mrr": 28000,
"currency": "usd"
},
{
"date": "2022-04-20",
"mrr": 30000,
"currency": "usd"
},
{
"date": "2022-04-21",
"mrr": 34000,
"currency": "usd"
},
{
"date": "2022-04-22",
"mrr": 35000,
"currency": "usd"
},
{
"date": "2022-04-23",
"mrr": 35500,
"currency": "usd"
},
{
"date": "2022-04-24",
"mrr": 37000,
"currency": "usd"
},
{
"date": "2022-04-25",
"mrr": 38000,
"currency": "usd"
},
{
"date": "2022-04-26",
"mrr": 40500,
"currency": "usd"
},
{
"date": "2022-04-27",
"mrr": 43500,
"currency": "usd"
},
{
"date": "2022-04-28",
"mrr": 47000,
"currency": "usd"
},
{
"date": "2022-04-29",
"mrr": 48000,
"currency": "usd"
},
{
"date": "2022-04-30",
"mrr": 50500,
"currency": "usd"
},
{
"date": "2022-05-01",
"mrr": 53500,
"currency": "usd"
},
{
"date": "2022-05-02",
"mrr": 55000,
"currency": "usd"
},
{
"date": "2022-05-03",
"mrr": 56500,
"currency": "usd"
},
{
"date": "2022-05-04",
"mrr": 57000,
"currency": "usd"
},
{
"date": "2022-05-05",
"mrr": 58000,
"currency": "usd"
},
{
"date": "2022-05-06",
"mrr": 58500,
"currency": "usd"
}
],
labels: [
"2022-04-07",
"2022-04-08",
"2022-04-09",
"2022-04-10",
"2022-04-11",
"2022-04-12",
"2022-04-13",
"2022-04-14",
"2022-04-15",
"2022-04-16",
"2022-04-17",
"2022-04-18",
"2022-04-19",
"2022-04-20",
"2022-04-21",
"2022-04-22",
"2022-04-23",
"2022-04-24",
"2022-04-25",
"2022-04-26",
"2022-04-27",
"2022-04-28",
"2022-04-29",
"2022-04-30",
"2022-05-01",
"2022-05-02",
"2022-05-03",
"2022-05-04",
"2022-05-05",
"2022-05-06"
],
data: [
0,
1500,
4000,
5000,
9000,
11500,
22500,
26000,
30000,
30000,
31000,
33000,
33500,
35500,
36500,
36500,
40000,
40500,
43500,
47000,
49000,
49500,
50000,
50000,
53000,
56000,
58000,
61000,
63500,
63500
]
}
}
calculatePercentage(from, to) {
if (from === 0) {
if (to > 0) {

View File

@ -36,7 +36,15 @@ export default class PaidMix extends Component {
get hasMultipleTiers() {
return this.dashboardStats.siteStatus?.hasMultipleTiers;
}
}
get totalMembers() {
return this.dashboardStats.memberCounts?.total ?? 0;
}
get isTotalMembersZero() {
return this.dashboardStats.memberCounts && this.totalMembers === 0;
}
@action
onSwitchMode(selected) {
@ -65,6 +73,24 @@ export default class PaidMix extends Component {
const annualPercentage = Math.round(this.dashboardStats.paidMembersByCadence.year / totalCadence * 100);
const barThickness = 5;
// fake empty data
if (this.isTotalMembersZero) {
return {
labels: ['Cadence'],
datasets: [{
label: 'Monthly',
data: [60],
backgroundColor: '#8E42FF',
barThickness
}, {
label: 'Annual',
data: [40],
backgroundColor: '#FB76B4',
barThickness
}]
};
}
if (this.mode === 'cadence') {
return {
labels: ['Cadence'],

View File

@ -0,0 +1,3 @@
<div class="gh-dashboard5-zero">
</div>

View File

@ -0,0 +1,6 @@
<div class="gh-dashboard5-zero">
<div class="gh-dashboard5-zero-message">
<h4>Get your first member to unlock analytics!</h4>
<p>Analytics will appear here as soon as someone<br />subscribes to your site.</p>
</div>
</div>

View File

@ -1163,6 +1163,22 @@ kbd {
background: #1c1e21;
}
.gh-dashboard5-recents .gh-dashboard5-list-item:hover {
background: rgba(28, 30, 33, 0.7);
}
.gh-dashboard5-resource .gh-dashboard5-list-item:hover {
background: rgba(28, 30, 33, 0.3);
}
.gh-dashboard5-community .gh-dashboard5-resource-footer {
color: #fff;
}
.gh-dashboard5-zero {
background: rgb(21, 23, 25, 0.8);
}
.gh-dashboard5-zero-message {
background-color: #1c1e21;
}

View File

@ -878,13 +878,23 @@ Dashboard v5 Anchor */
right: -18px;
}
.gh-dashboard5-anchor-empty {
.gh-dashboard5-group {
position: relative;
}
/* ---------------------------------
Dashboard v5 Zero */
.gh-dashboard5-zero {
position: absolute;
top: 16px;
left: 16px;
width: calc(100% - 32px);
height: calc(100% - 32px);
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255,255,255,0.8);
border: 1px solid var(--whitegrey);
border-radius: 6px;
-webkit-backdrop-filter: blur(3px);
backdrop-filter: blur(3px);
@ -893,41 +903,35 @@ Dashboard v5 Anchor */
justify-content: center;
}
.gh-dashboard5-anchor-empty-message {
background: #ffffff;
width: 416px;
padding: 32px 48px 48px;
.gh-dashboard5-zero-message {
background: #fff url(icons/analytics.svg) no-repeat 50% 36px;
background-size: 48px 48px;
min-width: 400px;
padding: 96px 48px 48px;
border-radius: 8px;
text-align: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.075);
box-shadow: 0 4px 24px rgba(0,0,0,0.066);
}
.gh-dashboard5-anchor-empty-message svg {
width: 48px;
height: auto;
margin: 0 0 16px;
fill: red;
}
.gh-dashboard5-anchor-empty-message h4 {
.gh-dashboard5-zero-message h4 {
font-size: 1.55rem;
font-weight: 700;
line-height: 1em;
margin: 0 0 12px;
margin: 0 0 10px;
padding: 0;
color: var(--black);
white-space: nowrap;
letter-spacing: -.3px;
}
.gh-dashboard5-anchor-empty-message p {
.gh-dashboard5-zero-message p {
font-size: 1.2rem;
font-weight: 600;
line-height: 1.4em;
line-height: 1.5em;
color: var(--black);
letter-spacing: -.1px;
margin: 0;
padding: 0;
margin: 0;
}

View File

@ -1 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>graph-stats-ascend</title><polyline class="a" points="23.25 12.75 23.25 6 16.5 6"/><path class="a" d="M23.25,6l-7.939,7.939a1.5,1.5,0,0,1-2.122,0l-3.128-3.128a1.5,1.5,0,0,0-2.122,0L.75,18"/></svg>
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.3125 28.6875V13.5H37.125" stroke="url(#paint0_linear_79_20)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M52.3125 13.5L34.4497 31.3628C34.1363 31.6764 33.7642 31.9252 33.3546 32.0949C32.9449 32.2647 32.5059 32.352 32.0625 32.352C31.6191 32.352 31.1801 32.2647 30.7704 32.0949C30.3608 31.9252 29.9887 31.6764 29.6753 31.3628L22.6372 24.3247C22.3238 24.0111 21.9517 23.7623 21.5421 23.5926C21.1324 23.4228 20.6934 23.3355 20.25 23.3355C19.8066 23.3355 19.3676 23.4228 18.9579 23.5926C18.5483 23.7623 18.1762 24.0111 17.8628 24.3247L1.6875 40.5" stroke="url(#paint1_linear_79_20)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_79_20" x1="44.7188" y1="13.5" x2="44.7188" y2="28.6875" gradientUnits="userSpaceOnUse">
<stop stop-color="#FB2D8D"/>
<stop offset="1" stop-color="#8E42FF"/>
</linearGradient>
<linearGradient id="paint1_linear_79_20" x1="27" y1="13.5" x2="27" y2="40.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#FB2D8D"/>
<stop offset="1" stop-color="#8E42FF"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 1.2 KiB