Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions demo/app/AgGrid/VirtualColumns/FlamingoKeeperColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\AgGrid\VirtualColumns;

use App\Models\FlamingoAgGridView;
use Clickbar\AgGrid\AgGridQueryBuilder;
use Clickbar\AgGrid\AgGridVirtualColumn;
use Clickbar\AgGrid\Data\AgGridSetValue;
use Illuminate\Support\Collection;

/** @extends AgGridVirtualColumn<FlamingoAgGridView> */
class FlamingoKeeperColumn extends AgGridVirtualColumn
{
public function getValue($row): mixed
{
return $row->keeper_name;
}

public function getSetValues(AgGridQueryBuilder $builder): Collection
{
return $builder
->distinct()
->select('keeper_id', 'keeper_name')
->orderBy('keeper_name')
->get()
->map(fn ($data) => new AgGridSetValue($data->keeper_id, $data->keeper_name));
}

public function getOrderColumns(): array
{
return ['keeper_name'];
}

public function getFilterColumn(): string
{
return 'keeper_id';
}
}
34 changes: 33 additions & 1 deletion demo/app/Models/FlamingoAgGridView.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

namespace App\Models;

use App\AgGrid\VirtualColumns\FlamingoKeeperColumn;
use Clickbar\AgGrid\AgGridColumnDefinition;
use Clickbar\AgGrid\Contracts\AgGridExportable;
use Clickbar\AgGrid\Contracts\AgGridHasVirtualColumns;
use Clickbar\AgGrid\Model\AgGridViewModel;

class FlamingoAgGridView extends AgGridViewModel
class FlamingoAgGridView extends AgGridViewModel implements AgGridExportable, AgGridHasVirtualColumns
{
protected $table = 'flamingo_ag_grid_view';

Expand All @@ -24,4 +28,32 @@ class FlamingoAgGridView extends AgGridViewModel
'zoo_created_at' => 'immutable_datetime',
'zoo_updated_at' => 'immutable_datetime',
];

public function getVirtualColumns(): array
{
return ['keeper' => new FlamingoKeeperColumn()];
}

