mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-25 09:03:12 +03:00
Moved the new dashboard over to a CSS Grid layout and cleaned up a ton of the code
refs: https://github.com/TryGhost/Team/issues/1507 - changed the layout over to use css grids instead of the random flex and divs - cleaned up the based dashboard-v5 file so its rendering much cleaner components - refactored and took out a ton of old css that wasn't needed anymore - moved the dashboard-v5 css into it's own css file to keep things cleaner - includes a few stylistic changes along the way
This commit is contained in:
parent
1b89416064
commit
e4891e3462
@ -1,50 +1,35 @@
|
||||
<section {{did-insert this.onInsert}}>
|
||||
<section class="gh-dashboard5-layout" {{did-insert this.onInsert}}>
|
||||
{{#if this.isLoading }}
|
||||
<GhLoadingSpinner />
|
||||
{{else}}
|
||||
{{#if this.areMembersEnabled}}
|
||||
<Dashboard::V5::Charts::Anchor
|
||||
@days={{this.days}}
|
||||
@onDaysChange={{this.onDaysChange}}
|
||||
@daysOptions={{this.daysOptions}}
|
||||
@selected={{this.selectedDaysOption}}
|
||||
/>
|
||||
<Dashboard::V5::Charts::Anchor />
|
||||
|
||||
{{!-- Could these if else statements be cleaned up more? --}}
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<section class="gh-dashboard5-split">
|
||||
<section class="gh-dashboard5-split">
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::Email />
|
||||
</section>
|
||||
</section>
|
||||
<Dashboard::V5::Charts:EmailOpenRate />
|
||||
</section>
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::Email />
|
||||
<Dashboard::V5::Charts::EmailOpenRate />
|
||||
{{else}}
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<section class="gh-dashboard5-split">
|
||||
<section class="gh-dashboard5-split">
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::Email />
|
||||
</section>
|
||||
</section>
|
||||
<Dashboard::V5::Charts:EmailOpenRate />
|
||||
</section>
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::Email />
|
||||
<Dashboard::V5::Charts::EmailOpenRate />
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<section class="gh-dashboard5-split">
|
||||
<Dashboard::V5::Charts::RecentPosts />
|
||||
<Dashboard::V5::Charts::RecentActivity />
|
||||
</section>
|
||||
|
||||
<Dashboard::V5::Charts::RecentPosts />
|
||||
<Dashboard::V5::Charts::RecentActivity />
|
||||
<Dashboard::V5::Resources::Help />
|
||||
|
||||
|
||||
{{!-- <Dashboard::V5::Resources::WhatsNew /> --}}
|
||||
{{!-- <Dashboard::V5::Resources::LatestNewsletters /> --}}
|
||||
{{!-- <Dashboard::V5::Resources::StaffPicks /> --}}
|
||||
{{/if}}
|
||||
|
||||
<Dashboard::V5::Prototype::ControlPanel />
|
||||
</section>
|
||||
|
||||
<Dashboard::V5::Prototype::ControlPanel />
|
@ -2,42 +2,14 @@ import Component from '@glimmer/component';
|
||||
import {action} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
const DAYS_OPTIONS = [{
|
||||
name: '7 Days',
|
||||
value: 7
|
||||
}, {
|
||||
name: '30 Days',
|
||||
value: 30
|
||||
}, {
|
||||
name: '90 Days',
|
||||
value: 90
|
||||
}, {
|
||||
name: 'All Time',
|
||||
value: 'all'
|
||||
}];
|
||||
|
||||
export default class DashboardDashboardV5Component extends Component {
|
||||
@service dashboardStats;
|
||||
|
||||
daysOptions = DAYS_OPTIONS;
|
||||
|
||||
get days() {
|
||||
return this.dashboardStats.chartDays;
|
||||
}
|
||||
|
||||
set days(days) {
|
||||
this.dashboardStats.chartDays = days;
|
||||
}
|
||||
|
||||
@action
|
||||
onInsert() {
|
||||
this.dashboardStats.loadSiteStatus();
|
||||
}
|
||||
|
||||
get selectedDaysOption() {
|
||||
return this.daysOptions.find(d => d.value === this.days);
|
||||
}
|
||||
|
||||
get isLoading() {
|
||||
return this.dashboardStats.siteStatus === null;
|
||||
}
|
||||
@ -53,9 +25,4 @@ export default class DashboardDashboardV5Component extends Component {
|
||||
get areMembersEnabled() {
|
||||
return this.dashboardStats.siteStatus?.membersEnabled;
|
||||
}
|
||||
|
||||
@action
|
||||
onDaysChange(selected) {
|
||||
this.days = selected.value;
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +1,67 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-anchor">
|
||||
<article class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-chart">
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-chart-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
<div class="gh-dashboard5-chart-container">
|
||||
<EmberChart
|
||||
@type={{this.chartType}}
|
||||
@data={{this.chartData}}
|
||||
@options={{this.chartOptions}}
|
||||
@height={{this.chartHeight}} />
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-stats{{unless this.hasPaidTiers ' is-solo'}}" {{did-insert this.loadCharts}}>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingTotal 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "total")}}>
|
||||
<div class="gh-dashboard5-hero {{unless this.hasPaidTiers 'is-solo'}}">
|
||||
{{#unless this.hasPaidTiers}}
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label={{gh-pluralize this.totalMembers "Total member" without-count=true}}
|
||||
@value={{format-number this.totalMembers}}
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.totalMembersTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
{{/unless}}
|
||||
|
||||
<div class="gh-dashboard5-chart">
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-chart-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
<div class="gh-dashboard5-chart-container">
|
||||
<EmberChart
|
||||
@type={{this.chartType}}
|
||||
@data={{this.chartData}}
|
||||
@options={{this.chartOptions}}
|
||||
@height={{if this.hasPaidTiers this.chartHeight this.chartHeightSmall}} />
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if this.hasPaidTiers}}
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingPaid 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "paid")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label={{gh-pluralize this.paidMembers "Paid member" without-count=true}}
|
||||
@value={{format-number this.paidMembers}}
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.paidMembersTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingMonthly 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "monthly")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="MRR"
|
||||
@value="${{gh-price-amount this.currentMRR}}"
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.mrrTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<div class="gh-dashboard5-stats{{unless this.hasPaidTiers ' is-solo'}}" {{did-insert this.loadCharts}}>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingTotal 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "total")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label={{gh-pluralize this.totalMembers "Total member" without-count=true}}
|
||||
@value={{format-number this.totalMembers}}
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.totalMembersTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingPaid 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "paid")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label={{gh-pluralize this.paidMembers "Total paid member" without-count=true}}
|
||||
@value={{format-number this.paidMembers}}
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.paidMembersTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingMonthly 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "monthly")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="MRR"
|
||||
@value="${{gh-price-amount this.currentMRR}}"
|
||||
@trends={{this.hasTrends}}
|
||||
@percentage={{this.mrrTrend}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-selections">
|
||||
<div class="gh-dashboard5-selects">
|
||||
{{#if this.chartShowingPaid}}
|
||||
<div class="prototype-selection">
|
||||
<div class="gh-dashboard5-select">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedPaidOption}}
|
||||
@options={{this.paidOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{this.paidOptionsChange}}
|
||||
@onChange={{this.onPaidChange}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@ -61,12 +72,12 @@
|
||||
</PowerSelect>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="prototype-selection">
|
||||
<div class="gh-dashboard5-select">
|
||||
<PowerSelect
|
||||
@selected={{@selected}}
|
||||
@options={{@daysOptions}}
|
||||
@selected={{this.selectedDaysOption}}
|
||||
@options={{this.daysOptions}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{@onDaysChange}}
|
||||
@onChange={{this.onDaysChange}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
|
@ -6,11 +6,25 @@ import {tracked} from '@glimmer/tracking';
|
||||
|
||||
const DATE_FORMAT = 'D MMM YYYY';
|
||||
|
||||
const DAYS_OPTIONS = [{
|
||||
name: '7 Days',
|
||||
value: 7
|
||||
}, {
|
||||
name: '30 Days',
|
||||
value: 30
|
||||
}, {
|
||||
name: '90 Days',
|
||||
value: 90
|
||||
}, {
|
||||
name: 'All Time',
|
||||
value: 'all'
|
||||
}];
|
||||
|
||||
const PAID_OPTIONS = [{
|
||||
name: 'Paid total',
|
||||
name: 'Total Paid Members',
|
||||
value: 'paid'
|
||||
}, {
|
||||
name: 'Paid breakdown',
|
||||
name: 'Paid Members By Day',
|
||||
value: 'breakdown'
|
||||
}];
|
||||
|
||||
@ -19,8 +33,22 @@ export default class Anchor extends Component {
|
||||
@tracked chartDisplay = 'total';
|
||||
@tracked paidOptionSelected = 'paid';
|
||||
|
||||
daysOptions = DAYS_OPTIONS;
|
||||
paidOptions = PAID_OPTIONS;
|
||||
|
||||
get days() {
|
||||
return this.dashboardStats.chartDays;
|
||||
}
|
||||
|
||||
set days(days) {
|
||||
this.dashboardStats.chartDays = days;
|
||||
}
|
||||
|
||||
@action
|
||||
onInsert() {
|
||||
this.dashboardStats.loadSiteStatus();
|
||||
}
|
||||
|
||||
@action
|
||||
loadCharts() {
|
||||
this.dashboardStats.loadMemberCountStats();
|
||||
@ -34,11 +62,20 @@ export default class Anchor extends Component {
|
||||
}
|
||||
|
||||
@action
|
||||
paidOptionsChange(selected) {
|
||||
onPaidChange(selected) {
|
||||
this.paidOptionSelected = selected.value;
|
||||
this.changeChartDisplay(selected.value);
|
||||
}
|
||||
|
||||
@action
|
||||
onDaysChange(selected) {
|
||||
this.days = selected.value;
|
||||
}
|
||||
|
||||
get selectedDaysOption() {
|
||||
return this.daysOptions.find(d => d.value === this.days);
|
||||
}
|
||||
|
||||
get selectedPaidOption() {
|
||||
return this.paidOptions.find(d => d.value === this.paidOptionSelected);
|
||||
}
|
||||
@ -413,7 +450,11 @@ export default class Anchor extends Component {
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 325;
|
||||
return 300;
|
||||
}
|
||||
|
||||
get chartHeightSmall() {
|
||||
return 250;
|
||||
}
|
||||
|
||||
calculatePercentage(from, to) {
|
||||
|
@ -1,29 +1,27 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-rate">
|
||||
<section class="gh-dashboard5-section gh-dashboard5-email-open-rate">
|
||||
<article class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-insert">
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Open rate"
|
||||
@value="{{this.currentOpenRate}}%" />
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Email open rate"
|
||||
@value="{{this.currentOpenRate}}%" />
|
||||
|
||||
<div class="gh-dashboard5-chart">
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-chart-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
<div class="gh-dashboard5-chart-ticks">
|
||||
<span>100%</span>
|
||||
<span>75%</span>
|
||||
<span>50%</span>
|
||||
<span>25%</span>
|
||||
</div>
|
||||
<div class="gh-dashboard5-chart-container">
|
||||
<EmberChart
|
||||
@type={{this.chartType}}
|
||||
@data={{this.chartData}}
|
||||
@options={{this.chartOptions}}
|
||||
@height={{this.chartHeight}} />
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard5-chart">
|
||||
{{#if this.loading}}
|
||||
<div class="gh-dashboard5-chart-loading" style={{html-safe (concat "height: " this.chartHeight "px;")}}/>
|
||||
{{else}}
|
||||
<div class="gh-dashboard5-chart-ticks">
|
||||
<span>100%</span>
|
||||
<span>75%</span>
|
||||
<span>50%</span>
|
||||
<span>25%</span>
|
||||
</div>
|
||||
<div class="gh-dashboard5-chart-container">
|
||||
<EmberChart
|
||||
@type={{this.chartType}}
|
||||
@data={{this.chartData}}
|
||||
@options={{this.chartOptions}}
|
||||
@height={{this.chartHeight}} />
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
@ -1,13 +1,13 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-email">
|
||||
<article class="gh-dashboard5-box">
|
||||
<div {{did-insert this.loadCharts}} class="gh-dashboard5-insert">
|
||||
<div class="gh-dashboard5-insert-item">
|
||||
<div {{did-insert this.loadCharts}} class="gh-dashboard5-rows">
|
||||
<div class="gh-dashboard5-row">
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Newsletter subscribers"
|
||||
@value={{format-number this.dataSubscribers.total}} />
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-insert-item">
|
||||
<div class="gh-dashboard5-row">
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Emails sent over last 30 days"
|
||||
@value={{format-number this.dataEmailsSent}} />
|
||||
|
@ -1,13 +1,13 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-engagement">
|
||||
<article {{did-insert this.loadCharts}} class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-insert">
|
||||
<div class="gh-dashboard5-insert-item">
|
||||
<div class="gh-dashboard5-rows">
|
||||
<div class="gh-dashboard5-row">
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Engaged over 30 days"
|
||||
@value={{this.data30Days}}
|
||||
/>
|
||||
</div>
|
||||
<div class="gh-dashboard5-insert-item">
|
||||
<div class="gh-dashboard5-row">
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Engaged over 7 days"
|
||||
@value={{this.data7Days}}
|
||||
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="prototype-selection">
|
||||
<div class="gh-dashboard5-select">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedStatusOption}}
|
||||
@options={{this.statusOptions}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-activity">
|
||||
<section class="gh-dashboard5-section gh-dashboard5-recent-activity">
|
||||
<article class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-list" data-test-dashboard-member-activity>
|
||||
<div class="gh-dashboard5-list-header">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<section class="gh-dashboard5-section gh-dashboard5-posts">
|
||||
<section class="gh-dashboard5-section gh-dashboard5-recent-posts">
|
||||
<article class="gh-dashboard5-box">
|
||||
<div class="gh-dashboard5-list" {{did-insert this.loadPosts}}>
|
||||
<div class="gh-dashboard5-list-header">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="gh-main-section prototype-panel" {{did-insert this.onInsert}}>
|
||||
<div class="gh-main-section prototype-control-panel" {{did-insert this.onInsert}}>
|
||||
<h4 class="gh-main-section-header small bn">Prototype control panel</h4>
|
||||
|
||||
<div class="gh-expandable">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="gh-main-section gh-members-help">
|
||||
<div class="gh-main-section gh-members-help gh-dashboard5-help">
|
||||
<div class="gh-main-section-block">
|
||||
<div class="gh-main-section-content grey">
|
||||
<a href="https://ghost.org/resources/build-audience-subscriber-signups/" target="_blank" class="gh-members-help-card" rel="noopener noreferrer">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div
|
||||
class="dashboard-prototype-newsletters"
|
||||
class="dashboard-prototype-newsletters gh-dashboard5-latest-newsletters"
|
||||
{{did-insert this.load}}
|
||||
>
|
||||
{{#if (not (or this.loading this.error))}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="gh-dashboard5-list" {{did-insert this.load}}>
|
||||
<div class="gh-dashboard5-list gh-dashboard5-staff-picks" {{did-insert this.load}}>
|
||||
{{#if (not (or this.loading this.error))}}
|
||||
<div class="gh-dashboard5-title">
|
||||
<h4>Staff picks</h4>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div {{did-insert this.load}}>
|
||||
<div class="gh-dashboard5-whats-new" {{did-insert this.load}}>
|
||||
{{#if (not (or this.loading this.error))}}
|
||||
<div class="gh-dashboard-box whats-new {{if this.whatsNew.hasNew "has-new"}}">
|
||||
<div class="gh-dashboard-header-container">
|
||||
|
@ -69,6 +69,7 @@
|
||||
@import "layouts/fullscreen-wizard.css";
|
||||
@import "layouts/post-preview.css";
|
||||
@import "layouts/dashboard.css";
|
||||
@import "layouts/dashboard-v5.css";
|
||||
@import "layouts/products.css";
|
||||
@import "layouts/offers.css";
|
||||
|
||||
|
@ -69,6 +69,7 @@
|
||||
@import "layouts/fullscreen-wizard.css";
|
||||
@import "layouts/post-preview.css";
|
||||
@import "layouts/dashboard.css";
|
||||
@import "layouts/dashboard-v5.css";
|
||||
@import "layouts/products.css";
|
||||
@import "layouts/offers.css"
|
||||
|
||||
|
680
ghost/admin/app/styles/layouts/dashboard-v5.css
Normal file
680
ghost/admin/app/styles/layouts/dashboard-v5.css
Normal file
@ -0,0 +1,680 @@
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Prototype */
|
||||
|
||||
.prototype-control-panel {
|
||||
margin-top: 50vh; /* Keep it out of view */
|
||||
}
|
||||
|
||||
.prototype-states-buttons {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.prototype-paid-mix-dropdown {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.prototype-counts {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.prototype-section {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.prototype-section > h2 {
|
||||
font-size: 1.65rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.4em;
|
||||
margin-bottom: 8px;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.prototype-counts.col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.prototype-counts > * {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.prototype-box {
|
||||
border: 1px solid var(--whitegrey);
|
||||
padding: 28px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.prototype-box .number {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Layout */
|
||||
|
||||
.gh-dashboard5 {
|
||||
max-width: 1230px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.gh-dashboard5-layout {
|
||||
display: grid;
|
||||
grid-gap: 32px;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: auto auto auto auto;
|
||||
grid-template-areas:
|
||||
"anchor anchor anchor anchor"
|
||||
"engagement email email-open-rate email-open-rate"
|
||||
"recent-posts recent-posts recent-activity recent-activity"
|
||||
"help help help help";
|
||||
}
|
||||
|
||||
.gh-dashboard5-rows {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gh-dashboard5-row {
|
||||
flex: 1;
|
||||
padding: 4px 0 16px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.gh-dashboard5-row:last-child {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-section {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.gh-dashboard5-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-title h4 {
|
||||
margin: 0 16px 0 0;
|
||||
font-size: 1.65rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.4em;
|
||||
color: #15171a;
|
||||
}
|
||||
|
||||
.gh-dashboard5-box {
|
||||
flex: 1;
|
||||
border: 1px solid var(--whitegrey);
|
||||
padding: 24px;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-hero {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-hero.is-solo .gh-dashboard5-metric {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.gh-dashboard5 .gh-members-help {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-selects {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
right: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.gh-dashboard5-select {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-selects .gh-dashboard5-select {
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.gh-dashboard5-select .ember-power-select-selected-item {
|
||||
font-size: 1.2rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
letter-spacing: .3px;
|
||||
line-height: 1em;
|
||||
padding: 0;
|
||||
color: var(--midlightgrey);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Chart */
|
||||
|
||||
.gh-dashboard5-chart {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.gh-dashboard5-chart-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-chart-ticks {
|
||||
flex: none;
|
||||
padding: 8px 24px 16px 0;
|
||||
font-size: 1.2rem;
|
||||
text-transform: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: .2px;
|
||||
color: var(--midgrey);
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.gh-dashboard5-chart-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
width: 100%; /* hack for ChartJS responsive resizing */
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Percentage */
|
||||
|
||||
.gh-dashboard5-percentage {
|
||||
flex: 0;
|
||||
background: var(--whitegrey-d1);
|
||||
border-radius: 3px;
|
||||
font-size: 1.2rem;
|
||||
line-height: 1;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0;
|
||||
color: var(--midgrey);
|
||||
padding: 2px 4px;
|
||||
margin: 5px 0 3px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-percentage.is-positive {
|
||||
background: color-mod(var(--green) a(13%));
|
||||
color: color-mod(var(--green) l(-5%));
|
||||
}
|
||||
|
||||
.gh-dashboard5-percentage.is-negative {
|
||||
background: color-mod(var(--yellow) a(20%));
|
||||
color: color-mod(var(--yellow) l(-8%));
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Metric */
|
||||
|
||||
.gh-dashboard5-metric {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-stretch {
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric-label {
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
letter-spacing: .3px;
|
||||
line-height: 1em;
|
||||
margin: 0 0 14px;
|
||||
padding: 0;
|
||||
color: var(--midgrey);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-large .gh-dashboard5-metric-label {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-reverse .gh-dashboard5-metric-label {
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-center .gh-dashboard5-metric-label {
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric-value {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
font-size: 2.8rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: -.1px;
|
||||
line-height: 1em;
|
||||
white-space: nowrap;
|
||||
margin: 0 0 8px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-large .gh-dashboard5-metric-value {
|
||||
font-size: 3.6rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-center .gh-dashboard5-metric-value {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric.is-reverse.is-large .gh-dashboard5-metric-value {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-metric-extra {
|
||||
text-transform: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: .2px;
|
||||
color: var(--midlightgrey);
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 List */
|
||||
|
||||
.gh-dashboard5-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-header {
|
||||
display: grid;
|
||||
grid-template-columns: 65% 20% 15%;
|
||||
padding: 0 0 24px;
|
||||
border-bottom: 1px solid var(--whitegrey);
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-title {
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
letter-spacing: .3px;
|
||||
line-height: 1em;
|
||||
padding: 0;
|
||||
color: #7c8b9a;
|
||||
white-space: nowrap;
|
||||
padding: 0 24px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item {
|
||||
padding: 14px 0;
|
||||
display: grid;
|
||||
grid-template-columns: 65% 20% 15%;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid var(--whitegrey);
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-list-item {
|
||||
grid-template-columns: 80% 20%;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item:nth-child(3) {
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item > span {
|
||||
padding: 0 24px 4px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item a {
|
||||
font-weight: 500;
|
||||
font-size: 1.5rem;
|
||||
color: var(--darkgrey);
|
||||
padding: 0 64px 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item > span {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item svg {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin: 0 0.75rem 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-item > a > span {
|
||||
color: var(--midgrey);
|
||||
padding: 0 0 0 0.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gh-dashboard5-list-footer {
|
||||
border-top: 1px solid var(--whitegrey);
|
||||
padding: 20px 0 0;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Anchor */
|
||||
|
||||
.gh-dashboard5-anchor {
|
||||
grid-area: anchor;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-box {
|
||||
padding: 24px 24px 8px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: calc(100% + 48px);
|
||||
padding: 0 8px;
|
||||
margin: 12px -24px 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-title {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor.is-top .gh-dashboard5-stats {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats-button {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 20px 16px 24px 12px;
|
||||
margin: 2px 4px 2px 2px;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected {
|
||||
color: var(--black);
|
||||
background: var(--white) !important;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 3%);
|
||||
border: 1px solid var(--whitegrey);
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats.is-solo .gh-dashboard5-stats-button.is-selected {
|
||||
background: transparent;
|
||||
box-shadow: 0 none;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats-highlight {
|
||||
width: 1px;
|
||||
height: 3px;
|
||||
border-radius: 5px;
|
||||
background: var(--whitegrey);
|
||||
margin: 8px 0 0;
|
||||
background: #5B98F2;
|
||||
opacity: 0;
|
||||
transition: width 175ms ease-out, opacity 125ms linear;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected .gh-dashboard5-stats-highlight {
|
||||
width: 25px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-chart {
|
||||
flex-direction: column;
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks {
|
||||
flex-direction: row;
|
||||
padding: 12px 0 4px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span:first-child,
|
||||
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span:last-child {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Email */
|
||||
|
||||
.gh-dashboard5-email {
|
||||
grid-area: email;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Engagement */
|
||||
|
||||
.gh-dashboard5-engagement {
|
||||
grid-area: engagement;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Recent Posts */
|
||||
|
||||
.gh-dashboard5-recent-posts {
|
||||
grid-area: recent-posts;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-box {
|
||||
padding: 28px 24px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-title {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-list-item {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-list-item:nth-child(4),
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-list-item:nth-child(5) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-list-item a > span{
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
color: var(--darkgrey);
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-dashboard5-list-item a > span {
|
||||
display: inline-block;
|
||||
height: 57px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .gh-content-entry-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px !important;
|
||||
color: rgb(21, 23, 26);
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-posts .footer {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Recent Activity */
|
||||
|
||||
.gh-dashboard5-recent-activity {
|
||||
grid-area: recent-activity;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-box {
|
||||
padding: 28px 24px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-list-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px 0;
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-list-item .member-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-list-item .member-avatar {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #70DEB1;
|
||||
border-radius: 24px;
|
||||
margin: 0 12px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-recent-activity .gh-dashboard5-list-item > span.gh-dashboard-activity-time {
|
||||
font-size: 1.2rem;
|
||||
color: var(--midlightgrey);
|
||||
text-align: right;
|
||||
padding-right: 0;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Email Open Rate */
|
||||
|
||||
.gh-dashboard5-email-open-rate {
|
||||
grid-area: email-open-rate;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email-open-rate .gh-dashboard5-chart {
|
||||
margin: 24px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email-open-rate .gh-dashboard5-chart-ticks {
|
||||
padding: 0 16px 0 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5-email-open-rate .gh-dashboard5-metric-label {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Section Help */
|
||||
|
||||
.gh-dashboard5-help {
|
||||
grid-area: help;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
Dashboard v5 Misc */
|
||||
|
||||
.gh-dashboard5 .gh-offers-help {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gh-dashboard5 .gh-list-header {
|
||||
border-bottom: 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user