Skip to content

Commit 3ee43ec

Browse files
committed
feat(charts): Add download button to save charts as png
1 parent dadcefa commit 3ee43ec

File tree

5 files changed

+119
-26
lines changed

5 files changed

+119
-26
lines changed

src/components/BarChart.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<script>
22
import { HorizontalBar } from 'vue-chartjs'
3+
import Printable from '@/mixins/Printable'
34
45
export default {
56
extends: HorizontalBar,
7+
mixins: [Printable],
68
props: {
79
chartData: {
810
type: Array | Object,
@@ -106,6 +108,10 @@
106108
}
107109
]
108110
}, this.options)
111+
112+
setTimeout(() => {
113+
this.download()
114+
}, 500)
109115
},
110116
methods: {
111117
formatNumber (num) {

src/components/Download.vue

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<template>
2+
<a
3+
:href="link"
4+
:download="name + '.png'"
5+
title="Download as PNG"
6+
class="Chart__download"
7+
>
8+
🖨
9+
</a>
10+
</template>
11+
12+
<script>
13+
export default {
14+
name: 'DownloadButton',
15+
props: {
16+
name: {
17+
type: String,
18+
default: 'chart'
19+
},
20+
link: {
21+
type: String,
22+
default: ''
23+
}
24+
}
25+
}
26+
</script>
27+
28+
<style lang="scss" scoped>
29+
@import "../assets/styles/_variables.scss";
30+
.Chart__download {
31+
cursor: pointer;
32+
border: 1px solid #f1f1f1;
33+
border-radius: rem(5);
34+
padding: rem(5);
35+
text-decoration: none;
36+
37+
&:hover {
38+
border-color: color(robin-egg-blue);
39+
}
40+
}
41+
</style>

src/components/LineChart.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<script>
22
import { Line } from 'vue-chartjs'
3+
import Printable from '@/mixins/Printable'
34
45
export default {
56
extends: Line,
7+
mixins: [Printable],
68
props: {
79
chartData: {
810
type: Array | Object,
@@ -100,6 +102,10 @@
100102
}
101103
]
102104
}, this.options)
105+
106+
setTimeout(() => {
107+
this.download()
108+
}, 500)
103109
},
104110
methods: {
105111
formatNumber (num) {

src/mixins/Printable.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
methods: {
3+
download () {
4+
let image = this.$refs.canvas.toDataURL('image/png')
5+
this.$emit('generate', image)
6+
}
7+
}
8+
}

src/pages/Start.vue

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
type="search" name="search"
1111
>
1212
<button class="Search__button" @click="requestData">Find</button>
13-
<span class="Search__icon" @click="toggleSettings()">
13+
<span class="Search__icon" @click.prevent="toggleSettings()">
1414
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 54" enable-background="new 0 0 54 54"><path d="M51.22 21h-5.052c-.812 0-1.481-.447-1.792-1.197s-.153-1.54.42-2.114l3.572-3.571c.525-.525.814-1.224.814-1.966 0-.743-.289-1.441-.814-1.967l-4.553-4.553c-1.05-1.05-2.881-1.052-3.933 0l-3.571 3.571c-.574.573-1.366.733-2.114.421-.75-.311-1.197-.98-1.197-1.792v-5.052c0-1.533-1.247-2.78-2.78-2.78h-6.44c-1.533 0-2.78 1.247-2.78 2.78v5.052c0 .812-.447 1.481-1.197 1.792-.748.313-1.54.152-2.114-.421l-3.571-3.571c-1.052-1.052-2.883-1.05-3.933 0l-4.553 4.553c-.525.525-.814 1.224-.814 1.967 0 .742.289 1.44.814 1.966l3.572 3.571c.573.574.73 1.364.42 2.114s-.98 1.197-1.792 1.197h-5.052c-1.533 0-2.78 1.247-2.78 2.78v6.439c0 1.534 1.247 2.781 2.78 2.781h5.052c.812 0 1.481.447 1.792 1.197s.153 1.54-.42 2.114l-3.572 3.571c-.525.525-.814 1.224-.814 1.966 0 .743.289 1.441.814 1.967l4.553 4.553c1.051 1.051 2.881 1.053 3.933 0l3.571-3.572c.574-.573 1.363-.731 2.114-.42.75.311 1.197.98 1.197 1.792v5.052c0 1.533 1.247 2.78 2.78 2.78h6.439c1.533 0 2.78-1.247 2.78-2.78v-5.052c0-.812.447-1.481 1.197-1.792.751-.312 1.54-.153 2.114.42l3.571 3.572c1.052 1.052 2.883 1.05 3.933 0l4.553-4.553c.525-.525.814-1.224.814-1.967 0-.742-.289-1.44-.814-1.966l-3.572-3.571c-.573-.574-.73-1.364-.42-2.114s.981-1.197 1.793-1.197h5.052c1.533 0 2.78-1.247 2.78-2.78v-6.44c0-1.533-1.247-2.78-2.78-2.78zm.78 9.22c0 .43-.35.78-.78.78h-5.052c-1.624 0-3.019.932-3.64 2.432-.622 1.5-.295 3.146.854 4.294l3.572 3.571c.305.305.305.8 0 1.104l-4.553 4.553c-.304.304-.799.306-1.104 0l-3.571-3.572c-1.149-1.149-2.794-1.474-4.294-.854-1.5.621-2.432 2.016-2.432 3.64v5.052c0 .43-.35.78-.78.78h-6.44c-.43 0-.78-.35-.78-.78v-5.052c0-1.624-.932-3.019-2.432-3.64-.503-.209-1.021-.311-1.533-.311-1.014 0-1.997.4-2.761 1.164l-3.571 3.572c-.306.306-.801.304-1.104 0l-4.553-4.553c-.305-.305-.305-.8 0-1.104l3.572-3.571c1.148-1.148 1.476-2.794.854-4.294-.621-1.499-2.016-2.431-3.64-2.431h-5.052c-.43 0-.78-.35-.78-.78v-6.44c0-.43.35-.78.78-.78h5.052c1.624 0 3.019-.932 3.64-2.432.622-1.5.295-3.146-.854-4.294l-3.572-3.571c-.305-.305-.305-.8 0-1.104l4.553-4.553c.304-.305.799-.305 1.104 0l3.571 3.571c1.147 1.147 2.792 1.476 4.294.854 1.5-.62 2.432-2.015 2.432-3.639v-5.052c0-.43.35-.78.78-.78h6.439c.431 0 .781.35.781.78v5.052c0 1.624.932 3.019 2.432 3.64 1.502.622 3.146.294 4.294-.854l3.571-3.571c.306-.305.801-.305 1.104 0l4.553 4.553c.305.305.305.8 0 1.104l-3.572 3.571c-1.148 1.148-1.476 2.794-.854 4.294.621 1.5 2.016 2.432 3.64 2.432h5.052c.43-.001.78.349.78.779v6.44zM27 18c-4.963 0-9 4.037-9 9s4.037 9 9 9 9-4.037 9-9-4.037-9-9-9zm0 16c-3.859 0-7-3.141-7-7s3.141-7 7-7 7 3.141 7 7-3.141 7-7 7z"/>
1515
</svg>
1616
</span>
@@ -39,44 +39,48 @@
3939
</div>
4040
</div>
4141

42-
<package-info :package-name="packageName" :total-downloads="totalDownloads" :period="formattedPeriod" v-if="loaded"></package-info>
42+
<package-info :package-name="packageName" :total-downloads="totalDownloads" :period="formattedPeriod" v-if="loaded"/>
4343
<div class="Chart__container" v-if="loaded">
4444
<div class="Chart__title">
45-
Downloads per Day <span>{{ formattedPeriod }}</span>
46-
<hr>
45+
<h2>Downloads per Day <span>{{ formattedPeriod }}</span></h2>
46+
<DownloadButton :name="packageName + '-daily'" :link="dailyPng"/>
4747
</div>
48+
<hr>
4849
<div class="Chart__content">
49-
<line-chart v-if="loaded" :chart-data="downloads" :chart-labels="labels"></line-chart>
50+
<line-chart chart-id="line-daily" v-if="loaded" :chart-data="downloads" :chart-labels="labels" @generate="setDailyPng"/>
5051
</div>
5152
</div>
5253

5354
<div class="Chart__container" v-if="loaded">
5455
<div class="Chart__title">
55-
Downloads per Week <span>{{ formattedPeriod }}</span>
56-
<hr>
56+
<h2>Downloads per Week <span>{{ formattedPeriod }}</span></h2>
57+
<DownloadButton :name="packageName + '-weekly'" :link="weeklyPng"/>
5758
</div>
59+
<hr>
5860
<div class="Chart__content">
59-
<line-chart v-if="loaded" :chart-data="downloadsWeek" :chart-labels="labelsWeek"></line-chart>
61+
<line-chart chart-id="line-weekly" v-if="loaded" :chart-data="downloadsWeek" :chart-labels="labelsWeek" @generate="setWeeklyPng"/>
6062
</div>
6163
</div>
6264

6365
<div class="Chart__container" v-if="loaded">
6466
<div class="Chart__title">
65-
Downloads per Month <span>{{ formattedPeriod }}</span>
66-
<hr>
67+
<h2>Downloads per Month <span>{{ formattedPeriod }}</span></h2>
68+
<DownloadButton :name="packageName + '-monthly'" :link="monthlyPng"/>
6769
</div>
70+
<hr>
6871
<div class="Chart__content">
69-
<line-chart v-if="loaded" :chart-data="downloadsMonth" :chart-labels="labelsMonth"></line-chart>
72+
<line-chart v-if="loaded" chart-id="line-monthly" :chart-data="downloadsMonth" :chart-labels="labelsMonth" @generate="setMonthlyPng"/>
7073
</div>
7174
</div>
7275

7376
<div class="Chart__container" v-if="loaded">
7477
<div class="Chart__title">
75-
Downloads per Year <span>{{ formattedPeriod }}</span>
76-
<hr>
78+
<h2>Downloads per Year <span>{{ formattedPeriod }}</span></h2>
79+
<DownloadButton :name="packageName + '-yearly'" :link="yearlyPng"/>
7780
</div>
81+
<hr>
7882
<div class="Chart__content">
79-
<bar-chart v-if="loaded" :chart-data="downloadsYear" :chart-labels="labelsYear"></bar-chart>
83+
<bar-chart v-if="loaded" chart-id="bar-yearly" :chart-data="downloadsYear" :chart-labels="labelsYear" @generate="setYearlyPng"/>
8084
</div>
8185
</div>
8286
</div>
@@ -90,6 +94,7 @@
9094
import LineChart from '@/components/LineChart'
9195
import BarChart from '@/components/BarChart'
9296
import PackageInfo from '@/components/PackageInfo'
97+
import DownloadButton from '@/components/Download'
9398
9499
import {
95100
dateToYear,
@@ -106,7 +111,8 @@
106111
LineChart,
107112
BarChart,
108113
PackageInfo,
109-
Datepicker
114+
Datepicker,
115+
DownloadButton
110116
},
111117
metaInfo () {
112118
return {
@@ -137,7 +143,11 @@
137143
periodStart: '',
138144
periodEnd: new Date(),
139145
rawData: '',
140-
totalDownloads: ''
146+
totalDownloads: '',
147+
dailyPng: null,
148+
weeklyPng: null,
149+
monthlyPng: null,
150+
yearlyPng: null
141151
}
142152
},
143153
@@ -242,6 +252,19 @@
242252
eventCategory: 'Settings',
243253
eventAction: 'toggle'
244254
})
255+
},
256+
setDailyPng (payload) {
257+
this.dailyPng = payload
258+
},
259+
setWeeklyPng (payload) {
260+
this.weeklyPng = payload
261+
console.log('weekly', payload)
262+
},
263+
setMonthlyPng (payload) {
264+
this.monthlyPng = payload
265+
},
266+
setYearlyPng (payload) {
267+
this.yearlyPng = payload
245268
}
246269
}
247270
}
@@ -261,7 +284,7 @@
261284
262285
.content {
263286
background: color(ghost-white);
264-
min-height: calc(100vh - 191px);
287+
min-height: calc(100vh - 207px);
265288
}
266289
267290
.title {
@@ -358,22 +381,31 @@
358381
.Chart__container {
359382
border-radius: $base-border-radius;
360383
background-color: #fff;
361-
box-shadow: 0 2px 7px 0 rgba(0, 0, 0, 0.2);
384+
box-shadow: 0 15px 30px 0 rgba(0,0,0,.11), 0 5px 15px 0 rgba(0,0,0,.08);
362385
padding: rem(20) rem(40);
363386
margin: rem(50) 0;
364387
}
365388
366389
.Chart__title {
367-
color: color(fjord);
368-
margin-bottom: rem(40);
369-
font-weight: 600;
370-
font-size: rem(16);
390+
display: flex;
391+
flex-direction: row;
392+
margin-bottom: rem(20);
393+
justify-content: space-between;
371394
372-
> span {
373-
font-weight: 400;
374-
color: color(robin-egg-blue);
395+
h2 {
396+
display: flex;
397+
align-items: center;
398+
color: color(fjord);
399+
margin: 0;
400+
font-weight: 600;
375401
font-size: rem(16);
376-
margin-left: rem(25);
402+
403+
> span {
404+
font-weight: 400;
405+
color: color(robin-egg-blue);
406+
font-size: rem(16);
407+
margin-left: rem(25);
408+
}
377409
}
378410
}
379411

0 commit comments

Comments
 (0)