Skip to content

Commit

Permalink
feat: add stats
Browse files Browse the repository at this point in the history
  • Loading branch information
bayang committed May 15, 2022
1 parent 7e157b3 commit 8b7368b
Show file tree
Hide file tree
Showing 13 changed files with 378 additions and 2 deletions.
27 changes: 27 additions & 0 deletions src/jelu-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/jelu-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
"@vueuse/core": "8.2.6",
"@vueuse/router": "8.2.6",
"axios": "0.26.1",
"chart.js": "^3.7.1",
"daisyui": "2.14.3",
"dayjs": "1.11.0",
"floating-vue": "^2.0.0-beta.15",
"sweetalert2": "11.4.8",
"theme-change": "^2.0.2",
"vue": "3.2.33",
"vue-avatar-sdh": "^1.0.3",
"vue-chartjs": "^4.1.0",
"vue-i18n": "^9.1.9",
"vue-router": "4.0.14",
"vuejs-sidebar-menu": "^1.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/jelu-ui/src/components/AdminBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const items = ref([{ name:t('settings.profile'), tooltip:t('settings.my_profile'
{ name:t('settings.authors'), icon:"bxs-user-account", href:"/profile/admin/authors", tooltip: t('settings.author_management') },
{ name:t('settings.imports'), icon:"bxs-file-plus", href:"/profile/imports", tooltip: t('settings.csv_import') },
{ name:t('settings.messages'), icon:"bxs-message-alt-detail", href:"/profile/messages" },
{ name:t('settings.stats'), icon:"bxs-chart", href:"/profile/stats", tooltip: t('settings.stats') },
])
if (store.getters.isAdmin) {
Expand Down
152 changes: 152 additions & 0 deletions src/jelu-ui/src/components/UserStats.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<script setup lang="ts">
import { useTitle } from '@vueuse/core';
import { BarElement, CategoryScale, Chart as ChartJS, ChartData, Legend, LinearScale, Title, Tooltip } from 'chart.js';
import dayjs from "dayjs";
import { Ref, ref, watch } from "vue";
import { Bar } from 'vue-chartjs';
import { useI18n } from 'vue-i18n';
import dataService from "../services/DataService";
const { t } = useI18n({
inheritLocale: true,
useScope: 'global'
})
useTitle('Jelu | Stats')
console.log(dayjs('2020-1-1').format('MMMM'))
console.log(dayjs('2020-3-1').format('MMMM'))
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
const getYears = () => {
dataService.yearsWithStats()
.then(res => {
years.value = res
})
.catch(e => {
console.log(e)
})
}
const getAllStats = () => {
dataService.yearStats()
.then(res => {
let labels = res.map(r => r.year)
const updatedChartData = {
labels: labels,
datasets: [
{
label: 'finished',
backgroundColor: '#bbbbbb',
data: res.map(r => r.finished)
},
{
label: 'dropped',
backgroundColor: '#f87979',
data: res.map(r => r.dropped)
}
]
}
chartData.value = { ...updatedChartData }
})
.catch(e => {
console.log(e)
})
}
const getYearStats = () => {
if (currentYear.value != null) {
dataService.monthStatsForYear(currentYear.value)
.then(res => {
let labels = res.map(r => r.month).map(m => dayjs(`2020-${m}-1`).format('MMMM'))
const updatedChartData = {
labels: labels,
datasets: [
{
label: 'finished',
backgroundColor: '#bbbbbb',
data: res.map(r => r.finished)
},
{
label: 'dropped',
backgroundColor: '#f87979',
data: res.map(r => r.dropped)
}
]
}
yearChartData.value = { ...updatedChartData }
})
.catch(e => {
console.log(e)
})
}
}
const loaded = ref(false)
const chartData = ref<ChartData<'bar'>>({
datasets: []
})
const yearChartData = ref<ChartData<'bar'>>({
datasets: []
})
const years: Ref<Array<number>> = ref([])
const currentYear: Ref<number|null> = ref(null)
watch(currentYear, (newVal, oldVal) => {
console.log("year " + newVal + " " + oldVal)
getYearStats()
})
getAllStats()
getYears()
</script>

<template>
<div class="grid grid-cols-1 justify-center justify-items-center justify-self-center">
<h1 class="text-2xl typewriter w-11/12 sm:w-8/12 pb-4 capitalize">
{{ t('stats.all_time') }}
</h1>
<div class="">
<Bar
:chart-data="chartData"
/>
</div>
<h1 class="text-2xl typewriter w-11/12 sm:w-8/12 py-4 capitalize">
{{ t('stats.yearly_stats') }}
</h1>
<div v-if="years != null && years !== undefined && years.length > 0" class="">
<select
v-model="currentYear"
class="select select-bordered select-accent pt-2 mb-4"
>
<option
disabled
selected
>
{{ t('stats.choose_year') }}
</option>
<option
v-for="year in years"
:key="year"
:value="year"
>
{{ year }}
</option>
</select>
<Bar
:chart-data="yearChartData"
/>
</div>
</div>
</template>

<style scoped>
</style>
8 changes: 7 additions & 1 deletion src/jelu-ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@
"users_management" : "Users management",
"shortcuts" : "Shortcuts",
"shortcuts_tooltip" : "Keyboard shortcuts",
"messages" : "Messages"
"messages" : "Messages",
"stats" : "Stats"
},
"user" : {
"log_first" : "Please log in first"
Expand Down Expand Up @@ -244,5 +245,10 @@
"user-messages" : {
"link" : "link",
"mark_read": "mark as read"
},
"stats" : {
"all_time" : "All time stats",
"yearly_stats" : "Yearly stats",
"choose_year" : "Choose a year"
}
}
8 changes: 7 additions & 1 deletion src/jelu-ui/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"users_management" : "gestion des utilisateurs",
"shortcuts" : "Raccourcis",
"shortcuts_tooltip" : "Raccourcis claviers",
"messages" : "Messages"
"messages" : "Messages",
"stats" : "Statistiques"
},
"user" : {
"log_first" : "Veuillez vous identifier"
Expand Down Expand Up @@ -245,5 +246,10 @@
"user-messages" : {
"link" : "lien",
"mark_read": "marquer comme lu"
},
"stats" : {
"all_time" : "Données globales",
"yearly_stats" : "Statistiques annuelles",
"choose_year" : "Choisir une année"
}
}
12 changes: 12 additions & 0 deletions src/jelu-ui/src/model/YearStats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface YearStats {
dropped: number,
finished: number,
year: number
}

