2020-06-06 20:03:55 +02:00
|
|
|
<template>
|
|
|
|
<section class="dashboard content">
|
|
|
|
<header class="columns">
|
|
|
|
<div class="column is-two-thirds">
|
|
|
|
<h1 class="title is-5">{{ dayjs().format("ddd, DD MMM") }}</h1>
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
|
2020-07-04 18:55:02 +02:00
|
|
|
<section class="counts wrap-small">
|
|
|
|
<div class="tile is-ancestor">
|
|
|
|
<div class="tile is-vertical is-12">
|
|
|
|
<div class="tile">
|
|
|
|
<div class="tile is-parent is-vertical">
|
|
|
|
<b-loading v-if="isCountsLoading" active :is-full-page="false" />
|
|
|
|
<article class="tile is-child notification">
|
|
|
|
<div class="columns is-mobile">
|
|
|
|
<div class="column is-6">
|
|
|
|
<p class="title">{{ $utils.niceNumber(counts.lists.total) }}</p>
|
|
|
|
<p class="is-size-6 has-text-grey">Lists</p>
|
|
|
|
</div>
|
|
|
|
<div class="column is-6">
|
|
|
|
<ul class="no is-size-7 has-text-grey">
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.lists.public) }}</label> public
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.lists.private) }}</label> private
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.lists.optinSingle) }}</label>
|
|
|
|
single opt-in
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.lists.optinDouble) }}</label>
|
|
|
|
double opt-in</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article><!-- lists -->
|
|
|
|
|
|
|
|
<article class="tile is-child notification">
|
|
|
|
<div class="columns is-mobile">
|
|
|
|
<div class="column is-6">
|
|
|
|
<p class="title">{{ $utils.niceNumber(counts.campaigns.total) }}</p>
|
|
|
|
<p class="is-size-6 has-text-grey">Campaigns</p>
|
|
|
|
</div>
|
|
|
|
<div class="column is-6">
|
|
|
|
<ul class="no is-size-7 has-text-grey">
|
|
|
|
<li v-for="(num, status) in counts.campaigns.byStatus" :key="status">
|
|
|
|
<label>{{ num }}</label> {{ status }}
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article><!-- campaigns -->
|
|
|
|
</div><!-- block -->
|
|
|
|
|
|
|
|
<div class="tile is-parent">
|
|
|
|
<b-loading v-if="isCountsLoading" active :is-full-page="false" />
|
|
|
|
<article class="tile is-child notification">
|
|
|
|
<div class="columns is-mobile">
|
|
|
|
<div class="column is-6">
|
|
|
|
<p class="title">{{ $utils.niceNumber(counts.subscribers.total) }}</p>
|
|
|
|
<p class="is-size-6 has-text-grey">Subscribers</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="column is-6">
|
|
|
|
<ul class="no is-size-7 has-text-grey">
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.subscribers.blacklisted) }}</label>
|
|
|
|
blacklisted
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>{{ $utils.niceNumber(counts.subscribers.orphans) }}</label>
|
|
|
|
orphans
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div><!-- subscriber breakdown -->
|
|
|
|
</div><!-- subscriber columns -->
|
|
|
|
<hr />
|
|
|
|
<div class="columns">
|
|
|
|
<div class="column is-6">
|
|
|
|
<p class="title">{{ $utils.niceNumber(counts.messages) }}</p>
|
|
|
|
<p class="is-size-6 has-text-grey">Messages sent</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article><!-- subscribers -->
|
2020-06-06 20:03:55 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2020-07-04 18:55:02 +02:00
|
|
|
<div class="tile is-parent">
|
|
|
|
<b-loading v-if="isChartsLoading" active :is-full-page="false" />
|
|
|
|
<article class="tile is-child notification charts">
|
|
|
|
<div class="columns">
|
|
|
|
<div class="column is-6">
|
|
|
|
<h3 class="title is-size-6 has-text-right">Campaign views</h3>
|
|
|
|
<vue-c3 v-if="chartViewsInst" :handler="chartViewsInst"></vue-c3>
|
|
|
|
<empty-placeholder v-else-if="!isChartsLoading" />
|
|
|
|
</div>
|
|
|
|
<div class="column is-6">
|
|
|
|
<h3 class="title is-size-6 has-text-right">Link clicks</h3>
|
|
|
|
<vue-c3 v-if="chartClicksInst" :handler="chartClicksInst"></vue-c3>
|
|
|
|
<empty-placeholder v-else-if="!isChartsLoading" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article>
|
2020-06-06 20:03:55 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2020-07-04 18:55:02 +02:00
|
|
|
</div><!-- tile block -->
|
|
|
|
</section>
|
2020-06-06 20:03:55 +02:00
|
|
|
</section>
|
|
|
|
</template>
|
|
|
|
|
2020-07-04 18:55:02 +02:00
|
|
|
|
|
|
|
<style lang="css">
|
|
|
|
@import "~c3/c3.css";
|
|
|
|
</style>
|
|
|
|
|
2020-06-06 20:03:55 +02:00
|
|
|
<script>
|
|
|
|
import Vue from 'vue';
|
2020-07-04 18:55:02 +02:00
|
|
|
import VueC3 from 'vue-c3';
|
2020-06-06 20:03:55 +02:00
|
|
|
import dayjs from 'dayjs';
|
2020-07-04 18:55:02 +02:00
|
|
|
import { colors } from '../constants';
|
|
|
|
import EmptyPlaceholder from '../components/EmptyPlaceholder.vue';
|
2020-06-06 20:03:55 +02:00
|
|
|
|
|
|
|
export default Vue.extend({
|
2020-07-04 18:55:02 +02:00
|
|
|
components: {
|
|
|
|
EmptyPlaceholder,
|
|
|
|
VueC3,
|
|
|
|
},
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
// Unique Vue() instances for each chart.
|
|
|
|
chartViewsInst: null,
|
|
|
|
chartClicksInst: null,
|
|
|
|
|
|
|
|
isChartsLoading: true,
|
|
|
|
isCountsLoading: true,
|
|
|
|
|
|
|
|
counts: {
|
|
|
|
lists: {},
|
|
|
|
subscribers: {},
|
|
|
|
campaigns: {},
|
|
|
|
messages: 0,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
makeChart(label, data) {
|
|
|
|
const conf = {
|
|
|
|
data: {
|
|
|
|
columns: [
|
|
|
|
[label, ...data.map((d) => d.count).reverse()],
|
|
|
|
],
|
|
|
|
type: 'spline',
|
|
|
|
color() {
|
|
|
|
return colors.primary;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
axis: {
|
|
|
|
x: {
|
|
|
|
type: 'category',
|
|
|
|
categories: data.map((d) => dayjs(d.date).format('DD MMM')).reverse(),
|
|
|
|
tick: {
|
|
|
|
rotate: -45,
|
|
|
|
multiline: false,
|
|
|
|
culling: { max: 10 },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
legend: {
|
|
|
|
show: false,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
return conf;
|
|
|
|
},
|
|
|
|
},
|
2020-06-06 20:03:55 +02:00
|
|
|
|
|
|
|
computed: {
|
|
|
|
dayjs() {
|
|
|
|
return dayjs;
|
|
|
|
},
|
|
|
|
},
|
2020-07-04 18:55:02 +02:00
|
|
|
|
|
|
|
mounted() {
|
|
|
|
// Pull the counts.
|
|
|
|
this.$api.getDashboardCounts().then((r) => {
|
|
|
|
this.counts = r.data;
|
|
|
|
this.isCountsLoading = false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Pull the charts.
|
|
|
|
this.$api.getDashboardCharts().then((r) => {
|
|
|
|
this.isChartsLoading = false;
|
|
|
|
|
|
|
|
// vue-c3 lib requires unique instances of Vue() to communicate.
|
|
|
|
if (r.data.campaignViews.length > 0) {
|
|
|
|
this.chartViewsInst = this;
|
|
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.chartViewsInst.$emit('init',
|
|
|
|
this.makeChart('Campaign views', r.data.campaignViews));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r.data.linkClicks.length > 0) {
|
|
|
|
this.chartClicksInst = new Vue();
|
|
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.chartClicksInst.$emit('init',
|
|
|
|
this.makeChart('Link clicks', r.data.linkClicks));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2020-06-06 20:03:55 +02:00
|
|
|
});
|
|
|
|
</script>
|