From 68928b5e0739bdca581f810ecc1eda7d74198e0e Mon Sep 17 00:00:00 2001 From: Arno Kaimbacher Date: Fri, 2 Feb 2024 14:00:54 +0100 Subject: [PATCH] - HomeController.ts: addes api method for showing number of publications per month for given year - 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'); --- app/Controllers/Http/Api/HomeController.ts | 87 +++++++++++++++++++ commands/ValidateChecksum.ts | 10 ++- package-lock.json | 84 ++++++++++-------- resources/js/Components/Charts/LineChart.vue | 55 ++++++++++-- .../js/Components/Charts/chart.config.js | 2 +- resources/js/Dataset.ts | 2 +- resources/js/Pages/Dashboard.vue | 21 +++-- .../js/Pages/Submitter/Dataset/Create.vue | 56 ++++++++---- resources/js/Stores/main.ts | 16 ++++ start/routes/api.ts | 1 + 10 files changed, 260 insertions(+), 74 deletions(-) diff --git a/app/Controllers/Http/Api/HomeController.ts b/app/Controllers/Http/Api/HomeController.ts index 6f15773..cd4c2fc 100644 --- a/app/Controllers/Http/Api/HomeController.ts +++ b/app/Controllers/Http/Api/HomeController.ts @@ -53,4 +53,91 @@ export default class HomeController { }); } } + + public async findPublicationsPerMonth({ response }: HttpContextContract) { + const serverState = 'published'; + // const year = params.year; + // const from = parseInt(year); + try { + + // const datasets = await Database.from('documents as doc') + // .select([Database.raw(`date_part('month', server_date_published) as pub_month`), Database.raw('COUNT(*) as count')]) + // .where('server_state', serverState) + // .innerJoin('link_documents_persons as ba', 'doc.id', 'ba.document_id') + // .andWhereRaw(`date_part('year', server_date_published) = ?`, [from]) + // .groupBy('pub_month'); + // // .orderBy('server_date_published'); + + const years = [2021, 2022, 2023]; // Add the second year + + const result = await Database.from('documents as doc') + .select([ + Database.raw(`date_part('year', server_date_published) as pub_year`), + Database.raw(`date_part('month', server_date_published) as pub_month`), + Database.raw('COUNT(*) as count'), + ]) + .where('server_state', serverState) + // .innerJoin('link_documents_persons as ba', 'doc.id', 'ba.document_id') + // .whereIn('pub_year', years) // Filter by both years + .whereRaw(`date_part('year', server_date_published) IN (${years.join(',')})`) // Filter by both years + .groupBy('pub_year', 'pub_month') + .orderBy('pub_year', 'asc') + .orderBy('pub_month', 'asc'); + + const labels = Array.from({ length: 12 }, (_, i) => i + 1); // Assuming 12 months + + const inputDatasets: Map = result.reduce((acc, item) => { + const { pub_year, pub_month, count } = item; + + if (!acc[pub_year]) { + acc[pub_year] = { + data: Array.from({ length: 12 }).fill(0), + label: pub_year.toString(), + borderColor: this.getRandomHexColor, // pub_year === 2022 ? '#3e95cd' : '#8e5ea2', + fill: false, + }; + } + + acc[pub_year].data[pub_month - 1] = parseInt(count); + + return acc ; + }, {}); + + const outputDatasets = Object.entries(inputDatasets).map(([year, data]) => ({ + data: data.data, + label: year, + borderColor: data.borderColor, + fill: data.fill + })); + + const data = { + labels: labels, + datasets: outputDatasets, + }; + + return response.json(data); + } catch (error) { + return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ + message: error.message || 'Some error occurred while retrieving datasets.', + }); + } + } + + private getRandomHexColor() { + const letters = '0123456789ABCDEF'; + let color = '#'; + + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)]; + } + + return color; + } +} +interface ChartDataset { + data: Array; + label: string; + borderColor: string; + fill: boolean; + } diff --git a/commands/ValidateChecksum.ts b/commands/ValidateChecksum.ts index ce25b83..beb84dc 100644 --- a/commands/ValidateChecksum.ts +++ b/commands/ValidateChecksum.ts @@ -36,8 +36,12 @@ export default class ValidateChecksum extends BaseCommand { const { default: File } = await import('App/Models/File'); // const { default: HashValue } = await (await (import ('App/Models/HashValue'))); - // query all files from database: - const files = await File.query().preload('hashvalues'); + // query all published files from database: + const files = await File.query() + .whereHas('dataset', (dQuery) => { + dQuery.where('server_state', 'published'); + }) + .preload('hashvalues'); // const logLevel = Config.get('app.logger.level', 'info'); // console.log(this.logger.) @@ -56,7 +60,7 @@ export default class ValidateChecksum extends BaseCommand { } if (hashValue['md5'] === calculatedMd5FileHash) { - Logger.info(`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`); + Logger.info(`File id ${file.id} OK: stored md5 checksum: ${calculatedMd5FileHash}, same control md5 checksum: ${hashValue['md5']}`); } else { Logger.error( `File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`, diff --git a/package-lock.json b/package-lock.json index 6b307d6..96acef8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -916,9 +916,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", + "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -4101,9 +4101,9 @@ } }, "node_modules/@types/geojson": { - "version": "7946.0.13", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.13.tgz", - "integrity": "sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==", + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", "dev": true }, "node_modules/@types/glob": { @@ -4228,9 +4228,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -6368,9 +6368,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001581", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", - "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "version": "1.0.30001583", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz", + "integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==", "dev": true, "funding": [ { @@ -7175,9 +7175,9 @@ } }, "node_modules/css-loader": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.9.1.tgz", - "integrity": "sha512-OzABOh0+26JKFdMzlK6PY1u5Zx8+Ck7CVRlcGNZoY9qwJjdfu2VWFuprTIpPW+Av5TZTVViYWcFQaEEQURLknQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", @@ -7197,7 +7197,16 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/css-minimizer-webpack-plugin": { @@ -8112,9 +8121,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.650", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.650.tgz", - "integrity": "sha512-sYSQhJCJa4aGA1wYol5cMQgekDBlbVfTRavlGZVr3WZpDdOPcp6a6xUnFfrt8TqZhsBYYbDxJZCjGfHuGupCRQ==", + "version": "1.4.655", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.655.tgz", + "integrity": "sha512-2yszojF7vIZ68adIOvzV4bku8OZad9w5H9xF3ZAMZjPuOjBarlflUkjN6DggdV+L71WZuKUfKUhov/34+G5QHg==", "dev": true }, "node_modules/emittery": { @@ -8201,9 +8210,9 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", "dev": true, "peer": true, "bin": { @@ -10195,9 +10204,9 @@ } }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -11573,9 +11582,9 @@ "integrity": "sha512-QS9p+Q20YBxpE0dJBnF6CPURP7p1GUsxnhTxTWH5nG3A1F5w8Rg3T4Xyh5UlrFSbHp88oOciVP/0agsNLhkHdQ==" }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.6", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", + "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -11850,12 +11859,13 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.7.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.7.tgz", - "integrity": "sha512-+0n11YGyRavUR3IlaOzJ0/4Il1avMvJ1VJfhWfCn24ITQXhRr1gghbhhrda6tgtNcpZaWKdSuwKq20Jb7fnlyw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.0.tgz", + "integrity": "sha512-CxmUYPFcTgET1zImteG/LZOy/4T5rTojesQXkSNBiquhydn78tfbCE9sjIjnJ/UcjNjOC1bphTCCW5rrS7cXAg==", "dev": true, "dependencies": { - "schema-utils": "^4.0.0" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { "node": ">= 12.13.0" @@ -13070,9 +13080,9 @@ } }, "node_modules/pinia/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "dev": true, "hasInstallScript": true, "bin": { @@ -17191,9 +17201,9 @@ } }, "node_modules/webpack": { - "version": "5.90.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.0.tgz", - "integrity": "sha512-bdmyXRCXeeNIePv6R6tGPyy20aUobw4Zy8r0LUS2EWO+U+Ke/gYDgsCh7bl5rB6jPpr4r0SZa6dPxBxLooDT3w==", + "version": "5.90.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", + "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==", "dev": true, "peer": true, "dependencies": { diff --git a/resources/js/Components/Charts/LineChart.vue b/resources/js/Components/Charts/LineChart.vue index 02745b3..c4bf1f5 100644 --- a/resources/js/Components/Charts/LineChart.vue +++ b/resources/js/Components/Charts/LineChart.vue @@ -1,7 +1,29 @@ -