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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ final class FavoriteMenuType extends AbstractType
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'multiple' => true,
|
||||
'include_reports' => false,
|
||||
'filter_menus' => ['favorites', 'dashboard'],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
41
src/Form/Type/UserLanguageType.php
Normal file
41
src/Form/Type/UserLanguageType.php
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user