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

Feature/Virtual Page Action Executor #1649

Merged
merged 23 commits into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions demos/data-action/action-setup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Atk4\Ui\Demos;

// Demo for Model action

use Atk4\Ui\App;
use Atk4\Ui\Message;

/** @var App $app */
$country = new CountryLock($app->db);
$entity = $country->tryLoadAny();
$countryId = $entity->getId();

// Model actions for this file are setup in DemoActionUtil.
DemoActionsUtil::setupDemoActions($country);

\Atk4\Ui\Header::addTo($app, ['Assign Model action to button event', 'subHeader' => 'Execute model action on this country record by clicking on the appropriate button on the right.']);

$msg = Message::addTo($app, ['Notes', 'type' => 'info']);
$msg->text->addParagraph('When passing an action to a button event, Ui will determine what executor is required base on the action properties.');
$msg->text->addParagraph('If action require arguments, fields and/or preview, then a ModalExecutor will be use.');

\Atk4\Ui\View::addTo($app, ['ui' => 'ui clearing divider']);

$gl = \Atk4\Ui\GridLayout::addTo($app, ['rows' => 1, 'columns' => 2]);
$c = \Atk4\Ui\Card::addTo($gl, ['useLabel' => true], ['r1c1']);
$c->addContent(new \Atk4\Ui\Header(['Using country: ']));
$c->setModel($entity, [$country->fieldName()->iso, $country->fieldName()->iso3, $country->fieldName()->phonecode]);

$buttons = \Atk4\Ui\View::addTo($gl, ['ui' => 'vertical basic buttons'], ['r1c2']);

// Create a button for every action in Country model.
foreach ($country->getUserActions() as $action) {
$b = \Atk4\Ui\Button::addTo($buttons, [$action->getCaption()]);
// Assign action to button using current model id as url arguments.
$b->on('click', $action, ['args' => ['id' => $countryId]]);
}
15 changes: 15 additions & 0 deletions demos/data-action/jsactions-vp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Atk4\Ui\Demos;

use Atk4\Ui\UserAction\VpExecutor;

/** @var \Atk4\Ui\App $app */
require_once __DIR__ . '/../init-app.php';

$factory = $app->getExecutorFactory();
$factory->registerTypeExecutor($factory::STEP_EXECUTOR, [VpExecutor::class]);

require_once 'action-setup.php';
34 changes: 1 addition & 33 deletions demos/data-action/jsactions2.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,6 @@

namespace Atk4\Ui\Demos;

use Atk4\Ui\Message;

/** @var \Atk4\Ui\App $app */
require_once __DIR__ . '/../init-app.php';

// Demo for Model action

$country = new CountryLock($app->db);
$entity = $country->tryLoadAny();
$countryId = $entity->getId();

// Model actions for this file are setup in DemoActionUtil.
DemoActionsUtil::setupDemoActions($country);

\Atk4\Ui\Header::addTo($app, ['Assign Model action to button event', 'subHeader' => 'Execute model action on this country record by clicking on the appropriate button on the right.']);

$msg = Message::addTo($app, ['Notes', 'type' => 'info']);
$msg->text->addParagraph('When passing an action to a button event, Ui will determine what executor is required base on the action properties.');
$msg->text->addParagraph('If action require arguments, fields and/or preview, then a ModalExecutor will be use.');

\Atk4\Ui\View::addTo($app, ['ui' => 'ui clearing divider']);

$gl = \Atk4\Ui\GridLayout::addTo($app, ['rows' => 1, 'columns' => 2]);
$c = \Atk4\Ui\Card::addTo($gl, ['useLabel' => true], ['r1c1']);
$c->addContent(new \Atk4\Ui\Header(['Using country: ']));
$c->setModel($entity, [$country->fieldName()->iso, $country->fieldName()->iso3, $country->fieldName()->phonecode]);

$buttons = \Atk4\Ui\View::addTo($gl, ['ui' => 'vertical basic buttons'], ['r1c2']);

