Skip to content

Commit

Permalink
feat: auto-detect enums + getLabel method
Browse files Browse the repository at this point in the history
sakanjo committed Aug 6, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent ac10de3 commit bc12dd8
Showing 3 changed files with 56 additions and 22 deletions.
32 changes: 25 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@

> ✨ Help support the maintenance of this package by [sponsoring me](https://github.com/sponsors/sakanjo).
> Designed to work with **Laravel**, **Filament**, and more.
> Designed to work with **Laravel**, **Filament**, [Easy enum](https://github.com/sakanjo/laravel-easy-enum), and more.
![Preview](./art/preview.png)

@@ -42,6 +42,8 @@ Table of contents
* [Using trend metric](#using-trend-metric)
* [Using doughnut metric](#using-doughnut-metric)
* [Available growth rate types](#available-growth-rate-types)
* [Tips](#-tips)
* [using getLabel](#using-getLabel)
* [Practical examples](#-practical-examples)
* [Filamentphp v3 widgets](#filamentphp-v3-widgets)
* [Support the development](#-support-the-development)
@@ -110,15 +112,11 @@ Value::make(User::class)
```php
use SaKanjo\EasyMetrics\Metrics\Doughnut;
use App\Models\User;
use App\Enums\Gender;

[$labels, $data] = Doughnut::make(User::class)
->options(Gender::class)
->count('gender');
```

> It's always better to use the `options` method even though it's optional, since the retrieved data may not include all enum options.
#### Query types

The currently supported aggregate functions to calculate a given column compared to the previous time interval / range
@@ -295,10 +293,8 @@ use App\Models\User;
```php
use SaKanjo\EasyMetrics\Metrics\Doughnut;
use App\Models\User;
use App\Enums\Gender;

[$labels, $data, $growth] = Doughnut::make(User::class)
->options(Gender::class)
->withGrowthRate()
->count('gender');
```
@@ -309,6 +305,28 @@ use App\Enums\Gender;
- `GrowthRateType::Value`
- `GrowthRateType::Percentage`

## 🔥 Tips

#### Using getLabel

You can use the `getLabel` method to customize the retreived data labels, for example:

```php
<?php

namespace App\Enums;

use SaKanjo\EasyEnum;

enum ExampleEnum: int
{
use EasyEnum; // Includes getLabel method

case Active = 0;
case Disabled = 1;
}
```

## 🔥 Practical examples

#### Filamentphp v3 widgets
31 changes: 29 additions & 2 deletions src/Metrics/Doughnut.php
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use ReflectionEnum;
use SaKanjo\EasyMetrics\Result;

class Doughnut extends Metric
@@ -30,6 +31,21 @@ public function options(array|string $options): static
return $this;
}

public function getOptions(): array
{
if ($this->options) {
return $this->options;
}

$cast = $this->query->getModel()->getCasts()[$this->groupBy] ?? null;

if ($cast && (new ReflectionEnum($cast))->isBacked()) {
return Arr::pluck($cast::cases(), 'value');
}

return [];
}

public function min(string $column, string $groupBy)
{
return $this->setType('min', $groupBy, $column);
@@ -87,10 +103,21 @@ public function resolveValue(?array $range): array
})
->toArray();

$options = array_fill_keys($this->options ?? [], 0);

$options = array_fill_keys($this->getOptions(), 0);
$data = array_replace($options, $results);

$cast = $this->query->getModel()->getCasts()[$this->groupBy] ?? null;

if (
$cast &&
(new ReflectionEnum($cast))->isBacked() &&
method_exists($cast, 'getLabel')
) {
$data = Arr::mapWithKeys($data, fn (float $value, mixed $key) => [
$cast::from($key)->getLabel() => $value, // @phpstan-ignore-line
]);
}

return $data;
}

15 changes: 2 additions & 13 deletions tests/src/Doughnut/DoughnutTest.php
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@
]);
});

it('shows limited options when using `options` method', function () {
it('shows all options when not using `options` method', function () {
$sequence = [
// ['gender' => Gender::Male],
// ['gender' => Gender::Male],
@@ -54,6 +54,7 @@
->count('gender');

assertEquals($doughnut->getLabels(), [
Gender::Male->value,
Gender::Female->value,
]);
});
@@ -174,7 +175,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::ALL)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -183,7 +183,6 @@
assertEquals($doughnut->getGrowthRate(), [2, 3]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::ALL)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)
@@ -206,7 +205,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -215,7 +213,6 @@
assertEquals($doughnut->getGrowthRate(), [-1, -1]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)
@@ -238,7 +235,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -247,7 +243,6 @@
assertEquals($doughnut->getGrowthRate(), [-35, -30]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)
@@ -270,7 +265,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -279,7 +273,6 @@
assertEquals($doughnut->getGrowthRate(), [-70, -30]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)
@@ -302,7 +295,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -311,7 +303,6 @@
assertEquals($doughnut->getGrowthRate(), [-50, -30]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)
@@ -334,7 +325,6 @@
->create();

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Value)
@@ -343,7 +333,6 @@
assertEquals($doughnut->getGrowthRate(), [-20, -30]);

$doughnut = Doughnut::make(User::class)
->options(Gender::class)
->range(Range::TODAY)
->withGrowthRate()
->growthRateType(GrowthRateType::Percentage)

0 comments on commit bc12dd8

Please sign in to comment.