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

Minor table columns improvements #2149

Merged
merged 16 commits into from
Jan 30, 2024
Merged
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.
Copy link
Member Author

@mvorisek mvorisek Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* 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
Loading