// Create a button for every action in Country model.
foreach ($country->getUserActions() as $action) {
$b = \Atk4\Ui\Button::addTo($buttons, [$action->getCaption()]);
// Assign action to button using current model id as url arguments.
$b->on('click', $action, ['args' => ['id' => $countryId]]);
}
require_once 'action-setup.php';
3 changes: 2 additions & 1 deletion demos/init-app.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@
$menu = $layout->addMenuGroup(['Data Action Executor', 'icon' => 'wrench']);
$layout->addMenuItem(['Executor Examples'], [$path . 'actions'], $menu);
$layout->addMenuItem(['Assign action to event'], [$path . 'jsactions'], $menu);
$layout->addMenuItem(['Assign action to button event'], [$path . 'jsactions2'], $menu);
$layout->addMenuItem(['Assign action to button (Modal)'], [$path . 'jsactions2'], $menu);
$layout->addMenuItem(['Assign action to button (V. Page)'], [$path . 'jsactions-vp'], $menu);
$layout->addMenuItem(['Execute from Grid'], [$path . 'jsactionsgrid'], $menu);
$layout->addMenuItem(['Execute from Crud'], [$path . 'jsactionscrud'], $menu);
$layout->addMenuItem(['Executor Factory'], [$path . 'factory'], $menu);
Expand Down
4 changes: 4 additions & 0 deletions js/Release.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Release note

### version 1.20.0 (2021-07-14)

- Add redirect utils method.

### version 1.19.4 (2021-07-11)

- Remove "debounceTimeout" atk option.
Expand Down
2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "atkjs-ui",
"version": "1.19.4",
"version": "1.20.0",
"description": "Agile Toolkit Javascript library.",
"main": "lib/atkjs-ui.js",
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions js/src/atk-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ const atkUtils = (function () {
},
};
},
redirect: function (url, params) {
document.location = $.atkAddParams(url, params);
},
};
}());

Expand Down
117 changes: 0 additions & 117 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,6 @@ parameters:
-
path: 'src/UserAction/ExecutorFactory.php'
message: '~^Call to an undefined method Atk4\\Ui\\AbstractView::setAction\(\)\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Access to an undefined property Atk4\\Ui\\AbstractView::\$buttonSave\.$~'
-
path: 'src/View.php'
message: '~^Call to an undefined method Atk4\\Ui\\JsChain::emit\(\)\.$~'
Expand Down Expand Up @@ -625,15 +622,6 @@ parameters:
-
path: 'src/UserAction/JsCallbackExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\JsCallbackExecutor::\$jsSuccess \(Atk4\\Ui\\JsExpressionable\) does not accept array\|Closure\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$form \(string\) does not accept default value of type array\<int, string\>\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsStepSubmit\(\) should return array but returns Atk4\\Ui\\Message\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::addFormTo\(\) should return Atk4\\Ui\\Form but returns Atk4\\Ui\\AbstractView\.$~'
-
path: 'src/View.php'
message: '~^Property Atk4\\Data\\Field::\$type \(string\) does not accept null\.$~'
Expand Down Expand Up @@ -886,9 +874,6 @@ parameters:
-
path: 'src/UserAction/JsCallbackExecutor.php'
message: '~^Instanceof between Atk4\\Ui\\JsExpressionable and Closure will always evaluate to false\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Instanceof between Atk4\\Ui\\JsExpressionable and Closure will always evaluate to false\.$~'
-
path: 'src/View.php'
message: '~^Negated boolean expression is always false\.$~'
Expand All @@ -913,12 +898,6 @@ parameters:

