Compare commits

..

1 commit

Author SHA1 Message Date
Rajbir Singh
332acff57b TD-36: Implement Administration player filter options
All checks were successful
Quality Check / Linting (pull_request) Successful in 24s
Quality Check / Linting (push) Successful in 26s
2025-03-05 23:20:05 +01:00
8 changed files with 120 additions and 149 deletions

View file

@ -50,7 +50,7 @@
"stylelint-scss": "^6.11.0",
"typescript": "~5.6.2"
},
"api_version": "v0.0.0-rc.7",
"api_version": "v0.0.0-rc6",
"volta": {
"node": "22.13.1"
}

View file

@ -1,6 +1,5 @@
import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import {MAT_FORM_FIELD_DEFAULT_OPTIONS} from '@angular/material/form-field';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideRouter } from '@angular/router';
import { BASE_PATH, Configuration} from '@core/server';
@ -29,7 +28,6 @@ export const appConfig: ApplicationConfig = {
}
}),
{ provide: BASE_PATH, useValue: 'http://localhost:8080/api/v1' },
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { appearance: 'outline' } }
{ provide: BASE_PATH, useValue: 'http://localhost:8080/api/v1' }
]
};

View file

@ -0,0 +1,41 @@
@if (authService.$user|async; as user) {
<div class="search-container" style="display: flex; align-items: center; gap: 8px;">
<mat-form-field appearance="fill" floatLabel="always" style="flex: 1;">
<mat-label>Search</mat-label>
<input matInput [(ngModel)]="searchQuery" placeholder="Username"/>
</mat-form-field>
<button mat-raised-button color="primary" (click)="onSearch()">Search</button>
<button mat-raised-button color="warn" (click)="resetFilter()">Reset</button>
</div>
<div class="table-container">
<table mat-table [dataSource]="userList" class="mat-elevation-z8">
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef> Username</th>
<td mat-cell *matCellDef="let user"> {{ user.username }}</td>
</ng-container>
<ng-container matColumnDef="ban">
<th mat-header-cell *matHeaderCellDef class="ban-column"> Ban</th>
<td mat-cell *matCellDef="let user">
<button mat-mini-fab class="warn shadowless" (click)="banPlayer(user)">
<mat-icon>block</mat-icon>
</button>
</td>
</ng-container>
<thead>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
</thead>
<tbody>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</tbody>
</table>
</div>
} @else {
<p>Welcome to the Admin Page!</p>
}

View file

@ -0,0 +1,3 @@
.ban-column{
padding-right: 0.8rem;
}

View file

@ -0,0 +1,68 @@
import {AsyncPipe} from '@angular/common';
import {Component, OnInit} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormField, MatLabel} from '@angular/material/form-field';
import {MatIcon} from '@angular/material/icon';
import {MatInput} from '@angular/material/input';
import {MatTableModule} from '@angular/material/table';
import {AuthService} from '@core/auth/auth.service';
import UserData from '@core/auth/UserData';
import {AdministratablePlayer, AdminService, PlayerFilter} from '@core/server';
@Component({
selector: 'app-admin-overview',
templateUrl: './admin-overview.component.html',
styleUrls: ['./admin-overview.component.scss'],
standalone: true,
imports: [MatTableModule, MatButtonModule, MatLabel, MatInput, FormsModule, MatFormField, AsyncPipe, MatIcon]
})
export class AdminOverviewComponent implements OnInit {
displayedColumns: Array<string> = ['username', 'ban'];
userList: Array<AdministratablePlayer> = [];
searchQuery: string = '';
constructor(private adminService: AdminService, protected authService: AuthService) {
}
ngOnInit(): void {
this.authService.$user.subscribe((user) => {
if (user != undefined) {
return this.fetchPlayers();
}
});
}
fetchPlayers(): void {
const filter: PlayerFilter = {
page: 0,
pageSize: 32,
order: PlayerFilter.OrderEnum.Ascending,
username: this.searchQuery,
sortBy: 'username'
};
this.adminService.getAllPlayers(filter).subscribe(
(players) => {
this.userList = players;
},
(error) => {
console.error('Error fetching players:', error);
}
);
}
banPlayer(user: UserData): void {
console.log(`Banning user: ${user.username}`);
//implement banning logic
}
onSearch(): void {
this.fetchPlayers();
}
resetFilter(): void {
this.searchQuery = '';
this.fetchPlayers();
}
}

