Skip to content

Commit a9673de

Browse files
committed
add grouping by tag on reporting page
1 parent 9827a74 commit a9673de

File tree

5 files changed

+337
-304
lines changed

5 files changed

+337
-304
lines changed

app/Enums/TimeEntryAggregationType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum TimeEntryAggregationType: string
2020
case Client = 'client';
2121
case Billable = 'billable';
2222
case Description = 'description';
23+
case Tag = 'tag';
2324

2425
public static function fromInterval(TimeEntryAggregationTypeInterval $timeEntryAggregationTypeInterval): TimeEntryAggregationType
2526
{

app/Service/TimeEntryAggregationService.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
use App\Enums\Weekday;
1111
use App\Models\Client;
1212
use App\Models\Project;
13+
use App\Models\Tag;
1314
use App\Models\Task;
1415
use App\Models\TimeEntry;
1516
use App\Models\User;
1617
use Carbon\CarbonTimeZone;
1718
use Illuminate\Database\Eloquent\Builder;
1819
use Illuminate\Support\Carbon;
1920
use Illuminate\Support\Collection;
21+
use Illuminate\Support\Facades\DB;
2022
use Illuminate\Support\Facades\Log;
2123

2224
class TimeEntryAggregationService
@@ -48,6 +50,10 @@ public function getAggregatedTimeEntries(Builder $timeEntriesQuery, ?TimeEntryAg
4850
$group1Select = null;
4951
$group2Select = null;
5052
$groupBy = null;
53+
// If any grouping is by tag, expand rows per tag via CROSS JOIN LATERAL on the JSONB array
54+
if (($group1Type === TimeEntryAggregationType::Tag) || ($group2Type === TimeEntryAggregationType::Tag)) {
55+
$timeEntriesQuery->crossJoin(DB::raw("LATERAL jsonb_array_elements_text(coalesce(tags, '[]'::jsonb)) as tag(tag)"));
56+
}
5157
if ($group1Type !== null) {
5258
$group1Select = $this->getGroupByQuery($group1Type, $timezone, $startOfWeek);
5359
$groupBy = ['group_1'];
@@ -294,6 +300,17 @@ private function loadDescriptorsMap(array $keys, TimeEntryAggregationType $type)
294300
'color' => null,
295301
];
296302
}
303+
} elseif ($type === TimeEntryAggregationType::Tag) {
304+
$tags = Tag::query()
305+
->whereIn('id', $keys)
306+
->select('id', 'name')
307+
->get();
308+
foreach ($tags as $tag) {
309+
$descriptorMap[$tag->id] = [
310+
'description' => $tag->name,
311+
'color' => null,
312+
];
313+
}
297314
}
298315

299316
return $descriptorMap;
@@ -436,6 +453,8 @@ private function getGroupByQuery(TimeEntryAggregationType $group, string $timezo
436453
return 'billable';
437454
} elseif ($group === TimeEntryAggregationType::Description) {
438455
return 'description';
456+
} elseif ($group === TimeEntryAggregationType::Tag) {
457+
return 'tag';
439458
}
440459
}
441460

0 commit comments

Comments
 (0)