Adds start year input to report charts #483

This commit is contained in:
mateuswetah 2021-03-31 11:54:10 -03:00
parent 52dd5b6485
commit c565f0a0cb
7 changed files with 146 additions and 73 deletions

View File

@ -34,7 +34,8 @@
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; } flex-wrap: wrap; }
#tainacan-reports-app .postbox .box-header .box-header__item { #tainacan-reports-app .postbox .box-header .box-header__item {
margin-bottom: 10px; } margin-bottom: 10px;
line-height: 2rem; }
#tainacan-reports-app .graph-mode-switch { #tainacan-reports-app .graph-mode-switch {
display: inline-block; } display: inline-block; }
#tainacan-reports-app .graph-mode-switch button { #tainacan-reports-app .graph-mode-switch button {

View File

@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "AAAA,qBAAsB;EAClB,OAAO,EAAE,iBAAiB;EAC1B,MAAM,EAAE,CAAC;EAGT,4CAAuB;IACnB,OAAO,EAAE,GAAG;EAGhB,6BAAQ;IACJ,MAAM,EAAE,OAAO;EAGnB,wCAAmB;IACf,aAAa,EAAE,IAAI;EAGvB,8BAAS;IACL,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,UAAU;IACvB,eAAe,EAAE,MAAM;IAEvB,sCAAQ;MACJ,SAAS,EAAE,IAAI;MACf,OAAO,EAAE,CAAC;MAEV,+CAAS;QACL,MAAM,EAAE,OAAO;EAK3B,8BAAS;IACL,OAAO,EAAE,gBAAgB;IACzB,aAAa,EAAE,CAAC;IAChB,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,KAAK;IACjB,gBAAgB,EAAE,oCAAoC;IAEtD,oCAAM;MACF,WAAW,EAAE,IAAI;MACjB,SAAS,EAAE,QAAQ;IAEvB,wDAA4B;MACxB,MAAM,EAAE,iCAAiC;MACzC,UAAU,EAAE,IAAI;IAGpB,0CAAY;MACR,OAAO,EAAE,IAAI;MACb,WAAW,EAAE,QAAQ;MACrB,eAAe,EAAE,aAAa;MAC9B,SAAS,EAAE,IAAI;MAEf,4DAAkB;QACd,aAAa,EAAE,IAAI;EAI/B,wCAAmB;IACf,OAAO,EAAE,YAAY;IACrB,+CAAO;MACH,MAAM,EAAE,eAAe;MACvB,UAAU,EAAE,eAAe;MAC3B,UAAU,EAAE,eAAe;MAC3B,OAAO,EAAE,CAAC;MACV,MAAM,EAAE,OAAO;MAEf,uDAAU;QACN,KAAK,EAAE,oCAAoC", "mappings": "AAAA,qBAAsB;EAClB,OAAO,EAAE,iBAAiB;EAC1B,MAAM,EAAE,CAAC;EAGT,4CAAuB;IACnB,OAAO,EAAE,GAAG;EAGhB,6BAAQ;IACJ,MAAM,EAAE,OAAO;EAGnB,wCAAmB;IACf,aAAa,EAAE,IAAI;EAGvB,8BAAS;IACL,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,UAAU;IACvB,eAAe,EAAE,MAAM;IAEvB,sCAAQ;MACJ,SAAS,EAAE,IAAI;MACf,OAAO,EAAE,CAAC;MAEV,+CAAS;QACL,MAAM,EAAE,OAAO;EAK3B,8BAAS;IACL,OAAO,EAAE,gBAAgB;IACzB,aAAa,EAAE,CAAC;IAChB,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,KAAK;IACjB,gBAAgB,EAAE,oCAAoC;IAEtD,oCAAM;MACF,WAAW,EAAE,IAAI;MACjB,SAAS,EAAE,QAAQ;IAEvB,wDAA4B;MACxB,MAAM,EAAE,iCAAiC;MACzC,UAAU,EAAE,IAAI;IAGpB,0CAAY;MACR,OAAO,EAAE,IAAI;MACb,WAAW,EAAE,QAAQ;MACrB,eAAe,EAAE,aAAa;MAC9B,SAAS,EAAE,IAAI;MAEf,4DAAkB;QACd,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,IAAI;EAI7B,wCAAmB;IACf,OAAO,EAAE,YAAY;IACrB,+CAAO;MACH,MAAM,EAAE,eAAe;MACvB,UAAU,EAAE,eAAe;MAC3B,UAAU,EAAE,eAAe;MAC3B,OAAO,EAAE,CAAC;MACV,MAAM,EAAE,OAAO;MAEf,uDAAU;QACN,KAAK,EAAE,oCAAoC",
"sources": ["../../views/reports/tainacan-reports.scss"], "sources": ["../../views/reports/tainacan-reports.scss"],
"names": [], "names": [],
"file": "tainacan-reports.css" "file": "tainacan-reports.css"

