From 2bc5c41435b209de5e9f7fb9b804b2da02434437 Mon Sep 17 00:00:00 2001 From: akastijn Date: Mon, 24 Nov 2025 01:08:43 +0100 Subject: [PATCH] Add sorting functionality to staff playtime table and include roles in UI and database mapping --- .../database/luckperms/PlayerWithGroup.java | 2 +- .../database/luckperms/TeamMemberMapper.java | 5 ++-- .../head-mod/staff-pt/staff-pt.component.html | 9 +++---- .../head-mod/staff-pt/staff-pt.component.scss | 17 +++++++++++++ .../head-mod/staff-pt/staff-pt.component.ts | 24 +++++++++++++++++-- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerWithGroup.java b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerWithGroup.java index 3c94565..a0f480c 100644 --- a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerWithGroup.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerWithGroup.java @@ -2,5 +2,5 @@ package com.alttd.altitudeweb.database.luckperms; import java.util.UUID; -public record PlayerWithGroup(UUID uuid, String username, String group) { +public record PlayerWithGroup(String username, UUID uuid, String group) { } diff --git a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java index ec4a92c..9ac3766 100644 --- a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java @@ -22,10 +22,11 @@ public interface TeamMemberMapper { @ConstructorArgs({ @Arg(column = "username", javaType = String.class), - @Arg(column = "uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class) + @Arg(column = "uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class), + @Arg(column = "group", javaType = String.class) }) @Select(""" - SELECT players.username, players.uuid, players.primary_group AS 'group' + SELECT players.username, players.uuid, permissions.permission AS 'group' FROM luckperms_user_permissions AS permissions INNER JOIN luckperms_players AS players ON players.uuid = permissions.uuid WHERE permission IN (${groupPermissions}) diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html index 26439f3..eab71bf 100644 --- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html +++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html @@ -18,21 +18,22 @@ - +
- + - + - + diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss index 54d8ec4..42c77db 100644 --- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss +++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss @@ -21,6 +21,23 @@ width: 100%; } +/* Ensure good contrast in dark/light modes */ +.table-theme th.mat-mdc-header-cell, +.table-theme td.mat-mdc-cell, +.table-theme .mat-mdc-header-row, +.table-theme .mat-mdc-row { + color: var(--font-color); +} + +/* Apply class to table via HTML's class attribute if needed; here we style all mat tables in this component */ +table.mat-mdc-table { + color: var(--font-color); +} + +.mat-sort-header-arrow { + color: var(--font-color); +} + .no-data td { text-align: center; padding: 16px; diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts index 427d20a..9cc1b31 100644 --- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts +++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts @@ -4,13 +4,15 @@ import {MatTableModule} from '@angular/material/table'; import {MatButtonModule} from '@angular/material/button'; import {MatIconModule} from '@angular/material/icon'; import {MatTooltipModule} from '@angular/material/tooltip'; +import {MatSortModule} from '@angular/material/sort'; import {SiteService, StaffPlaytime} from '@api'; +import {Sort} from '@angular/material/sort'; import {HeaderComponent} from '@header/header.component'; @Component({ selector: 'app-staff-pt', standalone: true, - imports: [CommonModule, MatTableModule, MatButtonModule, MatIconModule, MatTooltipModule, HeaderComponent], + imports: [CommonModule, MatTableModule, MatButtonModule, MatIconModule, MatTooltipModule, MatSortModule, HeaderComponent], templateUrl: './staff-pt.component.html', styleUrl: './staff-pt.component.scss' }) @@ -18,13 +20,31 @@ export class StaffPtComponent implements OnInit { siteService = inject(SiteService); staffPt = signal([]); + sort = signal({active: 'playtime', direction: 'desc'} as Sort); + sortedStaffPt = computed(() => { + const data = [...this.staffPt()]; + const {active, direction} = this.sort(); + if (!direction || !active) return data; + const dir = direction === 'asc' ? 1 : -1; + return data.sort((a, b) => { + switch (active) { + case 'staff_member': + return a.staff_member.localeCompare(b.staff_member) * dir; + case 'role': + return a.role.localeCompare(b.role) * dir; + case 'playtime': + default: + return ((a.playtime ?? 0) - (b.playtime ?? 0)) * dir; + } + }); + }); weekStart = signal(this.getStartOfWeek(new Date())); weekEnd = computed(() => this.getEndOfWeek(this.weekStart())); todayStart = signal(this.startOfDay(new Date())); - displayedColumns = ['staff_member', 'playtime']; + displayedColumns = ['staff_member', 'playtime', 'role']; ngOnInit(): void { this.loadCurrentWeek();
Staff MemberStaff Member {{ row.staff_member }} PlaytimePlaytime {{ minutesToHm(row.playtime) }} RankRank {{ row.role }}