From 60d2fdff6de91665439b456cac48b7ab78062f1b Mon Sep 17 00:00:00 2001 From: Ionys320 <9364594+Ionys320@users.noreply.github.com> Date: Sat, 18 May 2024 00:26:46 +0200 Subject: [PATCH 1/8] feat(metrics): Implementing metrics into the status page --- package-lock.json | 62 +++++++++++++++++++- package.json | 5 +- resources/js/cachet.js | 10 +++- resources/views/components/metric.blade.php | 47 +++++++++++++++ resources/views/components/metrics.blade.php | 56 ++++++++++++++++++ resources/views/status-page/index.blade.php | 2 + src/View/Components/Metrics.php | 57 ++++++++++++++++++ 7 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 resources/views/components/metric.blade.php create mode 100644 resources/views/components/metrics.blade.php create mode 100644 src/View/Components/Metrics.php diff --git a/package-lock.json b/package-lock.json index 8b2e3012..6966958e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,10 @@ "@alpinejs/collapse": "^3.13.3", "@alpinejs/focus": "^3.13.3", "@alpinejs/ui": "^3.13.3-beta.4", - "alpinejs": "^3.13.3" + "alpinejs": "^3.13.3", + "chart.js": "^4.4.2", + "chartjs-adapter-moment": "^1.0.1", + "moment": "^2.30.1" }, "devDependencies": { "@alpinejs/anchor": "^3.13.3", @@ -304,6 +307,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1058,6 +1066,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz", + "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/chartjs-adapter-moment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz", + "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==", + "peerDependencies": { + "chart.js": ">=3.0.0", + "moment": "^2.10.2" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2590,6 +2618,14 @@ "node": "*" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4151,6 +4187,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4776,6 +4817,20 @@ "supports-color": "^7.1.0" } }, + "chart.js": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz", + "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==", + "requires": { + "@kurkle/color": "^0.3.0" + } + }, + "chartjs-adapter-moment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz", + "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==", + "requires": {} + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -5831,6 +5886,11 @@ "brace-expansion": "^1.1.7" } }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index 5e227ea2..61a028e5 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "@alpinejs/collapse": "^3.13.3", "@alpinejs/focus": "^3.13.3", "@alpinejs/ui": "^3.13.3-beta.4", - "alpinejs": "^3.13.3" + "alpinejs": "^3.13.3", + "chart.js": "^4.4.2", + "chartjs-adapter-moment": "^1.0.1", + "moment": "^2.30.1" } } diff --git a/resources/js/cachet.js b/resources/js/cachet.js index 50005015..31e976f5 100644 --- a/resources/js/cachet.js +++ b/resources/js/cachet.js @@ -1,3 +1,7 @@ +import 'moment'; +import Chart from 'chart.js/auto' +import 'chartjs-adapter-moment'; + import Alpine from 'alpinejs' import Anchor from '@alpinejs/anchor' @@ -5,9 +9,13 @@ import Collapse from '@alpinejs/collapse' import Focus from '@alpinejs/focus' import Ui from '@alpinejs/ui' +Chart.defaults.color = '#fff'; +window.Chart = Chart + Alpine.plugin(Anchor) Alpine.plugin(Collapse) Alpine.plugin(Focus) Alpine.plugin(Ui) -Alpine.start() +window.Alpine = Alpine +Alpine.start() \ No newline at end of file diff --git a/resources/views/components/metric.blade.php b/resources/views/components/metric.blade.php new file mode 100644 index 00000000..14aca1e9 --- /dev/null +++ b/resources/views/components/metric.blade.php @@ -0,0 +1,47 @@ +@props([ +'metric', +]) + +
+
+
+
{{ $metric->name }}
+ +
+ +
+ +

{{ $metric->description }}

