added supervisor setting for user (#4251)

This commit is contained in:
Kevin Papst
2023-08-20 13:18:35 +02:00
committed by GitHub
parent 9baa477bed
commit 3e61e0dce6
28 changed files with 358 additions and 612 deletions

View File

@@ -197,6 +197,7 @@ final class UserController extends BaseApiController
'include_roles' => $this->isGranted('roles', $profile),
'include_active_flag' => ($profile->getId() !== $this->getUser()->getId()),
'include_preferences' => $this->isGranted('preferences', $profile),
'include_supervisor' => $this->isGranted('supervisor', $profile),
]);
$form->setData($profile);

View File

@@ -316,7 +316,8 @@ final class ProfileController extends AbstractController
'action' => $this->generateUrl('user_profile_edit', ['username' => $user->getUserIdentifier()]),
'method' => 'POST',
'include_active_flag' => ($user->getId() !== $this->getUser()->getId()),
'include_preferences' => false,
'include_preferences' => true,
'include_supervisor' => $this->isGranted('supervisor', $user),
]
);
}

View File

@@ -233,6 +233,7 @@ final class UserController extends AbstractController
'method' => 'POST',
'include_active_flag' => true,
'include_preferences' => true,
'include_supervisor' => $this->isGranted('supervisor_other_profile'),
'include_teams' => $this->isGranted('teams_other_profile'),
'include_roles' => $this->isGranted('roles_other_profile'),
]);

View File

@@ -128,15 +128,15 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
*
* @var Collection<UserPreference>|null
*/
#[ORM\OneToMany(targetEntity: 'App\Entity\UserPreference', mappedBy: 'user', cascade: ['persist'])]
#[ORM\OneToMany(targetEntity: UserPreference::class, mappedBy: 'user', cascade: ['persist'])]
private ?Collection $preferences = null;
/**
* List of all team memberships.
*
* @var Collection<TeamMember>
*/
#[ORM\OneToMany(targetEntity: 'App\Entity\TeamMember', mappedBy: 'user', fetch: 'LAZY', cascade: ['persist'], orphanRemoval: true)]
#[ORM\JoinColumn(onDelete: 'CASCADE')]
#[ORM\OneToMany(targetEntity: TeamMember::class, mappedBy: 'user', fetch: 'LAZY', cascade: ['persist'], orphanRemoval: true)]
#[ORM\JoinColumn(onDelete: 'CASCADE', nullable: false)]
#[Assert\NotNull]
#[Serializer\Expose]
#[Serializer\Groups(['User_Entity'])]
@@ -216,6 +216,12 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
private bool $totpEnabled = false;
#[ORM\Column(name: 'system_account', type: 'boolean', nullable: false, options: ['default' => false])]
private bool $systemAccount = false;
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(onDelete: 'SET NULL', nullable: true)]
#[Serializer\Expose]
#[Serializer\Groups(['User_Entity'])]
#[OA\Property(ref: '#/components/schemas/User')]
private ?User $supervisor = null;
use ColorTrait;
@@ -1281,4 +1287,24 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
default => throw new \Exception('Unknown day: ' . $dateTime->format('Y-m-d'))
};
}
public function isWorkDay(\DateTimeInterface $dateTime): bool
{
return $this->getWorkHoursForDay($dateTime) > 0;
}
public function hasSupervisor(): bool
{
return $this->supervisor !== null;
}
public function getSupervisor(): ?User
{
return $this->supervisor;
}
public function setSupervisor(?User $supervisor): void
{
$this->supervisor = $supervisor;
}
}

View File

