- HomeController.ts: addes api method for showing number of publications per month for given year
All checks were successful
CI Pipeline / japa-tests (push) Successful in 50s

- adapted command ValidateChecksum.ts: on published files are checked. better information logging
- better LineChart.vue component: showing real statistics
- start/routes/apu.ts: added Route.get('/statistic/:year', 'HomeController.findPublicationsPerMonth');
This commit is contained in:
Kaimbacher 2024-02-02 14:00:54 +01:00
parent 8cef7390d7
commit 68928b5e07
10 changed files with 260 additions and 74 deletions

View file

@ -1,7 +1,29 @@
<script setup>
<script lang="ts" setup>
import { ref, watch, computed, onMounted } from 'vue';
import { Chart, LineElement, PointElement, LineController, LinearScale, CategoryScale, Tooltip } from 'chart.js';
import { Chart, LineElement, PointElement, LineController, LinearScale, CategoryScale, Tooltip, registerables } from 'chart.js';
import { Ref } from 'vue';
import { ChartDataCustomTypesPerDataset } from 'chart.js';
// interface Dataset {
// borderColor: string;
// // borderDash:
// // (0) []
// borderDashOffset: number;
// borderWidth: number;
// cubicInterpolationMode: string;
// data: Array<number>;
// fill: boolean;
// pointBackgroundColor: string;
// pointBorderColor: string;
// pointBorderWidth: number;
// pointHoverBackgroundColor: string;
// pointHoverBorderWidth: number;
// pointHoverRadius: number;
// pointRadius: number;
// tension: number;
// }
const props = defineProps({
data: {
type: Object,
@ -9,16 +31,38 @@ const props = defineProps({
},
});
const root = ref(null);
const root: Ref<HTMLCanvasElement | null> = ref<HTMLCanvasElement | null>(null);
let chart;
Chart.register(LineElement, PointElement, LineController, LinearScale, CategoryScale, Tooltip);
onMounted(() => {
Chart.register(...registerables);
// https://gitea.geologie.ac.at/kaiarn/geomon.viewer/src/branch/master/src/common/graphjs/geomon-timeseries-chart/geomon-timeseries-chart.component.ts
chart = new Chart(root.value, {
type: 'line',
data: props.data,
data: props.data as ChartDataCustomTypesPerDataset<"line", number[], string>,
// data: {
// labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
// // labels: [],
// datasets: [
// {
// data: [86, 114, 106, 106, 107, 111, 133, 221, 783, 2478, 2600, 2700],
// label: "Africa",
// borderColor: "#3e95cd",
// fill: false
// }, {
// data: [282, 350, 411, 502, 635, 809, 947, 1402, 3700, 5267, 444, 555],
// label: "Asia",
// borderColor: "#8e5ea2",
// fill: false
// }
// ]
// },
options: {
responsive: true,
maintainAspectRatio: false,
@ -32,11 +76,12 @@ onMounted(() => {
},
plugins: {
legend: {
display: false,
display: true,
},
},
},
});
});
const chartData = computed(() => props.data);

View file

@ -36,7 +36,7 @@ const datasetObject = (color, points) => {
};
};
export const sampleChartData = (points = 9) => {
export const sampleChartData = (points = 12) => {
const labels = [];
for (let i = 1; i <= points; i++) {

View file

@ -34,7 +34,7 @@ export interface Dataset {
| Array<DatasetReference>
| Array<File>
| (Array<number> | Array<Object>);
language: Ref<string>;
language: string;
licenses: Array<number> | Array<Object>;
rights: boolean;
type: string;

View file

@ -14,7 +14,7 @@ import {
mdiChartPie,
} from '@mdi/js';
// import { containerMaxW } from '@/config.js'; // "xl:max-w-6xl xl:mx-auto"
import * as chartConfig from '@/Components/Charts/chart.config.js';
// import * as chartConfig from '@/Components/Charts/chart.config.js';
import LineChart from '@/Components/Charts/LineChart.vue';
import SectionMain from '@/Components/SectionMain.vue';
import CardBoxWidget from '@/Components/CardBoxWidget.vue';
@ -27,14 +27,19 @@ import CardBoxClient from '@/Components/CardBoxClient.vue';
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
import SectionBannerStarOnGitHub from '@/Components/SectionBannerStarOnGitea.vue';
const chartData = ref();
const fillChartData = () => {
chartData.value = chartConfig.sampleChartData();
const mainService = MainService()
// const chartData = ref();
const fillChartData = async () => {
await mainService.fetchChartData(2022);
// chartData.value = chartConfig.sampleChartData();
// chartData.value = mainService.graphData;
};
onMounted(() => {
fillChartData();
const chartData = computed(() => mainService.graphData);
onMounted(async () => {
await mainService.fetchChartData(2022);
});
const mainService = MainService();
;
/* Fetch sample data */
mainService.fetch('clients');
mainService.fetch('history');
@ -131,7 +136,7 @@ const datasets = computed(() => mainService.datasets);
<SectionBannerStarOnGitHub />
<SectionTitleLineWithButton :icon="mdiChartPie" title="Trends overview (to do publications per year)" />
<SectionTitleLineWithButton :icon="mdiChartPie" title="Trends overview: Publications per month" />
<CardBox title="Performance" :icon="mdiFinance" :header-icon="mdiReload" class="mb-6" @header-icon-click="fillChartData">
<div v-if="chartData">
<line-chart :data="chartData" class="h-96" />

View file

@ -110,13 +110,13 @@ let dataset: Dataset;
if (Object.keys(mainService.dataset).length == 0) {
// language = ref('');
dataset = {
language: language,
language: language.value,
licenses: [],
rights: false,
type: '',
creating_corporation: 'Tethys RDR',
titles: [{ value: '', type: 'Main', language: language }],
descriptions: [{ value: '', type: 'Abstract', language: language }],
titles: [{ value: '', type: 'Main', language: language.value }],
descriptions: [{ value: '', type: 'Abstract', language: language.value }],
authors: [],
contributors: [],
project_id: undefined,
@ -150,11 +150,11 @@ if (Object.keys(mainService.dataset).length == 0) {
// mainService.setDataset(dataset, language);
} else {
// console.log(mainService.dataset);
language = ref(mainService.dataset.language);
language.value = mainService.dataset.language;
// dataset = mainService.dataset;
dataset = {
language: language,
language: mainService.dataset.language,
licenses: mainService.dataset.licenses,
rights: mainService.dataset.rights,
type: mainService.dataset.type,
@ -171,20 +171,23 @@ if (Object.keys(mainService.dataset).length == 0) {
files: mainService.dataset.files,
// upload: mainService.dataset.upload,
};
for (let index in mainService.dataset.titles) {
let title: Title = mainService.dataset.titles[index];
if (title.type == 'Main') {
title.language = language;
}
}
for (let index in mainService.dataset.descriptions) {
let description: Description = mainService.dataset.descriptions[index];
if (description.type == 'Abstract') {
description.language = language;
}
}
// for (let index in mainService.dataset.titles) {
// let title: Title = mainService.dataset.titles[index];
// if (title.type == 'Main') {
// title.language = language;
// }
// }
// for (let index in mainService.dataset.descriptions) {
// let description: Description = mainService.dataset.descriptions[index];
// if (description.type == 'Abstract') {
// description.language = language;
// }
// }
}
// const form = useForm<Dataset>({
// language: language,
// licenses: [],
@ -205,6 +208,21 @@ let form = useForm<Dataset>(dataset as Dataset);
// },
// });
watch(language, (currentValue) => {
if (currentValue != "") {
form.language = currentValue;
const mainTitle = form.titles?.find((title) => title.type === 'Main');
if (mainTitle) {
mainTitle.language = currentValue;
}
const mainAbstract = form.descriptions?.find((desc) => desc.type === 'Abstract');
if (mainAbstract) {
mainAbstract.language = currentValue;
}
mainService.setDataset(form.data());
}
});
let elevation = ref('no_elevation');
watch(elevation, (currentValue) => {
if (currentValue == 'absolut') {
@ -297,7 +315,7 @@ const submit = async () => {
// formStep.value++;
await form
.transform((data) => ({
...data,
...data,
files: files,
rights: form.rights && form.rights == true ? 'true' : 'false',
}))
@ -498,7 +516,7 @@ Removes a selected keyword
<div class="flex flex-col md:flex-row">
<FormField label="Language *" help="required: select dataset main language"
:class="{ 'text-red-400': errors.language }" class="w-full mx-2 flex-1">
<FormControl required v-model="form.language" :type="'select'"
<FormControl required v-model="language" :type="'select'"
placeholder="[Enter Language]" :errors="form.errors.language"
:options="{ de: 'de', en: 'en' }">
<div class="text-red-400 text-sm" v-if="form.errors.language">

View file

@ -67,6 +67,8 @@ export const MainService = defineStore('main', {
menu: menu,
totpState: 0,
graphData: {},
}),
actions: {
// payload = authenticated user
@ -165,6 +167,20 @@ export const MainService = defineStore('main', {
this.totpState = state;
},
async fetchChartData(year) {
// sampleDataKey= authors or datasets
axios
.get(`/api/statistic/${year}`)
.then((r) => {
if (r.data) {
this.graphData = r.data;
}
})
.catch((error) => {
alert(error.message);
});
},
// fetchfiles(id) {
// // sampleDataKey= authors or datasets
// axios