export interface MonthStats {
dropped: number,
finished: number,
year: number,
month: number
}
1 change: 1 addition & 0 deletions src/jelu-ui/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const router = createRouter({
{ path: 'imports', component: () => import(/* webpackChunkName: "recommend" */ './components/Imports.vue')},
{ path: 'settings', component: () => import(/* webpackChunkName: "recommend" */ './components/UserSettings.vue')},
{ path: 'messages', component: () => import(/* webpackChunkName: "recommend" */ './components/UserMessages.vue')},
{ path: 'stats', component: () => import(/* webpackChunkName: "recommend" */ './components/UserStats.vue')},
]
},
],
Expand Down
51 changes: 51 additions & 0 deletions src/jelu-ui/src/services/DataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { LibraryFilter } from "../model/LibraryFilter";
import { WikipediaSearchResult } from "../model/WikipediaSearchResult";
import { WikipediaPageResult } from "../model/WikipediaPageResult";
import { MessageCategory, UpdateUserMessage, UserMessage } from "../model/UserMessage";
import { MonthStats, YearStats } from "../model/YearStats";

class DataService {

Expand Down Expand Up @@ -59,6 +60,8 @@ class DataService {

private API_USER_MESSAGES = '/user-messages';

private API_STATS = '/stats';

private MODE: string;

private BASE_URL: string;
Expand Down Expand Up @@ -978,6 +981,54 @@ class DataService {
}
}

yearStats = async () => {
try {
const response = await this.apiClient.get<Array<YearStats>>(`${this.API_STATS}`);
console.log("called stats")
console.log(response)
return response.data;
}
catch (error) {
if (axios.isAxiosError(error) && error.response) {
console.log("error axios " + error.response.status + " " + error.response.data.error)
}
console.log("error stats " + (error as AxiosError).code)
throw new Error("error stats " + error)
}
}

monthStatsForYear = async (year: number) => {
try {
const response = await this.apiClient.get<Array<MonthStats>>(`${this.API_STATS}/${year}`);
console.log("called stats months")
console.log(response)
return response.data;
}
catch (error) {
if (axios.isAxiosError(error) && error.response) {
console.log("error axios " + error.response.status + " " + error.response.data.error)
}
console.log("error stats months " + (error as AxiosError).code)
throw new Error("error stats months " + error)
}
}

yearsWithStats = async () => {
try {
const response = await this.apiClient.get<Array<number>>(`${this.API_STATS}/years`);
console.log("called stats years")
console.log(response)
return response.data;
}
catch (error) {
if (axios.isAxiosError(error) && error.response) {
console.log("error axios " + error.response.status + " " + error.response.data.error)
}
console.log("error stats years " + (error as AxiosError).code)
throw new Error("error stats years " + error)
}
}

}


Expand Down
Loading

0 comments on commit 8b7368b

Please sign in to comment.