added project start and end date (#1303)

* added sortable js library
* activity in invoice is optional
* added javascript widget for paginated boxes
* fix activity dropdown for globals only
* added timesheet service to reduce code duplication
* use repository to query for teams in dropdowns
* added project validator
* validate project start and end against timesheet
* include begin and end in dynamic form requests for projects
* added timezone and language option to import flag, improve timesheet import speed
* deactivate cross-timezone filter
* add virtual fields to field order list
* composer update
* added param to ignore dates
* position loader icon fixed - fixes #1330
* permission problem when creating a new project - fixes #1340
* remove dev dependencies webserver and thanks bundle
* stop information leak (begin and end date) in duration mode - fixes #1307
* unify timesheet edit dialog for user and admins
* fix security issue, own rates exposed to unauthorized users in multi-update dialog
This commit is contained in:
Kevin Papst
2020-01-05 02:49:01 +01:00
committed by GitHub
parent 50383673ca
commit d6798eed1e
121 changed files with 2465 additions and 1439 deletions

View File

@@ -9,7 +9,6 @@
namespace App\Controller;
use App\Configuration\TimesheetConfiguration;
use App\Entity\MetaTableTypeInterface;
use App\Entity\Tag;
use App\Entity\Timesheet;
@@ -27,6 +26,7 @@ use App\Repository\ProjectRepository;
use App\Repository\Query\TimesheetQuery;
use App\Repository\TagRepository;
use App\Repository\TimesheetRepository;
use App\Timesheet\TimesheetService;
use App\Timesheet\TrackingMode\TrackingModeInterface;
use App\Timesheet\TrackingModeService;
use App\Timesheet\UserDateTimeFactory;
@@ -42,10 +42,6 @@ abstract class TimesheetAbstractController extends AbstractController
* @var UserDateTimeFactory
*/
protected $dateTime;
/**
* @var TimesheetConfiguration
*/
protected $configuration;
/**
* @var TimesheetRepository
*/
@@ -62,21 +58,25 @@ abstract class TimesheetAbstractController extends AbstractController
* @var ServiceExport
*/
protected $exportService;
/**
* @var TimesheetService
*/
private $service;
public function __construct(
UserDateTimeFactory $dateTime,
TimesheetConfiguration $configuration,
TimesheetRepository $repository,
TrackingModeService $service,
TrackingModeService $trackingModeService,
EventDispatcherInterface $dispatcher,
ServiceExport $exportService
ServiceExport $exportService,
TimesheetService $timesheetService
) {
$this->dateTime = $dateTime;
$this->configuration = $configuration;
$this->repository = $repository;
$this->trackingModeService = $service;
$this->trackingModeService = $trackingModeService;
$this->dispatcher = $dispatcher;
$this->exportService = $exportService;
$this->service = $timesheetService;
}
protected function getTrackingMode(): TrackingModeInterface
@@ -84,16 +84,6 @@ abstract class TimesheetAbstractController extends AbstractController
return $this->trackingModeService->getActiveMode();
}
protected function getSoftLimit(): int
{
return $this->configuration->getActiveEntriesSoftLimit();
}
protected function getRepository(): TimesheetRepository
{
return $this->repository;
}
protected function index($page, Request $request, string $renderTemplate, string $location): Response
{
$query = new TimesheetQuery();
@@ -127,7 +117,7 @@ abstract class TimesheetAbstractController extends AbstractController
$this->prepareQuery($query);
$pager = $this->getRepository()->getPagerfantaForQuery($query);
$pager = $this->repository->getPagerfantaForQuery($query);
return $this->render($renderTemplate, [
'entries' => $pager,
@@ -164,7 +154,7 @@ abstract class TimesheetAbstractController extends AbstractController
if ($editForm->isSubmitted() && $editForm->isValid()) {
try {
$this->getRepository()->save($entry);
$this->repository->save($entry);
$this->flashSuccess('action.update.success');
return $this->redirectToRoute($this->getTimesheetRoute(), ['page' => $request->get('page', 1)]);
@@ -199,8 +189,7 @@ abstract class TimesheetAbstractController extends AbstractController
protected function create(Request $request, string $renderTemplate, ProjectRepository $projectRepository, ActivityRepository $activityRepository, TagRepository $tagRepository): Response
{
$entry = new Timesheet();
$entry->setUser($this->getUser());
$entry = $this->service->createNewTimesheet($this->getUser());
if ($request->query->get('project')) {
$project = $projectRepository->find($request->query->get('project'));
@@ -218,24 +207,15 @@ abstract class TimesheetAbstractController extends AbstractController
}
}
$event = new TimesheetMetaDefinitionEvent($entry);
$this->dispatcher->dispatch($event);
$this->service->prepareNewTimesheet($entry, $request);
$mode = $this->getTrackingMode();
$mode->create($entry, $request);
$createForm = $this->getCreateForm($entry, $mode);
$createForm->handleRequest($request);
if ($createForm->isSubmitted() && $createForm->isValid()) {
try {
if (null === $entry->getEnd()) {
$this->getRepository()->stopActiveEntries(
$entry->getUser(),
$this->configuration->getActiveEntriesHardLimit()
);
}
$this->getRepository()->save($entry);
$this->service->saveNewTimesheet($entry);
$this->flashSuccess('action.update.success');
return $this->redirectToRoute($this->getTimesheetRoute());
@@ -273,7 +253,7 @@ abstract class TimesheetAbstractController extends AbstractController
$this->prepareQuery($query);
$entries = $this->getRepository()->getTimesheetsForQuery($query);
$entries = $this->repository->getTimesheetsForQuery($query);
$exporter = $this->exportService->getTimesheetExporterById($exporterId);
@@ -300,13 +280,20 @@ abstract class TimesheetAbstractController extends AbstractController
// remove all, which are not allowed to be edited
$timesheets = [];
$disallowed = 0;
/** @var Timesheet $timesheet */
foreach ($dto->getEntities() as $timesheet) {
if (!$this->isGranted('edit', $timesheet)) {
$disallowed++;
continue;
}
$timesheets[] = $timesheet;
}
if ($disallowed > 0) {
$this->flashWarning(sprintf('You are missing the permission to edit %s timesheets', $disallowed));
}
$dto->setEntities($timesheets);
if (count($dto->getEntities()) === 0) {
@@ -343,6 +330,7 @@ abstract class TimesheetAbstractController extends AbstractController
$timesheet->setExported($dto->isExported());
$execute = true;
}
// setting both values allows to erase wrong
if (null !== $dto->getHourlyRate()) {
$timesheet->setFixedRate(null);
$timesheet->setHourlyRate($dto->getHourlyRate());
@@ -411,6 +399,7 @@ abstract class TimesheetAbstractController extends AbstractController
'action' => $this->generateUrl($this->getMultiUpdateRoute(), []),
'method' => 'POST',
'include_exported' => $this->isGranted($this->getPermissionEditExport()),
'include_rate' => $this->isGranted($this->getPermissionEditRate()),
'include_user' => $this->includeUserInForms('multi'),
]);
}
@@ -424,7 +413,7 @@ abstract class TimesheetAbstractController extends AbstractController
return $this->createForm(MultiUpdateTable::class, $dto, [
'action' => $this->generateUrl($this->getTimesheetRoute()),
'repository' => $this->getRepository(),
'repository' => $this->repository,
'method' => 'POST',
]);
}
@@ -487,6 +476,11 @@ abstract class TimesheetAbstractController extends AbstractController
return 'edit_export_own_timesheet';
}
protected function getPermissionEditRate(): string
{
return 'edit_rate_own_timesheet';
}
protected function getCreateFormClassName(): string
{
return TimesheetEditForm::class;