Weekly reporting view (#1892)

This commit is contained in:
Kevin Papst
2020-08-16 12:20:33 +02:00
committed by GitHub
parent 2449a1e8bf
commit 2d4cfbe821
39 changed files with 1130 additions and 248 deletions

View File

@@ -42,4 +42,8 @@ class Constants
* Application wide default locale.
*/
public const DEFAULT_LOCALE = 'en';
/**
* Default color for Customer, Project and Activity entities
*/
public const DEFAULT_COLOR = '#d2d6de';
}

View File

@@ -9,7 +9,10 @@
namespace App\Controller;
use App\Configuration\LanguageFormattings;
use App\Entity\User;
use App\Timesheet\DateTimeFactory;
use App\Utils\LocaleFormats;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseAbstractController;
use Symfony\Component\Translation\DataCollectorTranslator;
@@ -108,7 +111,22 @@ abstract class AbstractController extends BaseAbstractController implements Serv
{
return array_merge(parent::getSubscribedServices(), [
'translator' => TranslatorInterface::class,
'logger' => LoggerInterface::class
'logger' => LoggerInterface::class,
LanguageFormattings::class => LanguageFormattings::class,
]);
}
protected function getDateTimeFactory(?User $user = null): DateTimeFactory
{
if (null === $user) {
$user = $this->getUser();
}
return new DateTimeFactory(new \DateTimeZone($user->getTimezone()));
}
protected function getLocaleFormats(string $locale): LocaleFormats
{
return new LocaleFormats($this->container->get(LanguageFormattings::class), $locale);
}
}

View File

