Release 2.31 (#5372)
* simplify translation * bump version * deprecate translations * pass date-range as argument to export and timesheet filter URL from monthly overview report * added class for use in responsive screens * show technical role name * simplify multi-update title * more statistic models * bump composer packages
This commit is contained in:
@@ -17,11 +17,11 @@ final class Constants
|
||||
/**
|
||||
* The current release version
|
||||
*/
|
||||
public const VERSION = '2.30.0';
|
||||
public const VERSION = '2.31.0';
|
||||
/**
|
||||
* The current release: major * 10000 + minor * 100 + patch
|
||||
*/
|
||||
public const VERSION_ID = 23000;
|
||||
public const VERSION_ID = 23100;
|
||||
/**
|
||||
* The software name
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,11 @@ final class DashboardController extends AbstractController
|
||||
*/
|
||||
private ?array $widgets = null;
|
||||
|
||||
public function __construct(private EventDispatcherInterface $eventDispatcher, private WidgetService $service, private BookmarkRepository $repository)
|
||||
public function __construct(
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly WidgetService $service,
|
||||
private readonly BookmarkRepository $repository
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -59,11 +59,12 @@ final class ProjectDateRangeController extends AbstractController
|
||||
$byCustomer[$customer->getId()]['projects'][] = $entry;
|
||||
}
|
||||
|
||||
return $this->render('reporting/project_daterange.html.twig', [
|
||||
return $this->render('reporting/project/daterange.html.twig', [
|
||||
'report_title' => 'report_project_daterange',
|
||||
'entries' => $byCustomer,
|
||||
'form' => $form->createView(),
|
||||
'queryEnd' => $dateRange->getEnd(),
|
||||
'queryBegin' => $begin,
|
||||
'queryEnd' => $end,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,16 +50,21 @@ final class ProjectSubscriber extends AbstractActionsSubscriber
|
||||
$event->addDivider();
|
||||
}
|
||||
|
||||
$dateRange = '';
|
||||
if (isset($payload['daterange']) && \is_string($payload['daterange'])) {
|
||||
$dateRange = $payload['daterange'];
|
||||
}
|
||||
|
||||
if ($this->isGranted('view_activity')) {
|
||||
$event->addActionToSubmenu('filter', 'activity', ['title' => 'activities', 'url' => $this->path('admin_activity', ['customers[]' => $customer->getId(), 'projects[]' => $project->getId()])]);
|
||||
}
|
||||
|
||||
if ($this->isGranted('view_other_timesheet')) {
|
||||
$event->addActionToSubmenu('filter', 'timesheet', ['title' => 'timesheet.filter', 'url' => $this->path('admin_timesheet', ['customers[]' => $customer->getId(), 'projects[]' => $project->getId()])]);
|
||||
$event->addActionToSubmenu('filter', 'timesheet', ['title' => 'timesheet.filter', 'url' => $this->path('admin_timesheet', ['customers[]' => $customer->getId(), 'projects[]' => $project->getId(), 'daterange' => $dateRange])]);
|
||||
}
|
||||
|
||||
if ($this->isGranted('create_export')) {
|
||||
$event->addActionToSubmenu('filter', 'export', ['title' => 'export', 'url' => $this->path('export', ['customers[]' => $customer->getId(), 'projects[]' => $project->getId(), 'exported' => 1, 'daterange' => ''])]);
|
||||
$event->addActionToSubmenu('filter', 'export', ['title' => 'export', 'url' => $this->path('export', ['customers[]' => $customer->getId(), 'projects[]' => $project->getId(), 'exported' => 1, 'daterange' => $dateRange])]);
|
||||
}
|
||||
|
||||
if ($event->hasSubmenu('filter')) {
|
||||
|
||||
54
src/Model/Statistic/DateRange.php
Normal file
54
src/Model/Statistic/DateRange.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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\Model\Statistic;
|
||||
|
||||
final class DateRange
|
||||
{
|
||||
/**
|
||||
* @var array<string, StatisticDate>
|
||||
*/
|
||||
private array $days = [];
|
||||
|
||||
public function __construct(\DateTimeInterface $begin, \DateTimeInterface $end)
|
||||
{
|
||||
if ($end < $begin) {
|
||||
throw new \InvalidArgumentException('End must be later than begin');
|
||||
}
|
||||
|
||||
$begin = \DateTimeImmutable::createFromInterface($begin);
|
||||
$begin = $begin->setTime(0, 0, 0);
|
||||
|
||||
$end = \DateTimeImmutable::createFromInterface($end);
|
||||
$end = $end->setTime(23, 59, 59);
|
||||
|
||||
do {
|
||||
$this->days[$begin->format('Y-m-d')] = new StatisticDate($begin);
|
||||
$begin = $begin->modify('+1 day');
|
||||
} while ($begin <= $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<StatisticDate>
|
||||
*/
|
||||
public function getDays(): array
|
||||
{
|
||||
return array_values($this->days);
|
||||
}
|
||||
|
||||
public function setDate(StatisticDate $date): void
|
||||
{
|
||||
$key = $date->getDate()->format('Y-m-d');
|
||||
if (!\array_key_exists($key, $this->days)) {
|
||||
throw new \InvalidArgumentException('Unknown date given');
|
||||
}
|
||||
|
||||
$this->days[$key] = $date;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ final class StatisticDate extends Timesheet
|
||||
private \DateTimeInterface $date;
|
||||
private int $billableDuration = 0;
|
||||
private float $billableRate = 0.00;
|
||||
private int $amount = 0;
|
||||
|
||||
public function __construct(\DateTimeInterface $date)
|
||||
{
|
||||
@@ -44,4 +45,14 @@ final class StatisticDate extends Timesheet
|
||||
{
|
||||
$this->billableRate = $billableRate;
|
||||
}
|
||||
|
||||
public function getAmount(): int
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
public function setAmount(int $amount): void
|
||||
{
|
||||
$this->amount = $amount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Twig;
|
||||
|
||||
use App\Constants;
|
||||
use App\Entity\EntityWithMetaFields;
|
||||
use App\Form\Type\DateRangeType;
|
||||
use App\Utils\Color;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
@@ -37,6 +38,7 @@ final class Extensions extends AbstractExtension
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('date_range', [$this, 'buildDateRange']),
|
||||
new TwigFunction('report_date', [$this, 'buildReportDate']),
|
||||
new TwigFunction('class_name', [$this, 'getClassName']),
|
||||
new TwigFunction('iso_day_by_name', [$this, 'getIsoDayByName']),
|
||||
@@ -90,6 +92,11 @@ final class Extensions extends AbstractExtension
|
||||
return $dateTime->format(self::REPORT_DATE);
|
||||
}
|
||||
|
||||
public function buildDateRange(\DateTimeInterface $begin, \DateTimeInterface $end): string
|
||||
{
|
||||
return $begin->format(self::REPORT_DATE) . DateRangeType::DATE_SPACER . $end->format(self::REPORT_DATE);
|
||||
}
|
||||
|
||||
public function getIsoDayByName(string $weekDay): int
|
||||
{
|
||||
$key = array_search(
|
||||
|
||||
Reference in New Issue
Block a user