public static function getAgGridColumnDefinitions(): array
{
return [
new AgGridColumnDefinition('id', 'ID'),
new AgGridColumnDefinition('flamingo_name', 'Flamingo Name'),
new AgGridColumnDefinition('flamingo_species', 'Flamingo Species'),
new AgGridColumnDefinition('flamingo_weight', 'Flamingo Weight'),
new AgGridColumnDefinition('flamingo_preferred_food_types', 'Flamingo Preferred Food Types'),
new AgGridColumnDefinition('flamingo_custom_properties', 'Flamingo Custom Properties'),
new AgGridColumnDefinition('flamingo_is_hungry', 'Flamingo is Hungry'),
new AgGridColumnDefinition('flamingo_last_vaccinated_on', 'Flamingo last vaccinated on'),
new AgGridColumnDefinition('keeper_id', 'Keeper ID'),
new AgGridColumnDefinition('keeper', 'Keeper Name'),
new AgGridColumnDefinition('zoo_id', 'Zoo ID'),
new AgGridColumnDefinition('zoo_name', 'Zoo Name'),
new AgGridColumnDefinition('zoo_address.street', 'Zoo Street'),
new AgGridColumnDefinition('zoo_address.city', 'Zoo City'),
new AgGridColumnDefinition('zoo_address.email', 'Zoo Mail'),
new AgGridColumnDefinition('zoo_address.phone', 'Zoo Phone'),
];

}
}
3 changes: 2 additions & 1 deletion demo/app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
Expand All @@ -19,6 +20,6 @@ public function register(): void
*/
public function boot(): void
{
//
Model::shouldBeStrict();
}
}
2 changes: 1 addition & 1 deletion demo/resources/js/Components/AgGrid/AgGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ async function exportServerSide(format: 'excel' | 'csv', onlySelected: boolean)
...parameters,
...(onlySelected ? api?.getServerSideSelectionState() : {}),
exportFormat: format,
exportCols: cols,
exportColumns: cols,
customFilters: props.customFilters,
},
{
Expand Down
13 changes: 9 additions & 4 deletions demo/resources/js/Models/Flamingo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,14 @@ export const flamingoViewColumnDefinition = [
{
headerValueGetter: () => 'Custom properties',
field: 'flamingo_custom_properties',
filter: false,
filter: true,
sortable: false,
suppressMenu: true
suppressMenu: false,
...getSetFilterParametersFor(
'flamingo_custom_properties',
route('api.view.flamingos.set-values'
)
)
},
{
headerValueGetter: () => 'Is hungry',
Expand Down Expand Up @@ -243,11 +248,11 @@ export const flamingoViewColumnDefinition = [
children: [
{
headerValueGetter: () => 'Name',
field: 'keeper_name',
field: 'keeper',
sortable: true,
filter: true,
...getSetFilterParametersFor(
'keeper_name',
'keeper',
route('api.view.flamingos.set-values'
)
)
Expand Down
18 changes: 18 additions & 0 deletions demo/resources/js/Utils/ag-grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ export function getSetFilterParametersFor(
})
},
refreshValuesOnOpen,
keyCreator: (params) => {
if (typeof params.value === 'string'){
return params.value
}
if (params.value === null){
return null
}
return params.value.value
},
valueFormatter: (params) => {
if (typeof params.value === 'string'){
return params.value
}
if (params.value === null){
return null
}
return params.value.label
}
},
}
}
13 changes: 12 additions & 1 deletion src/AgGridExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Clickbar\AgGrid\Contracts\AgGridExportable;
use Clickbar\AgGrid\Contracts\AgGridExportTimezoneProvider;
use Clickbar\AgGrid\Contracts\AgGridHasVirtualColumns;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection;
Expand All @@ -26,6 +27,9 @@ class AgGridExport implements FromQuery, ShouldAutoSize, WithColumnFormatting, W

private readonly array $columnsToExport;

/** @var array<string, AgGridVirtualColumn> */
private array $virtualColumns = [];

public function __construct(
private readonly Builder|Relation $queryBuilder,
?array $columnsToExport = null
Expand All @@ -36,8 +40,11 @@ public function __construct(
throw new \InvalidArgumentException('The model must implement the AgGridExportable interface.');
}

$this->columnDefinitions = collect($model->getAgGridColumnDefinitions())->keyBy('id');
if ($model instanceof AgGridHasVirtualColumns) {
$this->virtualColumns = $model->getVirtualColumns();
}

$this->columnDefinitions = collect($model->getAgGridColumnDefinitions())->keyBy('id');
$this->columnsToExport = $columnsToExport ?? $this->columnDefinitions->keys()->all();

$timezone = null;
Expand Down Expand Up @@ -72,6 +79,10 @@ public function map($row): array
/** @var AgGridColumnDefinition $columDefinition */
$columDefinition = $this->columnDefinitions[$column];

if (array_key_exists($column, $this->virtualColumns)) {
$row[$column] = $this->virtualColumns[$column]->getValue($row);
}

if ($columDefinition->valueGetter !== null) {
$value = $columDefinition->valueGetter->call($row, $row);
} else {
Expand Down
42 changes: 39 additions & 3 deletions src/AgGridQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Clickbar\AgGrid;

use Clickbar\AgGrid\Contracts\AgGridCustomFilterable;
use Clickbar\AgGrid\Contracts\AgGridHasVirtualColumns;
use Clickbar\AgGrid\Enums\AgGridDateFilterType;
use Clickbar\AgGrid\Enums\AgGridExportFormat;
use Clickbar\AgGrid\Enums\AgGridFilterType;
Expand Down Expand Up @@ -40,6 +41,8 @@ class AgGridQueryBuilder implements Responsable
/** @var class-string<JsonResource> | null */
protected ?string $resourceClass = null;

protected array $virtualColumns = [];

/**
* @param EloquentBuilder|Relation|Model|class-string<Model> $subject
*/
Expand All @@ -53,6 +56,10 @@ public function __construct(array $params, EloquentBuilder|Relation|Model|string
$this->subject = $subject;

$model = $subject->getModel();
if ($model instanceof AgGridHasVirtualColumns) {
$this->virtualColumns = $model->getVirtualColumns();
}

if ($model instanceof AgGridCustomFilterable) {
$model->applyAgGridCustomFilters($this->subject, $this->params['customFilters'] ?? []);
}
Expand Down Expand Up @@ -124,6 +131,10 @@ public function toSetValues(array $allowedColumns = []): Collection
throw InvalidSetValueOperation::make();
}

if ($this->hasVirtualColumnFor($colId)) {
return $this->virtualColumns[$colId]->getSetValues($this);
}

if (collect($allowedColumns)->first() !== '*' && ! in_array($colId, $allowedColumns)) {
throw UnauthorizedSetFilterColumn::make($colId);
}
Expand Down Expand Up @@ -204,6 +215,14 @@ public function toResponse($request): mixed

$data = $this->get();

if (! empty($this->virtualColumns)) {
foreach ($data as $row) {
foreach ($this->virtualColumns as $key => $virtualColumn) {
$row[$key] = $virtualColumn->getValue($row);
}
}
}

// wrap in a resource
if ($this->resourceClass !== null) {
/** @var class-string<JsonResource> $resourceClass */
Expand Down Expand Up @@ -266,7 +285,12 @@ protected function addFiltersToQuery(): void

foreach ($filters as $colId => $filter) {

$column = Column::fromColId($this->subject, $colId);
if ($this->hasVirtualColumnFor($colId)) {
$column = Column::fromColId($this->subject, $this->virtualColumns[$colId]->getFilterColumn());

} else {
$column = Column::fromColId($this->subject, $colId);
}

if ($column->hasRelations()) {
$this->subject->whereHas($column->getDottedRelation(), function (EloquentBuilder $builder) use ($column, $filter) {
Expand All @@ -292,8 +316,15 @@ protected function addSortsToQuery(): void
}

foreach ($sorts as $sort) {
$column = Column::fromColId($this->subject, $sort['colId']);
$this->subject->orderBy($column->getNameAsJsonPath(), $sort['sort']);
$colId = $sort['colId'];
if ($this->hasVirtualColumnFor($colId)) {
$columnNames = $this->virtualColumns[$colId]->getOrderColumns();
} else {
$columnNames = [Column::fromColId($this->subject, $colId)->getNameAsJsonPath()];
}
foreach ($columnNames as $columnName) {
$this->subject->orderBy($columnName, $sort['sort']);
}
}

// we need an additional sort condition so that the order is stable in all cases
Expand Down Expand Up @@ -428,4 +459,9 @@ protected function traverse($model, $key, $default = null): Model

return $model;
}

protected function hasVirtualColumnFor(string $colId): bool
{
return array_key_exists($colId, $this->virtualColumns);
}
}
28 changes: 28 additions & 0 deletions src/AgGridVirtualColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Clickbar\AgGrid;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

/**
* @template T of Model
*/
abstract class AgGridVirtualColumn
{
/**
* Build the value for this virtual column
*
* @param T $row with all columns
*/
abstract public function getValue($row): mixed;

public function getSetValues(AgGridQueryBuilder $builder): ?Collection
{
return null;
}

abstract public function getOrderColumns(): array;

abstract public function getFilterColumn(): string;
}
11 changes: 11 additions & 0 deletions src/Contracts/AgGridHasVirtualColumns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Clickbar\AgGrid\Contracts;

use Clickbar\AgGrid\AgGridVirtualColumn;

interface AgGridHasVirtualColumns
{
/** @return array<string, AgGridVirtualColumn> */
public function getVirtualColumns(): array;
}