Skip to content

Commit a52c3c0

Browse files
committed
wip
1 parent 390dbb4 commit a52c3c0

File tree

10 files changed

+106
-73
lines changed

10 files changed

+106
-73
lines changed

src/StoredEvents/EventsReplayCommand.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Tempest\Container\Container;
1010
use Tempest\Database\Builder\QueryBuilders\QueryBuilder;
1111

12+
use function Tempest\Database\query;
1213
use function Tempest\Support\arr;
1314
use function Tempest\Support\str;
1415

@@ -45,9 +46,7 @@ public function __invoke(?string $replay = null): void
4546
return;
4647
}
4748

48-
$eventCount = new QueryBuilder(StoredEvent::class)
49-
->select('COUNT(*) as `count`')
50-
->first()['count'];
49+
$eventCount = query(StoredEvent::class)->count()->execute();
5150

5251
$confirm = $this->confirm(sprintf(
5352
'We\'re going to replay %d events on %d %s, this will take a while. Continue?',

src/Web/Analytics/Chart.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66

77
final readonly class Chart
88
{
9+
910
public function __construct(
1011
public ImmutableArray $labels,
1112
public ImmutableArray $values,
12-
) {}
13+
public ?int $min = null,
14+
) {
15+
}
1316
}

src/Web/Analytics/PackageDownloadsPerDay/PackageDownloadsPerDayProjector.php

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
use App\StoredEvents\Projector;
66
use App\Web\Analytics\PackageDownloadsListed;
7+
use PDOException;
78
use Tempest\Database\Builder\QueryBuilders\QueryBuilder;
8-
use Tempest\Database\Query;
99
use Tempest\EventBus\EventHandler;
10+
use function Tempest\Database\query;
1011

1112
final readonly class PackageDownloadsPerDayProjector implements Projector
1213
{
@@ -15,6 +16,7 @@ public function clear(): void
1516
{
1617
new QueryBuilder(PackageDownloadsPerDay::class)
1718
->delete()
19+
->allowAll()
1820
->execute();
1921
}
2022

@@ -29,19 +31,28 @@ public function replay(object $event): void
2931
#[EventHandler]
3032
public function onPackageDownloadsListed(PackageDownloadsListed $event): void
3133
{
34+
$date = $event->date->setTime(0, 0);
35+
3236
$count = $event->total;
3337

3438
$count = max($count, 0);
3539

36-
PackageDownloadsPerDay::updateOrCreate(
37-
[
38-
'date' => $event->date,
39-
'package' => $event->package,
40-
],
41-
[
42-
'total' => $event->total,
43-
'count' => $count,
44-
],
45-
);
40+
$packageDownloadsPerDay = query(PackageDownloadsPerDay::class)
41+
->select()
42+
->where('date = ? AND package = ?', $date, $event->package)
43+
->first();
44+
45+
if (!$packageDownloadsPerDay) {
46+
$packageDownloadsPerDay = new PackageDownloadsPerDay(
47+
date: $date,
48+
package: $event->package,
49+
count: 0,
50+
total: 0,
51+
);
52+
}
53+
54+
$packageDownloadsPerDay->total = $event->total;
55+
$packageDownloadsPerDay->count = $count;
56+
$packageDownloadsPerDay->save();
4657
}
4758
}

src/Web/Analytics/PackageDownloadsPerHour/PackageDownloadsPerHourProjector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public function clear(): void
1515
{
1616
new QueryBuilder(PackageDownloadsPerHour::class)
1717
->delete()
18+
->allowAll()
1819
->execute();
1920
}
2021

src/Web/Analytics/StatsController.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Web\Analytics;
44

5+
use App\Web\Analytics\PackageDownloadsPerDay\PackageDownloadsPerDay;
56
use App\Web\Analytics\VisitsPerDay\VisitsPerDay;
67
use Tempest\Clock\Clock;
78
use Tempest\DateTime\Duration;
@@ -17,8 +18,19 @@
1718
#[Get('/stats')]
1819
public function __invoke(Clock $clock): View
1920
{
21+
$limit = 30;
22+
2023
$visitsPerDay = arr(
21-
query(VisitsPerDay::class)->select()->orderBy('date DESC')->limit(30)->all(),
24+
query(VisitsPerDay::class)->select()->orderBy('date DESC')->limit($limit)->all(),
25+
)->reverse();
26+
27+
$packageDownloadsPerDay = arr(
28+
query(PackageDownloadsPerDay::class)
29+
->select()
30+
->whereField('package', 'framework')
31+
->orderBy('date DESC')
32+
->limit($limit)
33+
->all(),
2234
)->reverse();
2335

2436
return view(
@@ -28,6 +40,12 @@ public function __invoke(Clock $clock): View
2840
labels: $visitsPerDay->map(fn (VisitsPerDay $item) => $item->date->format('Y-m-d')),
2941
values: $visitsPerDay->map(fn (VisitsPerDay $item) => $item->count),
3042
),
43+
44+
packageDownloadsPerDay: new Chart(
45+
labels: $packageDownloadsPerDay->map(fn (PackageDownloadsPerDay $item) => $item->date->format('Y-m-d')),
46+
values: $packageDownloadsPerDay->map(fn (PackageDownloadsPerDay $item) => $item->total),
47+
min: $packageDownloadsPerDay->sortByCallback(fn (PackageDownloadsPerDay $a, PackageDownloadsPerDay $b) => $a->total)->first()->total,
48+
),
3149
);
3250
}
3351
}

