Skip to content

Commit

Permalink
Added Sortable columns
Browse files Browse the repository at this point in the history
  • Loading branch information
jzaplet committed May 2, 2024
1 parent c0d4324 commit 7087e83
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 34 deletions.
32 changes: 16 additions & 16 deletions src/Collection/Helper/ColumnCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@

class ColumnCreator
{
public static function create(string $type, string $key, bool $visible): IColumn
public static function create(string $type, string $key, bool $visible, bool $sortable): IColumn
{
$keysMap = [
'email' => new EmailColumn(key: $key, name: $key, visible: $visible),
'phone' => new PhoneColumn(key: $key, name: $key, visible: $visible),
'url' => new UrlColumn(key: $key, name: $key, visible: $visible),
'video' => new VideoLinkColumn(key: $key, name: $key, visible: $visible),
'email' => new EmailColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
'phone' => new PhoneColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
'url' => new UrlColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
'video' => new VideoLinkColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
];

$columnByKey = null;
Expand All @@ -47,32 +47,32 @@ public static function create(string $type, string $key, bool $visible): IColumn
Types::DECIMAL,
Types::GUID,
Types::STRING,
Types::TEXT => $columnByKey ?: new StringColumn(key: $key, name: $key, visible: $visible),
Types::TEXT => $columnByKey ?: new StringColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::BLOB => new BlobColumn(key: $key, name: $key, visible: $visible),
Types::BLOB => new BlobColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::BOOLEAN => new BooleanColumn(key: $key, name: $key, visible: $visible),
Types::BOOLEAN => new BooleanColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::DATE_MUTABLE,
Types::DATE_IMMUTABLE => new DateColumn(key: $key, name: $key, visible: $visible),
Types::DATEINTERVAL => new DateTimeIntervalColumn(key: $key, name: $key, visible: $visible),
Types::DATE_IMMUTABLE => new DateColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
Types::DATEINTERVAL => new DateTimeIntervalColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::DATETIME_MUTABLE,
Types::DATETIME_IMMUTABLE,
Types::DATETIMETZ_MUTABLE,
Types::DATETIMETZ_IMMUTABLE => new DateTimeColumn(key: $key, name: $key, visible: $visible),
Types::DATETIMETZ_IMMUTABLE => new DateTimeColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::FLOAT,
Types::INTEGER,
Types::SMALLINT => new NumericColumn(key: $key, name: $key, visible: $visible),
Types::SMALLINT => new NumericColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::JSON => new JsonColumn(key: $key, name: $key, visible: $visible),
Types::SIMPLE_ARRAY => new ArrayColumn(key: $key, name: $key, visible: $visible),
Types::JSON => new JsonColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
Types::SIMPLE_ARRAY => new ArrayColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

Types::TIME_MUTABLE,
Types::TIME_IMMUTABLE => new TimeColumn(key: $key, name: $key, visible: $visible),
Types::TIME_IMMUTABLE => new TimeColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),

default => new UnknownColumn(key: $key, name: $key, visible: $visible),
default => new UnknownColumn(key: $key, name: $key, sortable: $sortable, visible: $visible),
};
}
}
12 changes: 3 additions & 9 deletions src/Collection/ICollectionRecipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,16 @@ public function source(): string;
/** @return string */
public function key(): string;

/**
* @throws \Megio\Collection\Exception\CollectionException
*/
/** @throws \Megio\Collection\Exception\CollectionException */
public function read(ReadBuilder $builder, RecipeRequest $request): ReadBuilder;

/**
* @throws \Megio\Collection\Exception\CollectionException
*/
/** @throws \Megio\Collection\Exception\CollectionException */
public function readAll(ReadBuilder $builder, RecipeRequest $request): ReadBuilder;

public function create(WriteBuilder $builder, RecipeRequest $request): WriteBuilder;

public function update(WriteBuilder $builder, RecipeRequest $request): WriteBuilder;

