Added a simple dialog for changing user settings.

This commit is contained in:
Jan Böhmer 2019-03-15 18:04:15 +01:00
parent e28eb3b84d
commit 62fe4afd74
5 changed files with 156 additions and 31 deletions

View file

@ -33,8 +33,11 @@ namespace App\Controller;
use App\Entity\User; use App\Entity\User;
use App\Form\UserSettingsType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Asset\Packages; use Symfony\Component\Asset\Packages;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
class UserController extends AbstractController class UserController extends AbstractController
@ -65,6 +68,32 @@ class UserController extends AbstractController
]); ]);
} }
/**
* @Route("/user/settings", name="user_settings")
*/
public function userSettings(Request $request, EntityManagerInterface $em)
{
$user = $this->getUser();
//When user change its settings, he should be logged in fully.
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
$form = $this->createForm(UserSettingsType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($user);
$em->flush();
$this->addFlash('success', 'user.settings.saved_flash');
}
return $this->render('Users/user_settings.html.twig', [
"settings_form" => $form->createView()
]);
}
/** /**
* Get either a Gravatar URL or complete image tag for a specified email address. * Get either a Gravatar URL or complete image tag for a specified email address.

View file

@ -34,6 +34,7 @@ namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/** /**
* This entity represents a user, which can log in and have permissions. * This entity represents a user, which can log in and have permissions.
@ -53,6 +54,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @ORM\Column(type="string", length=180, unique=true) * @ORM\Column(type="string", length=180, unique=true)
* @Assert\NotBlank
*/ */
protected $name; protected $name;
@ -62,51 +64,52 @@ class User extends NamedDBElement implements UserInterface
//protected $roles = []; //protected $roles = [];
/** /**
* @var string The hashed password * @var string|null The hashed password
* @ORM\Column(type="string") * @ORM\Column(type="string", nullable=true)
*/ */
protected $password; protected $password;
/** /**
* @var string The first name of the User * @var string|null The first name of the User
* @ORM\Column(type="string", length=255) * @ORM\Column(type="string", length=255, nullable=true)
*/ */
protected $first_name = ""; protected $first_name = "";
/** /**
* @var string The last name of the User * @var string|null The last name of the User
* @ORM\Column(type="string", length=255) * @ORM\Column(type="string", length=255, nullable=true)
*/ */
protected $last_name = ""; protected $last_name = "";
/** /**
* @var string The department the user is working * @var string|null The department the user is working
* @ORM\Column(type="string", length=255) * @ORM\Column(type="string", length=255, nullable=true)
*/ */
protected $department = ""; protected $department = "";
/** /**
* @var string The email address of the user * @var string|null The email address of the user
* @ORM\Column(type="string", length=255) * @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Email()
*/ */
protected $email = ""; protected $email = "";
/** /**
* @var string The language/locale the user prefers * @var string|null The language/locale the user prefers
* @ORM\Column(type="string", name="config_language") * @ORM\Column(type="string", name="config_language", nullable=true)
*/ */
protected $language = ""; protected $language = "";
/** /**
* @var string The timezone the user prefers * @var string|null The timezone the user prefers
* @ORM\Column(type="string", name="config_timezone") * @ORM\Column(type="string", name="config_timezone", nullable=true)
*/ */
protected $timezone = ""; protected $timezone = "";
/** /**
* @var string The theme * @var string|null The theme
* @ORM\Column(type="string", name="config_theme") * @ORM\Column(type="string", name="config_theme", nullable=true)
*/ */
protected $theme = ""; protected $theme = "";
@ -198,7 +201,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getFirstName(): string public function getFirstName(): ?string
{ {
return $this->first_name; return $this->first_name;
} }
@ -207,7 +210,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $first_name * @param string $first_name
* @return User * @return User
*/ */
public function setFirstName(string $first_name): User public function setFirstName(?string $first_name): User
{ {
$this->first_name = $first_name; $this->first_name = $first_name;
return $this; return $this;
@ -216,7 +219,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getLastName(): string public function getLastName(): ?string
{ {
return $this->last_name; return $this->last_name;
} }
@ -225,7 +228,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $last_name * @param string $last_name
* @return User * @return User
*/ */
public function setLastName(string $last_name): User public function setLastName(?string $last_name): User
{ {
$this->last_name = $last_name; $this->last_name = $last_name;
return $this; return $this;
@ -234,7 +237,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getDepartment(): string public function getDepartment(): ?string
{ {
return $this->department; return $this->department;
} }
@ -243,7 +246,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $department * @param string $department
* @return User * @return User
*/ */
public function setDepartment(string $department): User public function setDepartment(?string $department): User
{ {
$this->department = $department; $this->department = $department;
return $this; return $this;
@ -252,7 +255,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getEmail(): string public function getEmail(): ?string
{ {
return $this->email; return $this->email;
} }
@ -261,7 +264,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $email * @param string $email
* @return User * @return User
*/ */
public function setEmail(string $email): User public function setEmail(?string $email): User
{ {
$this->email = $email; $this->email = $email;
return $this; return $this;
@ -270,7 +273,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getLanguage(): string public function getLanguage(): ?string
{ {
return $this->language; return $this->language;
} }
@ -279,7 +282,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $language * @param string $language
* @return User * @return User
*/ */
public function setLanguage(string $language): User public function setLanguage(?string $language): User
{ {
$this->language = $language; $this->language = $language;
return $this; return $this;
@ -288,7 +291,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getTimezone(): string public function getTimezone(): ?string
{ {
return $this->timezone; return $this->timezone;
} }
@ -297,7 +300,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $timezone * @param string $timezone
* @return User * @return User
*/ */
public function setTimezone(string $timezone): User public function setTimezone(?string $timezone): User
{ {
$this->timezone = $timezone; $this->timezone = $timezone;
return $this; return $this;
@ -306,7 +309,7 @@ class User extends NamedDBElement implements UserInterface
/** /**
* @return string * @return string
*/ */
public function getTheme(): string public function getTheme(): ?string
{ {
return $this->theme; return $this->theme;
} }
@ -315,7 +318,7 @@ class User extends NamedDBElement implements UserInterface
* @param string $theme * @param string $theme
* @return User * @return User
*/ */
public function setTheme(string $theme): User public function setTheme(?string $theme): User
{ {
$this->theme = $theme; $this->theme = $theme;
return $this; return $this;

View file

@ -0,0 +1,53 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\LanguageType;
use Symfony\Component\Form\Extension\Core\Type\LocaleType;
use Symfony\Component\Form\Extension\Core\Type\ResetType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TimezoneType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserSettingsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, ['label'=>'user.username.label'])
->add('first_name', TextType::class, ['required' => false,
'label'=>'user.firstName.label'])
->add('last_name', TextType::class, ['required' => false,
'label'=>'user.lastName.label'])
->add('department', TextType::class, ['required' => false,
'label'=>'user.department.label'])
->add('email', EmailType::class, ['required' => false,
'label'=>'user.email.label'])
->add('language', LocaleType::class, ['required' => false,
'attr'=>['class'=> 'selectpicker', 'data-live-search' => true]
, 'placeholder' => 'user_settings.language.placeholder', 'label'=>'user.language_select'])
->add('timezone', TimezoneType::class, ['required' => false,
'attr'=>['class'=> 'selectpicker', 'data-live-search' => true],
'placeholder' => 'user_settings.timezone.placeholder', 'label'=>'user.timezone.label'])
->add('theme', ChoiceType::class, ['required' => false,
'placeholder' => 'user_settings.theme.placeholder', 'label'=>'user.theme.label'])
//Buttons
->add('save', SubmitType::class, ['label' => 'save'])
->add('reset', ResetType::class, ['label' => 'reset']);
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}

View file

@ -0,0 +1,40 @@
{% extends "main_card.html.twig" %}
{% block title %}{% trans %}user.settings.label{% endtrans %}{% endblock %}
{% block card_title %}<i class="fas fa-info-circle fa-fw" aria-hidden="true"></i>
{% trans %}user.settings.label{% endtrans %}{% endblock %}
{% block card_content %}
{{ form_start(settings_form) }}
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="data-tab" data-toggle="tab" href="#data" role="tab"
aria-controls="home" aria-selected="true">{% trans %}user_settings.data.label{% endtrans %}</a>
</li>
<li class="nav-item">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#configuration" role="tab"
aria-controls="profile" aria-selected="false">{% trans %}user_settings.configuration.label{% endtrans %}</a>
</li>
</ul>
<div class="tab-content mt-3 mb-3" id="myTabContent">
<div class="tab-pane fade show active" id="data" role="tabpanel" aria-labelledby="home-tab">
{{ form_row(settings_form.name) }}
{{ form_row(settings_form.first_name) }}
{{ form_row(settings_form.last_name) }}
{{ form_row(settings_form.department) }}
{{ form_row(settings_form.email) }}
</div>
<div class="tab-pane fade" id="configuration" role="tabpanel" aria-labelledby="profile-tab">
{{ form_row(settings_form.language) }}
{{ form_row(settings_form.timezone) }}
{{ form_row(settings_form.theme) }}
</div>
</div>
{{ form_row(settings_form.save) }}
{{ form_row(settings_form.reset) }}
{{ form_end(settings_form) }}
{% endblock %}

View file

@ -85,7 +85,7 @@
<ul class="dropdown-menu dropdown-menu-right" id="login-menu"> <ul class="dropdown-menu dropdown-menu-right" id="login-menu">
{% if app.user %} {% if app.user %}
<a class="dropdown-item disabled" href="#" >{% trans %}user.loggedin.label{% endtrans %} {{ app.user.firstName }} {{app.user.lastName}} ({{app.user.name}})</a> <a class="dropdown-item disabled" href="#" >{% trans %}user.loggedin.label{% endtrans %} {{ app.user.firstName }} {{app.user.lastName}} ({{app.user.name}})</a>
<a class="dropdown-item" href="user_settings.php"><i class="fa fa-cogs fa-fw" aria-hidden="true"></i> {% trans %}user.settings.label{% endtrans %}</a> <a class="dropdown-item" href="{{ path("user_settings") }}"><i class="fa fa-cogs fa-fw" aria-hidden="true"></i> {% trans %}user.settings.label{% endtrans %}</a>
<a class="dropdown-item" href="{{ path("user_info_self") }}"><i class="fa fa-info-circle fa-fw" aria-hidden="true"></i> {% trans %}user.info.label{% endtrans %}</a> <a class="dropdown-item" href="{{ path("user_info_self") }}"><i class="fa fa-info-circle fa-fw" aria-hidden="true"></i> {% trans %}user.info.label{% endtrans %}</a>
<li role="separator" class="dropdown-divider"></li> <li role="separator" class="dropdown-divider"></li>
<a class="dropdown-item" href="{{ path('logout') }}"><i class="fa fa-sign-out-alt fa-fw" aria-hidden="true"></i> {% trans %}user.logout{% endtrans %}</a> <a class="dropdown-item" href="{{ path('logout') }}"><i class="fa fa-sign-out-alt fa-fw" aria-hidden="true"></i> {% trans %}user.logout{% endtrans %}</a>