added team filter in timesheet search forms (#3590)
* added team filter in export and invoice search form * added teams select to timesheet filter * added team select to report filter * hide user and team filter if count < 2
This commit is contained in:
@@ -63,10 +63,6 @@ final class ReportUsersMonthController extends AbstractController
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
|
||||
$values = new MonthlyUserList();
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
|
||||
@@ -77,10 +73,21 @@ final class ReportUsersMonthController extends AbstractController
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
|
||||
if ($form->isSubmitted() && !$form->isValid()) {
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
if (!$form->isValid()) {
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
} else {
|
||||
if ($values->getTeam() !== null) {
|
||||
$query->setSearchTeams([$values->getTeam()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
|
||||
if ($values->getDate() === null) {
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
}
|
||||
|
||||
@@ -63,10 +63,6 @@ final class ReportUsersWeekController extends AbstractController
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
|
||||
$values = new WeeklyUserList();
|
||||
$values->setDate($dateTimeFactory->getStartOfWeek());
|
||||
|
||||
@@ -77,10 +73,21 @@ final class ReportUsersWeekController extends AbstractController
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
|
||||
if ($form->isSubmitted() && !$form->isValid()) {
|
||||
$values->setDate($dateTimeFactory->getStartOfWeek());
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
if (!$form->isValid()) {
|
||||
$values->setDate($dateTimeFactory->getStartOfWeek());
|
||||
} else {
|
||||
if ($values->getTeam() !== null) {
|
||||
$query->setSearchTeams([$values->getTeam()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
|
||||
if ($values->getDate() === null) {
|
||||
$values->setDate($dateTimeFactory->getStartOfWeek());
|
||||
}
|
||||
|
||||
@@ -73,9 +73,6 @@ final class ReportUsersYearController extends AbstractController
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
$defaultDate = $dateTimeFactory->createStartOfYear();
|
||||
|
||||
if (null !== ($financialYear = $systemConfiguration->getFinancialYearStart())) {
|
||||
@@ -92,10 +89,21 @@ final class ReportUsersYearController extends AbstractController
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
|
||||
if ($form->isSubmitted() && !$form->isValid()) {
|
||||
$values->setDate(clone $defaultDate);
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
if (!$form->isValid()) {
|
||||
$values->setDate(clone $defaultDate);
|
||||
} else {
|
||||
if ($values->getTeam() !== null) {
|
||||
$query->setSearchTeams([$values->getTeam()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$allUsers = $userRepository->getUsersForQuery($query);
|
||||
|
||||
if ($values->getDate() === null) {
|
||||
$values->setDate(clone $defaultDate);
|
||||
}
|
||||
|
||||
88
src/Form/Extension/ToolbarFormExtension.php
Normal file
88
src/Form/Extension/ToolbarFormExtension.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Form\Extension;
|
||||
|
||||
use App\Form\Toolbar\ExportToolbarForm;
|
||||
use App\Form\Toolbar\InvoiceToolbarForm;
|
||||
use App\Form\Toolbar\InvoiceToolbarSimpleForm;
|
||||
use App\Form\Toolbar\TimesheetExportToolbarForm;
|
||||
use App\Form\Toolbar\TimesheetToolbarForm;
|
||||
use App\Form\Toolbar\UserToolbarForm;
|
||||
use App\Reporting\MonthlyUserListForm;
|
||||
use App\Reporting\WeeklyUserListForm;
|
||||
use App\Reporting\YearlyUserListForm;
|
||||
use App\User\TeamService;
|
||||
use App\User\UserService;
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class ToolbarFormExtension extends AbstractTypeExtension
|
||||
{
|
||||
private $userService;
|
||||
private $teamService;
|
||||
private $teamNames = ['team', 'teams', 'searchTeams'];
|
||||
private $userNames = ['user', 'users'];
|
||||
|
||||
public function __construct(UserService $userService, TeamService $teamService)
|
||||
{
|
||||
$this->userService = $userService;
|
||||
$this->teamService = $teamService;
|
||||
}
|
||||
|
||||
public static function getExtendedTypes(): iterable
|
||||
{
|
||||
return [
|
||||
InvoiceToolbarForm::class,
|
||||
InvoiceToolbarSimpleForm::class,
|
||||
ExportToolbarForm::class,
|
||||
TimesheetToolbarForm::class,
|
||||
TimesheetExportToolbarForm::class,
|
||||
UserToolbarForm::class,
|
||||
WeeklyUserListForm::class,
|
||||
MonthlyUserListForm::class,
|
||||
YearlyUserListForm::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$deleteUser = false;
|
||||
foreach ($this->userNames as $name) {
|
||||
if ($builder->has($name) && $this->userService->countUser(true) < 2) {
|
||||
$deleteUser = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleteUser) {
|
||||
foreach ($this->userNames as $name) {
|
||||
if ($builder->has($name)) {
|
||||
$builder->remove($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$deleteTeams = false;
|
||||
foreach ($this->teamNames as $name) {
|
||||
if ($builder->has($name) && !$this->teamService->hasTeams()) {
|
||||
$deleteTeams = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleteTeams) {
|
||||
foreach ($this->teamNames as $name) {
|
||||
if ($builder->has($name)) {
|
||||
$builder->remove($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ class ExportToolbarForm extends AbstractToolbarForm
|
||||
$this->addTimesheetStateChoice($builder);
|
||||
if ($options['include_user']) {
|
||||
$this->addUsersChoice($builder);
|
||||
$this->addTeamsChoice($builder);
|
||||
}
|
||||
$this->addDateRange($builder, ['timezone' => $options['timezone']]);
|
||||
$this->addCustomerMultiChoice($builder, ['start_date_param' => null, 'end_date_param' => null, 'ignore_date' => true], true);
|
||||
|
||||
@@ -26,6 +26,7 @@ class InvoiceToolbarForm extends InvoiceToolbarSimpleForm
|
||||
$this->addSearchTermInputField($builder);
|
||||
if ($options['include_user']) {
|
||||
$this->addUsersChoice($builder);
|
||||
$this->addTeamsChoice($builder);
|
||||
}
|
||||
$this->addActivityMultiChoice($builder, $options, true);
|
||||
$this->addTagInputField($builder);
|
||||
|
||||
@@ -36,6 +36,7 @@ class TimesheetToolbarForm extends AbstractToolbarForm
|
||||
$this->addTagInputField($builder);
|
||||
if ($options['include_user']) {
|
||||
$this->addUsersChoice($builder);
|
||||
$this->addTeamsChoice($builder);
|
||||
}
|
||||
$this->addTimesheetStateChoice($builder);
|
||||
$this->addBillableChoice($builder);
|
||||
|
||||
@@ -9,11 +9,17 @@
|
||||
|
||||
namespace App\Reporting;
|
||||
|
||||
use App\Entity\Team;
|
||||
|
||||
abstract class AbstractUserList
|
||||
{
|
||||
private $date;
|
||||
private $decimal = false;
|
||||
private $sumType = 'duration';
|
||||
/**
|
||||
* @var Team|null
|
||||
*/
|
||||
private $team = null;
|
||||
|
||||
public function getDate(): ?\DateTime
|
||||
{
|
||||
@@ -48,4 +54,14 @@ abstract class AbstractUserList
|
||||
|
||||
$this->sumType = $sumType;
|
||||
}
|
||||
|
||||
public function getTeam(): ?Team
|
||||
{
|
||||
return $this->team;
|
||||
}
|
||||
|
||||
public function setTeam(?Team $team = null): void
|
||||
{
|
||||
$this->team = $team;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Reporting;
|
||||
|
||||
use App\Form\Type\MonthPickerType;
|
||||
use App\Form\Type\ReportSumType;
|
||||
use App\Form\Type\TeamType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -37,6 +38,11 @@ class MonthlyUserListForm extends AbstractType
|
||||
'view_timezone' => $options['timezone'],
|
||||
'start_date' => $options['start_date'],
|
||||
]);
|
||||
$builder->add('team', TeamType::class, [
|
||||
'multiple' => false,
|
||||
'required' => false,
|
||||
'width' => false,
|
||||
]);
|
||||
$builder->add('sumType', ReportSumType::class);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Reporting;
|
||||
|
||||
use App\Form\Type\ReportSumType;
|
||||
use App\Form\Type\TeamType;
|
||||
use App\Form\Type\WeekPickerType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -37,6 +38,11 @@ class WeeklyUserListForm extends AbstractType
|
||||
'view_timezone' => $options['timezone'],
|
||||
'start_date' => $options['start_date'],
|
||||
]);
|
||||
$builder->add('team', TeamType::class, [
|
||||
'multiple' => false,
|
||||
'required' => false,
|
||||
'width' => false,
|
||||
]);
|
||||
$builder->add('sumType', ReportSumType::class);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Reporting;
|
||||
|
||||
use App\Form\Type\ReportSumType;
|
||||
use App\Form\Type\TeamType;
|
||||
use App\Form\Type\YearPickerType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -38,6 +39,11 @@ class YearlyUserListForm extends AbstractType
|
||||
'start_date' => $options['start_date'],
|
||||
'show_range' => true,
|
||||
]);
|
||||
$builder->add('team', TeamType::class, [
|
||||
'multiple' => false,
|
||||
'required' => false,
|
||||
'width' => false,
|
||||
]);
|
||||
$builder->add('sumType', ReportSumType::class);
|
||||
}
|
||||
|
||||
|
||||
43
src/User/TeamService.php
Normal file
43
src/User/TeamService.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\User;
|
||||
|
||||
use App\Repository\TeamRepository;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class TeamService
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private $cache = [];
|
||||
private $repository;
|
||||
|
||||
public function __construct(TeamRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function countTeams(): int
|
||||
{
|
||||
if (!\array_key_exists('count', $this->cache)) {
|
||||
$this->cache['count'] = $this->repository->count([]);
|
||||
}
|
||||
|
||||
return $this->cache['count'];
|
||||
}
|
||||
|
||||
public function hasTeams(): bool
|
||||
{
|
||||
return $this->countTeams() > 0;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,11 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
*/
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private $cache = [];
|
||||
|
||||
private $repository;
|
||||
private $dispatcher;
|
||||
private $validator;
|
||||
@@ -44,6 +49,17 @@ class UserService
|
||||
$this->encoderFactory = $encoderFactory;
|
||||
}
|
||||
|
||||
public function countUser(?bool $enabled = null): int
|
||||
{
|
||||
$key = 'count' . ($enabled === null ? '_all' : ($enabled ? '_visible' : '_invisible'));
|
||||
|
||||
if (!\array_key_exists($key, $this->cache)) {
|
||||
$this->cache[$key] = $this->repository->countUser($enabled);
|
||||
}
|
||||
|
||||
return $this->cache[$key];
|
||||
}
|
||||
|
||||
public function createNewUser(): User
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
{% if form.users is defined %}
|
||||
{{ form_row(form.users) }}
|
||||
{% endif %}
|
||||
{% if form.teams is defined %}
|
||||
{{ form_row(form.teams) }}
|
||||
{% endif %}
|
||||
{{ form_row(form.billable) }}
|
||||
{{ form_row(form.exported) }}
|
||||
{{ form_row(form.state) }}
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
{% if form.users is defined %}
|
||||
{{ form_row(form.users, {'row_attr': {'class': 'invoice_search_form_row_users'}}) }}
|
||||
{% endif %}
|
||||
{% if form.teams is defined %}
|
||||
{{ form_row(form.teams, {'row_attr': {'class': 'invoice_search_form_row_teams'}}) }}
|
||||
{% endif %}
|
||||
{% if form.exported is defined %}
|
||||
{{ form_row(form.exported, {'row_attr': {'class': 'invoice_search_form_row_exported'}}) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ form_widget(form.date) }}
|
||||
{% if form.team is defined %}
|
||||
{{ form_widget(form.team) }}
|
||||
{% endif %}
|
||||
{% if form.sumType.vars.choices|length > 1 %}
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ form_widget(form.date) }}
|
||||
{% if form.team is defined %}
|
||||
{{ form_widget(form.team) }}
|
||||
{% endif %}
|
||||
{% if form.sumType.vars.choices|length > 1 %}
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
|
||||
Reference in New Issue
Block a user