@@ -14,12 +14,15 @@ use App\Reporting\MonthByUser;
use App\Reporting\MonthByUserForm;
use App\Reporting\MonthlyUserList;
use App\Reporting\MonthlyUserListForm;
use App\Reporting\WeekByUser;
use App\Reporting\WeekByUserForm;
use App\Repository\Query\UserQuery;
use App\Repository\TimesheetRepository;
use App\Repository\UserRepository;
use App\Timesheet\UserDateTimeFactory;
use Exception;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -39,46 +42,79 @@ final class ReportingController extends AbstractController
* @var UserRepository
*/
private $userRepository;
/**
* @var UserDateTimeFactory
*/
private $dateTimeFactory;
public function __construct(TimesheetRepository $timesheetRepository, UserRepository $userRepository, UserDateTimeFactory $dateTimeFactory)
public function __construct(TimesheetRepository $timesheetRepository, UserRepository $userRepository)
{
$this->timesheetRepository = $timesheetRepository;
$this->userRepository = $userRepository;
$this->dateTimeFactory = $dateTimeFactory;
}
/**
* @Route(path="/", name="reporting", methods={"GET"})
* @Route(path="/month_by_user", name="report_user_month", methods={"GET","POST"})
*
* @return Response
*/
public function monthByUser(Request $request)
public function defaultReport(): Response
{
$user = $this->getUser();
return $this->redirectToRoute('report_user_week');
}
private function canSelectUser(): bool
{
if (!$this->isGranted('view_other_timesheet')) {
return false;
}
$currentUser = $this->getUser();
if ($currentUser->canSeeAllData()) {
return true;
}
if ($currentUser->hasTeamAssignment()) {
return true;
}
return false;
}
/**
* @Route(path="/month_by_user", name="report_user_month", methods={"GET","POST"})
*
* @param Request $request
* @return Response
* @throws Exception
*/
public function monthByUser(Request $request): Response
{
$currentUser = $this->getUser();
$dateTimeFactory = $this->getDateTimeFactory($currentUser);
$localeFormats = $this->getLocaleFormats($request->getLocale());
$canChangeUser = $this->canSelectUser();
$values = new MonthByUser();
$values->setUser($user);
$values->setDate($this->dateTimeFactory->getStartOfMonth());
$values->setUser($currentUser);
$values->setDate($dateTimeFactory->getStartOfMonth());
$form = $this->createForm(MonthByUserForm::class, $values, [
'include_user' => $this->isGranted('view_other_timesheet') && $user->hasTeamAssignment(),
'include_user' => $canChangeUser,
'timezone' => $dateTimeFactory->getTimezone()->getName(),
'start_date' => $values->getDate(),
'format' => $localeFormats->getDateTypeFormat(),
]);
$form->submit($request->query->all(), false);
if ($values->getUser() === null) {
$values->setUser($user);
$values->setUser($currentUser);
}
if ($user !== $values->getUser() && !$this->isGranted('view_other_timesheet')) {
if ($currentUser !== $values->getUser() && !$canChangeUser) {
throw new AccessDeniedException('User is not allowed to see other users timesheet');
}
if ($values->getDate() === null) {
$values->setDate($this->dateTimeFactory->getStartOfMonth());
$values->setDate($dateTimeFactory->getStartOfMonth());
}
$start = $values->getDate();
@@ -110,12 +146,82 @@ final class ReportingController extends AbstractController
}
/**
* @Route(path="/monthly_users_list", name="report_monthly_users", methods={"GET","POST"})
* @Security("is_granted('view_other_timesheet')")
* @Route(path="/week_by_user", name="report_user_week", methods={"GET","POST"})
*
* @param Request $request
* @return Response
* @throws Exception
*/
public function montlyhUsersList(Request $request)
public function weekByUser(Request $request): Response
{
$currentUser = $this->getUser();
$dateTimeFactory = $this->getDateTimeFactory($currentUser);
$localeFormats = $this->getLocaleFormats($request->getLocale());
$canChangeUser = $this->canSelectUser();
$values = new WeekByUser();
$values->setUser($currentUser);
$values->setDate($dateTimeFactory->getStartOfWeek());
$form = $this->createForm(WeekByUserForm::class, $values, [
'include_user' => $canChangeUser,
'timezone' => $dateTimeFactory->getTimezone()->getName(),
'start_date' => $values->getDate(),
'format' => $localeFormats->getDateTypeFormat(),
]);
$form->submit($request->query->all(), false);
if ($values->getUser() === null) {
$values->setUser($currentUser);
}
if ($currentUser !== $values->getUser() && !$canChangeUser) {
throw new AccessDeniedException('User is not allowed to see other users timesheet');
}
if ($values->getDate() === null) {
$values->setDate($dateTimeFactory->getStartOfWeek());
}
$start = $dateTimeFactory->getStartOfWeek($values->getDate());
$end = $dateTimeFactory->getEndOfWeek($values->getDate());
$selectedUser = $values->getUser();
$previous = clone $start;
$previous->modify('-1 week');
$next = clone $start;
$next->modify('+1 week');
$data = $this->timesheetRepository->getDailyStats($selectedUser, $start, $end);
$rows = $this->prepareMonthlyData($data);
return $this->render('reporting/week_by_user.html.twig', [
'form' => $form->createView(),
'days' => $data,
'rows' => $rows,
'user' => $selectedUser,
'current' => $start,
'next' => $next,
'previous' => $previous,
]);
}
/**
* @Route(path="/monthly_users_list", name="report_monthly_users", methods={"GET","POST"})
* @Security("is_granted('view_other_timesheet')")
*
* @param Request $request
* @return Response
* @throws Exception
*/
public function monthlyUsersList(Request $request): Response
{
$currentUser = $this->getUser();
$dateTimeFactory = $this->getDateTimeFactory();
$localeFormats = $this->getLocaleFormats($request->getLocale());
$query = new UserQuery();
$query->setCurrentUser($currentUser);
@@ -124,18 +230,22 @@ final class ReportingController extends AbstractController
$rows = [];
$values = new MonthlyUserList();
$values->setDate($this->dateTimeFactory->getStartOfMonth());
$values->setDate($dateTimeFactory->getStartOfMonth());
$form = $this->createForm(MonthlyUserListForm::class, $values, []);
$form = $this->createForm(MonthlyUserListForm::class, $values, [
'timezone' => $dateTimeFactory->getTimezone()->getName(),
'start_date' => $values->getDate(),
'format' => $localeFormats->getDateTypeFormat(),
]);
$form->submit($request->query->all(), false);
if ($form->isSubmitted() && !$form->isValid()) {
$values->setDate($this->dateTimeFactory->getStartOfMonth());
$values->setDate($dateTimeFactory->getStartOfMonth());
}
if ($values->getDate() === null) {
$values->setDate($this->dateTimeFactory->getStartOfMonth());
$values->setDate($dateTimeFactory->getStartOfMonth());
}
$start = $values->getDate();

View File

@@ -9,6 +9,7 @@
namespace App\Entity;
use App\Constants;
use App\Export\Annotation as Exporter;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
@@ -36,6 +37,10 @@ trait ColorTrait
*/
public function getColor(): ?string
{
if ($this->color === Constants::DEFAULT_COLOR) {
return null;
}
return $this->color;
}

View File

@@ -9,6 +9,7 @@
namespace App\Form\Type;
use App\Constants;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\Type\ColorType;
@@ -17,7 +18,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class ColorPickerType extends AbstractType implements DataTransformerInterface
{
public const DEFAULT_COLOR = '#d2d6de';
public const DEFAULT_COLOR = Constants::DEFAULT_COLOR;
/**
* {@inheritdoc}

View File

@@ -9,8 +9,6 @@
namespace App\Form\Type;
use App\Timesheet\UserDateTimeFactory;
use App\Utils\LocaleSettings;
use App\Utils\MomentFormatConverter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
@@ -25,38 +23,16 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
final class MonthPickerType extends AbstractType
{
/**
* @var LocaleSettings
*/
private $localeSettings;
/**
* @var UserDateTimeFactory
*/
private $dateTime;
public function __construct(LocaleSettings $localeSettings, UserDateTimeFactory $dateTime)
{
$this->localeSettings = $localeSettings;
$this->dateTime = $dateTime;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$pickerFormat = $this->localeSettings->getDatePickerFormat();
$dateFormat = $this->localeSettings->getDateTypeFormat();
$timezone = $this->dateTime->getTimezone()->getName();
$resolver->setDefaults([
'widget' => 'single_text',
'html5' => false,
'format' => $dateFormat,
'format_picker' => $pickerFormat,
'model_timezone' => $timezone,
'view_timezone' => $timezone,
'format' => DateType::HTML5_FORMAT,
'start_date' => new \DateTime(),
]);
}
@@ -66,13 +42,13 @@ final class MonthPickerType extends AbstractType
$date = $form->getData();
if (null === $date) {
$date = $this->dateTime->getStartOfMonth();
$date = $options['start_date'];
}
$view->vars['month'] = $date;
$view->vars['previousMonth'] = (clone $date)->modify('-1 month');
$view->vars['nextMonth'] = (clone $date)->modify('+1 month');
$view->vars['momentFormat'] = (new MomentFormatConverter())->convert($this->localeSettings->getDateTypeFormat());
$view->vars['momentFormat'] = (new MomentFormatConverter())->convert($options['format']);
}
/**

View File

@@ -0,0 +1,69 @@
<?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\Type;
use App\Utils\MomentFormatConverter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Custom form field type to select a week via picker and select previous and next week.
*
* Always falls back to the current week if none or an invalid date is given.
*/
final class WeekPickerType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'widget' => 'single_text',
'html5' => false,
'format' => DateType::HTML5_FORMAT,
'start_date' => new \DateTime(),
]);
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
/** @var \DateTime|null $date */
$date = $form->getData();
if (null === $date) {
$date = $options['start_date'];
}
$view->vars['week'] = $date;
$view->vars['previousWeek'] = (clone $date)->modify('-1 week');
$view->vars['nextWeek'] = (clone $date)->modify('+1 week');
$view->vars['momentFormat'] = (new MomentFormatConverter())->convert($options['format']);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return DateType::class;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'weekpicker';
}
}