src/Web/Analytics/VisitsPerDay/VisitsPerDayProjector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public function clear(): void
2222
{
2323
new QueryBuilder(VisitsPerDay::class)
2424
->delete()
25+
->allowAll()
2526
->execute();
2627
}
2728

src/Web/Analytics/VisitsPerHour/VisitsPerHourProjector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function clear(): void
2323
{
2424
new QueryBuilder(VisitsPerHour::class)
2525
->delete()
26+
->allowAll()
2627
->execute();
2728
}
2829

src/Web/Analytics/chart.view.php

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/Web/Analytics/stats.view.php

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
<x-base>
2+
<x-aurora class="dark:hidden" />
3+
24
<x-slot name="head">
35
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
46
</x-slot>
57
6-
<div class="@HeroBlock">
7-
<div class="flex flex-col gap-4 px-4 items-center justify-center py-8 max-w-screen-xl mx-auto w-full text-white">
8-
<div class=" flex-1 flex flex-col items-center justify-center gap-8">
9-
<h1 class="text-[1.5rem] md:text-[2.5rem] max-w-[640px] leading-[1.1] text-center font-display font-extrabold">Tempest Stats</h1>
10-
</div>
11-
</div>
12-
</div>
13-
14-
<div class="w-full flex flex-col ">
8+
<div class="w-full flex flex-col pb-8">
159
<div class="w-full z-10 md:py-24 pt-12">
1610
<div class="w-full mx-auto grid md:grid-cols-2 xl:grid-cols-3 gap-12 md:px-24 px-8">
17-
<x-chart :chart="$visitsPerDay" label="Visits per day" title="Website visits last 30 days"></x-chart>
11+
<x-chart :chart="$visitsPerDay" label="Visits" chart-title="Website visits last 30 days"></x-chart>
12+
<x-chart :chart="$packageDownloadsPerDay" label="Downloads" chart-title="Package downloads over time"></x-chart>
1813
</div>
1914
</div>
2015
</div>

src/Web/Analytics/x-chart.view.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/**
4+
* @var \App\Web\Analytics\Chart $chart
5+
* @var string $label
6+
* @var string $title
7+
*/
8+
9+
use Symfony\Component\Uid\Uuid;
10+
11+
$uuid = Uuid::v4()->toString();
12+
?>
13+
14+
<div class="grid gap-2">
15+
<h2 class="font-bold">{{ $chartTitle }}</h2>
16+
<div>
17+
<canvas id="<?= $uuid ?>" class="h-[300px] w-[100px]"></canvas>
18+
</div>
19+
20+
<script>
21+
var ctx = document.getElementById('<?= $uuid ?>');
22+
23+
new Chart(ctx, {
24+
type: 'line',
25+
data: {
26+
labels: <?= json_encode($chart->labels->values()->toArray()) ?>,
27+
datasets: [{
28+
label: '<?= $label ?>',
29+
data: <?= json_encode($chart->values->values()->toArray()) ?>,
30+
borderWidth: 2
31+
}]
32+
},
33+
options: {
34+
maintainAspectRatio: false,
35+
elements: {
36+
line: {
37+
tension: 0.4
38+
}
39+
},
40+
scales: {
41+
y: {
42+
<?php if ($chart->min !== null): ?>
43+
min: <?= $chart->min - 100 ?>,
44+
<?php endif; ?>
45+
beginAtZero: true
46+
}
47+
}
48+
}
49+
});
50+
</script>
51+
</div>

0 commit comments

Comments
 (0)