/**
* @throws \Megio\Collection\Exception\CollectionException
*/
/** @throws \Megio\Collection\Exception\CollectionException */
public function getEntityMetadata(): RecipeEntityMetadata;
}
5 changes: 3 additions & 2 deletions src/Collection/ReadBuilder/ReadBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ public function buildByDbSchema(array $exclude = [], bool $persist = false): sel
{
$this->addIdColumnIfNotExists();

$sortableCols = ['id', 'createdAt', 'updatedAt'];
$invisibleCols = ['id', 'createdAt', 'updatedAt'];
$ignored = array_merge($exclude, ['id']);

foreach ($this->dbSchema->getUnionColumns() as $column) {
if (!in_array($column['name'], $ignored)) {
$visible = !in_array($column['name'], $invisibleCols);
$col = ColumnCreator::create($column['type'], $column['name'], $visible);
$col = ColumnCreator::create($column['type'], $column['name'], $visible, in_array($column['name'], $sortableCols));
$this->columns[$col->getKey()] = $col;
}
}
Expand Down Expand Up @@ -231,7 +232,7 @@ protected function addIdColumnIfNotExists(): void
{
if (!array_key_exists('id', $this->columns)) {
$this->columns = array_merge([
'id' => new StringColumn(key: 'id', name: 'ID', visible: false),
'id' => new StringColumn(key: 'id', name: 'ID', sortable: true, visible: false),
], $this->columns);
}
}
Expand Down
22 changes: 17 additions & 5 deletions src/Http/Request/Collection/ReadAllRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Megio\Collection\Exception\CollectionException;
use Megio\Collection\ReadBuilder\Column\Base\IColumn;
use Megio\Collection\ReadBuilder\ReadBuilder;
use Megio\Collection\ReadBuilder\ReadBuilderEvent;
use Megio\Collection\RecipeFinder;
Expand All @@ -30,9 +31,10 @@ public function __construct(
{
}

public function schema(): array
public function schema(array $data): array
{
$recipeKeys = array_map(fn($r) => $r->key(), $this->recipeFinder->load()->getAll());
$recipes = $this->recipeFinder->load()->getAll();
$recipeKeys = array_map(fn($r) => $r->key(), $recipes);

return [
'recipe' => Expect::anyOf(...$recipeKeys)->required(),
Expand All @@ -43,7 +45,7 @@ public function schema(): array
'orderBy' => Expect::arrayOf(Expect::structure([
'col' => Expect::string()->required(),
'desc' => Expect::bool()->required()
])->castTo('array'))->min(1)->default([['col' => 'createdAt', 'desc' => true]]),
])->castTo('array'))->min(0)->default([]),
'custom_data' => Expect::arrayOf('int|float|string|bool|null|array', 'string')->nullable()->default([]),
];
}
Expand All @@ -69,7 +71,6 @@ public function process(array $data): Response
return $this->error([$e->getMessage()]);
}


/** @noinspection DuplicatedCode */
if ($builder->countFields() === 1) {
return $this->error(["Collection '{$data['recipe']}' has no readable fields"]);
Expand All @@ -94,8 +95,19 @@ public function process(array $data): Response
->setFirstResult(($data['currentPage'] - 1) * $data['itemsPerPage'])
->setMaxResults($data['itemsPerPage']);

// Sortable columns
$sortable = array_filter($builder->getColumns(), fn(IColumn $col) => $col->isSortable());
$sortableKeys = array_map(fn(IColumn $col) => $col->getKey(), $sortable);

// Order by only by sortable columns
foreach ($data['orderBy'] as $param) {
$qb->addOrderBy("entity.{$param['col']}", $param['desc'] ? 'DESC' : 'ASC');
if (in_array($param['col'], $sortableKeys)) {
$qb->addOrderBy("entity.{$param['col']}", $param['desc'] ? 'DESC' : 'ASC');
}
}

if (!in_array('id', array_column($data['orderBy'], 'col'))) {
$qb->addOrderBy('entity.id', 'ASC');
}

$query = $qb->getQuery()->setHydrationMode(AbstractQuery::HYDRATE_ARRAY);
Expand Down
5 changes: 3 additions & 2 deletions src/Recipe/AdminRecipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Megio\Recipe;

use Megio\Collection\ReadBuilder\Column\EmailColumn;
use Megio\Collection\ReadBuilder\ReadBuilder;
use Megio\Collection\RecipeRequest;
use Megio\Collection\WriteBuilder\Field\Base\EmptyValue;
Expand All @@ -12,7 +13,6 @@
use Megio\Collection\WriteBuilder\Rule\RequiredRule;
use Megio\Collection\CollectionRecipe;
use Megio\Database\Entity\Admin;
use Symfony\Component\HttpFoundation\Request;

class AdminRecipe extends CollectionRecipe
{
Expand All @@ -33,7 +33,8 @@ public function read(ReadBuilder $builder, RecipeRequest $request): ReadBuilder

public function readAll(ReadBuilder $builder, RecipeRequest $request): ReadBuilder
{
return $builder->buildByDbSchema(['password']);
return $builder->buildByDbSchema(['password'], persist: true)
->add(new EmailColumn('email', 'E-mail', true));
}

public function create(WriteBuilder $builder, RecipeRequest $request): WriteBuilder
Expand Down

0 comments on commit 7087e83

Please sign in to comment.