Add new components, styles, and services for user management and navigation

This commit is contained in:
liosha84
2025-06-25 13:44:35 +03:00
parent 9b7465d3dc
commit 2ae1871330
125 changed files with 12940 additions and 1610 deletions
@@ -0,0 +1,65 @@
<!--<p>main.component works!</p>-->
<mat-toolbar class="fixed-top">
<button mat-raised-button routerLink="/" href="#">
My App
</button>
<span class="menu-spacer"></span>
<button mat-raised-button routerLink="tutorials">
Tutorials
</button>
@if (isLoggedIn) {
<button mat-raised-button routerLink="add-tutorial" >
Add tutorial
</button>
}
<span class="menu-spacer"></span>
@if (showAdminBoard) {
<button mat-raised-button routerLink="admin/welcome">
<mat-icon>manage_accounts</mat-icon>
Admin Bord
</button>
}
@if (showAdminBoard) {
<button mat-raised-button routerLink="system" >
<mat-icon>settings_applications</mat-icon>
System
</button>
}
<span class="menu-spacer"></span>
@if (isLoggedIn) {
<button mat-raised-button routerLink="register">
<mat-icon>app_registration</mat-icon>
Register
</button>
}
@if (!isLoggedIn) {
<button mat-raised-button (click)="openDialog('100ms', '5ms')" >
<!-- <i antIcon type="bell" theme="outline"></i>-->
<!-- <mat-icon>login</mat-icon>-->
Login
</button>
}
@if (isLoggedIn) {
<button mat-raised-button routerLink="profile" >
<mat-icon>account_circle</mat-icon>
{{ username }}
</button>
<button mat-raised-button (click)="logout()">
<mat-icon>logout</mat-icon>
Logout
</button>
}
</mat-toolbar>
<!--<app-nav-bar (NavCollapsedMob)="navMobClick()" (NavCollapse)="this.navCollapsed = !this.navCollapsed" />-->
<div class="router_outlet_padding">
<router-outlet/>
</div>
@@ -0,0 +1,15 @@
mat-toolbar{
background-color: rgba(153,153,153,0.16);
backdrop-filter: blur(8px);
}
.menu-spacer {
flex: 1 1 auto;
}
.fixed-top {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 1000; // Ensure toolbar stays above other content
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MainComponent } from './main.component';
describe('MainComponent', () => {
let component: MainComponent;
let fixture: ComponentFixture<MainComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MainComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MainComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,163 @@
import {Component, CUSTOM_ELEMENTS_SCHEMA, inject} from '@angular/core';
//import {NavigationComponent} from '../navigation/navigation.component';
import {NgClass} from '@angular/common';
import {NavigationComponent} from '../../layouts/admin-layout/navigation/navigation.component';
import {RouterLink, RouterOutlet} from '@angular/router';
import {BreadcrumbComponent} from '../../components/breadcrumb/breadcrumb.component';
import {NavBarComponent} from '../../layouts/admin-layout/nav-bar/nav-bar.component';
import {MatToolbar} from '@angular/material/toolbar';
import {MatButton} from '@angular/material/button';
import {IconDirective} from '@ant-design/icons-angular';
import {MatDialog} from '@angular/material/dialog';
import {Subscription} from 'rxjs';
import {TokenStorageService} from '../../services/token-storage.service';
import {AuthService} from '../../services/auth.service';
import {EventBusService} from '../../_shared/event-bus.service';
import {DialogComponent} from '../../components/dialog/dialog.component';
@Component({
selector: 'app-main.component',
imports: [
NavBarComponent,
MatToolbar,
MatButton,
RouterLink,
IconDirective,
RouterOutlet
],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
templateUrl: './main.component.html',
styleUrl: './main.component.scss'
})
export class MainComponent {
// public props
navCollapsed: boolean = false;
navCollapsedMob: boolean = false;
readonly dialog = inject(MatDialog);
//private authService = new AuthService(provideHttpClient())
public dialogData : DialogData = {password: "", username: ""};
private roles: string[] = [];
isLoggedIn = false;
showAdminBoard = false;
showModeratorBoard = false;
username?: string;
eventBusSub?: Subscription;
private errorMessage: any;
private isLoginFailed: boolean = false;
private storageService: TokenStorageService = inject(TokenStorageService);
private authService: AuthService = inject(AuthService);
private eventBusService: EventBusService = inject(EventBusService);
constructor(
) {}
ngOnInit(): void {
this.isLoggedIn = this.storageService.isLoggedIn();
if (this.isLoggedIn) {
const user = this.storageService.getUser();
this.roles = user.roles;
this.showAdminBoard = true;//this.roles.includes('ROLE_ADMIN');
this.showModeratorBoard = this.roles.includes('ROLE_MODERATOR');
this.username = user.username;
}
this.eventBusSub = this.eventBusService.on('logout', () => {
this.logout();
});
}
// public method
navMobClick() {
if (this.navCollapsedMob && !document.querySelector('app-navigation.pc-sidebar')?.classList.contains('mob-open')) {
this.navCollapsedMob = !this.navCollapsedMob;
setTimeout(() => {
this.navCollapsedMob = !this.navCollapsedMob;
}, 100);
} else {
this.navCollapsedMob = !this.navCollapsedMob;
}
if (document.querySelector('app-navigation.pc-sidebar')?.classList.contains('navbar-collapsed')) {
document.querySelector('app-navigation.pc-sidebar')?.classList.remove('navbar-collapsed');
}
}
handleKeyDown(event: KeyboardEvent): void {
if (event.key === 'Escape') {
this.closeMenu();
}
}
closeMenu() {
if (document.querySelector('app-navigation.pc-sidebar')?.classList.contains('mob-open')) {
document.querySelector('app-navigation.pc-sidebar')?.classList.remove('mob-open');
}
}
logout(): void {
this.authService.logout().subscribe({
next: res => {
console.log(res);
this.storageService.clean();
window.location.reload();
},
error: err => {
console.log(err);
}
});
}
openDialog(enterAnimationDuration: string, exitAnimationDuration: string) {
let dialogRef = this.dialog.open(DialogComponent, {
width: '350px',
enterAnimationDuration,
exitAnimationDuration,
data: {username: this.dialogData.username, password: this.dialogData.password}
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
if(result== null){
return;
}
this.dialogData = result;
this.authService.login(this.dialogData.username, this.dialogData.password).subscribe(
data => {
this.storageService.saveToken(data.accessToken);
this.storageService.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
let user = this.storageService.getUser();
this.roles = user.roles;
//this.username = user.username;
this.reloadPage();
},
err => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
}
);
});
}
reloadPage(): void {
window.location.reload();
}
}
export interface DialogData {
username: string;
password: string;
}
@@ -0,0 +1,13 @@
import {RouterModule} from '@angular/router';
import {MainComponent} from './main.component/main.component';
import {mainRouting} from './main.routing';
import {NgModule} from '@angular/core';
@NgModule({
declarations: [
],
imports: [mainRouting, MainComponent],
exports: [RouterModule],
})
export class MainModule {}
@@ -0,0 +1,44 @@
import {RouterModule, Routes} from '@angular/router';
import {HomeComponent} from '../components/home.component/home.component';
import {MainComponent} from './main.component/main.component';
import {TutorialsListComponent} from '../components/tutorials-list/tutorials-list.component';
import {TutorialsComponent} from '../components/tutorials.component/tutorials.component';
import {AddTutorialComponent} from '../components/add-tutorial/add-tutorial.component';
import {RegisterComponent} from '../components/register/register.component';
import {ProfileComponent} from '../components/profile/profile.component';
const MAIN_ROUTES: Routes =[
{
path: '',
component: MainComponent,
children: [
{
path: 'admin',
loadChildren: () =>
import('../admin-module/admin.module').then((m) => m.AdminModule),
},
{
path: 'home',
component: HomeComponent
},
{
path: 'tutorials',
component: TutorialsComponent
},
{
path: 'add-tutorial',
component: AddTutorialComponent
},
{
path: 'register',
component : RegisterComponent
},
{
path: 'profile',
component : ProfileComponent
}
],
}
];
export const mainRouting = RouterModule.forChild(MAIN_ROUTES);