Refactor FormsComponent and add AuthGuard for appeal route protection. Replace dynamic routing with static appeal route, restructure AppealComponent layout, and introduce responsive design adjustments. Update environment configuration for default auth status.
This commit is contained in:
parent
1f03a4bdc3
commit
c277306c2c
|
|
@ -107,8 +107,12 @@ export const routes: Routes = [
|
|||
loadComponent: () => import('./pages/reference/staffpowers/staffpowers.component').then(m => m.StaffpowersComponent)
|
||||
},
|
||||
{
|
||||
path: 'forms/:form',
|
||||
loadComponent: () => import('./pages/forms/forms.component').then(m => m.FormsComponent)
|
||||
path: 'forms/appeal',
|
||||
loadComponent: () => import('./pages/forms/appeal/appeal.component').then(m => m.AppealComponent),
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
requiredAuthorizations: ['SCOPE_user']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'forms',
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
|
|||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
|
||||
import {Observable} from 'rxjs';
|
||||
import {AuthService} from '@services/auth.service';
|
||||
import {environment} from '@environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
|
@ -18,7 +19,9 @@ export class AuthGuard implements CanActivate {
|
|||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
|
||||
if (environment.defaultAuthStatus) {
|
||||
return true;
|
||||
}
|
||||
if (!this.authService.checkAuthStatus()) {
|
||||
return this.router.createUrlTree(['/']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,19 @@
|
|||
<app-forms [currentPage]="'appeal'" [formTitle]="'Minecraft Appeal'">
|
||||
<div form-content>
|
||||
|
||||
</div>
|
||||
</app-forms>
|
||||
<div>
|
||||
<app-header [current_page]="'appeal'" height="200px" background_image="/public/img/backgrounds/staff.png"
|
||||
[overlay_gradient]="0.5">
|
||||
<div class="title" header-content>
|
||||
<h1>Appeal</h1>
|
||||
</div>
|
||||
</app-header>
|
||||
<main>
|
||||
<section class="darkmodeSection appeal-container">
|
||||
<section class="columnSection">
|
||||
<div class="columnContainer">
|
||||
<div class="columnParagraph">
|
||||
<p>hi</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.appeal-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 80vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
|
@ -1,21 +1,27 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {FormsComponent} from '../forms.component';
|
||||
import {AfterViewInit, Component, ElementRef, OnInit, Renderer2} from '@angular/core';
|
||||
import {FormControl, FormGroup, Validators} from '@angular/forms';
|
||||
import {AppealsService, MinecraftAppeal} from '@api';
|
||||
import {HeaderComponent} from '@header/header.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-appeal',
|
||||
imports: [
|
||||
FormsComponent
|
||||
HeaderComponent
|
||||
],
|
||||
templateUrl: './appeal.component.html',
|
||||
styleUrl: './appeal.component.scss'
|
||||
})
|
||||
export class AppealComponent implements OnInit {
|
||||
export class AppealComponent implements OnInit, AfterViewInit {
|
||||
|
||||
public form: FormGroup<Appeal>;
|
||||
private resizeObserver: ResizeObserver | null = null;
|
||||
private boundHandleResize: any;
|
||||
|
||||
constructor(private appealApi: AppealsService) {
|
||||
constructor(
|
||||
private appealApi: AppealsService,
|
||||
private elementRef: ElementRef,
|
||||
private renderer: Renderer2
|
||||
) {
|
||||
this.form = new FormGroup({
|
||||
username: new FormControl('', {nonNullable: true, validators: [Validators.required]}),
|
||||
punishmentId: new FormControl('', {nonNullable: true, validators: [Validators.required]}),
|
||||
|
|
@ -27,6 +33,62 @@ export class AppealComponent implements OnInit {
|
|||
ngOnInit() {
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.setupResizeObserver();
|
||||
this.updateContainerHeight();
|
||||
|
||||
this.boundHandleResize = this.handleResize.bind(this);
|
||||
window.addEventListener('resize', this.boundHandleResize);
|
||||
|
||||
setTimeout(() => this.updateContainerHeight(), 0);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
}
|
||||
|
||||
if (this.boundHandleResize) {
|
||||
window.removeEventListener('resize', this.boundHandleResize);
|
||||
}
|
||||
}
|
||||
|
||||
private handleResize() {
|
||||
this.updateContainerHeight();
|
||||
}
|
||||
|
||||
private setupResizeObserver() {
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
this.updateContainerHeight();
|
||||
});
|
||||
|
||||
const headerElement = document.querySelector('app-header');
|
||||
if (headerElement) {
|
||||
this.resizeObserver.observe(headerElement);
|
||||
}
|
||||
|
||||
const footerElement = document.querySelector('footer');
|
||||
if (footerElement) {
|
||||
this.resizeObserver.observe(footerElement);
|
||||
}
|
||||
}
|
||||
|
||||
private updateContainerHeight() {
|
||||
const headerElement = document.querySelector('app-header');
|
||||
const footerElement = document.querySelector('footer');
|
||||
|
||||
const container = this.elementRef.nativeElement.querySelector('.appeal-container');
|
||||
|
||||
if (headerElement && footerElement && container) {
|
||||
const headerHeight = headerElement.getBoundingClientRect().height;
|
||||
const footerHeight = footerElement.getBoundingClientRect().height;
|
||||
|
||||
const calculatedHeight = `calc(100vh - ${headerHeight}px - ${footerHeight}px)`;
|
||||
this.renderer.setStyle(container, 'min-height', calculatedHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public onSubmit() {
|
||||
if (this.form === undefined) {
|
||||
console.error('Form is undefined');
|
||||
|
|
@ -35,7 +97,6 @@ export class AppealComponent implements OnInit {
|
|||
if (this.form.valid) {
|
||||
this.sendForm()
|
||||
} else {
|
||||
// Mark all fields as touched to trigger validation display
|
||||
Object.keys(this.form.controls).forEach(field => {
|
||||
const control = this.form!.get(field);
|
||||
if (!(control instanceof FormGroup)) {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
<ng-container>
|
||||
<app-header [current_page]="currentPage" height="200px" background_image="/public/img/backgrounds/staff.png"
|
||||
[overlay_gradient]="0.5">
|
||||
[overlay_gradient]="0.5">
|
||||
<div class="title" header-content>
|
||||
<h1>{{ formTitle }}</h1>
|
||||
</div>
|
||||
</app-header>
|
||||
@if (!type) {
|
||||
@for (formType of FormType | keyvalue; track formType) {
|
||||
<button mat-raised-button (click)="setFormType(formType.value)">
|
||||
{{ formType }}
|
||||
</button>
|
||||
}
|
||||
}
|
||||
<div>
|
||||
<ng-content select="[form-content]"></ng-content>
|
||||
</div>
|
||||
<main>
|
||||
<section class="darkmodeSection">
|
||||
<section class="columnSection">
|
||||
<div class="columnContainer">
|
||||
<div class="columnParagraph">
|
||||
<a [routerLink]="['/forms/appeal']">
|
||||
<h2>Appeal</h2>
|
||||
<p>
|
||||
If you feel your punishment was unjust, click here to appeal.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -1,66 +1,17 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {HeaderComponent} from '@header/header.component';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {LoginDialogComponent} from '@shared-components/login/login.component';
|
||||
import { KeyValuePipe } from '@angular/common';
|
||||
import {FormType} from './form_type';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {AuthService} from '@services/auth.service';
|
||||
import {RouterLink} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-forms',
|
||||
imports: [
|
||||
HeaderComponent,
|
||||
MatButton,
|
||||
KeyValuePipe
|
||||
],
|
||||
RouterLink
|
||||
],
|
||||
templateUrl: './forms.component.html',
|
||||
styleUrl: './forms.component.scss'
|
||||
})
|
||||
export class FormsComponent implements OnInit {
|
||||
export class FormsComponent {
|
||||
@Input() formTitle: string = 'Form';
|
||||
@Input() currentPage: string = 'forms';
|
||||
|
||||
public type: FormType | undefined;
|
||||
|
||||
constructor(private authService: AuthService,
|
||||
private dialog: MatDialog,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.route.paramMap.subscribe(async params => {
|
||||
const code = params.get('code');
|
||||
|
||||
if (code) {
|
||||
this.authService.login(code).subscribe();
|
||||
} else if (!this.authService.checkAuthStatus()) {
|
||||
const dialogRef = this.dialog.open(LoginDialogComponent, {
|
||||
width: '400px',
|
||||
disableClose: true
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap.subscribe(params => {
|
||||
switch (params.get('form')) {
|
||||
case FormType.APPEAL:
|
||||
this.type = FormType.APPEAL;
|
||||
this.currentPage = 'appeal';
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid type");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected readonly FormType = FormType;
|
||||
protected readonly Object = Object;
|
||||
|
||||
public setFormType(formType: FormType) {
|
||||
this.type = formType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import {catchError, tap} from 'rxjs/operators';
|
|||
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||
import {JwtHelperService} from '@auth0/angular-jwt';
|
||||
import {JwtClaims} from '@custom-types/jwt_interface'
|
||||
import {environment} from '@environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthService {
|
||||
private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
|
||||
private isAuthenticatedSubject = new BehaviorSubject<boolean>(environment.defaultAuthStatus);
|
||||
public isAuthenticated$ = this.isAuthenticatedSubject.asObservable();
|
||||
|
||||
private userClaimsSubject = new BehaviorSubject<JwtClaims | null>(null);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: 'http://localhost:8080'
|
||||
apiUrl: 'http://localhost:8080',
|
||||
defaultAuthStatus: true
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export const environment = {
|
||||
production: true,
|
||||
apiUrl: 'https://alttd.com'
|
||||
apiUrl: 'https://alttd.com',
|
||||
defaultAuthStatus: false
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user