+
+
+ + + +
+ +
+
+ + \ No newline at end of file diff --git a/resources/views/components/metrics.blade.php b/resources/views/components/metrics.blade.php new file mode 100644 index 00000000..b7975faa --- /dev/null +++ b/resources/views/components/metrics.blade.php @@ -0,0 +1,56 @@ + + +
+ @foreach($metrics as $metric) + + + @endforeach +
\ No newline at end of file diff --git a/resources/views/status-page/index.blade.php b/resources/views/status-page/index.blade.php index 5fef4e98..ca96ff1f 100644 --- a/resources/views/status-page/index.blade.php +++ b/resources/views/status-page/index.blade.php @@ -14,6 +14,8 @@ @endforeach + + @if($schedules->isNotEmpty()) @endif diff --git a/src/View/Components/Metrics.php b/src/View/Components/Metrics.php new file mode 100644 index 00000000..77c95efc --- /dev/null +++ b/src/View/Components/Metrics.php @@ -0,0 +1,57 @@ +subDays(30); + + $metrics = $this->metrics($startDate); + + // Convert each metric point to Chart.js format (x, y) + $metrics->each(function ($metric) { + $metric->metricPoints->transform(function ($point) { + return [ + 'x' => $point->created_at->toIso8601String(), + 'y' => $point->value, + ]; + }); + }); + + return view('cachet::components.metrics', [ + 'metrics' => $metrics + ]); + } + + /** + * Fetch the available metrics and their points. + */ + private function metrics(Carbon $startDate): Collection + { + return Metric::query() + ->with([ + 'metricPoints' => fn ($query) => $query->orderBy('created_at'), + ]) + ->where('visible', '>=', !auth()->check()) + ->whereHas('metricPoints', function (Builder $query) use ($startDate) { + $query->where('created_at', '>=', $startDate); + }) + ->orderBy('places', 'asc') + ->get(); + } +} From 3a131576f3254f862f5411856d8cc2967c012a04 Mon Sep 17 00:00:00 2001 From: Ionys320 <9364594+Ionys320@users.noreply.github.com> Date: Sat, 18 May 2024 00:38:14 +0200 Subject: [PATCH 2/8] fix(metric): Fix datasets' label (use the `suffix` instead of `name`) --- resources/views/components/metrics.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/metrics.blade.php b/resources/views/components/metrics.blade.php index b7975faa..be47d812 100644 --- a/resources/views/components/metrics.blade.php +++ b/resources/views/components/metrics.blade.php @@ -25,7 +25,7 @@ function init() { type: 'line', data: { datasets: [{ - label: this.metric.name, + label: this.metric.suffix, data: this.points[this.period], fill: false, borderColor: 'rgb(75, 192, 192)', From 1f51e3b8c23eb629eff3226428e0557d0bae7f12 Mon Sep 17 00:00:00 2001 From: Ionys <9364594+Ionys320@users.noreply.github.com> Date: Mon, 20 May 2024 14:09:36 +0200 Subject: [PATCH 3/8] feat(metrics): Optimize the `whereHas` Co-authored-by: James Brooks --- src/View/Components/Metrics.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/View/Components/Metrics.php b/src/View/Components/Metrics.php index 77c95efc..d7f71c04 100644 --- a/src/View/Components/Metrics.php +++ b/src/View/Components/Metrics.php @@ -48,9 +48,7 @@ private function metrics(Carbon $startDate): Collection 'metricPoints' => fn ($query) => $query->orderBy('created_at'), ]) ->where('visible', '>=', !auth()->check()) - ->whereHas('metricPoints', function (Builder $query) use ($startDate) { - $query->where('created_at', '>=', $startDate); - }) + ->whereHas('metricPoints', fn (Builder $query) => $query->where('created_at', '>=', $startDate)) ->orderBy('places', 'asc') ->get(); } From f019e14aa48f40f81ffe67036790abd5535737ec Mon Sep 17 00:00:00 2001 From: Ionys <9364594+Ionys320@users.noreply.github.com> Date: Mon, 20 May 2024 14:10:11 +0200 Subject: [PATCH 4/8] feat(metrics): Simplify a bit the code of metric points transformation Co-authored-by: James Brooks --- src/View/Components/Metrics.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/View/Components/Metrics.php b/src/View/Components/Metrics.php index d7f71c04..d12b52fc 100644 --- a/src/View/Components/Metrics.php +++ b/src/View/Components/Metrics.php @@ -25,12 +25,10 @@ public function render(): View // Convert each metric point to Chart.js format (x, y) $metrics->each(function ($metric) { - $metric->metricPoints->transform(function ($point) { - return [ - 'x' => $point->created_at->toIso8601String(), - 'y' => $point->value, - ]; - }); + $metric->metricPoints->transform(fn ($point) => [ + 'x' => $point->created_at->toIso8601String(), + 'y' => $point->value, + ]); }); return view('cachet::components.metrics', [ From b23afce4cde9611034a8d7a2d5a53c2e7e015483 Mon Sep 17 00:00:00 2001 From: Ionys <9364594+Ionys320@users.noreply.github.com> Date: Mon, 20 May 2024 14:11:03 +0200 Subject: [PATCH 5/8] feat(metric): Simplify the code for setting metric/period data in Alpine Co-authored-by: James Brooks --- resources/views/components/metric.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/components/metric.blade.php b/resources/views/components/metric.blade.php index 14aca1e9..6b7f1e6a 100644 --- a/resources/views/components/metric.blade.php +++ b/resources/views/components/metric.blade.php @@ -32,8 +32,8 @@ \ No newline at end of file +