Skip to content

Commit

Permalink
Minor table columns improvements (#2149)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek authored Jan 30, 2024
1 parent 5aaca5b commit 595e3cd
Show file tree
Hide file tree
Showing 22 changed files with 140 additions and 124 deletions.
2 changes: 1 addition & 1 deletion docs/tablecolumn.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ fields of your models and will conditionally add Link on top of Money formatting
The callback must return array of seeds like:

```
[[\Atk4\Ui\Table\Column\Link::class], \Atk4\Ui\Table\Column\Money::class]
[[\Atk4\Ui\Table\Column\Link::class], [\Atk4\Ui\Table\Column\Money::class]]
```

Multiple decorators will be created and merged.
Expand Down
1 change: 1 addition & 0 deletions js/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = {
'import/resolver': 'webpack',
},
rules: {
'brace-style': ['error', '1tbs'],
'class-methods-use-this': 'off',
'comma-dangle': ['error', {
arrays: 'always-multiline',
Expand Down
8 changes: 6 additions & 2 deletions js/src/plugins/confirm.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ export default class AtkConfirmPlugin extends AtkPlugin {

// create wrapper function for using proper "this" context
if (this.settings.onApprove) {
options.onApprove = () => { this.settings.onApprove.call(context); };
options.onApprove = () => {
this.settings.onApprove.call(context);
};
}
if (this.settings.onDeny) {
options.onDeny = () => { this.settings.onDeny.call(context); };
options.onDeny = () => {
this.settings.onDeny.call(context);
};
}

options = Object.assign(options, this.settings.modalOptions);
Expand Down
4 changes: 3 additions & 1 deletion js/src/services/upload.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ class UploadService {
data,
uploadUrl,
completeCb = function (r, c) {},
xhrCb = function () { return new window.XMLHttpRequest(); }
xhrCb = function () {
return new window.XMLHttpRequest();
}
) {
const formData = new FormData();

Expand Down
4 changes: 3 additions & 1 deletion js/src/setup-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ atk.options = (function () {
const data = {};

return {
set: (name, value) => { data[name] = value; },
set: (name, value) => {
data[name] = value;
},
get: (name) => data[name],
};
}());
Expand Down
6 changes: 0 additions & 6 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,6 @@ parameters:
-
path: 'src/Header.php'
message: '~^Property Atk4\\Ui\\Header::\$subHeader \(string\) does not accept \$this\(Atk4\\Ui\\Header\)\.$~'
-
path: 'src/JsSearch.php'
message: '~^Property Atk4\\Ui\\JsSearch::\$placeHolder \(Atk4\\Ui\\Form\\Control\\Line\|null\) does not accept default value of type string\.$~'
-
path: 'src/Label.php'
message: '~^Property Atk4\\Ui\\Label::\$detail \(string\|false\|null\) does not accept \$this\(Atk4\\Ui\\Label\)\.$~'
Expand Down Expand Up @@ -386,9 +383,6 @@ parameters:
-
path: 'src/Grid.php'
message: '~^Parameter #2 \$defaults of static method Atk4\\Core\\Factory::factory\(\) expects array, Atk4\\Ui\\Table\|false given\.$~'
-
path: 'src/JsSearch.php'
message: '~^Parameter #2 \$value of method Atk4\\Ui\\HtmlTemplate::trySet\(\) expects string\|null, Atk4\\Ui\\Form\\Control\\Line given\.$~'
-
path: 'src/Menu.php'
message: '~^Parameter #1 \$object of method Atk4\\Ui\\View::add\(\) expects Atk4\\Ui\\AbstractView, array<int\|string, array<int, string>\|string> given\.$~'
Expand Down
2 changes: 1 addition & 1 deletion public/js/atkjs-ui.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/atkjs-ui.min.js.map

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions src/Grid.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ class Grid extends View

public $defaultTemplate = 'grid.html';

/** @var array Defines which Table Decorator to use for ActionButtons. */
protected $actionButtonsDecorator = [Table\Column\ActionButtons::class];
/** @var array Table\Column seed to use for ActionButtons. */
protected $actionButtonsSeed = [Table\Column\ActionButtons::class];

/** @var array Defines which Table Decorator to use for ActionMenu. */
protected $actionMenuDecorator = [Table\Column\ActionMenu::class, 'label' => 'Actions...'];
/** @var array Table\Column seed to use for ActionMenu. */
protected $actionMenuSeed = [Table\Column\ActionMenu::class, 'label' => 'Actions...'];

#[\Override]
protected function init(): void
Expand Down Expand Up @@ -373,15 +373,17 @@ public function addExecutorButton(ExecutorInterface $executor, Button $button =
if (!$confirmation) {
$confirmation = '';
}
$disabled = is_bool($executor->getAction()->enabled) ? !$executor->getAction()->enabled : $executor->getAction()->enabled;
$disabled = is_bool($executor->getAction()->enabled)
? !$executor->getAction()->enabled
: $executor->getAction()->enabled;

return $this->getActionButtons()->addButton($button, $executor, $confirmation, $disabled);
}

private function getActionButtons(): Table\Column\ActionButtons
{
if ($this->actionButtons === null) {
$this->actionButtons = $this->table->addColumn(null, $this->actionButtonsDecorator);
$this->actionButtons = $this->table->addColumn(null, $this->actionButtonsSeed);
}

return $this->actionButtons; // @phpstan-ignore-line
Expand All @@ -408,12 +410,15 @@ public function addActionMenuItem($view, $action = null, string $confirmMsg = ''
public function addExecutorMenuItem(ExecutorInterface $executor)
{
$item = $this->getExecutorFactory()->createTrigger($executor->getAction(), ExecutorFactory::TABLE_MENU_ITEM);

// ConfirmationExecutor take care of showing the user confirmation, thus make it empty
$confirmation = !$executor instanceof ConfirmationExecutor ? $executor->getAction()->getConfirmation() : '';
if (!$confirmation) {
$confirmation = '';
}
$disabled = is_bool($executor->getAction()->enabled) ? !$executor->getAction()->enabled : $executor->getAction()->enabled;
$disabled = is_bool($executor->getAction()->enabled)
? !$executor->getAction()->enabled
: $executor->getAction()->enabled;

return $this->getActionMenu()->addActionMenuItem($item, $executor, $confirmation, $disabled);
}
Expand All @@ -424,7 +429,7 @@ public function addExecutorMenuItem(ExecutorInterface $executor)
private function getActionMenu()
{
if (!$this->actionMenu) {
$this->actionMenu = $this->table->addColumn(null, $this->actionMenuDecorator);
$this->actionMenu = $this->table->addColumn(null, $this->actionMenuSeed);
}

return $this->actionMenu; // @phpstan-ignore-line
Expand Down
2 changes: 1 addition & 1 deletion src/JsSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class JsSearch extends View
*/
public $autoQuery = false;

/** @var Form\Control\Line|null The input field. */
/** @var string|null */
public $placeHolder = 'Search';

/**
Expand Down
18 changes: 7 additions & 11 deletions src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ public function getDataRowHtml(): string
}

// we need to smartly wrap things up
$cell = null;
$cellHtml = null;
$tdAttr = [];
foreach ($column as $cKey => $c) {
if ($cKey !== array_key_last($column)) {
Expand All @@ -659,19 +659,15 @@ public function getDataRowHtml(): string
$html = $c->getDataCellHtml($field, $tdAttr);
}

if ($cell) {
if ($name) {
$cellHtml = $cellHtml === null
? $html
: ($name
// if name is set, we can wrap things
$cell = str_replace('{$' . $name . '}', $cell, $html);
} else {
$cell .= ' ' . $html;
}
} else {
$cell = $html;
}
? str_replace('{$' . $name . '}', $cellHtml, $html)
: $cellHtml . ' ' . $html);
}

$output[] = $cell;
$output[] = $cellHtml;
}

return implode('', $output);
Expand Down
59 changes: 37 additions & 22 deletions src/Table/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Column
/** @var Table Link back to the table, where column is used. */
public $table;

/** Contains any custom attributes that may be applied on head, body or foot. */
/** @var array<'head'|'body'|'foot'|'all', array<string, string|list<string>>> Contains any custom attributes that may be applied on head, body or foot. */
public array $attr = [];

/** @var string|null If set, will override column header value. */
Expand Down Expand Up @@ -87,7 +87,7 @@ protected function assertColumnViewNotInitialized(View $view): void
*
* @internal
*/
protected function cloneColumnView(View $view, string $nameSuffix): View
protected function cloneColumnView(View $view, Model $row, string $nameSuffix): View
{
$this->assertColumnViewNotInitialized($view);

Expand Down Expand Up @@ -117,7 +117,7 @@ protected function cloneColumnView(View $view, string $nameSuffix): View

$view = $cloneViewWithAddLaterFx($view);
$view->shortName = 'c' . $this->nameInTableCache . '_' . $nameSuffix . '_r'
. $this->getApp()->uiPersistence->typecastSaveField($this->table->model->getField($this->table->model->idField), $this->table->currentRow->getId());
. $this->getApp()->uiPersistence->typecastSaveField($row->getField($row->idField), $row->getId());
$view->name = \Closure::bind(static fn (Table $table) => $view->_shorten($table->name, $view->shortName, null), null, Table::class)($this->table);

return $view;
Expand Down Expand Up @@ -256,11 +256,10 @@ public function setHeaderDropdown($items, string $icon = 'caret square down', st
}

/**
* Adds a new class to the cells of this column. The optional second argument may be "head",
* "body" or "foot". If position is not defined, then class will be applied on all cells.
* Adds a new class to the cells of this column.
*
* @param string $class
* @param string $position
* @param string $class
* @param 'head'|'body'|'foot'|'all' $position
*
* @return $this
*/
Expand All @@ -272,16 +271,15 @@ public function addClass($class, $position = 'body')
}

/**
* Adds a new attribute to the cells of this column. The optional second argument may be "head",
* "body" or "foot". If position is not defined, then attribute will be applied on all cells.
* Adds a new attribute to the cells of this column.
*
* You can also use the "{$name}" value if you wish to specific row value:
*
* $table->column['name']->setAttr('data', '{$id}');
*
* @param string $attr
* @param string $value
* @param string $position
* @param string $attr
* @param string $value
* @param 'head'|'body'|'foot'|'all' $position
*
* @return $this
*/
Expand All @@ -292,24 +290,42 @@ public function setAttr($attr, $value, $position = 'body')
return $this;
}

public function getTagAttributes(string $position, array $attr = []): array
/**
* @param array<string, string|list<string>> ...$attributesArr
*/
protected function mergeTagAttributes(array ...$attributesArr): array
{
// "all" applies on all positions
// $position is for specific position classes
foreach (['all', $position] as $key) {
if (isset($this->attr[$key])) {
$attr = array_merge_recursive($attr, $this->attr[$key]);
$res = [];
foreach ($attributesArr as $attributes) {
foreach ($attributes as $k => $v) {
if (is_string($v)) {
$res[$k] = $v;
} else {
$res[$k] = array_merge($res[$k] ?? [], $v);
}
}
}

return $attr;
return $res;
}

/**
* @param 'head'|'body'|'foot' $position
*/
public function getTagAttributes(string $position, array $attr = []): array
{
return $this->mergeTagAttributes(
$this->attr['all'] ?? [],
$this->attr[$position] ?? [],
$attr
);
}

/**
* Returns a suitable cell tag with the supplied value. Applies modifiers
* added through addClass and setAttr.
*
* @param string $position 'head', 'body' or 'tail'
* @param 'head'|'body'|'foot' $position
* @param string|array<int, array{0: string, 1?: array<0|string, string|bool>, 2?: string|array|null}|string>|null $value either HTML or array defining HTML structure, see App::getTag help
* @param array<string, string|bool|array> $attr extra attributes to apply on the tag
*/
Expand Down Expand Up @@ -398,8 +414,7 @@ public function getTotalsCellHtml(Field $field, $value): string
* The must correspond to the name of the field, although you can also use multiple tags. The tag
* will also be formatted before inserting, see UI Persistence formatting in the documentation.
*
* This method will be executed only once per table rendering, if you need to format data manually,
* you should use $this->table->onHook('beforeRow' or 'afterRow', ...);
* If you need to format data manually, you can use $this->table->onHook(Lister::HOOK_BEFORE_ROW or Lister::HOOK_AFTER_ROW, ...);
*/
public function getDataCellHtml(Field $field = null, array $attr = []): string
{
Expand Down
25 changes: 10 additions & 15 deletions src/Table/Column/ActionButtons.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ActionButtons extends Table\Column
public $buttons = [];

/** @var array<string, \Closure(Model): bool> Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */
protected $callbacks = [];
protected $isEnabledFxs = [];

#[\Override]
protected function init(): void
Expand All @@ -37,7 +37,7 @@ protected function init(): void
}

/**
* Adds a new button which will execute $callback when clicked.
* Adds a new button which will execute $action when clicked.
*
* @param string|array|View $button
* @param JsExpressionable|JsCallbackSetClosure|ExecutorInterface $action
Expand All @@ -62,7 +62,7 @@ public function addButton($button, $action = null, string $confirmMsg = '', $isD
if ($isDisabled === true) {
$button->addClass('disabled');
} elseif ($isDisabled !== false) {
$this->callbacks[$name] = $isDisabled;
$this->isEnabledFxs[$name] = $isDisabled;
}

$button->setApp($this->table->getApp());
Expand Down Expand Up @@ -124,30 +124,25 @@ public function getDataCellTemplate(Field $field = null): string
}

// render our buttons
$outputHtml = '';
$outputHtmls = [];
foreach ($this->buttons as $name => $button) {
$button = $this->cloneColumnView($button, $name);
$outputHtml .= $button->getHtml();
$button = $this->cloneColumnView($button, $this->table->currentRow, $name);
$outputHtmls[] = $button->getHtml();
}

return $this->getApp()->getTag('div', ['class' => 'ui buttons'], [$outputHtml]);
return $this->getApp()->getTag('div', ['class' => 'ui buttons'], $outputHtmls);
}

#[\Override]
public function getHtmlTags(Model $row, ?Field $field): array
{
$tags = [];
foreach ($this->callbacks as $name => $callback) {
// if action is enabled then do not set disabled class
if ($callback($row)) {
continue;
foreach ($this->isEnabledFxs as $name => $isEnabledFx) {
if (!$isEnabledFx($row)) {
$tags['_' . $name . '_disabled'] = 'disabled';
}

$tags['_' . $name . '_disabled'] = 'disabled';
}

return $tags;
}

// rest will be implemented for crud
}
Loading

0 comments on commit 595e3cd

Please sign in to comment.