Release 2.34 (#5465)

* fix timing issue in timesheet edit form with deactivated rounding
* bump packages
* only show update messages for newer plugin versions
* replace deprecated method
* remove internal from API
* remove technical terms from translation
* prevent calls to internal symfony methods
* helper method to flag entry as modified
* support meta-fields in weekly-hourse view
* fix running timesheets were deleted in weekly-hourse
This commit is contained in:
Kevin Papst
2025-05-09 14:22:47 +02:00
committed by GitHub
parent 452a8d9390
commit dfd97fd6f3
35 changed files with 428 additions and 362 deletions

View File

@@ -60,10 +60,10 @@ use Twig\Environment;
final class InvoiceController extends AbstractController
{
public function __construct(
private ServiceInvoice $service,
private InvoiceTemplateRepository $templateRepository,
private InvoiceRepository $invoiceRepository,
private EventDispatcherInterface $dispatcher
private readonly ServiceInvoice $service,
private readonly InvoiceTemplateRepository $templateRepository,
private readonly InvoiceRepository $invoiceRepository,
private readonly EventDispatcherInterface $dispatcher
) {
}
@@ -333,7 +333,7 @@ final class InvoiceController extends AbstractController
{
$invoice = null;
if (null !== ($id = $request->get('id'))) {
if (null !== ($id = $request->query->get('id'))) {
$invoice = $this->invoiceRepository->find($id);
}

View File

@@ -28,7 +28,7 @@ final class PluginController extends AbstractController
$installed = [];
$plugins = $manager->getPlugins();
foreach ($plugins as $plugin) {
$installed[] = $plugin->getId();
$installed[$plugin->getId()] = $plugin;
}
$page = new PageSetup('menu.plugin');
@@ -36,18 +36,23 @@ final class PluginController extends AbstractController
$all = $this->getPluginInformation($client, $cache);
$bundles = [];
$updates = [];
foreach ($all as $item) {
if ($item['bundle'] !== null) {
$bundles[$item['bundle']] = $item;
if (\array_key_exists($item['bundle'], $installed)) {
$updates[$item['bundle']] = version_compare($installed[$item['bundle']]->getMetadata()->getVersion(), $item['latest_release']) === -1;
}
}
}
return $this->render('plugin/index.html.twig', [
'page_setup' => $page,
'plugins' => $plugins,
'installed' => $installed,
'installed' => array_keys($installed),
'extensions' => $all,
'bundles' => $bundles,
'updates' => $updates,
]);
}

View File

@@ -10,6 +10,7 @@
namespace App\Controller;
use App\Configuration\SystemConfiguration;
use App\Event\QuickEntryMetaDisplayEvent;
use App\Form\QuickEntryForm;
use App\Form\WeekByUserForm;
use App\Model\QuickEntryWeek;
@@ -19,6 +20,7 @@ use App\Repository\TimesheetRepository;
use App\Timesheet\FavoriteRecordService;
use App\Timesheet\TimesheetService;
use App\Utils\PageSetup;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
@@ -34,7 +36,8 @@ final class QuickEntryController extends AbstractController
private readonly SystemConfiguration $configuration,
private readonly TimesheetService $timesheetService,
private readonly TimesheetRepository $repository,
private readonly FavoriteRecordService $favoriteRecordService
private readonly FavoriteRecordService $favoriteRecordService,
private readonly EventDispatcherInterface $dispatcher,
)
{
}
@@ -149,6 +152,11 @@ final class QuickEntryController extends AbstractController
$defaultHour = (int) $defaultBegin->format('H');
$defaultMinute = (int) $defaultBegin->format('i');
// find additional meta-fields exclusively for QuickEntry view
$event = new QuickEntryMetaDisplayEvent($query);
$this->dispatcher->dispatch($event);
$metaFields = $event->getFields();
$formModel = new QuickEntryWeek($startWeek);
foreach ($rows as $id => $row) {
@@ -168,10 +176,12 @@ final class QuickEntryController extends AbstractController
$model->addTimesheet($day['entry']);
}
}
$model->setMetaFields($metaFields);
}
// create prototype model
$empty = $formModel->createRow($user);
$empty->setMetaFields($metaFields);
$empty->markAsPrototype();
foreach ($week as $dayId => $day) {
$tmp = $this->timesheetService->createNewTimesheet($user);
@@ -219,7 +229,11 @@ final class QuickEntryController extends AbstractController
foreach ($tmpModel->getTimesheets() as $timesheet) {
if ($timesheet->getId() !== null) {
$duration = $timesheet->getDuration(false);
if ($duration === null || $timesheet->isRunning()) {
// previously running timesheets were deleted, which was wrong
// so now we distinguish between running timesheets and null duration
if ($timesheet->isRunning()) {
$saveTimesheets[] = $timesheet;
} elseif ($duration === null) {
$deleteTimesheets[] = $timesheet;
} else {
$saveTimesheets[] = $timesheet;
@@ -263,6 +277,7 @@ final class QuickEntryController extends AbstractController
'page_setup' => $page,
'days' => $week,
'form' => $form->createView(),
'metaColumns' => $metaFields,
]);
}
}

View File

@@ -147,9 +147,7 @@ abstract class TimesheetAbstractController extends AbstractController
$event = new TimesheetMetaDefinitionEvent($entry);
$this->dispatcher->dispatch($event);
$page = $request->get('page');
$page = is_numeric($page) ? (int) $page : 1;
$editForm = $this->getEditForm($entry, $page);
$editForm = $this->getEditForm($entry);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
@@ -157,7 +155,7 @@ abstract class TimesheetAbstractController extends AbstractController
$this->service->updateTimesheet($entry);
$this->flashSuccess('action.update.success');
return $this->redirectToRoute($this->getTimesheetRoute(), ['page' => $request->get('page', 1)]);
return $this->redirectToRoute($this->getTimesheetRoute());
} catch (\Exception $ex) {
$this->flashUpdateException($ex);
}
@@ -494,14 +492,13 @@ abstract class TimesheetAbstractController extends AbstractController
]);
}
private function getEditForm(Timesheet $entry, int $page): FormInterface
private function getEditForm(Timesheet $entry): FormInterface
{
$mode = $this->getTrackingMode();
return $this->createForm($this->getEditFormClassName(), $entry, [
'action' => $this->generateUrl($this->getEditRoute(), [
'id' => $entry->getId(),
'page' => $page,
]),
'include_rate' => $this->isGranted('edit_rate', $entry),
'include_exported' => $this->isGranted('edit_export', $entry),