Skip to content
This repository has been archived by the owner on Jan 16, 2018. It is now read-only.

OLD note - ignore #77

Open
sstok opened this issue Jan 16, 2018 · 0 comments
Open

OLD note - ignore #77

sstok opened this issue Jan 16, 2018 · 0 comments

Comments

@sstok
Copy link
Contributor

sstok commented Jan 16, 2018

Datagrid

The Datagrid package functionality is currently very limited, there needs
to be a clear description about what must be support by default.

The Datagrid package is responsible for:

  • Configuration of Columns (Label, data-provider, display configuration (format, locale).
  • Building a Datagrid (with pre-configured Columns), and keep a data-list for rendering.
  • Passing a DatagridBuilder className will try to create a Datagrid
    by it's name (or loader, for Service injection), must implement DatagridConfigurator;
    • buildDatagrid(DatagridBuilder $builder, array $options): Datagrid
    • Use simple class inheritance and Traits for extending. (DONE)

Each Datagrid object has it's own 'unique' name.

The Datagrid package knows nothing about the environment usage (web, cli).
Rendering and Request handling is done by other packages.

The package provides a Query interface with the following methods:

  • setSorting(['column-name' => 'ASC|DESC'])
  • getSorting(): array
  • getIterator(): Iterator

The Query interface works as a lazy loading adapter for fetching data.

Query implementations for engines are provided by external packages:

  • Doctrine DBAL
  • Doctrine ORM
  • Pomm 2
  • Propel2? (NO! Not for now)

Ideas:

  • Only allow a Traversable object for Data, use Generator for rendering rows. (REJECTED)
  • Limit view transformer to a single instance, add a ChainFormatter for combining (DONE)
  • Remove ArrayToDateTimeTransformer (unneeded, only allow a DateTimeInterface, string and timestamp) (DONE)

View rendering

Theming is a complex topic, so here's an overall breakdown:

  • The renderer has two types of themes:

    • defaultThemes (always accessible)
    • local themes (loaded explicitly loaded by the current template)
  • Themes can be set for any type of element, but are usually set on the datagrid level

  • The renderer keeps track of the hierarchy levels to ensure variables
    set at a higher level (row > cell) are accessible at a deeper level.

    And deeper variables don't leak to higher levels.
    This tracked per resource, starting from the current point.

  • Each unique block-name (plus suffix) is resolved only once,
    and then used for each rendering.

...

  • Each column has unique block prefix _[datagrid_name]_[column_name],
    used for caching and specific theming. (DONE)
  • When rendering a block, the render engine first checks if the block-name
    is already determined (by reading the cached data).
    If not the block_prefixes is traversed with type (header, cell, row, datagrid).
  • Once a suitable block is found, the name is stored for feature reference:
    • Header: Not cached, rendered only once.
    • Cell block: HeaderView (Used because the HeaderView only exists once per column)
    • Row: DatagridView

Problem: The CompoundColumnType columns must inherit the parent column
name in there block-name. But informing a column it's nested, is done 'after'
the options are set, making it impossible to get the correct block-name.

  • (ACCEPTED, DONE) Requiring all nested columns are explicitly configured is not an option,
    unless we only recommend the Builder:

    $builder
        ->createCompound($name, $options)
        ->add($name, $type, $options)
        ...
        end()
        // `end()` registers the CompoundColumn in the Datagrid, and returns the parent builder
        // all columns receive the CompoundColumn as `parent` option.
    

    This would also solve the unfriendly API for CompoundColumn registering 🙆🏼
    which currently requires the DatagridFactory.

    • Recursion checking is not done, as anyone hitting this is already wrong.
    • Add a new method createCompound to DatagridBuilderInterface
    • Add a new class CompoundColumnBuilder (with interface)

Psr7 Handler

Handles PSR-7 ServerRequests, and handles RollerworksSearch operations.
RollerworksSearch is an optional dependency.

Operation without search enabled:

// Build a new Datagrid.
$datagrid = $datagridFactory->createDatagrid(UsersDatagrid::class, 'users_datagrid', ['options']);

// Query object which provides the actual data.
$query = ...;

// Is a Service when used with Symfony
$dataGridHandler = DatagridHandlerFactory::create();
$dataGridHandler->setQuery($query);
$dataGridHandler->handle($datagrid, $request);

// Optional
// Batch consists of an Action (config), and a Selection($ids, $all, $datagrid) object.
// $handler is a callable which processes the actual batch operation.
$batchConfig = new BatchConfig(callable Handler(BatchAction(...), Selection(...)), array $config);
$batchConfig->enableSelectAll(); // and disable.

$batchConfig->setAction('name', new BatchAction(...)); // BatchAction is an interface, custom implementations required.

// Internally this calls bind($datagrid), which produces a new configuration object.
$dataGridHandler->setBatchConfiguration($batchConfig);

// ...

// When a 'change-request' is provided, do a redirect when there are no errors.
// This only applies to batch actions (and editable cells), not search.
if ($dataGridHandler->changeRequested() && $dataGridHandler->isValid()) {
    // Do a redirect.
}

// Render the datagrid: WebDatagridView
// Errors are automatically provided for rendering.
// $dataGridHandler->createView();

Operation with Search enabled.

// Build a new Datagrid.
$datagrid = ...;

// Query object which provides the actual data.
// Query object must be a `SearchConditionAwareQuery` instance.
$query = ...;

$fieldSet = ...;

$dataGridHandler = DatagridHandlerFactory::createSearchAble($fieldSet);
$dataGridHandler->setQuery($query);

// Set sorting and search condition (if any).
$dataGridHandler->handle($datagrid, $request);

// When a 'change-request' is provided, do a redirect when there are no errors.
if ($dataGridHandler->changeRequested() && $dataGridHandler->isValid()) {
    // Do a redirect.
} else if ($dataGridHandler->searchConditionChanged() && $dataGridHandler->isValid()) {
    // Do a redirect.
    // $dataGridHandler->getSearchCode();
}

// Render the datagrid: WebDatagridView
// Errors are automatically provided for rendering.
// $dataGridHandler->createView();
$users = ; // Any Source
$datagrid = $this->get('rollerworks_datagrid.factory')->createDatagrid(UsersDatagrid::class);
$datagrid->setData($users);
$datagrid->handleRequest($request);

if ($datagrid->search->needsRedirect()) {
    return $this->redirectToRoute('users_list', ['search' => $datagrid->search->searchCode]);
}

return new Response($this->get('twig')->render('@App/users.html.twig', ['datagrid' => $datagrid->createView()]));

Twig renderer

  • Cache resolved block-name with the Datagrid/Column view instance

Datagrid Symfony Bridge (Silex service-provider & Bundle)

Both RollerworksSearch and Twig are already enabled by default.

The name of a datagrid is used for search processor prefix and sorting
configuration.

// Build a new Datagrid.
$datagrid = ...;

// Query object which provides the actual data.
// Query object must be a `SearchConditionAwareQuery` instance.
$query = ...;

$fieldSet = ...;

// TODO Search form.

$dataGridHandler = $this->get('rollerworks_datagrid.handler_factory')->create($fieldSet, $datagrid);
$dataGridHandler->setQuery($query);

// Set sorting and search condition (if any).
// NB. $request must be a PSR-7 ServerRequest object.
$dataGridHandler->handle($request);

// When a 'change-request' is provided, do a redirect when there are no errors.
if ($dataGridHandler->changeRequested() && $dataGridHandler->isValid()) {
    // Do a redirect.
} else if ($dataGridHandler->searchConditionChanged() && $dataGridHandler->isValid()) {
    // Do a redirect.
    // $dataGridHandler->getSearchCode();
}

// Render the datagrid: WebDatagridView
// Errors are automatically provided for rendering.
// $dataGridHandler->createView();
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant