Skip to content

Commit

Permalink
Adjust code for removed UserAction::$modifier property (#2231)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek authored Nov 23, 2024
1 parent 75603bf commit aa8a745
Show file tree
Hide file tree
Showing 20 changed files with 56 additions and 50 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Agile UI is the quickest way for building back-end UI, admin interfaces, data ma
- Agile UI offers out-of-the-box components, you don't need front-end development experience.
- Agile UI is interactive, making it very easy to trigger PHP code on JS events.
- Agile UI is compact - single file, several lines of code - that's all it takes.
- Agile UI is extensible - integrates VueJS for custom components and interactive behaviours.
- Agile UI is extensible - integrates VueJS for custom components and interactive behaviors.

[![Build](https://github.com/atk4/ui/actions/workflows/test-unit.yml/badge.svg?branch=develop)](https://github.com/atk4/ui/actions?query=branch:develop)
[![CodeCov](https://codecov.io/gh/atk4/ui/branch/develop/graph/badge.svg)](https://codecov.io/gh/atk4/ui)
Expand Down
2 changes: 1 addition & 1 deletion demos/collection/card-deck.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
'callback' => static function (Country $country, $email) {
return 'Your request for information was sent to email: ' . $email;
},
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORD,
]);

$infoAction->args = [
Expand Down
2 changes: 1 addition & 1 deletion demos/data-action/actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
'args' => [
'path' => ['type' => 'string', 'required' => true],
],
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORD,
]);

Header::addTo($app, [
Expand Down
4 changes: 2 additions & 2 deletions demos/data-action/jsactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
$country = new Country($app->db);

$sendEmailAction = $country->addUserAction('Email', [
'confirmation' => 'Are you sure you wish to send an email?',
'confirmation' => 'Are you sure to send an email?',
'callback' => static function (Country $country) {
return 'Email to Kristy in ' . $country->name . ' has been sent!';
},
Expand All @@ -42,7 +42,7 @@

// note here that we explicitly required a JsCallbackExecutor for the greet action
$country->addUserAction('greet', [
'appliesTo' => UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => UserAction::APPLIES_TO_NO_RECORD,
'args' => [
'name' => [
'type' => 'string',
Expand Down
2 changes: 1 addition & 1 deletion demos/data-action/jsactionscrud.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
'args' => [
'path' => ['type' => 'string', 'required' => true],
],
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORD,
]);

$files->addUserAction('download', static function (Model $entity) {
Expand Down
4 changes: 2 additions & 2 deletions demos/tutorial/actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
$model = new Model($owner->getApp()->db, ['table' => 'test']);

$model->addUserAction('greet', [
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORD,
'args' => [
'name' => [
'type' => 'string',
Expand All @@ -130,7 +130,7 @@
]);

$model->addUserAction('ask_age', [
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORDS,
'appliesTo' => Model\UserAction::APPLIES_TO_NO_RECORD,
'args' => [
'age' => [
'type' => 'integer',
Expand Down
2 changes: 1 addition & 1 deletion docs/callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ another request to the server:
- the {php:meth}`Callback::set()` will notice this argument and execute "terminate()"
- terminate() will exit app execution and output 'in callback' back to user.

Calling {php:meth}`App::terminate()` will prevent the default behaviour (of rendering UI) and will
Calling {php:meth}`App::terminate()` will prevent the default behavior (of rendering UI) and will
output specified string instead, stopping further execution of your application.

# Return value of set()
Expand Down
6 changes: 3 additions & 3 deletions docs/dataexecutor.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ Executors can use the HOOK_AFTER_EXECUTE hook in order to return javascript acti
executing. It is use in Crud for example in order to display users of successful model UserAction execution. Either by displaying
Toast messages or removing a row within a Crud table.

Some Ui View component, like Crud for example, will also set javascript action to return based on the UserAction::modifier property.
For example it the modifier property is set to MODIFIER_DELETE then Crud will know it has to delete a table row on the
other hand, if MODIFIER_UPDATE is set, then Table needs to be reloaded.
Some Ui View component, like Crud for example, will also set javascript action to return based on the UserAction behavior.
For example if the action deleted an entity then Crud will delete a table row. If the action updated an entity
then Table needs to be reloaded.

## The Executor Factory

Expand Down
2 changes: 1 addition & 1 deletion docs/form-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ function (string $value, $key) {

### Dropdown Settings

There's a bunch of settings to influence Dropdown behaviour.
There's a bunch of settings to influence Dropdown behavior.

:::{php:attr} empty
:::
Expand Down
2 changes: 1 addition & 1 deletion docs/grid.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ $grid->menu->addItem('show selection')
:::

When grid is associated with a model that supports order, it will automatically make itself sortable. You can
override this behaviour by setting $sortable property to `true` or `false`.
override this behavior by setting $sortable property to `true` or `false`.

You can also set $sortable property for each table column decorator. That way you can enable/disable sorting
of particular columns.
Expand Down
2 changes: 1 addition & 1 deletion docs/multiline.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ You will find a list of Vue component associated with each field type within the
:::{php:attr} fieldMapToComponent
:::

Each control being a Vue component means that they accept 'Props' that may change their look or behaviour.
Each control being a Vue component means that they accept 'Props' that may change their look or behavior.
Props on each component may be applied globally, i.e. to all control within Multiline that use that control, or
per component.

Expand Down
2 changes: 1 addition & 1 deletion docs/view.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ View::addTo($app, ['defaultTemplate' => __DIR__ . '/../templates/mytpl.httml']);

Agile UI does not currently provide advanced search path for templates, by default the
template is loaded from folder `vendor/atk4/ui/template`. To change this
behaviour, see {php:meth}`App::loadTemplate()`.
behavior, see {php:meth}`App::loadTemplate()`.

:::{php:attr} region
:::
Expand Down
2 changes: 1 addition & 1 deletion docs/virtualpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Returns JS action which will trigger loading. The action will be carried out in
:::

If you have NOT invoked jsLoad in your code, Loader will automatically assign it do DOM Ready(). If the automatic
behaviour does not work, you should set value for $loadEvent:
behavior does not work, you should set value for $loadEvent:

- null = load on DOM ready unless you have invoked jsLoad() in the code.
- true = load on DOM ready
Expand Down
2 changes: 1 addition & 1 deletion src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ public function getTag(string $tag, array $attr = [], $value = null): string
}
// see https://mathiasbynens.be/notes/etago
$result[] = preg_replace('~(?<=<)(?=/\s*' . preg_quote($tag, '~') . '|!--)~', '\\\\', $v);
} elseif (is_array($value)) { // todo, remove later and fix wrong usages, this is the original behaviour, only directly passed strings were escaped
} elseif (is_array($value)) { // todo, remove later and fix wrong usages, this is the original behavior, only directly passed strings were escaped
$result[] = $v;
} else {
$result[] = $this->encodeHtml($v);
Expand Down
2 changes: 1 addition & 1 deletion src/Behat/MinkSeleniumDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected function mouseOverElement(WebDriverElement $element): void
{
// move the element into the viewport
// needed at least for Firefox as Selenium moveto does move the mouse cursor only
$this->executeScript('arguments[0].scrollIntoView({ behaviour: \'instant\', block: \'center\', inline: \'center\' })', [$element]);
$this->executeScript('arguments[0].scrollIntoView({ behavior: \'instant\', block: \'center\', inline: \'center\' })', [$element]);

$this->getWebDriverSession()->moveto(['element' => $element->getID()]);
}
Expand Down
4 changes: 2 additions & 2 deletions src/CardDeck.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public function setModel(Model $model, ?array $fields = null, ?array $extra = nu

// add no record scope action to menu
if ($this->useAction && $this->menu) {
foreach ($this->getModelActions(Model\UserAction::APPLIES_TO_NO_RECORDS) as $k => $action) {
foreach ($this->getModelActions(Model\UserAction::APPLIES_TO_NO_RECORD) as $k => $action) {
$executor = $this->initActionExecutor($action);
$this->menuActions[$k]['button'] = $this->menu->addItem(
$this->getExecutorFactory()->createTrigger($action, ExecutorFactory::MENU_ITEM)
Expand Down Expand Up @@ -287,7 +287,7 @@ private function getModelActions(string $appliesTo): array
$this->singleScopeActions,
array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions)
);
} elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORDS && $this->noRecordScopeActions !== []) {
} elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORD && $this->noRecordScopeActions !== []) {
$actions = array_combine(
$this->noRecordScopeActions,
array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions)
Expand Down
54 changes: 28 additions & 26 deletions src/Crud.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Crud extends Grid
/** @var bool|null Should we use table column drop-down menu to display user actions? */
public $useMenuActions;

/** @var array<string, array{item: MenuItem, executor: AbstractView&ExecutorInterface}> Collection of APPLIES_TO_NO_RECORDS Scope Model action menu item */
/** @var array<string, array{item: MenuItem, executor: AbstractView&ExecutorInterface}> Collection of APPLIES_TO_NO_RECORD Scope Model action menu item */
private array $menuItems = [];

/** @var list<string> Model single scope action to include in table action column. Will include all single scope actions if empty. */
Expand All @@ -51,7 +51,10 @@ class Crud extends Grid
public $defaultMsg = 'Done!';

/** @var list<array<string, \Closure(Form, UserAction\ModalExecutor): void>> Callback containers for model action. */
public $onActions = [];
public array $onActions = [];

/** @var mixed Recently created/updated record ID. */
private $updatedId;

/** @var mixed Recently deleted record ID. */
private $deletedId;
Expand Down Expand Up @@ -96,9 +99,14 @@ public function setModel(Model $model, ?array $fields = null): void

parent::setModel($model, $this->displayFields);

// grab model ID when using delete
// must be set before delete action execute
$this->model->onHook(Model::HOOK_BEFORE_SAVE, function (Model $entity) {
$this->updatedId = $entity->getId();
});
$this->model->onHook(Model::HOOK_AFTER_SAVE, function (Model $entity) {
$this->updatedId = $entity->getId();
});
$this->model->onHook(Model::HOOK_AFTER_DELETE, function (Model $entity) {
$this->updatedId = null;
$this->deletedId = $entity->getId();
});

Expand All @@ -116,7 +124,7 @@ public function setModel(Model $model, ?array $fields = null): void
}

if ($this->menu) {
foreach ($this->_getModelActions(Model\UserAction::APPLIES_TO_NO_RECORDS) as $k => $action) {
foreach ($this->_getModelActions(Model\UserAction::APPLIES_TO_NO_RECORD) as $k => $action) {
if ($action->enabled) {
$executor = $this->initActionExecutor($action);
$this->menuItems[$k]['item'] = $this->menu->addItem(
Expand Down Expand Up @@ -176,13 +184,13 @@ protected function jsExecute($return, Model\UserAction $action): JsBlock
$res->addStatement($jsAction);
}

// display msg return by action or depending on action modifier
// display msg return by action or depending on action behavior
if (is_string($return)) {
$res->addStatement($this->jsCreateNotifier($return));
} else {
if ($action->modifier === Model\UserAction::MODIFIER_CREATE || $action->modifier === Model\UserAction::MODIFIER_UPDATE) {
if ($this->updatedId !== null) {
$res->addStatement($this->jsCreateNotifier($this->saveMsg));
} elseif ($action->modifier === Model\UserAction::MODIFIER_DELETE) {
} elseif ($this->deletedId !== null) {
$res->addStatement($this->jsCreateNotifier($this->deleteMsg));
} else {
$res->addStatement($this->jsCreateNotifier($this->defaultMsg));
Expand All @@ -193,26 +201,20 @@ protected function jsExecute($return, Model\UserAction $action): JsBlock
}

/**
* Return proper JS actions depending on action modifier type.
* Return proper JS actions depending on action behavior.
*/
protected function getJsGridAction(Model\UserAction $action): ?JsExpressionable
{
switch ($action->modifier) {
case Model\UserAction::MODIFIER_UPDATE:
case Model\UserAction::MODIFIER_CREATE:
$js = $this->container->jsReload($this->_getReloadArgs());

break;
case Model\UserAction::MODIFIER_DELETE:
// use deleted record ID to remove row, fallback to closest tr if ID is not available
$js = $this->deletedId
? $this->js(false, null, 'tr[data-id="' . $this->getApp()->uiPersistence->typecastAttributeSaveField($this->model->getIdField(), $this->deletedId) . '"]')
: (new Jquery())->closest('tr');
$js = $js->transition('fade left', new JsFunction([], [new JsExpression('this.remove()')]));

break;
default:
$js = null;
if ($this->updatedId !== null) {
$js = $this->container->jsReload($this->_getReloadArgs());
} elseif ($this->deletedId !== null) {
// use deleted record ID to remove row, fallback to closest tr if ID is not available
$js = $this->deletedId
? $this->js(false, null, 'tr[data-id="' . $this->getApp()->uiPersistence->typecastAttributeSaveField($this->model->getIdField(), $this->deletedId) . '"]')
: (new Jquery())->closest('tr');
$js = $js->transition('fade left', new JsFunction([], [new JsExpression('this.remove()')]));
} else {
$js = null;
}

return $js;
Expand Down Expand Up @@ -292,7 +294,7 @@ private function _getModelActions(string $appliesTo): array
$this->singleScopeActions,
array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions)
);
} elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORDS && $this->noRecordScopeActions !== []) {
} elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORD && $this->noRecordScopeActions !== []) {
$actions = array_combine(
$this->noRecordScopeActions,
array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions)
Expand Down
2 changes: 1 addition & 1 deletion src/UserAction/CommonExecutorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected function executeModelActionLoad(Model\UserAction $action): Model\UserA
} else {
$action = $action->getActionForEntity($model->load($id));
}
} elseif (!$action->isOwnerEntity() && in_array($action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) {
} elseif (!$action->isOwnerEntity() && in_array($action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORD, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) {
$action = $action->getActionForEntity($model->createEntity());
}

Expand Down
2 changes: 1 addition & 1 deletion src/UserAction/JsCallbackExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private function executeModelActionLoad(Model\UserAction $action): Model\UserAct
} else {
$action = $action->getActionForEntity($model->load($id));
}
} elseif (!$action->isOwnerEntity() && in_array($action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORDS, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) {
} elseif (!$action->isOwnerEntity() && in_array($action->appliesTo, [Model\UserAction::APPLIES_TO_NO_RECORD, Model\UserAction::APPLIES_TO_SINGLE_RECORD], true)) {
$action = $action->getActionForEntity($model->createEntity());
}

Expand Down
6 changes: 5 additions & 1 deletion src/UserAction/StepExecutorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ trait StepExecutorTrait
public $previewType = 'html';

/** @var array<string, array<mixed>> View seed for displaying title for each step. */
protected $stepTitle = ['args' => [], 'fields' => [], 'preview' => []];
protected array $stepTitle = [
'args' => [],
'fields' => [],
'preview' => [],
];

/** @var string */
public $finalMsg = 'Complete!';
Expand Down

0 comments on commit aa8a745

Please sign in to comment.