View File

@@ -0,0 +1,48 @@
<?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\Reporting;
use App\Entity\User;
abstract class DateByUser
{
/**
* @var User
*/
private $user;
/**
* @var \DateTime
*/
private $date;
public function getUser(): ?User
{
return $this->user;
}
public function setUser(User $user): self
{
$this->user = $user;
return $this;
}
public function getDate(): ?\DateTime
{
return $this->date;
}
public function setDate(\DateTime $date): self
{
$this->date = $date;
return $this;
}
}

View File

@@ -9,40 +9,6 @@
namespace App\Reporting;
use App\Entity\User;
final class MonthByUser
final class MonthByUser extends DateByUser
{
/**
* @var User
*/
private $user;
/**
* @var \DateTime
*/
private $date;
public function getUser(): ?User
{
return $this->user;
}
public function setUser(User $user): MonthByUser
{
$this->user = $user;
return $this;
}
public function getDate(): ?\DateTime
{
return $this->date;
}
public function setDate(\DateTime $date): MonthByUser
{
$this->date = $date;
return $this;
}
}

View File

@@ -12,6 +12,7 @@ namespace App\Reporting;
use App\Form\Type\MonthPickerType;
use App\Form\Type\UserType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -32,7 +33,12 @@ class MonthByUserForm extends AbstractType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('date', MonthPickerType::class);
$builder->add('date', MonthPickerType::class, [
'model_timezone' => $options['timezone'],
'view_timezone' => $options['timezone'],
'start_date' => $options['start_date'],
'format' => $options['format'],
]);
if ($options['include_user']) {
$builder->add('user', UserType::class, ['width' => false]);
@@ -46,6 +52,9 @@ class MonthByUserForm extends AbstractType
{
$resolver->setDefaults([
'data_class' => MonthByUser::class,
'timezone' => date_default_timezone_get(),
'start_date' => new \DateTime(),
'format' => DateType::HTML5_FORMAT,
'include_user' => false,
'csrf_protection' => false,
'method' => 'GET',

View File

@@ -11,6 +11,7 @@ namespace App\Reporting;
use App\Form\Type\MonthPickerType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -31,7 +32,12 @@ class MonthlyUserListForm extends AbstractType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('date', MonthPickerType::class);
$builder->add('date', MonthPickerType::class, [
'model_timezone' => $options['timezone'],
'view_timezone' => $options['timezone'],
'start_date' => $options['start_date'],
'format' => $options['format'],
]);
}
/**
@@ -41,6 +47,9 @@ class MonthlyUserListForm extends AbstractType
{
$resolver->setDefaults([
'data_class' => MonthlyUserList::class,
'timezone' => date_default_timezone_get(),
'start_date' => new \DateTime(),
'format' => DateType::HTML5_FORMAT,
'csrf_protection' => false,
'method' => 'GET',
]);

View File

@@ -0,0 +1,14 @@
<?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\Reporting;
final class WeekByUser extends DateByUser
{
}

View File

@@ -0,0 +1,63 @@
<?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\Reporting;
use App\Form\Type\UserType;
use App\Form\Type\WeekPickerType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class WeekByUserForm extends AbstractType
{
/**
* Simplify cross linking between pages by removing the block prefix.
*
* @return null|string
*/
public function getBlockPrefix()
{
return null;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('date', WeekPickerType::class, [
'model_timezone' => $options['timezone'],
'view_timezone' => $options['timezone'],
'start_date' => $options['start_date'],
'format' => $options['format'],
]);
if ($options['include_user']) {
$builder->add('user', UserType::class, ['width' => false]);
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => WeekByUser::class,
'timezone' => date_default_timezone_get(),
'start_date' => new \DateTime(),
'format' => DateType::HTML5_FORMAT,
'include_user' => false,
'csrf_protection' => false,
'method' => 'GET',
]);
}
}

View File

@@ -444,7 +444,11 @@ class TimesheetRepository extends EntityRepository
$results[$dateKey]['rate'] += $rate;
$results[$dateKey]['duration'] += $duration;
$detailsId = $result->getProject()->getCustomer()->getId() . '_' . $result->getProject()->getId();
$detailsId =
$result->getProject()->getCustomer()->getId()
. '_' . $result->getProject()->getId()
. '_' . $result->getActivity()->getId()
;
if (!isset($results[$dateKey]['details'][$detailsId])) {
$results[$dateKey]['details'][$detailsId] = [
'project' => $result->getProject(),

View File

@@ -0,0 +1,101 @@
<?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\Timesheet;
use DateTime;
use DateTimeZone;
class DateTimeFactory
{
/**
* @var DateTimeZone
*/
private $timezone;
public function __construct(?DateTimeZone $timezone = null)
{
if (null === $timezone) {
$timezone = new \DateTimeZone(date_default_timezone_get());
}
$this->setTimezone($timezone);
}
public function setTimezone(DateTimeZone $timezone)
{
$this->timezone = $timezone;
}
public function getTimezone(): DateTimeZone
{
return $this->timezone;
}
public function getStartOfMonth(): DateTime
{
$date = $this->createDateTime('first day of this month');
$date->setTime(0, 0, 0);
return $date;
}
public function getStartOfWeek(?DateTime $date = null): DateTime
{
if (null === $date) {
$date = $this->createDateTime('now');
}
return $this->createWeekDateTime($date->format('Y'), $date->format('W'), 1, 0, 0, 0);
}
public function getEndOfWeek(?DateTime $date = null): DateTime
{
if (null === $date) {
$date = $this->createDateTime('now');
}
return $this->createWeekDateTime($date->format('Y'), $date->format('W'), 7, 23, 59, 59);
}
public function getEndOfMonth(): DateTime
{
$date = $this->createDateTime('last day of this month');
$date->setTime(23, 59, 59);
return $date;
}
private function createWeekDateTime($year, $week, $day, $hour, $minute, $second)
{
$date = new DateTime('now', $this->getTimezone());
$date->setISODate($year, $week, $day);
$date->setTime($hour, $minute, $second);
return $date;
}
public function createDateTime(string $datetime = 'now'): DateTime
{
$date = new DateTime($datetime, $this->getTimezone());
return $date;
}
/**
* @param string $format
* @param null|string $datetime
* @return bool|DateTime
*/
public function createDateTimeFromFormat(string $format, ?string $datetime = 'now')
{
$date = DateTime::createFromFormat($format, $datetime, $this->getTimezone());
return $date;
}
}

View File

@@ -11,26 +11,31 @@ namespace App\Timesheet;
use App\Entity\User;
use App\Security\CurrentUser;
use DateTimeZone;
class UserDateTimeFactory
/**
* @internal use DateTimeFactory instead: this one relies on the global context and will be deprecated in the future
*/
class UserDateTimeFactory extends DateTimeFactory
{
/**
* @var \DateTimeZone
*/
private $timezone;
/**
* @var CurrentUser
*/
private $user;
/**
* @var bool
*/
private $initializedFromUser = false;
public function __construct(CurrentUser $user)
{
parent::__construct(null);
$this->user = $user;
}
public function getTimezone(): \DateTimeZone
public function getTimezone(): DateTimeZone
{
if (null === $this->timezone) {
if ($this->initializedFromUser === false) {
$timezone = date_default_timezone_get();
$user = $this->user->getUser();
@@ -38,44 +43,12 @@ class UserDateTimeFactory
$timezone = $user->getTimezone();
}
$this->timezone = new \DateTimeZone($timezone);
$timezone = new DateTimeZone($timezone);
parent::setTimezone($timezone);
$this->initializedFromUser = true;
}
return $this->timezone;
}
public function getStartOfMonth(): \DateTime
{
$date = $this->createDateTime('first day of this month');
$date->setTime(0, 0, 0);
return $date;
}
public function getEndOfMonth(): \DateTime
{
$date = $this->createDateTime('last day of this month');
$date->setTime(23, 59, 59);
return $date;
}
public function createDateTime(string $datetime = 'now'): \DateTime
{
$date = new \DateTime($datetime, $this->getTimezone());
return $date;
}
/**
* @param string $format
* @param null|string $datetime
* @return bool|\DateTime
*/
public function createDateTimeFromFormat(string $format, ?string $datetime = 'now')
{
$date = \DateTime::createFromFormat($format, $datetime, $this->getTimezone());
return $date;
return parent::getTimezone();
}
}

View File

@@ -230,34 +230,36 @@ class DateExtensions extends AbstractExtension
return $date->format($this->timeFormat);
}
public function monthName(\DateTime $dateTime): string
/**
* @see https://framework.zend.com/manual/1.12/en/zend.date.constants.html#zend.date.constants.selfdefinedformats
* @see http://userguide.icu-project.org/formatparse/datetime
*
* @param DateTime $dateTime
* @param string $format
* @return string
*/
private function formatIntl(\DateTime $dateTime, string $format): string
{
// @see http://userguide.icu-project.org/formatparse/datetime
$formatter = new \IntlDateFormatter(
$this->locale,
\IntlDateFormatter::FULL,
\IntlDateFormatter::FULL,
$dateTime->getTimezone()->getName(),
\IntlDateFormatter::GREGORIAN,
'LLLL'
$format
);
return $formatter->format($dateTime);
}
public function monthName(\DateTime $dateTime, bool $withYear = false): string
{
return $this->formatIntl($dateTime, ($withYear ? 'LLLL yyyy' : 'LLLL'));
}
public function dayName(\DateTime $dateTime, bool $short = false): string
{
// @see http://userguide.icu-project.org/formatparse/datetime
$formatter = new \IntlDateFormatter(
$this->locale,
\IntlDateFormatter::FULL,
\IntlDateFormatter::FULL,
$dateTime->getTimezone()->getName(),
\IntlDateFormatter::GREGORIAN,
$short ? 'EE' : 'EEEE'
);
return $formatter->format($dateTime);
return $this->formatIntl($dateTime, ($short ? 'EE' : 'EEEE'));
}
/**

View File

@@ -10,6 +10,10 @@
namespace App\Twig;
use App\Constants;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\EntityWithMetaFields;
use App\Entity\Project;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
@@ -27,6 +31,7 @@ class Extensions extends AbstractExtension
return [
new TwigFilter('docu_link', [$this, 'documentationLink']),
new TwigFilter('multiline_indent', [$this, 'multilineIndent']),
new TwigFilter('color', [$this, 'color']),
];
}
@@ -40,6 +45,34 @@ class Extensions extends AbstractExtension
];
}
public function color(EntityWithMetaFields $entity): ?string
{
if ($entity instanceof Activity) {
if (!empty($entity->getColor())) {
return $entity->getColor();
}
if (null !== $entity->getProject()) {
$entity = $entity->getProject();
}
}
if ($entity instanceof Project) {
if (!empty($entity->getColor())) {
return $entity->getColor();
}
$entity = $entity->getCustomer();
}
if ($entity instanceof Customer) {
if (!empty($entity->getColor())) {
return $entity->getColor();
}
}
return null;
}
/**
* @param object $object
* @return null|string

View File

@@ -54,6 +54,7 @@ final class ReportingExtension extends AbstractExtension
$event = new ReportingEvent($user);
if ($this->security->isGranted('view_reporting')) {
$event->addReport(new Report('week_by_user', 'report_user_week', 'report_user_week'));
$event->addReport(new Report('month_by_user', 'report_user_month', 'report_user_month'));
if ($this->security->isGranted('view_other_timesheet')) {
$event->addReport(new Report('monthly_users_list', 'report_monthly_users', 'report_monthly_users'));