mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
First round of getting better styles into the new dashboard
refs: https://github.com/TryGhost/Team/issues/1462 - remove dummy percentages where not necessary - trying out a narrower width for the dashboard - added in a basic layout for the various charts - added more specific styles to each of the graphs - tried out a different way of displaying metrics - different way to show headers for each module - made the grid and flex layouts a little more flexible - there are some bits to still clean up with code
This commit is contained in:
parent
60a3b742ea
commit
3b9525dd63
@ -1,90 +1,95 @@
|
||||
<section {{did-insert this.onInsert}} class="gh-dashboard5">
|
||||
<section {{did-insert this.onInsert}}>
|
||||
|
||||
{{#if this.isLoading }}
|
||||
<GhLoadingSpinner />
|
||||
{{else}}
|
||||
{{#if this.areMembersEnabled}}
|
||||
<section class="gh-dashboard5-section">
|
||||
<Dashboard::V5::ChartMembersCounts />
|
||||
<section class="gh-dashboard5-section gh-dashboard5-overview">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartTotalMembers @days={{this.days}} />
|
||||
</article>
|
||||
<div class="prototype-selection">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedDaysOption}}
|
||||
@options={{this.daysOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{this.onDaysChange}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@matchTriggerWidth={{false}}
|
||||
as |option|
|
||||
>
|
||||
{{#if option.name}}{{option.name}}{{else}}<span class="red">Unknown option</span>{{/if}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="gh-dashboard5-section">
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3>Members</h3>
|
||||
<div class="prototype-selection">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedDaysOption}}
|
||||
@options={{this.daysOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{this.onDaysChange}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@matchTriggerWidth={{false}}
|
||||
as |option|
|
||||
>
|
||||
{{#if option.name}}{{option.name}}{{else}}<span class="red">Unknown option</span>{{/if}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
</div>
|
||||
{{#if this.hasPaidTiers}}
|
||||
<div class="gh-dashboard5-paid">
|
||||
<section class="gh-dashboard5-section">
|
||||
<div class="gh-dashboard5-growth">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartMonthlyRevenue @days={{this.days}} />
|
||||
</article>
|
||||
|
||||
<div class="gh-dashboard5-growth">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartTotalPaid @days={{this.days}} />
|
||||
</article>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartPaidMembers @days={{this.days}}/>
|
||||
</article>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartPaidMix />
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<section class="gh-dashboard5-split is-third">
|
||||
<section class="gh-dashboard5-section gh-dashboard5-email">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartEmail />
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="gh-dashboard5-section gh-dashboard5-engagement">
|
||||
<Dashboard::V5::ChartEngagement />
|
||||
</section>
|
||||
</section>
|
||||
{{else}}
|
||||
<section class="gh-dashboard5-section gh-dashboard5-engagement">
|
||||
<Dashboard::V5::ChartEngagement />
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<section class="gh-dashboard5-section gh-dashboard5-email">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartTotalMembers @days={{this.days}} />
|
||||
<Dashboard::V5::ChartEmail />
|
||||
</article>
|
||||
|
||||
{{#if this.hasPaidTiers}}
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartMonthlyRevenue @days={{this.days}} />
|
||||
</article>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartTotalPaid @days={{this.days}} />
|
||||
</article>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartPaidMembers @days={{this.days}}/>
|
||||
</article>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::ChartPaidMix />
|
||||
</article>
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
<section class="gh-dashboard5-section">
|
||||
<Dashboard::V5::ChartEngagement />
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<section class="gh-dashboard5-section">
|
||||
<Dashboard::V5::ChartEmail />
|
||||
</section>
|
||||
</section>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<section class="gh-dashboard5-split">
|
||||
<section class="gh-dashboard5-section">
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3>Recent posts</h3>
|
||||
</div>
|
||||
<section class="gh-dashboard5-section gh-dashboard5-posts">
|
||||
<article class="gh-dashboard5-box">
|
||||
<Dashboard::V5::RecentPosts />
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="gh-dashboard5-section">
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3>Recent activity</h3>
|
||||
</div>
|
||||
<Dashboard::LatestMemberActivity />
|
||||
<section class="gh-dashboard5-section gh-dashboard5-activity">
|
||||
<Dashboard::V5::RecentActivity />
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="gh-dashboard5-section">
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3>Resources</h3>
|
||||
</div>
|
||||
<div class="gh-main-section gh-offers-help">
|
||||
<div class="gh-main-section-block">
|
||||
<div class="gh-main-section-content grey">
|
||||
|
@ -1,21 +1,23 @@
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3 {{did-insert this.loadCharts}}>Email</h3>
|
||||
</div>
|
||||
<div class="gh-dashboard5-container gh-dashboard5-email">
|
||||
<h3 {{did-insert this.loadCharts}}>Email</h3>
|
||||
<div class="gh-dashboard5-insert">
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">Newsletter subscribers</h4>
|
||||
<div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.total}}</div>
|
||||
<div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.paid}} paid</div>
|
||||
<div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.free}} free</div>
|
||||
{{!-- <h4 class="gh-dashboard5-metric">Newsletter subscribers</h4> --}}
|
||||
{{!-- <div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.total}}</div> --}}
|
||||
{{!-- <div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.paid}} paid</div> --}}
|
||||
{{!-- <div class="gh-dashboard5-number is-small">{{format-number this.dataSubscribers.free}} free</div> --}}
|
||||
|
||||
<h4 class="gh-dashboard5-metric is-split">Email</h4>
|
||||
<div class="gh-dashboard5-number">{{format-number this.dataSubscribers.total}}</div>
|
||||
<small class="gh-dashboard5-info">Newsletter subscribers</small>
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">Emails sent in the past 30 days</h4>
|
||||
<div class="gh-dashboard5-number is-small">{{format-number this.dataEmailsSent}}</div>
|
||||
<h4 class="gh-dashboard5-metric is-split"> </h4>
|
||||
<div class="gh-dashboard5-number">{{format-number this.dataEmailsSent}}</div>
|
||||
<small class="gh-dashboard5-info">Sent in the past 30 days</small>
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric is-main">Email open rate</h4>
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
@ -25,5 +27,9 @@
|
||||
@options={{this.chartOptions}}
|
||||
@height={{this.chartHeight}} />
|
||||
{{/if}}
|
||||
<div>
|
||||
<div class="gh-dashboard5-number">58%</div>
|
||||
<small class="gh-dashboard5-info">Open rate</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -49,20 +49,61 @@ export default class ChartEmailOpenRate extends Component {
|
||||
data,
|
||||
fill: false,
|
||||
backgroundColor: '#14b8ff',
|
||||
tension: 0.1
|
||||
tension: 0.1,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: false,
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
borderColor: '#14b8ff',
|
||||
borderJoinStyle: 'miter',
|
||||
maxBarThickness: 20,
|
||||
minBarLength: 2
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
return {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
autoSkip: true,
|
||||
maxRotation: 0,
|
||||
minRotation: 0
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 100;
|
||||
return 175;
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,33 @@
|
||||
<div class="gh-dashboard5-header">
|
||||
<h3 {{did-insert this.loadCharts}}>Engagement</h3>
|
||||
<div class="prototype-selection">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedStatusOption}}
|
||||
@options={{this.statusOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{this.onSwitchStatus}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@matchTriggerWidth={{false}}
|
||||
as |option|
|
||||
>
|
||||
{{#if option.name}}{{option.name}}{{else}}<span class="red">Unknown option</span>{{/if}}
|
||||
</PowerSelect>
|
||||
<h3 {{did-insert this.loadCharts}}>Engagement</h3>
|
||||
|
||||
<article class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-insert">
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric is-split">Engagement</h4>
|
||||
<div class="gh-dashboard5-number">{{this.data30Days}}</div>
|
||||
<small class="gh-dashboard5-info">Last 30 days</small>
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric is-split"> </h4>
|
||||
<div class="gh-dashboard5-number">{{this.data7Days}}</div>
|
||||
<small class="gh-dashboard5-info">Last 7 days</small>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="prototype-selection">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedStatusOption}}
|
||||
@options={{this.statusOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{this.onSwitchStatus}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@matchTriggerWidth={{false}}
|
||||
as |option|
|
||||
>
|
||||
{{#if option.name}}{{option.name}}{{else}}<span class="red">Unknown option</span>{{/if}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-container">
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">Engaged in past 30 days</h4>
|
||||
<div class="gh-dashboard5-number is-small">{{this.data30Days}}</div>
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">Engaged in past 7 days</h4>
|
||||
<div class="gh-dashboard5-number is-small">{{this.data7Days}}</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,23 @@
|
||||
<div class="gh-dashboard5-insert">
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">{{gh-pluralize this.totalMembers "Total member" without-count=true}}</h4>
|
||||
<div class="gh-dashboard5-number">{{format-number this.totalMembers}}</div>
|
||||
{{#if this.hasTrends}}
|
||||
<Dashboard::v5::parts::ChartPercentage @percentage={{this.totalMembersTrend}}/>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">{{gh-pluralize this.paidMembers "Paid member" without-count=true}}</h4>
|
||||
<div class="gh-dashboard5-number">{{format-number this.paidMembers}}</div>
|
||||
{{#if this.hasTrends}}
|
||||
<Dashboard::v5::parts::ChartPercentage @percentage={{this.paidMembersTrend}}/>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard5-box">
|
||||
<h4 class="gh-dashboard5-metric">{{gh-pluralize this.freeMembers "Free member" without-count=true}}</h4>
|
||||
<div class="gh-dashboard5-number">{{format-number this.freeMembers}}</div>
|
||||
{{#if this.hasTrends}}
|
||||
<Dashboard::v5::parts::ChartPercentage @percentage={{this.freeMembersTrend}}/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,51 @@
|
||||
import Component from '@glimmer/component';
|
||||
import {action} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default class ChartMembersCountInsert extends Component {
|
||||
@service dashboardStats;
|
||||
|
||||
@action
|
||||
loadCharts() {
|
||||
this.dashboardStats.loadMembersCounts();
|
||||
}
|
||||
|
||||
get totalMembers() {
|
||||
return this.dashboardStats.memberCounts?.total ?? 0;
|
||||
}
|
||||
|
||||
get paidMembers() {
|
||||
return this.dashboardStats.memberCounts?.paid ?? 0;
|
||||
}
|
||||
|
||||
get freeMembers() {
|
||||
return this.dashboardStats.memberCounts?.free ?? 0;
|
||||
}
|
||||
|
||||
get hasTrends() {
|
||||
return this.dashboardStats.memberCounts !== null && this.dashboardStats.memberCountsTrend !== null;
|
||||
}
|
||||
|
||||
get totalMembersTrend() {
|
||||
return this.calculatePercentage(this.dashboardStats.memberCountsTrend.total, this.dashboardStats.memberCounts.total);
|
||||
}
|
||||
|
||||
get paidMembersTrend() {
|
||||
return this.calculatePercentage(this.dashboardStats.memberCountsTrend.paid, this.dashboardStats.memberCounts.paid);
|
||||
}
|
||||
|
||||
get freeMembersTrend() {
|
||||
return this.calculatePercentage(this.dashboardStats.memberCountsTrend.free, this.dashboardStats.memberCounts.free);
|
||||
}
|
||||
|
||||
calculatePercentage(from, to) {
|
||||
if (from === 0) {
|
||||
if (to > 0) {
|
||||
return 100;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.round((to - from) / from * 100);
|
||||
}
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
<h4
|
||||
class="gh-dashboard5-metric is-main"
|
||||
<div class="gh-dashboard5-number"
|
||||
{{did-insert this.loadCharts}}
|
||||
{{did-update this.loadCharts @days}}
|
||||
>
|
||||
Monthly revenue (MMR)
|
||||
</h4>
|
||||
>$32</div>
|
||||
<small class="gh-dashboard5-info">Monthly revenue (MMR)</small>
|
||||
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
|
@ -32,22 +32,77 @@ export default class ChartMonthlyRevenue extends Component {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: data,
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: '#F5FBFF',
|
||||
backgroundColor: '#F5FBFF',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
borderColor: '#14b8ff',
|
||||
tension: 0.1
|
||||
borderJoinStyle: 'miter',
|
||||
maxBarThickness: 20,
|
||||
minBarLength: 2
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
return {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
autoSkip: true,
|
||||
maxRotation: 0,
|
||||
minRotation: 0
|
||||
},
|
||||
type: 'time',
|
||||
time: {
|
||||
displayFormats: {
|
||||
'millisecond': 'MMM DD',
|
||||
'second': 'MMM DD',
|
||||
'minute': 'MMM DD',
|
||||
'hour': 'MMM DD',
|
||||
'day': 'MMM DD',
|
||||
'week': 'MMM DD',
|
||||
'month': 'MMM DD',
|
||||
'quarter': 'MMM DD',
|
||||
'year': 'MMM DD',
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
>
|
||||
Paid members
|
||||
</h4>
|
||||
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
|
@ -34,22 +34,75 @@ export default class ChartPaidMembers extends Component {
|
||||
datasets: [
|
||||
{
|
||||
data: newData,
|
||||
fill: false,
|
||||
fill: true,
|
||||
backgroundColor: '#14b8ff',
|
||||
tension: 0.1
|
||||
tension: 0.1,
|
||||
borderWidth: 0,
|
||||
barThickness: 10,
|
||||
minBarLength: 3
|
||||
},{
|
||||
data: canceledData,
|
||||
fill: false,
|
||||
fill: true,
|
||||
backgroundColor: '#E16262',
|
||||
tension: 0.1
|
||||
tension: 0.1,
|
||||
borderWidth: 0,
|
||||
barThickness: 10,
|
||||
minBarLength: 3
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
return {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: true,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
autoSkip: true,
|
||||
maxRotation: 0,
|
||||
minRotation: 0
|
||||
},
|
||||
type: 'time',
|
||||
time: {
|
||||
displayFormats: {
|
||||
'millisecond': 'MMM DD',
|
||||
'second': 'MMM DD',
|
||||
'minute': 'MMM DD',
|
||||
'hour': 'MMM DD',
|
||||
'day': 'MMM DD',
|
||||
'week': 'MMM DD',
|
||||
'month': 'MMM DD',
|
||||
'quarter': 'MMM DD',
|
||||
'year': 'MMM DD',
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
<h4
|
||||
{{!-- <h4
|
||||
class="gh-dashboard5-metric is-main"
|
||||
{{did-insert this.loadCharts}}
|
||||
{{did-update this.loadCharts @days}}
|
||||
>
|
||||
Total members
|
||||
</h4>
|
||||
</h4> --}}
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
<Dashboard::V5::ChartMembersCountsInsert />
|
||||
<EmberChart
|
||||
@type={{this.chartType}}
|
||||
@data={{this.chartData}}
|
||||
|
@ -32,22 +32,77 @@ export default class ChartTotalMembers extends Component {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: data,
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: '#F5FBFF',
|
||||
backgroundColor: '#F5FBFF',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
borderColor: '#14b8ff',
|
||||
tension: 0.1
|
||||
// borderJoinStyle: 'miter',
|
||||
maxBarThickness: 20,
|
||||
minBarLength: 2
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
return {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
autoSkip: true,
|
||||
maxRotation: 0,
|
||||
minRotation: 0
|
||||
},
|
||||
type: 'time',
|
||||
time: {
|
||||
displayFormats: {
|
||||
'millisecond': 'MMM DD',
|
||||
'second': 'MMM DD',
|
||||
'minute': 'MMM DD',
|
||||
'hour': 'MMM DD',
|
||||
'day': 'MMM DD',
|
||||
'week': 'MMM DD',
|
||||
'month': 'MMM DD',
|
||||
'quarter': 'MMM DD',
|
||||
'year': 'MMM DD',
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 75;
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
<h4
|
||||
class="gh-dashboard5-metric is-main"
|
||||
<div class="gh-dashboard5-number"
|
||||
{{did-insert this.loadCharts}}
|
||||
{{did-update this.loadCharts @days}}
|
||||
>
|
||||
Total paid
|
||||
</h4>
|
||||
>$999</div>
|
||||
<small class="gh-dashboard5-info">Total paid</small>
|
||||
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
|
@ -32,22 +32,77 @@ export default class ChartTotalPaid extends Component {
|
||||
labels,
|
||||
datasets: [{
|
||||
data,
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: '#F5FBFF',
|
||||
backgroundColor: '#F5FBFF',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
borderColor: '#14b8ff',
|
||||
tension: 0.1
|
||||
borderJoinStyle: 'miter',
|
||||
maxBarThickness: 20,
|
||||
minBarLength: 2
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
return {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
drawTicks: false,
|
||||
display: false,
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
autoSkip: true,
|
||||
maxRotation: 0,
|
||||
minRotation: 0
|
||||
},
|
||||
type: 'time',
|
||||
time: {
|
||||
displayFormats: {
|
||||
'millisecond': 'MMM DD',
|
||||
'second': 'MMM DD',
|
||||
'minute': 'MMM DD',
|
||||
'hour': 'MMM DD',
|
||||
'day': 'MMM DD',
|
||||
'week': 'MMM DD',
|
||||
'month': 'MMM DD',
|
||||
'quarter': 'MMM DD',
|
||||
'year': 'MMM DD',
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 100;
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
66
ghost/admin/app/components/dashboard/v5/recent-activity.hbs
Normal file
66
ghost/admin/app/components/dashboard/v5/recent-activity.hbs
Normal file
@ -0,0 +1,66 @@
|
||||
{{#if this.shouldDisplay}}
|
||||
<div class="gh-dashboard-box activity gh-list" data-test-dashboard-member-activity>
|
||||
{{!-- <li class="gh-list-row header">
|
||||
<div class="gh-list-header gh-posts-title-header">Recent Activity</div>
|
||||
</li> --}}
|
||||
<h4 class="gh-dashboard5-metric is-split">Recent activity</h4>
|
||||
<div class="content">
|
||||
{{#let (members-event-fetcher filter=(if (feature "membersActivityFeed") (members-event-filter excludeEmailEvents=true)) pageSize=5) as |eventsFetcher|}}
|
||||
{{#if eventsFetcher.isLoading}}
|
||||
Loading...
|
||||
{{/if}}
|
||||
|
||||
{{#if eventsFetcher.isError}}
|
||||
<p class="error">
|
||||
There was an error loading events
|
||||
{{#if eventsFetcher.errorMessage}}
|
||||
<code>{{eventsFetcher.errorMessage}}</code>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#unless (or eventsFetcher.isLoading eventsFetcher.isError)}}
|
||||
<div class="gh-event-timeline">
|
||||
{{#if eventsFetcher.data}}
|
||||
<ul class="gh-dashboard-activity-list">
|
||||
{{#each eventsFetcher.data as |event|}}
|
||||
{{#let (parse-member-event event) as |parsedEvent|}}
|
||||
<li class="gh-dashboard-activity-item" data-test-dashboard-member-activity-item>
|
||||
<LinkTo class="member-details" @route="member" @model="{{parsedEvent.memberId}}">
|
||||
<div class="gh-dashboard-activity-container">
|
||||
{{svg-jar parsedEvent.icon}}
|
||||
<div class="gh-dashboard-activity-detail">
|
||||
<div class="gh-dashboard-activity-name">
|
||||
{{parsedEvent.subject}}
|
||||
</div>
|
||||
<div class="gh-dashboard-activity-event">
|
||||
{{parsedEvent.action}}
|
||||
{{parsedEvent.object}}
|
||||
<span class="highlight">{{parsedEvent.info}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LinkTo>
|
||||
<span class="gh-dashboard-activity-time">{{moment-from-now parsedEvent.timestamp}}</span>
|
||||
</li>
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<div class="gh-no-data-list" data-test-no-member-activities>
|
||||
{{svg-jar "no-data-list"}}
|
||||
<span>No member activity available.</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if (feature "membersActivityFeed")}}
|
||||
<div class="footer">
|
||||
<LinkTo @route="members-activity" @query={{reset-query-params "members-activity"}}>See all activity →</LinkTo>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/let}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
23
ghost/admin/app/components/dashboard/v5/recent-activity.js
Normal file
23
ghost/admin/app/components/dashboard/v5/recent-activity.js
Normal file
@ -0,0 +1,23 @@
|
||||
import Component from '@glimmer/component';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default class RecentActivity extends Component {
|
||||
@service feature;
|
||||
@service session;
|
||||
@service settings;
|
||||
|
||||
get shouldDisplay() {
|
||||
if (this.feature.improvedOnboarding) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const isOwner = this.session.user?.isOwnerOnly;
|
||||
const hasCompletedLaunchWizard = this.settings.get('editorIsLaunchComplete');
|
||||
|
||||
if (isOwner && !hasCompletedLaunchWizard) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
|
||||
<ol class="gh-list" {{did-insert this.loadPosts}}>
|
||||
<li class="gh-list-row header">
|
||||
<h4 class="gh-dashboard5-metric is-split">Recent posts</h4>
|
||||
{{!--
|
||||
<div class="gh-list-header gh-posts-title-header">Title</div>
|
||||
<div class="gh-list-header gh-posts-sends-header">Sends</div>
|
||||
<div class="gh-list-header gh-posts-opens-header">Opens</div>
|
||||
--}}
|
||||
</li>
|
||||
{{#each this.posts as |post|}}
|
||||
<GhPostsListItem
|
||||
|
@ -1138,16 +1138,26 @@ a.gh-dashboard-container {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5 {
|
||||
max-width: 1230px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.gh-dashboard5-split {
|
||||
display: flex;
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.gh-dashboard5-split.is-third {
|
||||
grid-template-columns: 2fr 1fr;
|
||||
}
|
||||
|
||||
.gh-dashboard5-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-container {
|
||||
@ -1185,7 +1195,7 @@ a.gh-dashboard-container {
|
||||
.gh-dashboard5-number {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
font-size: 3.9rem;
|
||||
font-size: 3rem;
|
||||
line-height: 4rem;
|
||||
font-weight: 600;
|
||||
color: #15171a;
|
||||
@ -1196,7 +1206,7 @@ a.gh-dashboard-container {
|
||||
}
|
||||
|
||||
.gh-dashboard5-number.is-small {
|
||||
font-size: 2.8rem;
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric {
|
||||
@ -1215,6 +1225,35 @@ a.gh-dashboard-container {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-split {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
font-size: 1.8rem;
|
||||
text-transform: none;
|
||||
margin: 0 0 32px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-split small {
|
||||
font-size: 1.1rem;
|
||||
text-transform: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
margin: 4px 0 0 0;
|
||||
padding: 0;
|
||||
color: var(--midgrey);
|
||||
}
|
||||
|
||||
.gh-dashboard5-info {
|
||||
font-size: 1.3rem;
|
||||
text-transform: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
margin: 2px 0 0;
|
||||
padding: 0;
|
||||
color: var(--midgrey);
|
||||
}
|
||||
|
||||
.gh-dashboard5-percentage {
|
||||
flex: 0;
|
||||
background: var(--whitegrey-d1);
|
||||
@ -1256,13 +1295,17 @@ a.gh-dashboard-container {
|
||||
margin: 0 -8px 6px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email {
|
||||
.gh-dashboard5-email > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email .gh-dashboard5-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
.gh-dashboard5-email .gh-dashboard5-box {
|
||||
border-width: 1px 0 1px 1px;
|
||||
border-radius: 0;
|
||||
@ -1284,46 +1327,49 @@ a.gh-dashboard-container {
|
||||
.gh-dashboard5-email .gh-dashboard5-box:nth-child(3) {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
} */
|
||||
|
||||
.gh-dashboard5-growth {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: auto auto auto;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: auto auto;
|
||||
gap: 0;
|
||||
margin-top: -25px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(1) {
|
||||
/* .gh-dashboard5-growth .gh-dashboard5-box:nth-child(1) {
|
||||
grid-column: 1 / span 2;
|
||||
grid-row: 1;
|
||||
border-radius: 3px 3px 0 0;
|
||||
border-width: 1px;
|
||||
} */
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(1) {
|
||||
grid-column: 1 / span 2;
|
||||
grid-row: 1 / span 2;
|
||||
border-radius: 3px 0 0 0;
|
||||
border-width: 1px;
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(2) {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 1px 1px;
|
||||
grid-column: 3 / span 2;
|
||||
grid-row: 1;
|
||||
border-radius: 0 3px 0 0;
|
||||
border-width: 1px 1px 1px 0;
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(3) {
|
||||
grid-column: 2;
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
border-radius: 0;
|
||||
border-radius: 0 0 0 3px;
|
||||
border-width: 0 1px 1px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(4) {
|
||||
grid-column: 1;
|
||||
grid-row: 3;
|
||||
border-radius: 0 0 0 3px;
|
||||
border-width: 0 1px 1px 1px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-growth .gh-dashboard5-box:nth-child(5) {
|
||||
grid-column: 2;
|
||||
grid-row: 3;
|
||||
grid-column: 4;
|
||||
grid-row: 2;
|
||||
border-radius: 0 0 3px 0;
|
||||
border-width: 0 1px 1px 0;
|
||||
}
|
||||
@ -1338,4 +1384,191 @@ a.gh-dashboard-container {
|
||||
|
||||
.gh-dashboard5 .gh-offers-help {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview > .gh-dashboard5-box {
|
||||
padding: 0;
|
||||
/* min-height: 346px; */
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview .gh-dashboard5-insert {
|
||||
width: 75%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 20px 28px 0px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview .gh-dashboard5-insert .gh-dashboard5-box {
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 0 0;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview .gh-dashboard5-insert .gh-dashboard5-box:first-child {
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 0 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview .gh-dashboard5-insert .gh-dashboard5-box:last-child {
|
||||
border-radius: 0;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-overview .prototype-selection {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement > .gh-dashboard5-box {
|
||||
padding: 0;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement .gh-dashboard5-insert {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 20px 28px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement .gh-dashboard5-insert .gh-dashboard5-box {
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 0 0;
|
||||
padding: 8px 24px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-engagement .gh-dashboard5-insert .gh-dashboard5-box:last-child {
|
||||
border-left-width: 0;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-split .gh-dashboard5-engagement .gh-dashboard5-insert {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 20px 28px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.gh-dashboard5-split .gh-dashboard5-engagement .gh-dashboard5-insert .gh-dashboard5-box {
|
||||
border-radius: 0;
|
||||
border-width: 0 0 1px;
|
||||
padding: 8px 24px 24px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-split .gh-dashboard5-engagement .gh-dashboard5-insert .gh-dashboard5-box:last-child {
|
||||
border-bottom-width: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-section .prototype-selection {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-section .ember-power-select-selected-item {
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
color: #15171a;
|
||||
}
|
||||
|
||||
.gh-dashboard5 .gh-list-header {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-posts .gh-content-entry-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px !important;
|
||||
color: rgb(21, 23, 26);
|
||||
/* white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%; */
|
||||
}
|
||||
|
||||
.gh-dashboard5-posts .gh-dashboard5-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-posts .footer {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email canvas {
|
||||
border-bottom: 1px solid #ebeef0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email > .gh-dashboard5-box {
|
||||
padding: 0;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email .gh-dashboard5-insert {
|
||||
margin: 20px 28px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email .gh-dashboard5-insert .gh-dashboard5-box:nth-child(1) {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 1px 0;
|
||||
padding: 8px 24px 24px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email .gh-dashboard5-insert .gh-dashboard5-box:nth-child(2) {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
border-radius: 0;
|
||||
border-width: 0 1px 0 0;
|
||||
padding: 20px 24px 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email .gh-dashboard5-insert .gh-dashboard5-box:nth-child(3) {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / span 2;
|
||||
border-radius: 0;
|
||||
border-width: 0;
|
||||
padding: 8px 0 0 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
<section class="gh-canvas" {{scroll-top}}>
|
||||
<GhCanvasHeader class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>
|
||||
Dashboard
|
||||
</h2>
|
||||
</GhCanvasHeader>
|
||||
|
||||
{{#if (feature "dashboardV5")}}
|
||||
<Dashboard::DashboardV5 />
|
||||
<div class="gh-dashboard5">
|
||||
<GhCanvasHeader class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>
|
||||
Dashboard
|
||||
</h2>
|
||||
</GhCanvasHeader>
|
||||
<Dashboard::DashboardV5 />
|
||||
</div>
|
||||
{{else}}
|
||||
<GhCanvasHeader class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>
|
||||
Dashboard
|
||||
</h2>
|
||||
</GhCanvasHeader>
|
||||
<div class="view-container gh-dashboard">
|
||||
{{#if (and this.session.user.isOwnerOnly (not this.settings.editorIsLaunchComplete) (not (feature "improvedOnboarding")))}}
|
||||
<section class="gh-dashboard-area lw-banner">
|
||||
|
Loading…
Reference in New Issue
Block a user