Closed mhuser closed 1 year ago
I finally managed it by using javascript to set value of an hidden form input in a static modal. Any other idea for better implementation welcome.
$mod2 = \atk4\ui\Modal::addTo($app);
$form2 = \atk4\ui\Form::addTo($mod2);
$form2->addControl('selection_data', [\atk4\ui\Form\Control\Hidden::class]);
$val2 = $form2->getControl('selection_data');
$val2->setAttr(['type' => 'hidden']);
$form2->addControl('role',
[
\atk4\ui\Form\Control\Lookup::class,
'model' => new Role($app->db),
'placeholder' => 'Search by name',
'search' => ['Name'],
]);
$form2->onSubmit(function ($f){
$errors = [];
if (!$f->model->get('role')) {
$errors[] = $f->error('role', 'Required');
}
if ($errors) {
return $errors;
}
$user_ids = explode(',', $f->model->get('selection_data'));
foreach($user_ids as $id){
$m = new RoleLine($f->getApp()->db);
$m->set('IdRole', $f->model->get('role'));
$m->set('IdUser', $id);
$m->set('department_id', $f->getApp()->department->getId());
$m->save();
}
$modal_chain = new \atk4\ui\jQuery('.ui.modal');
$modal_chain->modal('hide');
return [$modal_chain];
});
$grid->menu->addItem(['Attribuer rôle', 'icon'=>'theater masks'])
->on('click',
function($j, $param) use ($mod2, $val2) {
return [$val2->jsInput()->val($param), $mod2->show()];
},
[$sel->jsChecked()]);
@mhuser is there anything to be improve in atk4/ui?
Hello @mvorisek thank you a lot for asking!
I find atk4/ui is a really great tool!
When starting to use Grid
I stumbled on this:
It is easy to create a grid with a model and some conditions. When interacting with it, it is also very straightforward to
$grid->menu->addItem(...);
to pop a JsModal
and add a new record or perform an action on all records$grid->addModalAction(...);
to pop a modal and perform an action with a Form
on a single existing recordAnd all of this even without writing any JavaScript, which is incredibly nice!
However, when it come to performing an action on a selection of records, things escalated quickly:
The demo page introduce $grid->addSelection();
with only a JsExpression
that pop up an alert. Such is also the documentation.
To be honest, I fear this is not very helpful for an individual with limited atk4/ui skills like me.
The solution above works, but the code required for it is verbose and error-prone when several actions exist. In comparison, the other atk4/ui lines look nice.
I have later discovered this documentation making an exemple of multiple selection in Grid
and calling Action
. But I was not able to get the full power of it yet.
In my wildest dream, there are two elements that could be improved with Atk4/Ui/Grid
:
$grid->menu->addItem(...)
would receive the $grid->addSelection()
results in some transparent way (even if not using it)Thank you for the perfect analysis.
To have the ability that
$grid->menu->addItem(...)
would receive the$grid->addSelection()
results in some transparent way (even if not using it)
If you can, please submit a PR with an improvement.
To have a checkbox in the title row that check/unchecks all the column
opened https://github.com/atk4/ui/issues/1877, it is a separate issue
If you can, please submit a PR with an improvement.
Thank you.
Let's try it. This will enable me to better understand what is going behind the hood and I will be the first to benefits from it.
I know that the question may sound silly, but once I have cloned atk4-ui master on a development web server, how can I get the demos to work? I guess there is something to do with composer to setup autoload.
run composer update
in atk4/ui root directory
Thank you so much !
OK, I have the running demo and the sqlite db was populated thanks to your composer hint.
I have no css styles yet at this stage. This is because the app tries to have stylesheets and others loaded by their full local paths instead of relative path from the server adress. This is forbidden by the server.
Seems strange to me to have to modify the demos/init-app.php
to force the paths. Is there some magic configuration to do or a doc I could follow without bothering you?
in the latest develop version it should be configured automatically in:
https://github.com/atk4/ui/blob/b1b2268862f35c730425fdb410aec5a1406ac2f7/src/App.php#L630-L655
please describe:
$_SERVER
variable at l632 or any entry place, and post here the dataApache HTTP Server 2.4 and PHP 74 on a local NAS server. atk4-ui
is a subdirectory in the http/web directory.
Using version up to commit b1b2268862f35c730425fdb410aec5a1406ac2f7
$_SERVER
:
USER: http
HOME: /var/services/web
SCRIPT_NAME: /atk4-ui/demos/test.php
REQUEST_URI: /atk4-ui/demos/test.php
QUERY_STRING:
REQUEST_METHOD: GET
SERVER_PROTOCOL: HTTP/1.1
GATEWAY_INTERFACE: CGI/1.1
REMOTE_PORT: 60394
SCRIPT_FILENAME: /var/services/web/atk4-ui/demos/test.php
SERVER_ADMIN: [no address given]
CONTEXT_DOCUMENT_ROOT: /var/services/web
CONTEXT_PREFIX:
REQUEST_SCHEME: https
DOCUMENT_ROOT: /var/services/web
REMOTE_ADDR: 2a02:aa17:327f:6380:4463:ac80:9642:44a
SERVER_PORT: 443
SERVER_ADDR: 2a02:aa17:327f:6380:211:32ff:fe80:2943
SERVER_NAME: etml-elo.diskstation.me
SERVER_SOFTWARE: Apache/2.4.43 (Unix)
SERVER_SIGNATURE:
PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin:/usr/local/sbin:/usr/local/bin
HTTP_SEC_FETCH_USER: ?1
HTTP_SEC_FETCH_SITE: none
HTTP_SEC_FETCH_MODE: navigate
HTTP_SEC_FETCH_DEST: document
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_COOKIE: stay_login=0; smid=A6w2rEfFtRb89YYpRiAdBaohBHOfLMuH-Ej4D9SMdB3Df7fCpRt8JvaopH7tF8bX0RGcuYMyTjTT7opuYOqSuw
HTTP_ACCEPT_ENCODING: gzip, deflate, br
HTTP_ACCEPT_LANGUAGE: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
HTTP_CONNECTION: close
HTTP_HOST: etml-elo.diskstation.me
HTTP_X_REAL_PORT: 49908
HTTP_X_PORT: 443
HTTP_X_HTTPS: on
HTTP_X_REAL_IP: 2a02:aa17:327f:6380:4463:ac80:9642:44a
HTTP_X_FORWARDED_BY: 2a02:aa17:327f:6380:211:32ff:fe80:2943
proxy-nokeepalive: 1
MOD_X_SENDFILE_ENABLED: yes
HTTPS: on
FCGI_ROLE: RESPONDER
PHP_SELF: /atk4-ui/demos/test.php
REQUEST_TIME_FLOAT: 1666799611.7181
REQUEST_TIME: 1666799611
I will take a look.
for now, edit the App cdns here https://github.com/atk4/ui/blob/b1b2268862f35c730425fdb410aec5a1406ac2f7/src/App.php#L147 or anywhere where you create your App
Thanks to you I am now up and running!
I applied this bodge to demos/init-app.php
foreach ($app->cdn as $k => $v) {
if (str_starts_with($v, '/') && !str_starts_with($v, '//')) {
$app->cdn[$k] = str_replace('/volume1/web', 'https://etml-elo.diskstation.me', $v);
}
}
Draft started in #1920
@mhuser before https://github.com/atk4/ui/blob/b1b2268862f35c730425fdb410aec5a1406ac2f7/src/App.php#L641 line I added:
$localDirPath = '/var/services/web';
$subdir = '/atk4-ui';
$_SERVER = [
'HOME' => $localDirPath,
'REQUEST_METHOD' => 'GET',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'GATEWAY_INTERFACE' => 'CGI/1.1',
'REMOTE_PORT' => '60394',
'SCRIPT_NAME' => $subdir . '/demos/test.php',
'REQUEST_URI' => $subdir . '/demos/test.php',
'QUERY_STRING' => '',
'SCRIPT_FILENAME' => $localDirPath . $subdir . '/demos/test.php',
'CONTEXT_DOCUMENT_ROOT' => $localDirPath,
'CONTEXT_PREFIX' => '',
'REQUEST_SCHEME' => 'https',
'DOCUMENT_ROOT' => $localDirPath,
'REMOTE_ADDR' => '2a02:aa17:327f:6380:4463:ac80:9642:44a',
'SERVER_PORT' => '443',
'SERVER_ADDR' => '2a02:aa17:327f:6380:211:32ff:fe80:2943',
'SERVER_NAME' => 'etml-elo.diskstation.me',
'HTTP_HOST' => 'etml-elo.diskstation.me',
'HTTP_X_REAL_PORT' => '49908',
'HTTP_X_PORT' => '443',
'HTTP_X_HTTPS' => 'on',
'HTTP_X_REAL_IP' => '2a02:aa17:327f:6380:4463:ac80:9642:44a',
'HTTP_X_FORWARDED_BY' => '2a02:aa17:327f:6380:211:32ff:fe80:2943',
'HTTPS' => 'on',
'PHP_SELF' => $subdir . '/demos/test.php',
];
and demos/index.php
demos homepage has about this content:
navigate to the homepage and please post here:
<script src="...
is rendered currently on your side and what link you expectui
repo and are there any symlinks [1]?[1] can be analysed by linux realpath
https://serverfault.com/questions/1069147/how-can-i-quickly-test-a-path-in-bash-to-determine-if-any-segment-of-it-is-a-sym
<script src="/volume1/web/atk4-ui/public/external/jquery/dist/jquery.min.js">...
<script src="/atk4-ui/public/external/jquery/dist/jquery.min.js">...
/volume1/web/atk4-ui/
but it appears to be somehow a symlink of /var/services/web/atk4-ui/
I think it is my configuration that is the issue (the server is on a Synology NAS setup from their package)
Thank you a lot for the data! I will do my best to make it working. As there is no modrewrite, it should be possible :)
I was able to reproduce with the following filesystem configuration:
RUN mkdir /mount && mkdir /mount/html && chmod 0777 /mount/html
RUN ln -s /mount/html /var/www/ht # /var/www/html directory cannot be removed as mounted by Docker
WORKDIR /mount/html
and
foreach ($_SERVER as $k => $v) {
if (is_string($v)) {
$_SERVER[$k] = preg_replace('~^/mount/html~', '/var/www/ht', $v, 1);
}
}
at the beginning of the demos/index.php
file the output is then like:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Agile UI Demo v4.0-dev</title>
<meta charset="utf-8">
<script>'use strict'; window.__atkBundlePublicPath = '/mount/html/public';</script>
<script src="/mount/html/public/external/jquery/dist/jquery.js"></script>
<script src="/mount/html/public/external/fomantic-ui/dist/semantic.js"></script>
<link rel="stylesheet" type="text/css" href="/mount/html/public/external/fomantic-ui/dist/semantic.css">
...
and when var_dump([$localPath, $requestLocalPath, $res])
is added to https://github.com/atk4/ui/blob/7102df96dc980ef04bc6c770897715bb3efeb25f/src/App.php#L652 it shows:
array(3) {
[0]=>
string(46) "/mount/html/src/../public/external/jquery/dist"
[1]=>
string(27) "/var/www/ht/demos/index.php"
[2]=>
string(40) "/mount/html/public/external/jquery/dist/"
}
more debug:
$localPath = realpath($localPath);
$localPathRelative = $fs->makePathRelative($localPath, dirname($requestLocalPath));
var_dump([$localPath, dirname($requestLocalPath), $localPathRelative]);
$res = '/' . $fs->makePathRelative($requestUrlPath . '/' . $localPathRelative, '/');
var_dump([$requestUrlPath . '/' . $localPathRelative, $res]);
shows
array(3) {
[0]=>
string(18) "/mount/html/public"
[1]=>
string(17) "/var/www/ht/demos"
[2]=>
string(30) "../../../../mount/html/public/"
}
array(2) {
[0]=>
string(37) "/demos/../../../../mount/html/public/"
[1]=>
string(19) "/mount/html/public/"
}
array(3) {
[0]=>
string(39) "/mount/html/public/external/jquery/dist"
[1]=>
string(17) "/var/www/ht/demos"
[2]=>
string(51) "../../../../mount/html/public/external/jquery/dist/"
}
array(2) {
[0]=>
string(58) "/demos/../../../../mount/html/public/external/jquery/dist/"
[1]=>
string(40) "/mount/html/public/external/jquery/dist/"
}
Looks similar to the issue I faced !
please test if adding:
$localPath = realpath($localPath);
$requestLocalPath = realpath($requestLocalPath);
at https://github.com/atk4/ui/blob/7102df96dc980ef04bc6c770897715bb3efeb25f/src/App.php#L651 fixes the path calculation, eg. fixes https://github.com/atk4/ui/issues/1727#issuecomment-1295960552
Yes, it fixes for my situation. With these lines, I do not need to tweak the cdns any more!
@mhuser thank you for reporting the problem and helping me to understand it, fix merged in https://github.com/atk4/ui/pull/1936, I was litte worried about realpath
performance with many calls, but it turned out __DIR__
is resolved implicitly, and all inputs should be constructed using it, thus with this knowledge/assumptiom, the fix requires only one realpath
per app, ❤️
@mvorisek This sounds great! Thank you a lot for the quick fix!
First of all, I want to thank you for this great tool that is atk4/ui ! Since some time I have a question which I believe does not find answer in the documentation (but maybe I am just blinded). Let's suppose we have two models
User
andRole
andUser
hasMany
Role
.\Atk4\Ui\Grid
andaddCondition
to display a givenRole
and add aUser
.Role
list of aUser
and add one using the same method.My question is : how to use
$grid->addSelection()
to mass-attribute aRole
to a selected set ofUser
? (Which enable to use grid filtering and sorting) In the demo there is a call to some javascriptBut I does not understand how to relies on a php callback instead that would receive the selected id list and perform some processing such at foreach the list and create the appropriate role lines or others.