frontend: add theme toggle functionality

This commit is contained in:
juancarmore 2025-07-21 11:40:34 +02:00
parent a0e23cd4a7
commit e2f5725fa5
6 changed files with 47 additions and 27 deletions

View File

@ -11,7 +11,16 @@
<mat-icon>account_circle</mat-icon>
</button> -->
<button mat-icon-button (click)="onLogoutClicked.emit()" aria-label="Logout" id="logout-btn">
<button
mat-icon-button
(click)="toggleTheme()"
[matTooltip]="isDarkMode() ? 'Switch to light mode' : 'Switch to dark mode'"
aria-label="Toggle theme mode"
id="theme-toggle-btn"
>
<mat-icon>{{ isDarkMode() ? 'wb_sunny' : 'nights_stay' }}</mat-icon>
</button>
<button mat-icon-button (click)="onLogoutClicked.emit()" matTooltip="Logout" aria-label="Logout" id="logout-btn">
<mat-icon>logout</mat-icon>
</button>
</mat-toolbar>

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, Output, Signal, ViewChild } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
@ -8,7 +8,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { ConsoleNavLink } from '@lib/models';
import { AppDataService } from '@lib/services';
import { AppDataService, ThemeService } from '@lib/services';
@Component({
selector: 'ov-console-nav',
@ -33,11 +33,17 @@ export class ConsoleNavComponent {
isSideMenuCollapsed = false;
version = '';
isDarkMode: Signal<boolean>;
@Input() navLinks: ConsoleNavLink[] = [];
@Output() onLogoutClicked: EventEmitter<void> = new EventEmitter<void>();
constructor(private appDataService: AppDataService) {
constructor(
private appDataService: AppDataService,
private themeService: ThemeService
) {
this.version = `${this.appDataService.getVersion()} (${this.appDataService.getEdition()})`;
this.isDarkMode = this.themeService.isDark;
}
async toggleSideMenu() {
@ -49,4 +55,8 @@ export class ConsoleNavComponent {
await this.sidenav.open();
}
}
toggleTheme() {
this.themeService.toggleTheme();
}
}

View File

@ -21,7 +21,12 @@ export class ConsoleComponent {
icon: 'code_blocks',
iconClass: 'material-symbols-outlined ov-developer-icon'
},
{ label: 'Users & Permissions', route: 'users-permissions', icon: 'passkey', iconClass: 'ov-settings-icon material-symbols-outlined' }
{
label: 'Users & Permissions',
route: 'users-permissions',
icon: 'passkey',
iconClass: 'ov-settings-icon material-symbols-outlined'
}
// { label: 'About', route: 'about', icon: 'info' }
];

View File

@ -4,7 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatIconModule } from '@angular/material/icon';
import { NavigationService, RecordingManagerService, RoomService, ThemeService } from '@lib/services';
import { NavigationService, RecordingManagerService, RoomService } from '@lib/services';
import { MeetRecordingStatus, MeetRoom } from '@lib/typings/ce';
interface OverviewStats {
@ -36,8 +36,7 @@ export class OverviewComponent implements OnInit {
constructor(
private roomService: RoomService,
private recordingService: RecordingManagerService,
private navigationService: NavigationService,
private themeService: ThemeService
private navigationService: NavigationService
) {}
async ngOnInit() {
@ -59,7 +58,8 @@ export class OverviewComponent implements OnInit {
totalRooms: rooms.length,
activeRooms: rooms.filter((room: MeetRoom) => !room.markedForDeletion).length,
totalRecordings: recordings.length,
playableRecordings: recordings.filter((recording) => recording.status === MeetRecordingStatus.COMPLETE).length,
playableRecordings: recordings.filter((recording) => recording.status === MeetRecordingStatus.COMPLETE)
.length,
hasData: rooms.length > 0 || recordings.length > 0,
isLoading: false
};

View File

@ -34,15 +34,6 @@ export class ThemeService {
this.listenToSystemChanges();
}
/**
* Changes the current theme
*/
public setTheme(theme: Theme): void {
this._currentTheme.set(theme);
this.applyThemeToDocument(theme);
this.saveThemePreference(theme);
}
/**
* Toggles between light and dark theme
*/
@ -51,6 +42,15 @@ export class ThemeService {
this.setTheme(newTheme);
}
/**
* Changes the current theme
*/
private setTheme(theme: Theme): void {
this._currentTheme.set(theme);
this.applyThemeToDocument(theme);
this.saveThemePreference(theme);
}
/**
* Applies the theme to the document
*/
@ -127,11 +127,4 @@ export class ThemeService {
const systemTheme = this.getSystemPreference();
this.setTheme(systemTheme);
}
/**
* Gets the theme value as string for use in templates
*/
public getThemeValue(): Theme {
return this._currentTheme();
}
}

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { AppDataService } from '@lib/services';
import { AppDataService, ThemeService } from '@lib/services';
import packageInfo from '../../package.json';
@Component({
@ -11,7 +11,10 @@ import packageInfo from '../../package.json';
imports: [RouterOutlet]
})
export class AppComponent implements OnInit {
constructor(private appDataService: AppDataService) {}
constructor(
private appDataService: AppDataService,
private themeService: ThemeService
) {}
ngOnInit() {
this.appDataService.setVersion(packageInfo.version);