View File

@ -111,14 +111,20 @@ export const fetchTaxonomyTerms = ({ commit }, taxonomyId) => {
}); });
}; };
export const fetchActivities = ({ commit }, { collectionId } ) => { export const fetchActivities = ({ commit }, { collectionId, startDate, force } ) => {
let endpoint = '/reports'; let endpoint = '/reports';
if (collectionId && collectionId != 'default') if (collectionId && collectionId != 'default')
endpoint += '/collection/' + collectionId + '/activities'; endpoint += '/collection/' + collectionId + '/activities?';
else else
endpoint += '/activities'; endpoint += '/activities?';
if (startDate)
endpoint += '&start=' + startDate;
if (startDate || force)
endpoint += '&force=yes';
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios.tainacan.get(endpoint) axios.tainacan.get(endpoint)

View File

@ -1,48 +1,87 @@
<template> <template>
<div> <div>
<div <div
v-if="!isFetchingData && chartData && !isBuildingChart && !isFetchingUsers" :class="{ 'skeleton': isFetchingData || !chartData || isBuildingChart || isFetchingUsers }"
class="postbox"> class="postbox">
<div class="users-charts columns is-multiline"> <div class="box-header">
<div <div
class="users-charts__card column is-one-third is-half-desktop" v-if="currentStart && currentEnd"
v-for="(chartSeries, index) of chartSeriesByUser" class="box-header__item tablenav-pages">
:key="index"> <label>
<div {{ $i18n.get('label_activities_last_year') }}&nbsp;
v-if="chartSeries[0].userId == 0" </label>
class="users-charts__card--header"> <span class="pagination-links">
<div class="anonymous-user-avatar" /> <span
<div class="users-charts__card--header-text"> @click="(!isBuildingChart && currentStart.getFullYear() > minYear) ? decreaseYear() : null"
<p>{{ $i18n.get('label_anonymous_user') }}</p> :class="{'tablenav-pages-navspan disabled' : isBuildingChart || currentStart.getFullYear() <= minYear}"
<span>{{ chartSeries[0].total }}</span> class="prev-page button"
</div> aria-hidden="true">
</div>
<div </span>
v-if="chartSeries[0].userId != 0 && users[chartSeries[0].userId]" <input
class="users-charts__card--header"> type="number"
<img :src="users[chartSeries[0].userId].avatar_urls['48']"> step="1"
<div class="users-charts__card--header-text"> :min="minYear"
<p>{{ users[chartSeries[0].userId].name }}</p> :max="maxYear"
<span>{{ chartSeries[0].total }}</span> class="screen-per-page"
</div> name="start_year"
</div> id="start_year"
<apexchart maxlength="6"
type="area" :disabled="isBuildingChart"
height="160" :value="currentStart.getFullYear()"
:series="chartSeries" @input="($event) => setStartYear($event.target.value)">
:options="chartOptionsByUser[index]" /> <span
@click="(!isBuildingChart && currentStart.getFullYear() <= maxYear) ? increaseYear() : null"
:class="{ 'tablenav-pages-navspan disabled': isBuildingChart || currentStart.getFullYear() > maxYear}"
aria-hidden="true"
class="next-page button">
</span>
<span class="paging-input">
{{ currentStart.toDateString() }} - {{ currentEnd.toDateString() }}
</span>
</span>
</div> </div>
</div> </div>
<apexchart <template v-if="!isFetchingData && chartData && !isBuildingChart && !isFetchingUsers">
type="area" <div class="users-charts columns is-multiline">
height="200" <div
:series="chartSeries" class="users-charts__card column is-one-third is-half-desktop"
:options="chartOptions" /> v-for="(chartSeries, index) of chartSeriesByUser"
:key="index">
<div
v-if="chartSeries[0].userId == 0"
class="users-charts__card--header">
<div class="anonymous-user-avatar" />
<div class="users-charts__card--header-text">
<p>{{ $i18n.get('label_anonymous_user') }}</p>
<span>{{ chartSeries[0].total }}</span>
</div>
</div>
<div
v-if="chartSeries[0].userId != 0 && users[chartSeries[0].userId]"
class="users-charts__card--header">
<img :src="users[chartSeries[0].userId].avatar_urls['48']">
<div class="users-charts__card--header-text">
<p>{{ users[chartSeries[0].userId].name }}</p>
<span>{{ chartSeries[0].total }}</span>
</div>
</div>
<apexchart
type="area"
height="160"
:series="chartSeries"
:options="chartOptionsByUser[index]" />
</div>
</div>
<apexchart
type="area"
height="200"
:series="chartSeries"
:options="chartOptions" />
</template>
</div> </div>
<div
v-else
style="min-height=740px"
class="skeleton postbox" />
</div> </div>
</template> </template>
@ -57,7 +96,11 @@ export default {
isFetchingUsers: false, isFetchingUsers: false,
users: {}, users: {},
chartSeriesByUser: [], chartSeriesByUser: [],
chartOptionsByUser: [] chartOptionsByUser: [],
maxYear: new Date().getFullYear() + 1,
minYear: 2018,
currentStart: '',
currentEnd: ''
} }
}, },
computed: { computed: {
@ -72,7 +115,7 @@ export default {
this.buildActivitiesChart(); this.buildActivitiesChart();
}, },
immediate: true immediate: true
} },
}, },
created() { created() {
this.isFetchingUsers = true; this.isFetchingUsers = true;
@ -91,16 +134,33 @@ export default {
...mapActions('activity', { ...mapActions('activity', {
fetchUsers: 'fetchUsers', fetchUsers: 'fetchUsers',
}), }),
increaseYear() {
this.setStartYear(this.currentEnd.getFullYear());
},
decreaseYear() {
let currentStartDate = new Date(this.currentStart.getTime());
this.setStartYear(new Date(currentStartDate.setFullYear(currentStartDate.getFullYear() - 1)).getFullYear());
},
setStartYear(newStartYear) {
let currentStartDate = new Date(this.currentStart.getTime());
const newStart = new Date(currentStartDate.setFullYear(newStartYear));
this.$emit('time-range-update', newStart.toISOString());
},
buildActivitiesChart() { buildActivitiesChart() {
this.isBuildingChart = true; this.isBuildingChart = true;
const daysWithActivities = (this.chartData.totals.by_interval && this.chartData.totals.by_interval.general) ? this.chartData.totals.by_interval.general : []; const daysWithActivities = (this.chartData.totals.by_interval && this.chartData.totals.by_interval.general) ? this.chartData.totals.by_interval.general : [];
const startDate = new Date(this.chartData.totals.by_interval.start).getTime(); this.currentStart = new Date(this.chartData.totals.by_interval.start);
const endDate = new Date(this.chartData.totals.by_interval.end).getTime(); this.currentEnd = new Date(this.chartData.totals.by_interval.end);
this.chartSeries = [{ if (daysWithActivities.length)
data: [] this.chartSeries = [{
}]; name: this.$i18n.get('activities'),
data: []
}];
else
this.chartSeries = [];
let maximumOfActivitiesInADay = 0; let maximumOfActivitiesInADay = 0;
daysWithActivities.forEach((activity) => { daysWithActivities.forEach((activity) => {
@ -115,7 +175,10 @@ export default {
this.chartOptions = { this.chartOptions = {
...this.areaChartOptions, ...this.areaChartOptions,
title: { title: {
text: this.$i18n.get('label_activities_last_year') text: ''
},
noData: {
text: daysWithActivities.length ? this.$i18n.get('label_loading_report') : this.$i18n.get('info_no_activities')
}, },
chart: { chart: {
id: 'generalchart', id: 'generalchart',
@ -136,10 +199,11 @@ export default {
}, },
xaxis: { xaxis: {
type: 'datetime', type: 'datetime',
min: startDate, min: this.currentStart.getTime(),
max: endDate max: this.currentEnd.getTime()
}, },
yaxis: { yaxis: {
show: daysWithActivities.length,
max: maximumOfActivitiesInADay, max: maximumOfActivitiesInADay,
tickAmount: 4, tickAmount: 4,
labels: { labels: {
@ -148,9 +212,11 @@ export default {
}, },
colors: ['#01295c'], colors: ['#01295c'],
}; };
console.log(this.chartSeries, this.chartOptions, this.currentStart, this.currentEnd);
const daysWithActivitiesByUser = JSON.parse(JSON.stringify(this.chartData.totals.by_interval.by_user)).sort((a, b) => parseInt(b.total) - parseInt(a.total)); const daysWithActivitiesByUser = JSON.parse(JSON.stringify(this.chartData.totals.by_interval.by_user)).sort((a, b) => parseInt(b.total) - parseInt(a.total));
this.chartSeriesByUser = [];
this.chartOptionsByUser = []
daysWithActivitiesByUser.forEach((daysWithActivityByUser) => { daysWithActivitiesByUser.forEach((daysWithActivityByUser) => {
this.chartSeriesByUser.push([{ this.chartSeriesByUser.push([{
total: daysWithActivityByUser.total, total: daysWithActivityByUser.total,
@ -186,8 +252,8 @@ export default {
}, },
xaxis: { xaxis: {
type: 'datetime', type: 'datetime',
min: startDate, min: this.currentStart.getTime(),
max: endDate max: this.currentEnd.getTime()
}, },
yaxis: { yaxis: {
max: maximumOfActivitiesInADay, max: maximumOfActivitiesInADay,
@ -208,9 +274,16 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.postbox { .postbox {
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column;
justify-content: flex-start;
min-height: 280px !important;
.screen-per-page {
width: 6em;
}
} }
.users-charts { .users-charts {
order: 3;
padding: 12px; padding: 12px;
.users-charts__card { .users-charts__card {

View File

@ -1,6 +1,8 @@
<template> <template>
<div v-if="taxonomiesList != undefined"> <div v-if="taxonomiesList != undefined">
<div class="postbox"> <div
:class="{ 'skeleton': isFetchingData || isBuildingChart || isFetchingTaxonomyTerms || !selectedTaxonomy || !selectedTaxonomy.id }"
class="postbox">
<div class="box-header"> <div class="box-header">
<div class="box-header__item"> <div class="box-header__item">
<label <label
@ -99,10 +101,6 @@
height="380px" height="380px"
:series="chartSeries" :series="chartSeries"
:options="chartOptions" /> :options="chartOptions" />
<div
v-else
style="min-height=380px"
class="skeleton postbox" />
</div> </div>
</div> </div>
</template> </template>

View File

@ -85,17 +85,11 @@
:chart-data="metadata" :chart-data="metadata"
:is-fetching-data="isFetchingMetadata" :is-fetching-data="isFetchingMetadata"
v-if="!isRepositoryLevel"/> v-if="!isRepositoryLevel"/>
</div>
<div class="columns">
<metadata-list-block
class="column is-full"
:chart-data="metadataList"
v-if="!isRepositoryLevel" />
<activities-block <activities-block
class="column is-full" class="column is-full"
:chart-data="activities" :chart-data="activities"
:is-fetching-data="isFetchingActivities" :is-fetching-data="isFetchingActivities"
v-if="isRepositoryLevel" /> @time-range-update="loadActivities" />
</div> </div>
</div> </div>
</template> </template>
@ -141,10 +135,10 @@ export default {
this.loadMetadata(); this.loadMetadata();
this.loadActivities(); this.loadActivities();
if (this.isRepositoryLevel) if (this.isRepositoryLevel) {
this.loadCollectionsList(); this.loadCollectionsList();
this.loadTaxonomiesList(); this.loadTaxonomiesList();
}
}, },
immediate: true immediate: true
} }
@ -197,9 +191,9 @@ export default {
.then(() => this.isFetchingTaxonomiesList = false) .then(() => this.isFetchingTaxonomiesList = false)
.catch(() => this.isFetchingTaxonomiesList = false); .catch(() => this.isFetchingTaxonomiesList = false);
}, },
loadActivities() { loadActivities(startDate) {
this.isFetchingActivities = true; this.isFetchingActivities = true;
this.fetchActivities({ collectionId: this.selectedCollection }) this.fetchActivities({ collectionId: this.selectedCollection, startDate: startDate })
.then(() => this.isFetchingActivities = false) .then(() => this.isFetchingActivities = false)
.catch(() => this.isFetchingActivities = false); .catch(() => this.isFetchingActivities = false);
} }

View File

@ -54,6 +54,7 @@
.box-header__item { .box-header__item {
margin-bottom: 10px; margin-bottom: 10px;
line-height: 2rem;
} }
} }
} }