Amélioration de l'expérience utilisateur
This commit is contained in:
parent
76ddc9fe30
commit
b087a7130c
@ -44,13 +44,23 @@ return [
|
||||
'user' => '@app/modules/user/messages'
|
||||
]
|
||||
],
|
||||
'Nette\Mail\SmtpMailer' => [
|
||||
'construct' => [
|
||||
getenv('SMTP_HOST'),
|
||||
getenv('SMTP_USER'),
|
||||
getenv('SMTP_PASSWORD'),
|
||||
(int) getenv('SMTP_PORT'),
|
||||
getenv('SMTP_ENCRYPTION'),
|
||||
]
|
||||
],
|
||||
],
|
||||
'modules' => [
|
||||
'site' => 'app\modules\site\Module',
|
||||
'user' => [
|
||||
'class' => 'app\modules\user\Module',
|
||||
'controllerMap' => [
|
||||
'admin' => 'app\overrides\user\controllers\AdminController'
|
||||
'admin' => 'app\overrides\user\controllers\AdminController',
|
||||
'default' => 'app\overrides\user\controllers\DefaultController',
|
||||
]
|
||||
],
|
||||
],
|
||||
|
@ -35,11 +35,20 @@ final class AuthMiddleware implements MiddlewareInterface
|
||||
|
||||
$router = $this->application->getComponent('Piko\Router');
|
||||
assert($router instanceof \Piko\Router);
|
||||
|
||||
$loginUrl = $router->getUrl('user/default/login');
|
||||
|
||||
$params = $request->getServerParams();
|
||||
$allowedUrls = [
|
||||
$loginUrl,
|
||||
$router->getUrl('user/default/reminder'),
|
||||
$router->getUrl('user/default/reset-password'),
|
||||
$router->getUrl('user/default/check-registration'),
|
||||
];
|
||||
|
||||
if ($user->isGuest() && $params['REQUEST_URI'] != $loginUrl) {
|
||||
$params = $request->getServerParams();
|
||||
$path = rtrim(parse_url($params['REQUEST_URI'], PHP_URL_PATH), '/');
|
||||
|
||||
if ($user->isGuest() && !in_array($path, $allowedUrls)) {
|
||||
|
||||
$response= new Response();
|
||||
|
||||
|
@ -19,25 +19,7 @@ class Module extends \Piko\Module
|
||||
$view = $this->application->getComponent('Piko\View');
|
||||
$view->params['user'] = $user;
|
||||
$view->params['language'] = $this->application->language;
|
||||
// $view->attachBehavior('vite', 'app\lib\Vite::vite');
|
||||
$vite = new Vite($view);
|
||||
$vite->loadEntry('main.js');
|
||||
|
||||
$userModule = $this->application->getModule('user');
|
||||
assert ($userModule instanceof \app\modules\user\Module);
|
||||
|
||||
$userModule->on(CreateControllerEvent::class, function(CreateControllerEvent $event) {
|
||||
$event->controller->on(BeforeActionEvent::class, function (BeforeActionEvent $event) {
|
||||
|
||||
$action = $event->actionId;
|
||||
|
||||
switch($action) {
|
||||
case 'login':
|
||||
$event->controller->layout = 'minimal';
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* @var $this \Piko\View */
|
||||
/* @var $content string */
|
||||
|
||||
if (!$this->title) $this->title = 'Openai';
|
||||
if (!$this->title) $this->title = 'IA Assistant';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= $this->params['language'] ?>">
|
||||
|
@ -52,9 +52,12 @@ class DefaultController extends \Piko\Controller
|
||||
|
||||
if (!empty($post)) {
|
||||
|
||||
$user = new User($this->db);
|
||||
$module = $this->module;
|
||||
assert ($module instanceof \app\modules\user\Module);
|
||||
|
||||
$user = new User($this->db);
|
||||
$user->scenario = User::SCENARIO_REGISTER;
|
||||
$user->passwordMinLength = $module->passwordMinLength;
|
||||
|
||||
$user->bind($post);
|
||||
|
||||
@ -89,8 +92,12 @@ class DefaultController extends \Piko\Controller
|
||||
|
||||
if (!empty($post)) {
|
||||
|
||||
$module = $this->module;
|
||||
assert ($module instanceof \app\modules\user\Module);
|
||||
|
||||
$user = new User($this->db);
|
||||
$user->scenario = 'register';
|
||||
$user->passwordMinLength = $module->passwordMinLength;
|
||||
$user->bind($post);
|
||||
$user->isValid();
|
||||
$errors = $user->getErrors();
|
||||
@ -156,13 +163,17 @@ class DefaultController extends \Piko\Controller
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
// $user->sendResetPassword();
|
||||
$app = $this->module->getApplication();
|
||||
$router = $app->getComponent('Piko\Router');
|
||||
$mailer = $app->getComponent('Nette\Mail\SmtpMailer');
|
||||
$user->sendResetPassword($router, $mailer);
|
||||
$message['type'] = 'success';
|
||||
$message['content'] = __(
|
||||
'user',
|
||||
'A link has been sent to you by email ({email}). It will allow you to recreate your password.',
|
||||
['email' => $user->email]
|
||||
);
|
||||
$reminder = '';
|
||||
} else {
|
||||
$message['type'] = 'danger';
|
||||
$message['content'] = __('user', 'Account not found.');
|
||||
@ -186,7 +197,7 @@ class DefaultController extends \Piko\Controller
|
||||
$user = User::findByAuthKey($token);
|
||||
|
||||
if (!$user) {
|
||||
throw new HttpException('Not found', 404);
|
||||
throw new HttpException('User not found', 404);
|
||||
}
|
||||
|
||||
$message = false;
|
||||
|
@ -19,7 +19,7 @@ Une demande de changement de mot passe a été effectuée pour votre compte sur
|
||||
|
||||
Votre identifiant est : {username}.
|
||||
|
||||
Pour changer votre mot de passe , cliquez sur le lien ci-dessous.
|
||||
Pour changer votre mot de passe , cliquez sur ou copiez-collez dans votre navigateur le lien ci-dessous.
|
||||
|
||||
{link}
|
||||
|
||||
|
@ -43,7 +43,8 @@ class User extends \Piko\DbRecord implements \Piko\User\IdentityInterface
|
||||
const SCENARIO_RESET = 'reset';
|
||||
|
||||
public static \PDO $pdo;
|
||||
public static Module $module;
|
||||
|
||||
public int $passwordMinLength = 8;
|
||||
|
||||
/**
|
||||
* The table name
|
||||
@ -267,11 +268,11 @@ class User extends \Piko\DbRecord implements \Piko\User\IdentityInterface
|
||||
$this->errors['password'] = __('user', 'Password must be filled in.');
|
||||
|
||||
} elseif (($this->scenario == self::SCENARIO_REGISTER || $this->scenario == self::SCENARIO_RESET) &&
|
||||
strlen($this->password) < static::$module->passwordMinLength) {
|
||||
strlen($this->password) < $this->passwordMinLength) {
|
||||
$this->errors['password'] = __(
|
||||
'user',
|
||||
'Password is to short. Minimum {num}: characters.',
|
||||
['num' => static::$module->passwordMinLength]
|
||||
['num' => (string) $this->passwordMinLength]
|
||||
);
|
||||
}
|
||||
|
||||
@ -367,7 +368,7 @@ class User extends \Piko\DbRecord implements \Piko\User\IdentityInterface
|
||||
$subject = __('user', 'Password change request on {site_name}', ['site_name' => $siteName]);
|
||||
|
||||
$mail = new Message();
|
||||
$mail->setFrom($siteName . ' <' . getenv('NO_REPLY_EMAIL') . '>')
|
||||
$mail->setFrom(getenv('NO_REPLY_EMAIL'), $siteName)
|
||||
->addTo($this->email)
|
||||
->setSubject($subject)
|
||||
->setBody($message);
|
||||
|
@ -1,10 +1,12 @@
|
||||
<?php
|
||||
use piko\Piko;
|
||||
/* @var $this \piko\View */
|
||||
use function Piko\I18n\__;
|
||||
|
||||
assert($this instanceof Piko\View);
|
||||
|
||||
/* @var $message array */
|
||||
/* @var $reminder string */
|
||||
|
||||
$this->title = Piko::t('user', 'Forget password');
|
||||
$this->title = __('user', 'Forget password');
|
||||
|
||||
if (is_array($message)) {
|
||||
$this->params['message'] = $message;
|
||||
@ -18,10 +20,10 @@ if (is_array($message)) {
|
||||
|
||||
<form method="post" id="reminder-form" novalidate>
|
||||
<div class="form-group">
|
||||
<label for="reminder"><?= Piko::t('user', 'Your email or your username') ?></label>
|
||||
<label for="reminder"><?= __('user', 'Your email or your username') ?></label>
|
||||
<input type="text" class="form-control" id="reminder" name="reminder" value="<?= $reminder ?>" autocomplete="off">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><?= Piko::t('user', 'Send') ?></button>
|
||||
<button type="submit" class="btn btn-primary"><?= __('user', 'Send') ?></button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
@ -1,74 +1,76 @@
|
||||
<?php
|
||||
use piko\Piko;
|
||||
use function Piko\I18n\__;
|
||||
|
||||
assert($this instanceof Piko\View);
|
||||
|
||||
/* @var $this \piko\View */
|
||||
/* @var $user piko\user\models\User */
|
||||
/* @var $message array */
|
||||
/* @var $router \piko\Router */
|
||||
|
||||
$router = Piko::get('router');
|
||||
|
||||
$this->title = Piko::t('user', 'Change your account ({account}) password',['account' => $user->username]);
|
||||
|
||||
if (is_array($message)) {
|
||||
$this->params['message'] = $message;
|
||||
|
||||
echo '<div class="container text-center"><a class="btn btn-primary" href="'. $router->getUrl('user/default/login').'">'
|
||||
. Piko::t('user', 'Login') . '</a></div>';
|
||||
|
||||
return;
|
||||
}
|
||||
$this->title = __('user', 'Change your account ({account}) password',['account' => $user->username]);
|
||||
|
||||
$js = <<<SCRIPT
|
||||
jQuery(document).ready(function($) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
function validateField(event) {
|
||||
var field = event.target;
|
||||
|
||||
function validateField(e) {
|
||||
var that = this;
|
||||
|
||||
$.post('{$router->getUrl('user/default/check-registration')}', $('#register-form').serialize(), function(errors) {
|
||||
if (errors[that.name]) {
|
||||
$(that).addClass('is-invalid')
|
||||
$(that).removeClass('is-valid')
|
||||
$(that).next('.invalid-feedback').text(errors[that.name])
|
||||
fetch('{$this->getUrl('user/default/check-registration')}', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(new FormData(document.getElementById('register-form')))
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(errors => {
|
||||
if (errors[field.name]) {
|
||||
field.classList.add('is-invalid');
|
||||
field.classList.remove('is-valid');
|
||||
field.nextElementSibling.textContent = errors[field.name];
|
||||
} else {
|
||||
$(that).removeClass('is-invalid')
|
||||
$(that).addClass('is-valid')
|
||||
field.classList.remove('is-invalid');
|
||||
field.classList.add('is-valid');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#password').focusout(validateField);
|
||||
$('#password2').focusout(validateField);
|
||||
|
||||
document.getElementById('password').addEventListener('focusout', validateField);
|
||||
document.getElementById('password2').addEventListener('focusout', validateField);
|
||||
});
|
||||
SCRIPT;
|
||||
|
||||
$this->registerJs($js);
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<div class="container" style="margin-top: 100px">
|
||||
<div class="container">
|
||||
|
||||
<h1 class="h4"><?= $this->title ?></h1>
|
||||
|
||||
<?php if (!empty($message) && $message['type'] === 'success'): ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?= $message['content'] ?>
|
||||
<p class="text-center"><a class="btn btn-primary" href="<?= $this->getUrl('user/default/login') ?>">
|
||||
<?= __('user', 'Login') ?></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<form method="post" id="register-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password"><?= Piko::t('user', 'Password') ?></label>
|
||||
<div class="mb-2">
|
||||
<label for="password"><?= __('user', 'Password') ?></label>
|
||||
<input type="password" class="form-control" id="password" name="password" value="" autocomplete="off">
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password2"><?= Piko::t('user', 'Confirm your password') ?></label>
|
||||
<div class="mb-2">
|
||||
<label for="password2"><?= __('user', 'Confirm your password') ?></label>
|
||||
<input type="password" class="form-control" id="password2" name="password2" value="" autocomplete="off">
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><?= Piko::t('user', 'Send') ?></button>
|
||||
<button type="submit" class="btn btn-primary"><?= __('user', 'Send') ?></button>
|
||||
</form>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
14
overrides/user/controllers/DefaultController.php
Normal file
14
overrides/user/controllers/DefaultController.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace app\overrides\user\controllers;
|
||||
|
||||
class DefaultController extends \app\modules\user\controllers\DefaultController
|
||||
{
|
||||
public function init(): void
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->user->isGuest()) {
|
||||
$this->layout = 'minimal';
|
||||
}
|
||||
}
|
||||
}
|
47
overrides/user/views/default/login.php
Normal file
47
overrides/user/views/default/login.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
use function Piko\I18n\__;
|
||||
|
||||
assert($this instanceof Piko\View);
|
||||
|
||||
/**
|
||||
* @var $message boolean | array
|
||||
* @var $canRegister boolean
|
||||
*/
|
||||
|
||||
$this->title = __('user', 'Login');
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
assert(is_array($message));
|
||||
|
||||
?>
|
||||
|
||||
<main class="form-signin w-100 m-auto">
|
||||
|
||||
<?php if (!empty($message)): ?>
|
||||
<div class="container alert alert-<?= $message['type'] ?> alert-dismissible fade show" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
<?= $message['content'] ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<form action="<?= $this->getUrl('user/default/login') ?>" id="login-form" method="post">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="<?= __('user', 'Username') ?>">
|
||||
<label for="username"><?= __('user', 'Username') ?></label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating">
|
||||
<input type="password" class="form-control" id="loginform-password" name="password" placeholder="<?= __('user', 'Password') ?>">
|
||||
<label for="loginform-password"><?= __('user', 'Password') ?></label>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary w-100 py-2" type="submit"><?= __('user', 'Login') ?></button>
|
||||
<p class="mt-5 mb-3 text-body-secondary">
|
||||
<a href="<?= $this->getUrl('user/default/reminder')?>"><?= __('user', 'Forget password?') ?></a>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
|
48
overrides/user/views/default/reminder.php
Normal file
48
overrides/user/views/default/reminder.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
use function Piko\I18n\__;
|
||||
|
||||
assert($this instanceof Piko\View);
|
||||
|
||||
/* @var $message array */
|
||||
/* @var $reminder string */
|
||||
|
||||
$this->title = __('user', 'Forget password');
|
||||
|
||||
if (is_array($message)) {
|
||||
$this->params['message'] = $message;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<main class="form-reminder w-100 m-auto">
|
||||
|
||||
<h1 class="h3"><?= $this->title ?></h1>
|
||||
|
||||
<?php if (!empty($message)): ?>
|
||||
<div class="container alert alert-<?= $message['type'] ?> alert-dismissible fade show" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
<?= $message['content'] ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<form method="post" id="reminder-form" novalidate>
|
||||
<div class="form-floating">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="reminder"
|
||||
name="reminder"
|
||||
value="<?= $reminder ?>"
|
||||
autocomplete="off"
|
||||
placeholder="<?= __('user', 'Your email or your username') ?>">
|
||||
<label for="reminder"><?= __('user', 'Your email or your username') ?></label>
|
||||
</div>
|
||||
<p class="my-2">
|
||||
<button type="submit" class="btn btn-primary"><?= __('user', 'Send') ?></button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
@import "fonts";
|
||||
@import "hamburger";
|
||||
|
||||
// @import "chat";
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
@ -28,19 +26,6 @@ body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#chat {
|
||||
white-space: pre-wrap;
|
||||
|
||||
.user {
|
||||
color: #ffeaa4;
|
||||
}
|
||||
|
||||
.assistant {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.form-signin {
|
||||
max-width: 330px;
|
||||
padding: 1rem;
|
||||
@ -62,5 +47,14 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.form-reminder {
|
||||
max-width: 330px;
|
||||
padding: 1rem;
|
||||
|
||||
.form-floating:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user