frontend: add theme toggle functionality
This commit is contained in:
parent
a0e23cd4a7
commit
e2f5725fa5
@ -11,7 +11,16 @@
|
|||||||
<mat-icon>account_circle</mat-icon>
|
<mat-icon>account_circle</mat-icon>
|
||||||
</button> -->
|
</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>
|
<mat-icon>logout</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
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 { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
@ -8,7 +8,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
|
|||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { ConsoleNavLink } from '@lib/models';
|
import { ConsoleNavLink } from '@lib/models';
|
||||||
import { AppDataService } from '@lib/services';
|
import { AppDataService, ThemeService } from '@lib/services';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-console-nav',
|
selector: 'ov-console-nav',
|
||||||
@ -33,11 +33,17 @@ export class ConsoleNavComponent {
|
|||||||
isSideMenuCollapsed = false;
|
isSideMenuCollapsed = false;
|
||||||
version = '';
|
version = '';
|
||||||
|
|
||||||
|
isDarkMode: Signal<boolean>;
|
||||||
|
|
||||||
@Input() navLinks: ConsoleNavLink[] = [];
|
@Input() navLinks: ConsoleNavLink[] = [];
|
||||||
@Output() onLogoutClicked: EventEmitter<void> = new EventEmitter<void>();
|
@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.version = `${this.appDataService.getVersion()} (${this.appDataService.getEdition()})`;
|
||||||
|
this.isDarkMode = this.themeService.isDark;
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleSideMenu() {
|
async toggleSideMenu() {
|
||||||
@ -49,4 +55,8 @@ export class ConsoleNavComponent {
|
|||||||
await this.sidenav.open();
|
await this.sidenav.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleTheme() {
|
||||||
|
this.themeService.toggleTheme();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,12 @@ export class ConsoleComponent {
|
|||||||
icon: 'code_blocks',
|
icon: 'code_blocks',
|
||||||
iconClass: 'material-symbols-outlined ov-developer-icon'
|
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' }
|
// { label: 'About', route: 'about', icon: 'info' }
|
||||||
];
|
];
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatGridListModule } from '@angular/material/grid-list';
|
import { MatGridListModule } from '@angular/material/grid-list';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
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';
|
import { MeetRecordingStatus, MeetRoom } from '@lib/typings/ce';
|
||||||
|
|
||||||
interface OverviewStats {
|
interface OverviewStats {
|
||||||
@ -36,8 +36,7 @@ export class OverviewComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private roomService: RoomService,
|
private roomService: RoomService,
|
||||||
private recordingService: RecordingManagerService,
|
private recordingService: RecordingManagerService,
|
||||||
private navigationService: NavigationService,
|
private navigationService: NavigationService
|
||||||
private themeService: ThemeService
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@ -59,7 +58,8 @@ export class OverviewComponent implements OnInit {
|
|||||||
totalRooms: rooms.length,
|
totalRooms: rooms.length,
|
||||||
activeRooms: rooms.filter((room: MeetRoom) => !room.markedForDeletion).length,
|
activeRooms: rooms.filter((room: MeetRoom) => !room.markedForDeletion).length,
|
||||||
totalRecordings: recordings.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,
|
hasData: rooms.length > 0 || recordings.length > 0,
|
||||||
isLoading: false
|
isLoading: false
|
||||||
};
|
};
|
||||||
|
|||||||
@ -34,15 +34,6 @@ export class ThemeService {
|
|||||||
this.listenToSystemChanges();
|
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
|
* Toggles between light and dark theme
|
||||||
*/
|
*/
|
||||||
@ -51,6 +42,15 @@ export class ThemeService {
|
|||||||
this.setTheme(newTheme);
|
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
|
* Applies the theme to the document
|
||||||
*/
|
*/
|
||||||
@ -127,11 +127,4 @@ export class ThemeService {
|
|||||||
const systemTheme = this.getSystemPreference();
|
const systemTheme = this.getSystemPreference();
|
||||||
this.setTheme(systemTheme);
|
this.setTheme(systemTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the theme value as string for use in templates
|
|
||||||
*/
|
|
||||||
public getThemeValue(): Theme {
|
|
||||||
return this._currentTheme();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { AppDataService } from '@lib/services';
|
import { AppDataService, ThemeService } from '@lib/services';
|
||||||
import packageInfo from '../../package.json';
|
import packageInfo from '../../package.json';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -11,7 +11,10 @@ import packageInfo from '../../package.json';
|
|||||||
imports: [RouterOutlet]
|
imports: [RouterOutlet]
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
constructor(private appDataService: AppDataService) {}
|
constructor(
|
||||||
|
private appDataService: AppDataService,
|
||||||
|
private themeService: ThemeService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.appDataService.setVersion(packageInfo.version);
|
this.appDataService.setVersion(packageInfo.version);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user