# TODO these rules are generated, this ignores should be fixed in the code
# for level = 5
-
path: 'demos/_includes/ReloadTest.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsReload given\.$~'
-
path: 'demos/_includes/ViewTester.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsReload given\.$~'
-
path: 'demos/_unit-test/lookup-virtual-page.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\Menu::addItem\(\) expects array\|string\|null, Atk4\\Ui\\JsModal given\.$~'
Expand All @@ -934,9 +913,6 @@ parameters:
-
path: 'demos/collection/grid.php'
message: '~^Parameter \#1 \$name of method Atk4\\Ui\\Grid::addColumn\(\) expects string, null given\.$~'
-
path: 'demos/collection/table.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsToast given\.$~'
-
path: 'demos/data-action/jsactionsgrid.php'
message: '~^Parameter \#1 \$view of method Atk4\\Ui\\Grid::addActionMenuItem\(\) expects Atk4\\Ui\\View, string given\.$~'
Expand All @@ -958,9 +934,6 @@ parameters:
-
path: 'demos/interactive/virtual.php'
message: '~^Parameter \#1 \$title of class Atk4\\Ui\\JsModal constructor expects string, null given\.$~'
-
path: 'demos/javascript/reloading.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsReload given\.$~'
-
path: 'demos/javascript/reloading.php'
message: '~^Parameter \#1 \$defaults of method Atk4\\Ui\\Form\\Control\\Input::addAction\(\) expects array, string given\.$~'
Expand All @@ -982,18 +955,12 @@ parameters:
-
path: 'src/Card.php'
message: '~^Parameter \#2 \$selector of method Atk4\\Ui\\View::on\(\) expects Atk4\\Ui\\JsExpressionable\|string\|null, Atk4\\Data\\Model\\UserAction given\.$~'
-
path: 'src/Console.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsExpressionable given\.$~'
-
path: 'src/Form.php'
message: '~^Parameter \#1 \$object of method Atk4\\Ui\\View::add\(\) expects Atk4\\Ui\\View, Atk4\\Ui\\JsCallback given\.$~'
-
path: 'src/Form.php'
message: '~^Parameter \#2 \$value of method Atk4\\Ui\\View::setAttr\(\) expects string\|null, int given\.$~'
-
path: 'src/Form.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsConditionalForm given\.$~'
-
path: 'src/Form/Layout/Columns.php'
message: '~^Parameter \#2 \$fields of method Atk4\\Ui\\Form\\AbstractLayout::setModel\(\) expects array\|null, false given\.$~'
Expand Down Expand Up @@ -1036,18 +1003,9 @@ parameters:
-
path: 'src/Table/Column/Delete.php'
message: '~^Parameter \#1 \$object of method Atk4\\Ui\\View::add\(\) expects Atk4\\Ui\\View, Atk4\\Ui\\CallbackLater given\.$~'
-
path: 'src/UserAction/ConfirmationExecutor.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsExpressionable given\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Parameter \#2 \$selector of method Atk4\\Ui\\View::on\(\) expects Atk4\\Ui\\JsExpressionable\|string\|null, array\<int, mixed\> given\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Parameter \#2 \$action of method Atk4\\Ui\\View::js\(\) expects Atk4\\Ui\\JsExpression\|null, Atk4\\Ui\\JsExpressionable given\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Parameter \#1 \$object of method Atk4\\Ui\\View::add\(\) expects Atk4\\Ui\\View, string given\.$~'
-
path: 'src/View.php'
message: '~^Parameter \#1 \$object of method Atk4\\Ui\\View::add\(\) expects Atk4\\Ui\\View, Atk4\\Ui\\JsCallback given\.$~'
Expand Down Expand Up @@ -2401,81 +2359,6 @@ parameters:
-
path: 'src/UserAction/JsCallbackExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\JsCallbackExecutor::_hasAllArguments\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/JsExecutorInterface.php'
message: '~^Method Atk4\\Ui\\UserAction\\JsExecutorInterface::jsExecute\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$actionInitialized has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$step has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$nextStepBtn has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$execActionBtn has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$btns has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$loaderUi has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Property Atk4\\Ui\\UserAction\\ModalExecutor::\$loaderShim has no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::afterActionInit\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::executeModelAction\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::assignTrigger\(\) has parameter \$selector with no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::doArgs\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::doFields\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::doPreview\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::doFinal\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsGetExecute\(\) has parameter \$id with no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsGetExecute\(\) has parameter \$obj with no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsSetBtnState\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsSetSubmitBtn\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::jsSetPrevHandler\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::_addStepTitle\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::_jsSequencer\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::_handleException\(\) has no return typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::_handleException\(\) has parameter \$step with no typehint specified\.$~'
-
path: 'src/UserAction/ModalExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\ModalExecutor::_handleException\(\) has parameter \$view with no typehint specified\.$~'
-
path: 'src/UserAction/PreviewExecutor.php'
message: '~^Method Atk4\\Ui\\UserAction\\PreviewExecutor::initPreview\(\) has no return typehint specified\.$~'
Expand Down
2 changes: 1 addition & 1 deletion public/atkjs-ui.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/CardDeck.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ protected function init(): void

