Release 2.0.2 (#3856)

* allow to overwrite global spreadsheet styles
* bump version
* fix deprecations in vcard download
* bump composer packages
* added help page for all registered locales
* fix menu id's, cleanup times route, fix configurable homepage redirect
* format duration without leading zero in hours (unify javascript with php behavior)
* fix active records in all screen sizes
* improved responsiveness in XS
* fixed invoice number for customer null fields
* fix javascript respects multiple recent-activity dropdowns
* show recent activities on small screens
* fix user-profile layout column in XS
* fix search is always marked as active
This commit is contained in:
Kevin Papst
2023-02-21 19:21:49 +01:00
committed by GitHub
parent e474087257
commit 25469113fd
61 changed files with 821 additions and 580 deletions

View File

@@ -9,9 +9,10 @@
namespace App\Form\Model;
use App\Utils\EquatableInterface;
use DateTime;
final class DateRange
final class DateRange implements EquatableInterface
{
private ?DateTime $begin = null;
private ?DateTime $end = null;
@@ -49,4 +50,29 @@ final class DateRange
return $this;
}
public function isEqualTo(object $compare): bool
{
if (!$compare instanceof DateRange) {
return false;
}
if (($this->getBegin() === null && $compare->getBegin() !== null) || ($this->getBegin() !== null && $compare->getBegin() === null)) {
return false;
}
if (($this->getEnd() === null && $compare->getEnd() !== null) || ($this->getEnd() !== null && $compare->getEnd() === null)) {
return false;
}
if ($this->getBegin() !== null && $compare->getBegin() !== null && $this->getBegin()->getTimestamp() !== $compare->getBegin()->getTimestamp()) {
return false;
}
if ($this->getEnd() !== null && $compare->getEnd() !== null && $this->getEnd()->getTimestamp() !== $compare->getEnd()->getTimestamp()) {
return false;
}
return true;
}
}

View File

@@ -29,7 +29,6 @@ final class FavoriteMenuType extends AbstractType
{
$resolver->setDefaults([
'multiple' => true,
'include_reports' => false,
'filter_menus' => ['favorites', 'dashboard'],
]);
}

View File

@@ -9,20 +9,17 @@
namespace App\Form\Type;
use App\Entity\User;
use App\Event\ConfigureMainMenuEvent;
use App\Reporting\ReportingService;
use App\Utils\MenuItemModel;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;
final class MenuChoiceType extends AbstractType
{
public function __construct(private EventDispatcherInterface $eventDispatcher, private ReportingService $reportingService, private TranslatorInterface $translator)
public function __construct(private EventDispatcherInterface $eventDispatcher)
{
}
@@ -30,25 +27,19 @@ final class MenuChoiceType extends AbstractType
{
$resolver->setDefaults([
'required' => true,
'include_reports' => true,
'filter_menus' => [],
]);
$resolver->setDefault('choices', function (Options $options): array {
/** @var User $user */
$user = $options['user'];
return $this->getChoices($user, $options['include_reports'], $options['filter_menus']);
return $this->getChoices($options['filter_menus']);
});
}
/**
* @param User $user
* @param bool $withReports
* @param array<string> $filter
* @return array<string, string>
*/
private function getChoices(User $user, bool $withReports, array $filter): array
private function getChoices(array $filter): array
{
$event = new ConfigureMainMenuEvent();
$this->eventDispatcher->dispatch($event);
@@ -58,13 +49,6 @@ final class MenuChoiceType extends AbstractType
$choices += $this->getChoicesFromMenu($event->getAdminMenu(), $filter);
$choices += $this->getChoicesFromMenu($event->getSystemMenu(), $filter);
if ($withReports) {
foreach ($this->reportingService->getAvailableReports($user) as $report) {
$label = $this->translator->trans('menu.reporting') . ': ' . $this->translator->trans($report->getLabel(), [], 'reporting');
$choices[$label] = $report->getId();
}
}
return $choices;
}
@@ -82,13 +66,13 @@ final class MenuChoiceType extends AbstractType
continue;
}
if (!$child->hasChildren()) {
if (\count($child->getRouteArgs()) === 0) {
if (\count($child->getRouteArgs()) === 0 && $child->getRoute() !== null) {
$choices[$child->getLabel()] = $child->getIdentifier();
}
continue;
}
foreach ($child->getChildren() as $subChild) {
if (\count($subChild->getRouteArgs()) === 0) {
if (\count($subChild->getRouteArgs()) === 0 && $subChild->getRoute() !== null) {
$choices[$subChild->getLabel()] = $subChild->getIdentifier();
}
}

View File

@@ -0,0 +1,41 @@
<?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 Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Custom form field type to select the user language.
*/
final class UserLanguageType extends AbstractType
{
public function __construct(private UrlGeneratorInterface $router, private TranslatorInterface $translator)
{
}
public function configureOptions(OptionsResolver $resolver): void
{
$route = $this->router->generate('help_locales');
$message = $this->translator->trans('user.language.help');
$resolver->setDefaults([
'help_html' => true,
'help' => sprintf('<a href="%s" target="help_locales">%s</a>', $route, $message)
]);
}
public function getParent(): string
{
return LanguageType::class;
}
}