@@ -16,18 +16,18 @@ use Symfony\Component\Form\FormEvents;
trait ColorTrait
{
protected function addColor(FormBuilderInterface $builder): void
protected function addColor(FormBuilderInterface $builder, bool $required = false): void
{
$builder
->add('color', ColorChoiceType::class, [
'required' => false,
'required' => $required,
])
;
// this code exists only for backward compatibility
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) {
function (FormEvent $event) use ($required) {
if (!$event->getForm()->getConfig()->hasOption('choices')) {
return;
}
@@ -42,7 +42,7 @@ trait ColorTrait
}
$event->getForm()->add('color', ColorChoiceType::class, [
'required' => false,
'required' => $required,
'choices' => $choices,
]);
}

View File

@@ -23,47 +23,45 @@ class UserCreateType extends UserEditType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('username', null, [
'label' => 'username',
'required' => true,
'attr' => [
'autofocus' => 'autofocus'
],
])
->add('plainPassword', RepeatedType::class, [
'required' => true,
'type' => PasswordType::class,
'first_options' => [
'label' => 'password',
'attr' => ['autocomplete' => 'new-password'],
'block_prefix' => 'secret'
],
'second_options' => [
'label' => 'password_repeat',
'attr' => ['autocomplete' => 'new-password'],
'block_prefix' => 'secret'
],
]);
$builder->add('username', null, [
'label' => 'username',
'required' => true,
'attr' => [
'autofocus' => 'autofocus'
],
]);
$builder->add('plainPassword', RepeatedType::class, [
'required' => true,
'type' => PasswordType::class,
'first_options' => [
'label' => 'password',
'attr' => ['autocomplete' => 'new-password'],
'block_prefix' => 'secret'
],
'second_options' => [
'label' => 'password_repeat',
'attr' => ['autocomplete' => 'new-password'],
'block_prefix' => 'secret'
],
]);
parent::buildForm($builder, $options);
if ($options['include_teams'] === true) {
$builder
->add('teams', TeamType::class, [
'multiple' => true,
'expanded' => false,
'required' => false,
]);
$builder->add('teams', TeamType::class, [
'multiple' => true,
'expanded' => false,
'required' => false,
]);
}
if ($options['include_roles'] === true) {
$builder
->add('roles', UserRoleType::class, [
'multiple' => true,
'expanded' => false,
'required' => false,
]);
$builder->add('roles', UserRoleType::class, [
'multiple' => true,
'expanded' => false,
'required' => false,
]);
}
}

View File

@@ -12,9 +12,10 @@ namespace App\Form;
use App\Configuration\SystemConfiguration;
use App\Entity\User;
use App\Form\Type\AvatarType;
use App\Form\Type\LanguageType;
use App\Form\Type\MailType;
use App\Form\Type\TimezoneType;
use App\Form\Type\UserLanguageType;
use App\Form\Type\UserType;
use App\Form\Type\YesNoType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
@@ -35,20 +36,26 @@ class UserEditType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('alias', TextType::class, [
'label' => 'alias',
'required' => false,
])
->add('title', TextType::class, [
'label' => 'title',
'required' => false,
])
->add('accountNumber', TextType::class, [
'label' => 'account_number',
'required' => false,
])
;
/** @var User|null $user */
$user = null;
if (\array_key_exists('data', $options)) {
$user = $options['data'];
}
$builder->add('alias', TextType::class, [
'label' => 'alias',
'required' => false,
]);
$builder->add('title', TextType::class, [
'label' => 'title',
'required' => false,
]);
$builder->add('accountNumber', TextType::class, [
'label' => 'account_number',
'required' => false,
]);
if ($this->configuration->isThemeAllowAvatarUrls()) {
$builder->add('avatar', AvatarType::class, [
@@ -61,7 +68,7 @@ class UserEditType extends AbstractType
$builder->add('email', MailType::class);
if ($options['include_preferences']) {
$builder->add('language', LanguageType::class, [
$builder->add('language', UserLanguageType::class, [
'required' => true,
]);
@@ -75,12 +82,20 @@ class UserEditType extends AbstractType
'label' => 'active',
'help' => 'active.help'
]);
$builder->add('systemAccount', YesNoType::class, [
'label' => 'system_account',
'help' => 'system_account.help',
]);
}
$builder->add('systemAccount', YesNoType::class, [
'label' => 'system_account',
'help' => 'system_account.help',
]);
if ($options['include_supervisor']) {
$builder->add('supervisor', UserType::class, [
'required' => false,
'label' => 'supervisor',
'ignore_users' => ($user instanceof User && $user->getId() !== null ? [$user] : []),
]);
}
}
public function configureOptions(OptionsResolver $resolver): void
@@ -93,6 +108,7 @@ class UserEditType extends AbstractType
'csrf_token_id' => 'edit_user_profile',
'include_active_flag' => true,
'include_preferences' => true,
'include_supervisor' => true,
]);
}
}

View File

@@ -34,6 +34,7 @@ final class UserVoter extends Voter
'hourly-rate',
'view_team_member',
'contract',
'supervisor',
];
public function __construct(private RolePermissionManager $permissionManager)