if ($this->paginator !== false) {
$this->addPaginator();
$this->issetApp() ? $this->getApp()->stickyGet($this->paginator->name) : $this->stickyGet($this->paginator->name);
mvorisek marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/JsChain.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* IMPORTANT: don't write any JavaScript logic in PHP, only bind.
*
* IMPORTANT: all methods in this class are pre-pended with '_', to avoid clashes with js-mapping.
*
* @method Jquery redirect(...$args)
*/
class JsChain extends JsExpression
{
Expand Down
5 changes: 4 additions & 1 deletion src/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Loader extends View
/** @var Callback for triggering */
protected $cb;

/** @var array Url arguments. */
public $urlArgs = [];

protected function init(): void
{
parent::init();
Expand Down Expand Up @@ -92,7 +95,7 @@ protected function renderView(): void
{
if (!$this->cb->isTriggered()) {
if ($this->loadEvent) {
$this->js($this->loadEvent, $this->jsLoad());
$this->js($this->loadEvent, $this->jsLoad($this->urlArgs));
}
$this->add($this->shim);
}
Expand Down
4 changes: 1 addition & 3 deletions src/UserAction/ConfirmationExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ public function afterActionInit(Model\UserAction $action)

/**
* Return js expression that will trigger action executor.
*
* @return mixed
*/
public function jsExecute(array $urlArgs)
public function jsExecute(array $urlArgs): array
{
if (!$this->actionInitialized) {
throw new Exception('Action must be set prior to assign trigger.');
Expand Down
6 changes: 3 additions & 3 deletions src/UserAction/ExecutorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
class ExecutorFactory
{
public const JS_EXECUTOR = self::class . '@jsExecutorSeed';
public const MODAL_EXECUTOR = self::class . '@modalExecutorSeed';
public const STEP_EXECUTOR = self::class . '@stepExecutorSeed';
public const CONFIRMATION_EXECUTOR = self::class . '@confirmationExecutorClass';
public const BASIC_BUTTON = self::class . '@basicButton';
public const MODAL_BUTTON = self::class . '@modalExecutorButton';
Expand All @@ -38,7 +38,7 @@ class ExecutorFactory
*/
protected $executorSeed = [
self::JS_EXECUTOR => [JsCallbackExecutor::class],
self::MODAL_EXECUTOR => [ModalExecutor::class],
self::STEP_EXECUTOR => [ModalExecutor::class],
self::CONFIRMATION_EXECUTOR => [ConfirmationExecutor::class],
];

Expand Down Expand Up @@ -168,7 +168,7 @@ protected function createExecutor(UserAction $action, View $owner, string $requi
} else {
$seed = (!$action->args && !$action->fields && !$action->preview)
? $this->executorSeed[self::JS_EXECUTOR]
: $this->executorSeed[self::MODAL_EXECUTOR];
: $this->executorSeed[self::STEP_EXECUTOR];
}
}

Expand Down
Loading