View file

@ -1,43 +1,3 @@
<div class="dashboard">
@if (authService.$user|async) {
<div class="dashboard__search">
<mat-form-field class="dashboard__search__input-field">
<mat-icon matPrefix>search</mat-icon>
<input matInput placeholder="" #searchbar>
</mat-form-field>
<mat-form-field>
<mat-label>Banned</mat-label>
<mat-select>
<mat-option>Reset</mat-option>
<mat-option>Banned</mat-option>
<mat-option>Not Banned</mat-option>
</mat-select>
</mat-form-field>
<button mat-fab class="shadowless" (click)="onSearch(searchbar)">
<mat-icon>check</mat-icon>
</button>
<button mat-fab class="warn shadowless" (click)="resetFilter(searchbar)">
<mat-icon>backspace</mat-icon>
</button>
</div>
<mat-table [dataSource]="usersDataSource" class="dashboard__table">
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef>Username</th>
<td mat-cell *matCellDef="let user"> {{ user.username }}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let user">
<button mat-mini-fab class="warn shadowless" (click)="banPlayer(user)">
<mat-icon>block</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</mat-table>
} @else {
<p>Du musst eingeloggt sein, um dies zu sehen</p>
}
<app-admin-overview></app-admin-overview>
</div>

View file

@ -1,33 +0,0 @@
.dashboard {
display: flex;
flex-direction: column;
gap: 1rem;
&__search {
display: flex;
gap: 1rem;
&__input-field {
flex-grow: 1;
}
}
&__table {
tr, td {
display: flex;
height: auto;
}
.mat-column-username {
flex-grow: 1;
}
th.mat-column-actions {
display: none;
}
td.mat-column-actions {
padding: 0.25rem 0;
}
}
}

View file

@ -1,78 +1,12 @@
import {AsyncPipe} from '@angular/common';
import {Component, OnInit} from '@angular/core';
import {MatFabButton, MatMiniFabButton} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatIcon} from '@angular/material/icon';
import {MatInputModule} from '@angular/material/input';
import {MatSelectModule} from '@angular/material/select';
import {
MatTableDataSource, MatTableModule
} from '@angular/material/table';
import {AuthService} from '@core/auth/auth.service';
import UserData from '@core/auth/UserData';
import {AdministratablePlayer, AdminService, PlayerFilter} from '@core/server';
import { Component } from '@angular/core';
import {AdminOverviewComponent} from '@app/views/admin-overview/admin-overview.component';
@Component({
selector: 'app-dashboard',
imports: [
AsyncPipe,
MatIcon,
MatInputModule,
MatTableModule,
MatFormFieldModule,
MatMiniFabButton,
MatFabButton,
MatSelectModule
],
imports: [AdminOverviewComponent],
templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.scss'
})
export class DashboardComponent implements OnInit {
displayedColumns: Array<string> = ['username', 'actions'];
usersDataSource: MatTableDataSource<AdministratablePlayer> = new MatTableDataSource<AdministratablePlayer>([]);
constructor(private adminService: AdminService, protected authService: AuthService) {
}
ngOnInit(): void {
this.authService.$user.subscribe((user) => {
if (user != undefined) {
return this.fetchPlayers('');
}
});
}
fetchPlayers(querry: string): void {
const filter: PlayerFilter = {
page: 0,
pageSize: 32,
order: PlayerFilter.OrderEnum.Ascending,
username: querry,
sortBy: 'username'
};
this.adminService.getAllPlayers(filter).subscribe(
(players) => {
this.usersDataSource = new MatTableDataSource<AdministratablePlayer>(players);
},
(error) => {
console.error('Error fetching players:', error);
}
);
}
banPlayer(user: UserData): void {
console.log(`Banning user: ${user.username}`);
// TODO: implement banning logic
}
onSearch(searchbar: HTMLInputElement): void {
this.fetchPlayers(searchbar.value);
}
resetFilter(searchbar: HTMLInputElement): void {
searchbar.value = '';
this.fetchPlayers('');
}
export class DashboardComponent {
}