Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing interface for DataModel #1038

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
6 changes: 3 additions & 3 deletions assets/datagrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ dataGridRegisterExtension('datagrid.after_inline_edit', {
var grid = $('.datagrid-' + payload._datagrid_name);

if (payload._datagrid_inline_edited) {
grid.find('tr[data-id=' + payload._datagrid_inline_edited + '] > td').addClass('edited');
grid.find('tr[data-id="' + payload._datagrid_inline_edited + '"] > td').addClass('edited');
return grid.find('.datagrid-inline-edit-trigger').removeClass('hidden');
} else if (payload._datagrid_inline_edit_cancel) {
return grid.find('.datagrid-inline-edit-trigger').removeClass('hidden');
Expand Down Expand Up @@ -884,7 +884,7 @@ dataGridRegisterExtension('datagrid.redraw-item', {
success: function(payload) {
var row;
if (payload._datagrid_redraw_item_class) {
row = $('tr[data-id=' + payload._datagrid_redraw_item_id + ']');
row = $('tr[data-id="' + payload._datagrid_redraw_item_id + '"]');
return row.attr('class', payload._datagrid_redraw_item_class);
}
}
Expand All @@ -902,7 +902,7 @@ dataGridRegisterExtension('datagrid.reset-filter-by-column', {
ref = payload.non_empty_filters;
for (i = 0, len = ref.length; i < len; i++) {
key = ref[i];
grid.find('[data-datagrid-reset-filter-by-column=' + key + ']').removeClass('hidden');
grid.find('[data-datagrid-reset-filter-by-column="' + key + '"]').removeClass('hidden');
}
href = grid.find('.reset-filter').attr('href');
return grid.find('[data-datagrid-reset-filter-by-column]').each(function() {
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"contributte/application": "^0.5.0",
"nette/di": "^3.0.0",
"nette/forms": "^3.1.3",
"nette/utils": "^3.0.1",
"nette/utils": "^3.0.1 || ^4.0",
"symfony/property-access": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
},
"require-dev": {
Expand Down
38 changes: 32 additions & 6 deletions src/DataGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
use Ublaboo\DataGrid\Column\MultiAction;
use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
use Ublaboo\DataGrid\DataSource\IDataSource;
use Ublaboo\DataGrid\Exception\CannotChangeDataModelException;
use Ublaboo\DataGrid\Exception\DataGridColumnNotFoundException;
use Ublaboo\DataGrid\Exception\DataGridException;
use Ublaboo\DataGrid\Exception\DataGridFilterNotFoundException;
use Ublaboo\DataGrid\Exception\DataGridHasToBeAttachedToPresenterComponentException;
use Ublaboo\DataGrid\Exception\InitializingDataModelCallbacksException;
use Ublaboo\DataGrid\Export\Export;
use Ublaboo\DataGrid\Export\ExportCsv;
use Ublaboo\DataGrid\Filter\Filter;
Expand Down Expand Up @@ -237,7 +239,7 @@ class DataGrid extends Control
protected $toolbarButtons = [];

/**
* @var DataModel|null
* @var DataModelInterface|null
*/
protected $dataModel;

Expand Down Expand Up @@ -494,7 +496,7 @@ public function render(): void
/**
* Check whether datagrid has set some columns, initiated data source, etc
*/
if (!($this->dataModel instanceof DataModel)) {
if (!($this->dataModel instanceof DataModelInterface)) {
throw new DataGridException('You have to set a data source first.');
}

Expand Down Expand Up @@ -623,7 +625,7 @@ public function setRowCallback(callable $callback): self
*/
public function setPrimaryKey(string $primaryKey): self
{
if ($this->dataModel instanceof DataModel) {
if ($this->dataModel instanceof DataModelInterface) {
throw new DataGridException('Please set datagrid primary key before setting datasource.');
}

Expand All @@ -637,14 +639,26 @@ public function setPrimaryKey(string $primaryKey): self
* @param mixed $source
* @return static
* @throws InvalidArgumentException
* @throws InitializingDataModelCallbacksException
*/
public function setDataSource($source): self
{
$this->dataModel = new DataModel($source, $this->primaryKey);

$this->dataModel->onBeforeFilter[] = [$this, 'beforeDataModelFilter'];
$this->dataModel->onAfterFilter[] = [$this, 'afterDataModelFilter'];
$this->dataModel->onAfterPaginated[] = [$this, 'afterDataModelPaginated'];
$this->initializeCallbacks();

return $this;
}


/**
* @throws InitializingDataModelCallbacksException
*/
public function setDataModel(DataModelInterface $dataModel): self
{
$this->dataModel = $dataModel;

$this->initializeCallbacks();

return $this;
}
Expand Down Expand Up @@ -3324,4 +3338,16 @@ private function getPresenterInstance(): Presenter
return $this->getPresenter();
}


private function initializeCallbacks(): void
{
if ($this->dataModel === null) {
throw new InitializingDataModelCallbacksException();
}

$this->dataModel->onBeforeFilter[] = [$this, 'beforeDataModelFilter'];
$this->dataModel->onAfterFilter[] = [$this, 'afterDataModelFilter'];
$this->dataModel->onAfterPaginated[] = [$this, 'afterDataModelPaginated'];
}

}
2 changes: 1 addition & 1 deletion src/DataModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* @method onAfterFilter(IDataSource $dataSource)
* @method onAfterPaginated(IDataSource $dataSource)
*/
final class DataModel
final class DataModel implements DataModelInterface
{

use SmartObject;
Expand Down
27 changes: 27 additions & 0 deletions src/DataModelInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);
namespace Ublaboo\DataGrid;


use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
use Ublaboo\DataGrid\DataSource\IDataSource;
use Ublaboo\DataGrid\Utils\Sorting;

/**
* @method onBeforeFilter(IDataSource $dataSource)
* @method onAfterFilter(IDataSource $dataSource)
* @method onAfterPaginated(IDataSource $dataSource)
*/
interface DataModelInterface
{

public function getDataSource(): IDataSource;


public function filterData(?DataGridPaginator $paginatorComponent, Sorting $sorting, array $filters): iterable;


/**
* @return mixed
*/
public function filterRow(array $condition);
}
13 changes: 13 additions & 0 deletions src/Exception/InitializingDataModelCallbacksException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types = 1);

namespace Ublaboo\DataGrid\Exception;

use Throwable;

class InitializingDataModelCallbacksException extends DataGridException
{
public function __construct(?Throwable $previous = null)
{
parent::__construct("Cannot set callbacks before data model is set.", 0, $previous);
}
}
2 changes: 1 addition & 1 deletion src/InlineEdit/InlineEdit.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public function addControlsClasses(Container $container): void

break;
default:
if ($control->getControl()->getAttribute('class') === null) {
if ($control->getControlPrototype()->getAttribute('class') === null) {
$control->setAttribute('class', 'form-control input-sm form-control-sm');
}

Expand Down
100 changes: 100 additions & 0 deletions src/RestBasedDataModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types = 1);

namespace Ublaboo\DataGrid;

use Nette\SmartObject;
use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
use Ublaboo\DataGrid\DataSource\IDataSource;
use Ublaboo\DataGrid\Utils\Sorting;

/**
* @method onBeforeFilter(IDataSource $dataSource)
* @method onAfterFilter(IDataSource $dataSource)
* @method onAfterPaginated(IDataSource $dataSource)
*/
final class RestBasedDataModel implements DataModelInterface
{

use SmartObject;

/**
* @var array|callable[]
*/
public $onBeforeFilter = [];

/**
* @var array|callable[]
*/
public $onAfterFilter = [];

/**
* @var array|callable[]
*/
public $onAfterPaginated = [];

/**
* @var IDataSource
*/
private $dataSource;


public function __construct(IDataSource $source)
{
$this->dataSource = $source;
}


public function getDataSource(): IDataSource
{
return $this->dataSource;
}


public function filterData(
?DataGridPaginator $paginatorComponent,
Sorting $sorting,
array $filters
): iterable
{
$this->onBeforeFilter($this->dataSource);

$this->dataSource->filter($filters);

$this->onAfterFilter($this->dataSource);

/**
* Paginator is optional
*/
if ($paginatorComponent !== null) {
$paginator = $paginatorComponent->getPaginator();

$this->dataSource->sort($sorting)->limit(
$paginator->getOffset(),
$paginator->getItemsPerPage()
);

$this->onAfterPaginated($this->dataSource);

$data = $this->dataSource->getData();
$paginator->setItemCount($this->dataSource->getCount());

return $data;
}

return $this->dataSource->sort($sorting)->getData();
}


/**
* @return mixed
*/
public function filterRow(array $condition)
{
$this->onBeforeFilter($this->dataSource);
$this->onAfterFilter($this->dataSource);

return $this->dataSource->filterOne($condition)->getData();
}
}
46 changes: 26 additions & 20 deletions src/templates/datagrid.latte
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,10 @@
{/foreach}

<td class="col-action col-action-inline-edit">
{input $filter['inline_edit']['cancel'], class => 'btn btn-xs btn-danger'}
{input $filter['inline_edit']['submit'], class => 'btn btn-xs btn-primary'}
{block inline-edit-buttons}
{input $filter['inline_edit']['cancel'], class => 'btn btn-xs btn-danger'}
{input $filter['inline_edit']['submit'], class => 'btn btn-xs btn-primary'}
{/block}
{input $filter['inline_edit']['_id']}
{input $filter['inline_edit']['_primary_where_column']}
</td>
Expand All @@ -292,24 +294,26 @@
{$td->endTag()|noescape}
{/foreach}
<td n:if="$actions || $control->isSortable() || $itemsDetail || $inlineEdit || $inlineAdd" class="col-action">
{foreach $actions as $key => $action}
{if $row->hasAction($key)}
{if $action->hasTemplate()}
{include $action->getTemplate(), item => $item, (expand) $action->getTemplateVariables(), row => $row}
{else}
{$action->render($row)|noescape}
{block col-actions}
{foreach $actions as $key => $action}
{if $row->hasAction($key)}
{if $action->hasTemplate()}
{include $action->getTemplate(), item => $item, (expand) $action->getTemplateVariables(), row => $row}
{else}
{$action->render($row)|noescape}
{/if}
{/if}
{/foreach}
<span class="handle-sort btn btn-xs btn-default btn-secondary" n:if="$control->isSortable()">
<i n:block="icon-arrows-v" class="{$iconPrefix}arrows-v {$iconPrefix}arrows-alt-v"></i>
</span>
{if $inlineEdit && $row->hasInlineEdit()}
{$inlineEdit->renderButton($row)|noescape}
{/if}
{/foreach}
<span class="handle-sort btn btn-xs btn-default btn-secondary" n:if="$control->isSortable()">
<i n:block="icon-arrows-v" class="{$iconPrefix}arrows-v {$iconPrefix}arrows-alt-v"></i>
</span>
{if $inlineEdit && $row->hasInlineEdit()}
{$inlineEdit->renderButton($row)|noescape}
{/if}
{if $itemsDetail && $itemsDetail->shouldBeRendered($row)}
{$itemsDetail->renderButton($row)|noescape}
{/if}
{if $itemsDetail && $itemsDetail->shouldBeRendered($row)}
{$itemsDetail->renderButton($row)|noescape}
{/if}
{/block}
</td>
</tr>
{/if}
Expand Down Expand Up @@ -437,8 +441,10 @@
{/foreach}

<td class="col-action col-action-inline-edit">
{input $filter['inline_add']['cancel']}
{input $filter['inline_add']['submit']}
{block inline-add-buttons}
{input $filter['inline_add']['cancel']}
{input $filter['inline_add']['submit']}
{/block}
</td>
</tr>
{/if}
Expand Down