Weekly hours improvements (#4631)

* fix table padding
* reduced minimum quick-entry recent activity row amount
* use activity favorites in weekly hours
This commit is contained in:
Kevin Papst
2024-02-12 14:20:17 +01:00
committed by GitHub
parent 85a16a9363
commit 58cbf1776f
5 changed files with 52 additions and 37 deletions

View File

@@ -454,7 +454,7 @@ final class SystemConfiguration
public function getQuickEntriesRecentAmount(): int public function getQuickEntriesRecentAmount(): int
{ {
return $this->getIncrement('quick_entry.recent_activities', 5, 5); return $this->getIncrement('quick_entry.recent_activities', 5, 0);
} }
// ========== Company configurations ========== // ========== Company configurations ==========

View File

@@ -14,6 +14,7 @@ use App\Form\QuickEntryForm;
use App\Model\QuickEntryWeek; use App\Model\QuickEntryWeek;
use App\Repository\Query\TimesheetQuery; use App\Repository\Query\TimesheetQuery;
use App\Repository\TimesheetRepository; use App\Repository\TimesheetRepository;
use App\Timesheet\FavoriteRecordService;
use App\Timesheet\TimesheetService; use App\Timesheet\TimesheetService;
use App\Utils\PageSetup; use App\Utils\PageSetup;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -28,7 +29,12 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('quick-entry')] #[IsGranted('quick-entry')]
final class QuickEntryController extends AbstractController final class QuickEntryController extends AbstractController
{ {
public function __construct(private SystemConfiguration $configuration, private TimesheetService $timesheetService, private TimesheetRepository $repository) public function __construct(
private readonly SystemConfiguration $configuration,
private readonly TimesheetService $timesheetService,
private readonly TimesheetRepository $repository,
private readonly FavoriteRecordService $favoriteRecordService
)
{ {
} }
@@ -95,28 +101,36 @@ final class QuickEntryController extends AbstractController
// attach recent activities // attach recent activities
$amount = $this->configuration->getQuickEntriesRecentAmount(); $amount = $this->configuration->getQuickEntriesRecentAmount();
$startFrom = null; if ($amount > 0) {
$takeOverWeeks = $this->configuration->find('quick_entry.recent_activity_weeks'); $takeOverWeeks = $this->configuration->find('quick_entry.recent_activity_weeks');
if ($takeOverWeeks !== null && \intval($takeOverWeeks) > 0) { $startFrom = null;
$startFrom = clone $startWeek; if ($takeOverWeeks !== null && \intval($takeOverWeeks) > 0) {
$startFrom->modify(sprintf('-%s weeks', $takeOverWeeks)); $startFrom = clone $startWeek;
} $startFrom->modify(sprintf('-%s weeks', $takeOverWeeks));
$timesheets = $this->repository->getRecentActivities($user, $startFrom, $amount);
foreach ($timesheets as $timesheet) {
$id = $timesheet->getProject()->getId() . '_' . $timesheet->getActivity()->getId();
if (\array_key_exists($id, $rows)) {
continue;
} }
// there is an edge case possible with a project that starts and ends between the start and end date
// user could still select it from the dropdown, but it is better to hide a row than displaying already ended projects $favorites = $this->favoriteRecordService->favoriteEntries($user, $amount);
if ($timesheet->getProject() !== null && (!$timesheet->getProject()->isVisibleAtDate($startWeek) && !$timesheet->getProject()->isVisibleAtDate($endWeek))) { foreach ($favorites as $favorite) {
continue; $timesheet = $favorite->getTimesheet();
if ($startFrom !== null && !$favorite->isFavorite() && $startFrom > $timesheet->getBegin()) {
continue;
}
$id = $timesheet->getProject()->getId() . '_' . $timesheet->getActivity()->getId();
if (\array_key_exists($id, $rows)) {
continue;
}
// there is an edge case possible with a project that starts and ends between the start and end date
// user could still select it from the dropdown, but it is better to hide a row than displaying already ended projects
if ($timesheet->getProject() !== null && (!$timesheet->getProject()->isVisibleAtDate($startWeek) && !$timesheet->getProject()->isVisibleAtDate($endWeek))) {
continue;
}
$rows[$id] = [
'days' => $week,
'project' => $timesheet->getProject(),
'activity' => $timesheet->getActivity()
];
} }
$rows[$id] = [
'days' => $week,
'project' => $timesheet->getProject(),
'activity' => $timesheet->getActivity()
];
} }
$defaultBegin = $factory->createDateTime($this->configuration->getTimesheetDefaultBeginTime()); $defaultBegin = $factory->createDateTime($this->configuration->getTimesheetDefaultBeginTime());

View File

@@ -324,11 +324,9 @@ class TimesheetRepository extends EntityRepository
} }
/** /**
* @param User|null $user
* @param bool $ticktac
* @return Timesheet[] * @return Timesheet[]
*/ */
public function getActiveEntries(User $user = null, bool $ticktac = false): array public function getActiveEntries(?User $user = null, bool $ticktack = false): array
{ {
$qb = $this->getEntityManager()->createQueryBuilder(); $qb = $this->getEntityManager()->createQueryBuilder();
@@ -342,7 +340,7 @@ class TimesheetRepository extends EntityRepository
$qb->setParameter('user', $user); $qb->setParameter('user', $user);
} }
if ($ticktac) { if ($ticktack) {
$qb->setMaxResults(1); $qb->setMaxResults(1);
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();

View File

@@ -18,23 +18,22 @@ use Twig\Extension\RuntimeExtensionInterface;
final class TimesheetExtension implements RuntimeExtensionInterface final class TimesheetExtension implements RuntimeExtensionInterface
{ {
public function __construct(private TimesheetRepository $repository, private FavoriteRecordService $favoriteRecordService) public function __construct(
private readonly TimesheetRepository $repository,
private readonly FavoriteRecordService $favoriteRecordService
)
{ {
} }
/** /**
* @param User $user
* @param bool $ticktac
* @return array<Timesheet> * @return array<Timesheet>
*/ */
public function activeEntries(User $user, bool $ticktac = true): array public function activeEntries(User $user, bool $ticktack = true): array
{ {
return $this->repository->getActiveEntries($user, $ticktac); return $this->repository->getActiveEntries($user, $ticktack);
} }
/** /**
* @param User $user
* @param int $limit
* @return array<FavoriteTimesheet> * @return array<FavoriteTimesheet>
*/ */
public function favoriteEntries(User $user, int $limit = 5): array public function favoriteEntries(User $user, int $limit = 5): array

View File

@@ -31,13 +31,17 @@
{%- endif -%} {%- endif -%}
{%- endblock choice_widget_expanded %} {%- endblock choice_widget_expanded %}
{% block _quick_entry_form_rows_entry_timesheets_entry_widget %}
{{ form_row(form.duration, {row_attr: {class: 'p-0'}}) }}
{%- endblock %}
{% block quick_entry_week_row %} {% block quick_entry_week_row %}
<tr{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group qe-entry-week-row' ~ (not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}> <tr{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group qe-entry-week-row' ~ (not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}>
<td> <td>
{{ form_row(form.project) }} {{ form_row(form.project, {row_attr: {class: 'p-0'}}) }}
</td> </td>
<td> <td>
{{ form_row(form.activity) }} {{ form_row(form.activity, {row_attr: {class: 'p-0'}}) }}
</td> </td>
{% for timesheet in form.timesheets %} {% for timesheet in form.timesheets %}
<td class="text-center{% if timesheet.vars.data.begin is weekend %} weekend{% endif %}{% if timesheet.vars.data.begin is today %} today{% endif %}"> <td class="text-center{% if timesheet.vars.data.begin is weekend %} weekend{% endif %}{% if timesheet.vars.data.begin is today %} today{% endif %}">
@@ -189,7 +193,7 @@
<div class="duration-widget"> <div class="duration-widget">
{% if (form.vars.duration_presets is defined and form.vars.duration_presets is not empty) and (form.vars.disabled is same as (false)) %} {% if (form.vars.duration_presets is defined and form.vars.duration_presets is not empty) and (form.vars.disabled is same as (false)) %}
<div class="input-group input-group-flat"> <div class="input-group input-group-flat">
{% if form.vars.icon is not null %} {% if form.vars.icon is defined and form.vars.icon is not null %}
<span class="input-group-text"> <span class="input-group-text">
{{ icon(form.vars.icon) }} {{ icon(form.vars.icon) }}
</span> </span>
@@ -216,7 +220,7 @@
</div> </div>
</div> </div>
{% else %} {% else %}
{% if icon is not empty %} {% if icon is defined and icon is not empty %}
<div class="input-group input-group-flat"> <div class="input-group input-group-flat">
<span class="input-group-text"> <span class="input-group-text">
<i class="{{ icon|icon(false, icon) }}"></i> <i class="{{ icon|icon(false, icon) }}"></i>