Replace deprecated Angular directives (*ngFor, *ngIf) with modern Angular template syntax. Remove unused CommonModule imports across components for optimization. Clean up excess spacing and formatting in HTML files.

This commit is contained in:
akastijn 2025-07-15 21:48:23 +02:00
parent d3ef296784
commit c2b9a8a574
37 changed files with 689 additions and 646 deletions

View File

@ -15,11 +15,12 @@
"prefix": "app", "prefix": "app",
"architect": { "architect": {
"build": { "build": {
"builder": "@angular-devkit/build-angular:browser", "builder": "@angular/build:application",
"options": { "options": {
"outputPath": "dist", "outputPath": {
"base": "dist"
},
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts",
"polyfills": [ "polyfills": [
"zone.js" "zone.js"
], ],
@ -34,7 +35,8 @@
"styles": [ "styles": [
"src/styles.scss" "src/styles.scss"
], ],
"scripts": [] "scripts": [],
"browser": "src/main.ts"
}, },
"configurations": { "configurations": {
"production": { "production": {
@ -47,9 +49,7 @@
"optimization": true, "optimization": true,
"outputHashing": "all", "outputHashing": "all",
"sourceMap": false, "sourceMap": false,
"namedChunks": false, "namedChunks": false
"vendorChunk": false,
"buildOptimizer": true
}, },
"development": { "development": {
"sourceMap": true, "sourceMap": true,
@ -71,14 +71,12 @@
"optimization": true, "optimization": true,
"outputHashing": "all", "outputHashing": "all",
"sourceMap": false, "sourceMap": false,
"namedChunks": false, "namedChunks": false
"vendorChunk": false,
"buildOptimizer": true
} }
} }
}, },
"serve": { "serve": {
"builder": "@angular-devkit/build-angular:dev-server", "builder": "@angular/build:dev-server",
"configurations": { "configurations": {
"production": { "production": {
"buildTarget": "frontend:build:production" "buildTarget": "frontend:build:production"
@ -90,10 +88,10 @@
"defaultConfiguration": "development" "defaultConfiguration": "development"
}, },
"extract-i18n": { "extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n" "builder": "@angular/build:extract-i18n"
}, },
"test": { "test": {
"builder": "@angular-devkit/build-angular:karma", "builder": "@angular/build:karma",
"options": { "options": {
"polyfills": [ "polyfills": [
"zone.js", "zone.js",
@ -119,5 +117,31 @@
}, },
"cli": { "cli": {
"analytics": false "analytics": false
},
"schematics": {
"@schematics/angular:component": {
"type": "component"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
} }
} }

View File

@ -14,14 +14,14 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/cdk": "^19.2.18", "@angular/cdk": "^19.2.18",
"@angular/common": "^19.2.0", "@angular/common": "^20.1.0",
"@angular/compiler": "^19.2.0", "@angular/compiler": "^20.1.0",
"@angular/core": "^19.2.0", "@angular/core": "^20.1.0",
"@angular/forms": "^19.2.0", "@angular/forms": "^20.1.0",
"@angular/material": "^19.2.19", "@angular/material": "^19.2.19",
"@angular/platform-browser": "^19.2.0", "@angular/platform-browser": "^20.1.0",
"@angular/platform-browser-dynamic": "^19.2.0", "@angular/platform-browser-dynamic": "^20.1.0",
"@angular/router": "^19.2.0", "@angular/router": "^20.1.0",
"@auth0/angular-jwt": "^5.2.0", "@auth0/angular-jwt": "^5.2.0",
"@types/three": "^0.177.0", "@types/three": "^0.177.0",
"ngx-cookie-service": "^19.1.2", "ngx-cookie-service": "^19.1.2",
@ -31,9 +31,9 @@
"zone.js": "~0.15.0" "zone.js": "~0.15.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^19.2.5", "@angular/build": "^20.1.0",
"@angular/cli": "^19.2.5", "@angular/cli": "^20.1.0",
"@angular/compiler-cli": "^19.2.0", "@angular/compiler-cli": "^20.1.0",
"@types/jasmine": "~5.1.0", "@types/jasmine": "~5.1.0",
"jasmine-core": "~5.6.0", "jasmine-core": "~5.6.0",
"karma": "~6.4.0", "karma": "~6.4.0",
@ -43,4 +43,4 @@
"karma-jasmine-html-reporter": "~2.1.0", "karma-jasmine-html-reporter": "~2.1.0",
"typescript": "^5.8.3" "typescript": "^5.8.3"
} }
} }

View File

@ -1,15 +1,14 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule} from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
selector: 'app-about', selector: 'app-about',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent HeaderComponent
], ],
templateUrl: './about.component.html', templateUrl: './about.component.html',
styleUrl: './about.component.scss' styleUrl: './about.component.scss'
}) })

View File

@ -1,15 +1,14 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule} from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
selector: 'app-birthdays', selector: 'app-birthdays',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent HeaderComponent
], ],
templateUrl: './birthdays.component.html', templateUrl: './birthdays.component.html',
styleUrl: './birthdays.component.scss' styleUrl: './birthdays.component.scss'
}) })

View File

@ -1,16 +1,15 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule, NgOptimizedImage} from '@angular/common'; import { NgOptimizedImage } from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
selector: 'app-socials', selector: 'app-socials',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent, HeaderComponent,
NgOptimizedImage NgOptimizedImage
], ],
templateUrl: './socials.component.html', templateUrl: './socials.component.html',
styleUrl: './socials.component.scss' styleUrl: './socials.component.scss'
}) })

View File

@ -1,10 +1,10 @@
<ng-container> <ng-container>
<app-header [current_page]="'team'" height="450px" background_image="/public/img/backgrounds/staff.png" <app-header [current_page]="'team'" height="450px" background_image="/public/img/backgrounds/staff.png"
[overlay_gradient]="0.5">> [overlay_gradient]="0.5">>
<div class="title" header-content> <div class="title" header-content>
<h1>Staffing Team</h1> <h1>Staffing Team</h1>
<h2>The team that makes Altitude happen. Your owners, admins, moderators, and trainees are all working together to <h2>The team that makes Altitude happen. Your owners, admins, moderators, and trainees are all working together to
create Altitude, to create home. This is where the magic happens.</h2> create Altitude, to create home. This is where the magic happens.</h2>
</div> </div>
</app-header> </app-header>
@ -12,61 +12,75 @@
<section class="darkmodeSection"> <section class="darkmodeSection">
<div class="container teamContainer"> <div class="container teamContainer">
<h2 class="sectionTitle">Management</h2> <h2 class="sectionTitle">Management</h2>
<div *ngFor="let member of getTeamMembers('owner') | async" class="member"> @for (member of getTeamMembers('owner') | async; track member) {
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" <div class="member">
height="160" width="160" style="width: 160px;"> <img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
<h2>{{ member.name }}</h2> height="160" width="160" style="width: 160px;">
<p>Owner</p> <h2>{{ member.name }}</h2>
</div> <p>Owner</p>
<div *ngFor="let member of getTeamMembers('manager') | async" class="member"> </div>
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" }
height="160" width="160" style="width: 160px;"> @for (member of getTeamMembers('manager') | async; track member) {
<h2>{{ member.name }}</h2> <div class="member">
<p>Manager</p> <img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
</div> height="160" width="160" style="width: 160px;">
</div> <h2>{{ member.name }}</h2>
</section> <p>Manager</p>
<section class="darkmodeSectionThree"> </div>
<div class="container teamContainer"> }
<h2 class="sectionTitle">Admins</h2> </div>
<div *ngFor="let member of getTeamMembers('admin') | async" class="member"> </section>
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" <section class="darkmodeSectionThree">
height="160" width="160" style="width: 160px;"> <div class="container teamContainer">
<h2>{{ member.name }}</h2> <h2 class="sectionTitle">Admins</h2>
<p>Admin</p> @for (member of getTeamMembers('admin') | async; track member) {
</div> <div class="member">
</div> <img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
</section> height="160" width="160" style="width: 160px;">
<section class="darkmodeSection"> <h2>{{ member.name }}</h2>
<div class="container teamContainer"> <p>Admin</p>
<h2 class="sectionTitle">Head Moderators</h2> </div>
<div *ngFor="let member of getTeamMembers('headmod') | async" class="member"> }
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" </div>
height="160" width="160" style="width: 160px;"> </section>
<h2>{{ member.name }}</h2> <section class="darkmodeSection">
<p>Head Mod</p> <div class="container teamContainer">
</div> <h2 class="sectionTitle">Head Moderators</h2>
</div> @for (member of getTeamMembers('headmod') | async; track member) {
</section> <div class="member">
<section class="darkmodeSectionThree"> <img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
<div class="container teamContainer"> height="160" width="160" style="width: 160px;">
<h2 class="sectionTitle">Moderators</h2> <h2>{{ member.name }}</h2>
<div *ngFor="let member of getTeamMembers('moderator') | async" class="member"> <p>Head Mod</p>
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" </div>
height="160" width="160" style="width: 160px;"> }
<h2>{{ member.name }}</h2> </div>
</div> </section>
</div> <section class="darkmodeSectionThree">
</section> <div class="container teamContainer">
<section *ngIf="(getTeamMembers('trainee') | async)?.length ?? 0 > 0" class="darkmodeSection"> <h2 class="sectionTitle">Moderators</h2>
<div class="container teamContainer"> @for (member of getTeamMembers('moderator') | async; track member) {
<h2 class="sectionTitle">Trainees</h2> <div class="member">
<div *ngFor="let member of getTeamMembers('trainee') | async" class="member"> <img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin" height="160" width="160" style="width: 160px;">
height="160" width="160" style="width: 160px;"> <h2>{{ member.name }}</h2>
<h2>{{ member.name }}</h2> </div>
</div> }
</div> </div>
</section> </section>
</main> @if ((getTeamMembers('trainee') | async)?.length ?? 0 > 0) {
</ng-container> <section class="darkmodeSection">
<div class="container teamContainer">
<h2 class="sectionTitle">Trainees</h2>
@for (member of getTeamMembers('trainee') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
</div>
}
</div>
</section>
}
</main>
</ng-container>

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {BASE_PATH, Player, TeamService} from '@api'; import {BASE_PATH, Player, TeamService} from '@api';
import {CommonModule, NgOptimizedImage} from '@angular/common'; import { CommonModule, NgOptimizedImage } from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
import {CookieService} from 'ngx-cookie-service'; import {CookieService} from 'ngx-cookie-service';
import {map, Observable, shareReplay} from 'rxjs'; import {map, Observable, shareReplay} from 'rxjs';

View File

@ -1,13 +1,12 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {CommonModule} from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent HeaderComponent
], ],
selector: 'app-map', selector: 'app-map',
templateUrl: './map.component.html', templateUrl: './map.component.html',
styleUrl: './map.component.scss' styleUrl: './map.component.scss'

View File

@ -1,16 +1,15 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ALTITUDE_VERSION} from '@custom-types/constant'; import {ALTITUDE_VERSION} from '@custom-types/constant';
import {CommonModule, NgOptimizedImage} from '@angular/common'; import { NgOptimizedImage } from '@angular/common';
import {RouterLink} from '@angular/router'; import {RouterLink} from '@angular/router';
@Component({ @Component({
selector: 'app-footer', selector: 'app-footer',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
RouterLink, RouterLink,
NgOptimizedImage NgOptimizedImage
], ],
templateUrl: './footer.component.html', templateUrl: './footer.component.html',
styleUrl: './footer.component.scss' styleUrl: './footer.component.scss'
}) })

View File

@ -1,6 +1,6 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule} from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
import {RouterLink} from '@angular/router'; import {RouterLink} from '@angular/router';
@ -8,10 +8,9 @@ import {RouterLink} from '@angular/router';
selector: 'app-privacy', selector: 'app-privacy',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent, HeaderComponent,
RouterLink RouterLink
], ],
templateUrl: './privacy.component.html', templateUrl: './privacy.component.html',
styleUrl: './privacy.component.scss' styleUrl: './privacy.component.scss'
}) })

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
import {CommonModule} from '@angular/common';
import {RouterLink} from '@angular/router'; import {RouterLink} from '@angular/router';
@Component({ @Component({
@ -9,10 +9,9 @@ import {RouterLink} from '@angular/router';
standalone: true, standalone: true,
templateUrl: './terms.component.html', templateUrl: './terms.component.html',
imports: [ imports: [
CommonModule,
HeaderComponent, HeaderComponent,
RouterLink RouterLink
], ],
styleUrl: './terms.component.scss' styleUrl: './terms.component.scss'
}) })
export class TermsComponent { export class TermsComponent {

View File

@ -1,17 +1,17 @@
<ng-container> <ng-container>
<app-header [current_page]="currentPage" height="200px" background_image="/public/img/backgrounds/staff.png" <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> <div class="title" header-content>
<h1>{{ formTitle }}</h1> <h1>{{ formTitle }}</h1>
</div> </div>
</app-header> </app-header>
<ng-container *ngIf="!type"> @if (!type) {
<ng-container *ngFor="let formType of FormType | keyvalue"> @for (formType of FormType | keyvalue; track formType) {
<button mat-raised-button (click)="setFormType(formType.value)"> <button mat-raised-button (click)="setFormType(formType.value)">
{{ formType }} {{ formType }}
</button> </button>
</ng-container> }
</ng-container> }
<div> <div>
<ng-content select="[form-content]"></ng-content> <ng-content select="[form-content]"></ng-content>
</div> </div>

View File

@ -3,7 +3,7 @@ import {HeaderComponent} from '@header/header.component';
import {MatDialog} from '@angular/material/dialog'; import {MatDialog} from '@angular/material/dialog';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {LoginDialogComponent} from '@shared-components/login/login.component'; import {LoginDialogComponent} from '@shared-components/login/login.component';
import {KeyValuePipe, NgForOf, NgIf} from '@angular/common'; import { KeyValuePipe } from '@angular/common';
import {FormType} from './form_type'; import {FormType} from './form_type';
import {MatButton} from '@angular/material/button'; import {MatButton} from '@angular/material/button';
import {AuthService} from '@services/auth.service'; import {AuthService} from '@services/auth.service';
@ -12,11 +12,9 @@ import {AuthService} from '@services/auth.service';
selector: 'app-forms', selector: 'app-forms',
imports: [ imports: [
HeaderComponent, HeaderComponent,
NgIf,
NgForOf,
MatButton, MatButton,
KeyValuePipe KeyValuePipe
], ],
templateUrl: './forms.component.html', templateUrl: './forms.component.html',
styleUrl: './forms.component.scss' styleUrl: './forms.component.scss'
}) })

View File

@ -1,6 +1,6 @@
<ng-container> <ng-container>
<header id="top" <header id="top"
[ngStyle]="{ 'background-image': getBackgroundImage(),'height': height, 'background-position': getBackgroundPosition() }"> [ngStyle]="{ 'background-image': getBackgroundImage(),'height': height, 'background-position': getBackgroundPosition() }">
<nav id="nav" [ngClass]="active"> <nav id="nav" [ngClass]="active">
<div class="container"> <div class="container">
<div id="mobile_nav"> <div id="mobile_nav">
@ -27,7 +27,7 @@
<li><a [routerLink]="['/customfeatures']">Custom Features</a></li> <li><a [routerLink]="['/customfeatures']">Custom Features</a></li>
<li><a <li><a
href="https://kanboard.alttd.com/public/board/ef0c28f3d022f7e98801bbc97278e9a523c7c6dc2a3b0c58c47e2ebdbd1e">Suggestion href="https://kanboard.alttd.com/public/board/ef0c28f3d022f7e98801bbc97278e9a523c7c6dc2a3b0c58c47e2ebdbd1e">Suggestion
Board</a></li> Board</a></li>
</ul> </ul>
</li> </li>
<li> <li>
@ -62,98 +62,106 @@
<li><a href="https://alttd.com/blog/">Blog</a></li> <li><a href="https://alttd.com/blog/">Blog</a></li>
</ul> </ul>
</li> </li>
<li *ngIf="!isAuthenticated"> @if (!isAuthenticated) {
<a (click)="openLoginDialog()"> <li>
Login <a (click)="openLoginDialog()">
</a> Login
</li> </a>
</li>
}
</ul> </ul>
</div> </div>
</div> </div>
<a href="/"><img ngSrc="/public/img/logos/logo.png" priority alt="Altitude Server Logo" height="319" <a href="/"><img ngSrc="/public/img/logos/logo.png" priority alt="Altitude Server Logo" height="319"
width="550"></a> width="550"></a>
<ul id="nav_list"> <ul id="nav_list">
<li class="nav_li"><a [id]="getCurrentPageId(['home'])" class="nav_link" href="/" [ngClass]="active">Home</a> <li class="nav_li"><a [id]="getCurrentPageId(['home'])" class="nav_link" href="/" [ngClass]="active">Home</a>
</li> </li>
<li class="nav_li"> <li class="nav_li">
<span [id]="getCurrentPageId(['map', 'customfeatures', 'economy', 'events', 'mypet', 'warps', <span [id]="getCurrentPageId(['map', 'customfeatures', 'economy', 'events', 'mypet', 'warps',
'skyblock', 'claiming'])" class="nav_link fake_link" [ngClass]="active">Features</span> 'skyblock', 'claiming'])" class="nav_link fake_link" [ngClass]="active">Features</span>
<ul class="dropdown"> <ul class="dropdown">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/map']">Map</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/map']">Map</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/economy']">Economy</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/economy']">Economy</a></li>
<!-- <li class="navli"><a class="nav_link2" [routerLink]="['/events']">Events</a></li> --> <!-- <li class="navli"><a class="nav_link2" [routerLink]="['/events']">Events</a></li> -->
<li class="nav_li"><a class="nav_link2" [routerLink]="['/claiming']">Land Claiming</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/claiming']">Land Claiming</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/mypet']">MyPet</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/mypet']">MyPet</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/warps']">Warps</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/warps']">Warps</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/skyblock']">Skyblock</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/skyblock']">Skyblock</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/customfeatures']">Custom Features</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/customfeatures']">Custom Features</a></li>
<li class="nav_li"><a class="nav_link2" <li class="nav_li"><a class="nav_link2"
href="https://kanboard.alttd.com/public/board/ef0c28f3d022f7e98801bbc97278e9a523c7c6dc2a3b0c58c47e2ebdbd1e">Suggestion href="https://kanboard.alttd.com/public/board/ef0c28f3d022f7e98801bbc97278e9a523c7c6dc2a3b0c58c47e2ebdbd1e">Suggestion
Board</a></li> Board</a></li>
</ul> </ul>
</li> </li>
<li class="nav_li"> <li class="nav_li">
<span <span
[id]="getCurrentPageId(['guide', 'faq', 'ranks', 'rules', 'commandlist', 'mapart', 'lag', 'staffpowers', [id]="getCurrentPageId(['guide', 'faq', 'ranks', 'rules', 'commandlist', 'mapart', 'lag', 'staffpowers',
'nicknames', 'bans', 'discord-bans'])" class="nav_link fake_link" [ngClass]="active">Reference</span> 'nicknames', 'bans', 'discord-bans'])" class="nav_link fake_link" [ngClass]="active">Reference</span>
<ul class="dropdown">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/guide']">Guide Book</a></li>
<!-- <li class="navli"><a class="nav_link2" [routerLink]="['/faq']">FAQ</a></li> -->
<li class="nav_li"><a class="nav_link2" [routerLink]="['/ranks']">Ranks</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/rules']">Rules</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/commandlist']">Command List</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/mapart']">Mapart</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/lag']">Reducing Lag</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/staffpowers']">Staff Powers</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/nicknames']">Nicknames</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/bans']">Minecraft Bans</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/discord-bans']">Discord Bans</a></li>
</ul>
</li>
<li class="nav_li"><a class="nav_link" target="_blank" rel="noopener"
href="https://discordapp.com/invite/TGqpzCJ" [ngClass]="active">Discord</a></li>
<li class="nav_li"><a [id]="getCurrentPageId(['vote'])" class="nav_link" [routerLink]="['/vote']"
[ngClass]="active">Vote</a>
</li>
<li class="nav_li">
<a class="nav_link" target="_blank" rel="noopener" href="https://store.alttd.com"
[ngClass]="active">Store</a>
</li>
<li class="nav_li">
<a [id]="getCurrentPageId(['about', 'team', 'community', 'birthdays'])"
class="nav_link fake_link" [ngClass]="active">Altitude</a>
<ul class="dropdown">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/about']">About Us</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/socials']">Socials</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/team']">Team</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/birthdays']">Famous Birthdays</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/community']">Community</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" rel="noopener" [routerLink]="['/contact']">Contact
Us</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" rel="noopener" href="https://alttd.com/appeal">Ban
Appeal</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" href="https://alttd.com/blog/">Blog</a></li>
</ul>
</li>
@if (isAuthenticated) {
<li class="nav_li">
<a [id]="getCurrentPageId(['particles'])"
class="nav_link fake_link" [ngClass]="active">Special</a>
@if (hasAccess(['HEAD_MOD'])) {
<ul class="dropdown"> <ul class="dropdown">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/guide']">Guide Book</a></li>
<!-- <li class="navli"><a class="nav_link2" [routerLink]="['/faq']">FAQ</a></li> -->
<li class="nav_li"><a class="nav_link2" [routerLink]="['/ranks']">Ranks</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/rules']">Rules</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/commandlist']">Command List</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/mapart']">Mapart</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/lag']">Reducing Lag</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/staffpowers']">Staff Powers</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/nicknames']">Nicknames</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/bans']">Minecraft Bans</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/discord-bans']">Discord Bans</a></li>
</ul>
</li>
<li class="nav_li"><a class="nav_link" target="_blank" rel="noopener"
href="https://discordapp.com/invite/TGqpzCJ" [ngClass]="active">Discord</a></li>
<li class="nav_li"><a [id]="getCurrentPageId(['vote'])" class="nav_link" [routerLink]="['/vote']"
[ngClass]="active">Vote</a>
</li>
<li class="nav_li">
<a class="nav_link" target="_blank" rel="noopener" href="https://store.alttd.com"
[ngClass]="active">Store</a>
</li>
<li class="nav_li">
<a [id]="getCurrentPageId(['about', 'team', 'community', 'birthdays'])"
class="nav_link fake_link" [ngClass]="active">Altitude</a>
<ul class="dropdown">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/about']">About Us</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/socials']">Socials</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/team']">Team</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/birthdays']">Famous Birthdays</a></li>
<li class="nav_li"><a class="nav_link2" [routerLink]="['/community']">Community</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" rel="noopener" [routerLink]="['/contact']">Contact
Us</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" rel="noopener" href="https://alttd.com/appeal">Ban
Appeal</a></li>
<li class="nav_li"><a class="nav_link2" target="_blank" href="https://alttd.com/blog/">Blog</a></li>
</ul>
</li>
<li class="nav_li" *ngIf="isAuthenticated">
<a [id]="getCurrentPageId(['particles'])"
class="nav_link fake_link" [ngClass]="active">Special</a>
<ul class="dropdown" *ngIf="hasAccess(['HEAD_MOD'])">
<li class="nav_li"><a class="nav_link2" [routerLink]="['/particles']">Particles</a></li> <li class="nav_li"><a class="nav_link2" [routerLink]="['/particles']">Particles</a></li>
</ul> </ul>
</li> }
<li class="nav_li login-button" *ngIf="!isAuthenticated"> </li>
<a class="nav_link fake_link" (click)="openLoginDialog()"> }
Login @if (!isAuthenticated) {
</a> <li class="nav_li login-button">
</li> <a class="nav_link fake_link" (click)="openLoginDialog()">
</ul> Login
</a>
</li>
}
</ul>
<app-theme></app-theme> <app-theme></app-theme>
</div> </div>
</nav> </nav>
<ng-content select="[header-content]"></ng-content> <ng-content select="[header-content]"></ng-content>
</header> </header>
</ng-container> </ng-container>

View File

@ -5,7 +5,6 @@ import {RouterLink} from '@angular/router';
import {AuthService} from '@services/auth.service'; import {AuthService} from '@services/auth.service';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {LoginDialogComponent} from '@shared-components/login/login.component'; import {LoginDialogComponent} from '@shared-components/login/login.component';
import {MatButton} from '@angular/material/button';
import {MatDialog} from '@angular/material/dialog'; import {MatDialog} from '@angular/material/dialog';
@Component({ @Component({
@ -14,8 +13,7 @@ import {MatDialog} from '@angular/material/dialog';
CommonModule, CommonModule,
ThemeComponent, ThemeComponent,
RouterLink, RouterLink,
NgOptimizedImage, NgOptimizedImage
MatButton
], ],
selector: 'app-header', selector: 'app-header',
templateUrl: './header.component.html', templateUrl: './header.component.html',

View File

@ -1,157 +1,157 @@
<ng-container> <ng-container>
<app-header [current_page]="'home'" height="100vh" <app-header [current_page]="'home'" height="100vh"
[background_image]="'/public/img/backgrounds/120spawn-min.png'"> [background_image]="'/public/img/backgrounds/120spawn-min.png'">
<div class="title" header-content> <div class="title" header-content>
<h1 style="display: none;">Altitude</h1> <h1 style="display: none;">Altitude</h1>
<img id="header-img" ngSrc="/public/img/logos/logo.png" alt="The Altitude Minecraft Server" height="319" <img id="header-img" ngSrc="/public/img/logos/logo.png" alt="The Altitude Minecraft Server" height="319"
width="550"> width="550">
<h2 style="font-size: 2.5em;" id="homeh2">Altitude now on {{ ALTITUDE_VERSION }}!</h2> <h2 style="font-size: 2.5em;" id="homeh2">Altitude now on {{ ALTITUDE_VERSION }}!</h2>
<a id="scroll-button" (click)="scrollToSection()"> <a id="scroll-button" (click)="scrollToSection()">
<span></span> <span></span>
<p style="display: none;">Scroll Down</p> <p style="display: none;">Scroll Down</p>
</a> </a>
</div>
</app-header>
<main>
<section id="scrollingpoint" style="background: #202020; text-align: center; padding: 80px 0;">
<!-- TODO load player count from old api or backend?-->
<h2 style="color: white;"><span class="player-count">Loading...</span></h2>
<h2 style="color: white;">Server IP: play.alttd.com</h2>
<div style="padding-top: 35px;">
<app-copy-ip></app-copy-ip>
</div> </div>
</section> </app-header>
<section class="darkmodeSection"> <main>
<div class="container"> <section id="scrollingpoint" style="background: #202020; text-align: center; padding: 80px 0;">
<div class="paragraph"> <!-- TODO load player count from old api or backend?-->
<h2>Adventure Begins</h2> <h2 style="color: white;"><span class="player-count">Loading...</span></h2>
<p>You awake in a strange town, where are you? There are residents running about trading with each other and <h2 style="color: white;">Server IP: play.alttd.com</h2>
stories of distant realms with more towns. It's time to write your story. Welcome to Altitude, the laid-back <div style="padding-top: 35px;">
community-oriented server that hosts your home for Minecraft.</p> <app-copy-ip></app-copy-ip>
</div> </div>
<img ngSrc="/public/img/items/bookquill.png" style="width: 150px; align-self: center; margin: 0 auto;" </section>
alt="Alternative Altitude Server Logo" <section class="darkmodeSection">
height="150" width="150"> <div class="container">
</div> <div class="paragraph">
</section> <h2>Adventure Begins</h2>
<!-- <p>You awake in a strange town, where are you? There are residents running about trading with each other and
<section id="section1"> stories of distant realms with more towns. It's time to write your story. Welcome to Altitude, the laid-back
<div class="container" id="video"> community-oriented server that hosts your home for Minecraft.</p>
</div>
<img ngSrc="/public/img/items/bookquill.png" style="width: 150px; align-self: center; margin: 0 auto;"
alt="Alternative Altitude Server Logo"
height="150" width="150">
</div>
</section>
<!--
<section id="section1">
<div class="container" id="video">
<h2 style="display: none;">YouTube Trailer</h2> <h2 style="display: none;">YouTube Trailer</h2>
<div style="border-radius:5px;overflow:hidden;position:relative;width:100%"> <div style="border-radius:5px;overflow:hidden;position:relative;width:100%">
<img style="width: 100%" src="https://img.youtube.com/vi/Nzbj9Dbv5Wk/maxresdefault.jpg" alt="Altitude YouTube Trailer"> <img style="width: 100%" src="https://img.youtube.com/vi/Nzbj9Dbv5Wk/maxresdefault.jpg" alt="Altitude YouTube Trailer">
<div id="youtube"> <div id="youtube">
<div class="play" onclick="playVideo()"></div> <div class="play" onclick="playVideo()"></div>
</div> </div>
</div> </div>
</div>
</section>
-->
<section class="darkmodeSection">
<div class="container" style="padding: 10px 0 80px 0">
<iframe id="discord-widget" src="https://discordapp.com/widget?id=141644560005595136&theme=dark"></iframe>
<div class="paragraph" id="discord-p">
<h2>Meet the Community</h2>
<p>Altitude is home to players young and old from all around the globe, and here, everyone is family. Altitude
is your place to get together with friends and relax - and maybe enjoy some survival too. Altitude is
intended for older players, but all are welcome!</p>
<p>Don't have Discord? Keep up with news and announcements at the <a href="alttd.com/blog">blog</a>.</p>
<div style="display: flex; justify-content: center;">
<a target="_blank" rel="noopener" href="https://discordapp.com/invite/TGqpzCJ">
<div style="margin-top: 30px;" class="button-outer">
<span class="button-inner">Join Our Discord</span>
</div>
</a>
</div> </div>
</div> </section>
</div> -->
</section> <section class="darkmodeSection">
<section id="section2"> <div class="container" style="padding: 10px 0 80px 0">
<div class="customContainer"> <iframe id="discord-widget" src="https://discordapp.com/widget?id=141644560005595136&theme=dark"></iframe>
<h2 style="color: white; padding-bottom: 35px; font-size: 2.8em;">Survival Shaped by You</h2> <div class="paragraph" id="discord-p">
<p style="color: white; padding-bottom: 35px; font-size: 1.1em; margin: auto;">Altitude is built by the <h2>Meet the Community</h2>
community, for the community. We've added features requested by our members and several custom plugins to <p>Altitude is home to players young and old from all around the globe, and here, everyone is family. Altitude
create our "perfect" survival experience.</p> is your place to get together with friends and relax - and maybe enjoy some survival too. Altitude is
<div class="survivalShapedContainerPlugins"> intended for older players, but all are welcome!</p>
<div class="pluginColumn"> <p>Don't have Discord? Keep up with news and announcements at the <a href="alttd.com/blog">blog</a>.</p>
<h2>McMMO & MyPet</h2> <div style="display: flex; justify-content: center;">
<p>Two of the most requested plugins on Altitude, level up yourself and your pet with these MMO-based <a target="_blank" rel="noopener" href="https://discordapp.com/invite/TGqpzCJ">
plugins!</p> <div style="margin-top: 30px;" class="button-outer">
<a [routerLink]="['/mypet']"> <span class="button-inner">Join Our Discord</span>
<div class="button-outer"> </div>
<span class="button-inner">MyPet Info</span> </a>
</div> </div>
</a> </div>
</div> </div>
<div class="pluginColumn"> </section>
<h2>Dynamic map</h2> <section id="section2">
<p>See the world and the players around it in real-time! The map shows the entire survival world with claims <div class="customContainer">
and warps.</p> <h2 style="color: white; padding-bottom: 35px; font-size: 2.8em;">Survival Shaped by You</h2>
<a [routerLink]="['/map']"> <p style="color: white; padding-bottom: 35px; font-size: 1.1em; margin: auto;">Altitude is built by the
<div class="button-outer"> community, for the community. We've added features requested by our members and several custom plugins to
<span class="button-inner">Visit Map</span> create our "perfect" survival experience.</p>
<div class="survivalShapedContainerPlugins">
<div class="pluginColumn">
<h2>McMMO & MyPet</h2>
<p>Two of the most requested plugins on Altitude, level up yourself and your pet with these MMO-based
plugins!</p>
<a [routerLink]="['/mypet']">
<div class="button-outer">
<span class="button-inner">MyPet Info</span>
</div>
</a>
</div> </div>
</a> <div class="pluginColumn">
</div> <h2>Dynamic map</h2>
<div class="pluginColumn"> <p>See the world and the players around it in real-time! The map shows the entire survival world with claims
<h2>Player Shops</h2> and warps.</p>
<p>Our economy is built on player shops, encouraging player interaction and putting the control in your <a [routerLink]="['/map']">
hands.</p> <div class="button-outer">
<a [routerLink]="['/economy']"> <span class="button-inner">Visit Map</span>
<div class="button-outer"> </div>
<span class="button-inner">Shop Guide</span> </a>
</div> </div>
</a> <div class="pluginColumn">
<h2>Player Shops</h2>
<p>Our economy is built on player shops, encouraging player interaction and putting the control in your
hands.</p>
<a [routerLink]="['/economy']">
<div class="button-outer">
<span class="button-inner">Shop Guide</span>
</div>
</a>
</div>
</div>
</div> </div>
</div> </section>
</div> <section class="remove-mobile darkmodeSection">
</section> <div class="customContainer">
<section class="remove-mobile darkmodeSection"> <h2 style="padding-bottom: 35px; font-size: 2.8em;">Community Builds</h2>
<div class="customContainer"> <p style="padding-bottom: 35px; font-size: 1.1em; margin: auto;">Thank you to our brilliant players for sharing
<h2 style="padding-bottom: 35px; font-size: 2.8em;">Community Builds</h2> their impressive builds. Take a look at some of them here!<br>
<p style="padding-bottom: 35px; font-size: 1.1em; margin: auto;">Thank you to our brilliant players for sharing If you know of any builds that should be featured, please let us know!</p>
their impressive builds. Take a look at some of them here!<br> <div class="sliderWrapper">
If you know of any builds that should be featured, please let us know!</p> <div class="sliderContent">
<div class="sliderWrapper"> <div class="indexSlider">
<div class="sliderContent"> <div id="go-left" (click)="previousSlide()" class="circleBehind goLeft"></div>
<div class="indexSlider"> <div id="go-right" (click)="nextSlide()" class="circleBehind goRight"></div>
<div id="go-left" (click)="previousSlide()" class="circleBehind goLeft"></div> <div class="display">
<div id="go-right" (click)="nextSlide()" class="circleBehind goRight"></div> <span class="slide"
<div class="display">
<span class="slide"
[style.background-image]="'url(' + slide + ')'" [style.background-image]="'url(' + slide + ')'"
[style.opacity]="carouselOpacity" [style.opacity]="carouselOpacity"
[style.display]="'block'"></span> [style.display]="'block'"></span>
</div>
</div>
<div class="dots">
@for (slide of getSlideIndices(); track slide) {
<span class="dot" (click)="setSlide(slide)" [ngClass]="getDotClass(slide)"></span>
}
</div>
</div> </div>
</div> </div>
<div class="dots">
<ng-container *ngFor="let slide of getSlideIndices();">
<span class="dot" (click)="setSlide(slide)" [ngClass]="getDotClass(slide)"></span>
</ng-container>
</div>
</div> </div>
</div> </section>
</div> <section style="background: #202020;">
</section> <div class="customContainer">
<section style="background: #202020;"> <h2 id="quote" style="color: white; font-family: 'minecraft-text',sans-serif; line-height: 1.3em;">"Great
<div class="customContainer"> community, great people, great server all round . . . If it can bring back my love for minecraft, it could
<h2 id="quote" style="color: white; font-family: 'minecraft-text',sans-serif; line-height: 1.3em;">"Great work wonders for you."</h2>
community, great people, great server all round . . . If it can bring back my love for minecraft, it could <p style="color: white; margin-top:30px;">- /u/seanhanley1993</p>
work wonders for you."</h2> </div>
<p style="color: white; margin-top:30px;">- /u/seanhanley1993</p> </section>
</div> <section class="darkmodeSection">
</section> <div class="customContainer">
<section class="darkmodeSection"> <img ngSrc="/public/img/logos/log.png" alt="Alternative Altitude Server Logo" height="129"
<div class="customContainer"> width="120">
<img ngSrc="/public/img/logos/log.png" alt="Alternative Altitude Server Logo" height="129" <h2 style="margin: 20px 0; font-size: 1.8em; padding-bottom: 0 !important;">play.alttd.com</h2>
width="120"> <app-copy-ip></app-copy-ip>
<h2 style="margin: 20px 0; font-size: 1.8em; padding-bottom: 0 !important;">play.alttd.com</h2> </div>
<app-copy-ip></app-copy-ip> </section>
</div> <a (click)="this.scrollService.scrollToTop()" class="scroll-up-button, active">
</section> <span></span>
<a (click)="this.scrollService.scrollToTop()" class="scroll-up-button, active"> <p style="display: none;">Scroll Down</p>
<span></span> </a>
<p style="display: none;">Scroll Down</p> </main>
</a> </ng-container>
</main>
</ng-container>

View File

@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {Title} from '@angular/platform-browser'; import {Title} from '@angular/platform-browser';
import {ALTITUDE_VERSION} from '@custom-types/constant'; import {ALTITUDE_VERSION} from '@custom-types/constant';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule, NgOptimizedImage} from '@angular/common'; import { CommonModule, NgOptimizedImage } from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
import {CopyIpComponent} from '@shared-components/copy-ip/copy-ip.component'; import {CopyIpComponent} from '@shared-components/copy-ip/copy-ip.component';
import {RouterLink} from '@angular/router'; import {RouterLink} from '@angular/router';

View File

@ -6,36 +6,42 @@
<mat-card-content> <mat-card-content>
<div class="frames-container"> <div class="frames-container">
<mat-tab-group [selectedIndex]="frames.indexOf(currentFrame)" <mat-tab-group [selectedIndex]="frames.indexOf(currentFrame)"
(selectedIndexChange)="switchFrame(frames[$event])"> (selectedIndexChange)="switchFrame(frames[$event])">
<mat-tab *ngFor="let frameId of frames" [label]="frameId"> @for (frameId of frames; track frameId) {
<div class="frame-content"> <mat-tab [label]="frameId">
<h3>Particles in {{ frameId }}</h3> <div class="frame-content">
<div class="particles-list"> <h3>Particles in {{ frameId }}</h3>
<div *ngFor="let particle of particleData.frames[frameId]; let i = index" class="particle-item"> <div class="particles-list">
<span class="particle-item-text"> @for (particle of particleData.frames[frameId]; track particle; let i = $index) {
Particle {{ i + 1 }}: ({{ particle.x.toFixed(2) }}, {{ particle.y.toFixed(2) }} <div class="particle-item">
, {{ particle.z.toFixed(2) }}) <span class="particle-item-text">
</span> Particle {{ i + 1 }}: ({{ particle.x.toFixed(2) }}, {{ particle.y.toFixed(2) }}
<button mat-icon-button (click)="removeParticle(frameId, i)"> , {{ particle.z.toFixed(2) }})
<mat-icon>delete</mat-icon> </span>
</button> <button mat-icon-button (click)="removeParticle(frameId, i)">
<button mat-icon-button (click)="highlightParticle(frameId, i)"> <mat-icon>delete</mat-icon>
<mat-icon>lightbulb</mat-icon> </button>
<button mat-icon-button (click)="highlightParticle(frameId, i)">
<mat-icon>lightbulb</mat-icon>
</button>
</div>
}
@if (!particleData.frames[frameId] || particleData.frames[frameId].length === 0) {
<div
class="no-particles">
No particles in this frame. Click on the plane to add particles.
</div>
}
</div>
<div class="frame-actions">
<button mat-raised-button color="warn" (click)="removeFrame(frameId)"
[disabled]="frames.length <= 1">
Remove Frame
</button> </button>
</div> </div>
<div *ngIf="!particleData.frames[frameId] || particleData.frames[frameId].length === 0"
class="no-particles">
No particles in this frame. Click on the plane to add particles.
</div>
</div> </div>
<div class="frame-actions"> </mat-tab>
<button mat-raised-button color="warn" (click)="removeFrame(frameId)" }
[disabled]="frames.length <= 1">
Remove Frame
</button>
</div>
</div>
</mat-tab>
</mat-tab-group> </mat-tab-group>
<div class="add-frame"> <div class="add-frame">
<button mat-raised-button color="primary" (click)="addFrame()"> <button mat-raised-button color="primary" (click)="addFrame()">

View File

@ -2,7 +2,7 @@ import {Component} from '@angular/core';
import {MatButton, MatIconButton} from "@angular/material/button"; import {MatButton, MatIconButton} from "@angular/material/button";
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card"; import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card";
import {MatTab, MatTabGroup} from "@angular/material/tabs"; import {MatTab, MatTabGroup} from "@angular/material/tabs";
import {NgForOf, NgIf} from "@angular/common";
import {ParticleData} from '../../models/particle.model'; import {ParticleData} from '../../models/particle.model';
import {MatIcon} from '@angular/material/icon'; import {MatIcon} from '@angular/material/icon';
import {ParticleManagerService} from '../../services/particle-manager.service'; import {ParticleManagerService} from '../../services/particle-manager.service';
@ -19,10 +19,8 @@ import {FrameManagerService} from '../../services/frame-manager.service';
MatIcon, MatIcon,
MatIconButton, MatIconButton,
MatTab, MatTab,
MatTabGroup, MatTabGroup
NgForOf, ],
NgIf
],
templateUrl: './frames.component.html', templateUrl: './frames.component.html',
styleUrl: './frames.component.scss' styleUrl: './frames.component.scss'
}) })

View File

@ -13,25 +13,27 @@
<mat-form-field appearance="fill" class="type-field"> <mat-form-field appearance="fill" class="type-field">
<mat-label>Select Particle Type</mat-label> <mat-label>Select Particle Type</mat-label>
<input type="text" <input type="text"
placeholder="Search for a particle type" placeholder="Search for a particle type"
matInput matInput
[formControl]="particleTypeControl" [formControl]="particleTypeControl"
[matAutocomplete]="auto"> [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn"> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngFor="let type of filteredParticleTypes | async" [value]="type"> @for (type of filteredParticleTypes | async; track type) {
{{ type }} <mat-option [value]="type">
</mat-option> {{ type }}
</mat-autocomplete> </mat-option>
</mat-form-field> }
</div> </mat-autocomplete>
</mat-form-field>
</div>
<div class="size-slider"> <div class="size-slider">
<mat-slider min="0.1" max="4" step="0.1" class="full-width"> <mat-slider min="0.1" max="4" step="0.1" class="full-width">
<input matSliderThumb [(ngModel)]="selectedSize"> <input matSliderThumb [(ngModel)]="selectedSize">
</mat-slider> </mat-slider>
<span>Size: {{ selectedSize }}</span> <span>Size: {{ selectedSize }}</span>
</div>
</div> </div>
</div> </mat-card-content>
</mat-card-content> </mat-card>
</mat-card> </div>
</div>

View File

@ -10,7 +10,7 @@ import {MatInputModule} from '@angular/material/input';
import {MatAutocompleteModule} from '@angular/material/autocomplete'; import {MatAutocompleteModule} from '@angular/material/autocomplete';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators'; import {map, startWith} from 'rxjs/operators';
import {AsyncPipe, NgForOf} from '@angular/common'; import { AsyncPipe } from '@angular/common';
@Component({ @Component({
selector: 'app-particle', selector: 'app-particle',
@ -26,9 +26,8 @@ import {AsyncPipe, NgForOf} from '@angular/common';
MatFormFieldModule, MatFormFieldModule,
MatInputModule, MatInputModule,
MatAutocompleteModule, MatAutocompleteModule,
NgForOf,
AsyncPipe AsyncPipe
], ],
templateUrl: './particle.component.html', templateUrl: './particle.component.html',
styleUrl: './particle.component.scss' styleUrl: './particle.component.scss'
}) })

View File

@ -22,7 +22,9 @@
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Particle Type</mat-label> <mat-label>Particle Type</mat-label>
<mat-select [(ngModel)]="particleData.particle_type"> <mat-select [(ngModel)]="particleData.particle_type">
<mat-option *ngFor="let type of particleTypes" [value]="type">{{ type }}</mat-option> @for (type of particleTypes; track type) {
<mat-option [value]="type">{{ type }}</mat-option>
}
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
@ -73,21 +75,21 @@
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Repeat Delay</mat-label> <mat-label>Repeat Delay</mat-label>
<input matInput type="number" [(ngModel)]="particleData.repeat_delay" <input matInput type="number" [(ngModel)]="particleData.repeat_delay"
placeholder="Enter repeat delay"> placeholder="Enter repeat delay">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="form-row"> <div class="form-row">
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Random Offset</mat-label> <mat-label>Random Offset</mat-label>
<input matInput type="number" [(ngModel)]="particleData.random_offset" <input matInput type="number" [(ngModel)]="particleData.random_offset"
placeholder="Enter random offset"> placeholder="Enter random offset">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="form-row"> <div class="form-row">
<mat-checkbox [(ngModel)]="particleData.stationary"><span>Stationary</span></mat-checkbox> <mat-checkbox [(ngModel)]="particleData.stationary"><span>Stationary</span></mat-checkbox>
</div> </div>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div> </div>

View File

@ -2,7 +2,7 @@ import {Component} from '@angular/core';
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card"; import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card";
import {MatCheckbox} from "@angular/material/checkbox"; import {MatCheckbox} from "@angular/material/checkbox";
import {MatFormField, MatInput, MatLabel} from "@angular/material/input"; import {MatFormField, MatInput, MatLabel} from "@angular/material/input";
import {NgForOf} from "@angular/common";
import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {ParticleData, ParticleType} from '../../models/particle.model'; import {ParticleData, ParticleType} from '../../models/particle.model';
import {MatSelect} from '@angular/material/select'; import {MatSelect} from '@angular/material/select';
@ -22,10 +22,9 @@ import {ParticleManagerService} from '../../services/particle-manager.service';
MatLabel, MatLabel,
MatOption, MatOption,
MatSelect, MatSelect,
NgForOf,
ReactiveFormsModule, ReactiveFormsModule,
FormsModule FormsModule
], ],
templateUrl: './properties.component.html', templateUrl: './properties.component.html',
styleUrl: './properties.component.scss' styleUrl: './properties.component.scss'
}) })

View File

@ -8,47 +8,49 @@
</div> </div>
<div class="button-row"> <div class="button-row">
<button mat-mini-fab color="primary" (click)="resetCamera()" <button mat-mini-fab color="primary" (click)="resetCamera()"
matTooltip="Reset camera"> matTooltip="Reset camera">
<mat-icon>location_searching</mat-icon> <mat-icon>location_searching</mat-icon>
</button> </button>
<button mat-mini-fab color="primary" (click)="togglePlaneLock()" <button mat-mini-fab color="primary" (click)="togglePlaneLock()"
[matTooltip]="isPlaneLocked ? 'Unlock Plane' : 'Lock Plane'"> [matTooltip]="isPlaneLocked ? 'Unlock Plane' : 'Lock Plane'">
<mat-icon>{{ isPlaneLocked ? 'lock' : 'lock_open' }}</mat-icon> <mat-icon>{{ isPlaneLocked ? 'lock' : 'lock_open' }}</mat-icon>
</button> </button>
</div> </div>
<div *ngIf="isPlaneLocked" class="plane-orientation-buttons"> @if (isPlaneLocked) {
<button mat-mini-fab color="warn" (click)="setPlaneOrientation(planeOrientations.VERTICAL_ABOVE)" <div class="plane-orientation-buttons">
[class.active]="currentPlaneOrientation === planeOrientations.VERTICAL_ABOVE" <button mat-mini-fab color="warn" (click)="setPlaneOrientation(planeOrientations.VERTICAL_ABOVE)"
matTooltip="Vertical Above"> [class.active]="currentPlaneOrientation === planeOrientations.VERTICAL_ABOVE"
<mat-icon>arrow_upward</mat-icon> matTooltip="Vertical Above">
</button> <mat-icon>arrow_upward</mat-icon>
<button mat-mini-fab color="warn" (click)="setPlaneOrientation(planeOrientations.VERTICAL_BELOW)" </button>
[class.active]="currentPlaneOrientation === planeOrientations.VERTICAL_BELOW" <button mat-mini-fab color="warn" (click)="setPlaneOrientation(planeOrientations.VERTICAL_BELOW)"
matTooltip="Vertical Below"> [class.active]="currentPlaneOrientation === planeOrientations.VERTICAL_BELOW"
<mat-icon>arrow_downward</mat-icon> matTooltip="Vertical Below">
</button> <mat-icon>arrow_downward</mat-icon>
<button mat-mini-fab color="primary" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_FRONT)" </button>
[class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_FRONT" <button mat-mini-fab color="primary" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_FRONT)"
matTooltip="Horizontal Front"> [class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_FRONT"
<mat-icon>arrow_forward</mat-icon> matTooltip="Horizontal Front">
</button> <mat-icon>arrow_forward</mat-icon>
<button mat-mini-fab color="primary" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_BEHIND)" </button>
[class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_BEHIND" <button mat-mini-fab color="primary" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_BEHIND)"
matTooltip="Horizontal Behind"> [class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_BEHIND"
<mat-icon>arrow_back</mat-icon> matTooltip="Horizontal Behind">
</button> <mat-icon>arrow_back</mat-icon>
<button mat-mini-fab color="accent" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_RIGHT)" </button>
[class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_RIGHT" <button mat-mini-fab color="accent" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_RIGHT)"
matTooltip="Horizontal Right"> [class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_RIGHT"
<mat-icon>arrow_right</mat-icon> matTooltip="Horizontal Right">
</button> <mat-icon>arrow_right</mat-icon>
<button mat-mini-fab color="accent" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_LEFT)" </button>
[class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_LEFT" <button mat-mini-fab color="accent" (click)="setPlaneOrientation(planeOrientations.HORIZONTAL_LEFT)"
matTooltip="Horizontal Left"> [class.active]="currentPlaneOrientation === planeOrientations.HORIZONTAL_LEFT"
<mat-icon>arrow_left</mat-icon> matTooltip="Horizontal Left">
</button> <mat-icon>arrow_left</mat-icon>
</div> </button>
</div>
}
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {AfterViewInit, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core'; import {AfterViewInit, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core';
import {MatMiniFabButton} from '@angular/material/button'; import {MatMiniFabButton} from '@angular/material/button';
import {NgIf} from '@angular/common';
import {IntersectionPlaneService, PlaneOrientation} from '../../services/intersection-plane.service'; import {IntersectionPlaneService, PlaneOrientation} from '../../services/intersection-plane.service';
import {MatIcon} from '@angular/material/icon'; import {MatIcon} from '@angular/material/icon';
import {MatTooltip} from '@angular/material/tooltip'; import {MatTooltip} from '@angular/material/tooltip';
@ -16,12 +16,11 @@ import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
MatIcon, MatIcon,
MatMiniFabButton, MatMiniFabButton,
MatTooltip, MatTooltip,
NgIf,
FormsModule, FormsModule,
MatInput, MatInput,
MatFormField, MatFormField,
MatLabel MatLabel
], ],
templateUrl: './render-container.component.html', templateUrl: './render-container.component.html',
styleUrl: './render-container.component.scss' styleUrl: './render-container.component.scss'
}) })

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, ViewChild} from '@angular/core'; import {Component, ElementRef, ViewChild} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button'; import {MatButtonModule} from '@angular/material/button';
import {MatInputModule} from '@angular/material/input'; import {MatInputModule} from '@angular/material/input';
@ -28,7 +28,6 @@ import {ParticlesService} from '@api';
selector: 'app-particles', selector: 'app-particles',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
MatButtonModule, MatButtonModule,
@ -44,8 +43,8 @@ import {ParticlesService} from '@api';
PropertiesComponent, PropertiesComponent,
ParticleComponent, ParticleComponent,
FramesComponent, FramesComponent,
RenderContainerComponent, RenderContainerComponent
], ],
templateUrl: './particles.component.html', templateUrl: './particles.component.html',
styleUrl: './particles.component.scss' styleUrl: './particles.component.scss'
}) })

View File

@ -1,6 +1,6 @@
<ng-container> <ng-container>
<app-header [current_page]="'bans'" height="200px" background_image="/public/img/backgrounds/staff.png" <app-header [current_page]="'bans'" height="200px" background_image="/public/img/backgrounds/staff.png"
[overlay_gradient]="0.5">> [overlay_gradient]="0.5">>
<div class="title" header-content> <div class="title" header-content>
<h1>Minecraft Punishments</h1> <h1>Minecraft Punishments</h1>
</div> </div>
@ -13,78 +13,81 @@
<div class="historyButtonContainer"> <div class="historyButtonContainer">
<div [id]="getCurrentButtonId('all')" class="button-outer" (click)="changeHistoryPunishment('all')"> <div [id]="getCurrentButtonId('all')" class="button-outer" (click)="changeHistoryPunishment('all')">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">All</span> [ngClass]="active">All</span>
</div> </div>
<div [id]="getCurrentButtonId('ban')" class="button-outer" (click)="changeHistoryPunishment('ban')"> <div [id]="getCurrentButtonId('ban')" class="button-outer" (click)="changeHistoryPunishment('ban')">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">Bans</span> [ngClass]="active">Bans</span>
</div> </div>
<div [id]="getCurrentButtonId('mute')" class="button-outer" (click)="changeHistoryPunishment('mute')"> <div [id]="getCurrentButtonId('mute')" class="button-outer" (click)="changeHistoryPunishment('mute')">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">Mutes</span> [ngClass]="active">Mutes</span>
</div> </div>
<div [id]="getCurrentButtonId('warn')" class="button-outer" (click)="changeHistoryPunishment('warn')"> <div [id]="getCurrentButtonId('warn')" class="button-outer" (click)="changeHistoryPunishment('warn')">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">Warnings</span> [ngClass]="active">Warnings</span>
</div> </div>
<div [id]="getCurrentUserTypeButtonId('player')" class="button-outer" (click)="changeUserType('player')" <div [id]="getCurrentUserTypeButtonId('player')" class="button-outer" (click)="changeUserType('player')"
style="margin-left: 120px;"> style="margin-left: 120px;">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">Player</span> [ngClass]="active">Player</span>
</div> </div>
<div [id]="getCurrentUserTypeButtonId('staff')" class="button-outer" (click)="changeUserType('staff')"> <div [id]="getCurrentUserTypeButtonId('staff')" class="button-outer" (click)="changeUserType('staff')">
<span class="button-inner" <span class="button-inner"
[ngClass]="active">Staff</span> [ngClass]="active">Staff</span>
</div> </div>
</div> </div>
<div class="historySearchContainer"> <div class="historySearchContainer">
<input class="historySearch" <input class="historySearch"
type="search" type="search"
placeholder="Search.." placeholder="Search.."
[(ngModel)]="searchTerm" [(ngModel)]="searchTerm"
(input)="filterNames()" (input)="filterNames()"
(keyup.enter)="search()" (keyup.enter)="search()"
> >
<div class="dropdown-results" *ngIf="filteredNames.length > 0 && searchTerm"> @if (filteredNames.length > 0 && searchTerm) {
<div <div class="dropdown-results">
class="dropdown-item" @for (name of filteredNames; track name) {
*ngFor="let name of filteredNames" <div
(mousedown)="selectName(name)"> class="dropdown-item"
{{ name }} (mousedown)="selectName(name)">
</div> {{ name }}
</div>
}
</div>
}
</div> </div>
</div> </div>
<div class="historyTable">
<app-history [userType]="userType" [punishmentType]="punishmentType"
[page]="page" [searchTerm]="finalSearchTerm" (pageChange)="updatePageSize($event)"
(selectItem)="setSearch($event)">
</app-history>
</div>
<div class="changePageButtons">
<button [ngClass]="{'active': buttonActive(0), 'disabled': !buttonActive(0)}"
[disabled]="!buttonActive(0)"
(click)="setPage(0)" class="historyPageButton">
First page
</button>
<button [ngClass]="{'active': buttonActive(0), 'disabled': !buttonActive(0)}"
[disabled]="!buttonActive(0)"
(click)="previousPage()" class="historyPageButton">
Previous page
</button>
<span class="pageNumber">{{ this.page }} / {{ getMaxPage() }}</span>
<button [ngClass]="{'active': buttonActive(getMaxPage()), 'disabled': !buttonActive(getMaxPage())}"
[disabled]="!buttonActive(getMaxPage())"
(click)="nextPage()" class="historyPageButton">
Next page
</button>
<button [ngClass]="{'active': buttonActive(getMaxPage()), 'disabled': !buttonActive(getMaxPage())}"
[disabled]="!buttonActive(getMaxPage())"
(click)="setPage(getMaxPage())" class="historyPageButton">
Last page
</button>
</div>
</div> </div>
<div class="historyTable"> </section>
<app-history [userType]="userType" [punishmentType]="punishmentType" </main>
[page]="page" [searchTerm]="finalSearchTerm" (pageChange)="updatePageSize($event)" </ng-container>
(selectItem)="setSearch($event)">
</app-history>
</div>
<div class="changePageButtons">
<button [ngClass]="{'active': buttonActive(0), 'disabled': !buttonActive(0)}"
[disabled]="!buttonActive(0)"
(click)="setPage(0)" class="historyPageButton">
First page
</button>
<button [ngClass]="{'active': buttonActive(0), 'disabled': !buttonActive(0)}"
[disabled]="!buttonActive(0)"
(click)="previousPage()" class="historyPageButton">
Previous page
</button>
<span class="pageNumber">{{ this.page }} / {{ getMaxPage() }}</span>
<button [ngClass]="{'active': buttonActive(getMaxPage()), 'disabled': !buttonActive(getMaxPage())}"
[disabled]="!buttonActive(getMaxPage())"
(click)="nextPage()" class="historyPageButton">
Next page
</button>
<button [ngClass]="{'active': buttonActive(getMaxPage()), 'disabled': !buttonActive(getMaxPage())}"
[disabled]="!buttonActive(getMaxPage())"
(click)="setPage(getMaxPage())" class="historyPageButton">
Last page
</button>
</div>
</div>
</section>
</main>
</ng-container>

View File

@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {HeaderComponent} from "@header/header.component"; import {HeaderComponent} from "@header/header.component";
import {HistoryComponent} from './history/history.component'; import {HistoryComponent} from './history/history.component';
import {HistoryCount, HistoryService} from '@api'; import {HistoryCount, HistoryService} from '@api';
import {NgClass, NgForOf, NgIf} from '@angular/common'; import { NgClass } from '@angular/common';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {catchError, map, Observable} from 'rxjs'; import {catchError, map, Observable} from 'rxjs';
import {SearchParams} from './search-terms'; import {SearchParams} from './search-terms';
@ -12,11 +12,9 @@ import {SearchParams} from './search-terms';
imports: [ imports: [
HeaderComponent, HeaderComponent,
HistoryComponent, HistoryComponent,
NgIf,
FormsModule, FormsModule,
NgForOf,
NgClass NgClass
], ],
templateUrl: './bans.component.html', templateUrl: './bans.component.html',
styleUrl: './bans.component.scss' styleUrl: './bans.component.scss'
}) })

View File

@ -1,6 +1,6 @@
<ng-container> <ng-container>
<app-header [current_page]="'bans'" height="200px" background_image="/public/img/backgrounds/staff.png" <app-header [current_page]="'bans'" height="200px" background_image="/public/img/backgrounds/staff.png"
[overlay_gradient]="0.5">> [overlay_gradient]="0.5">>
<div class="title" header-content> <div class="title" header-content>
<h1>Minecraft Punishments</h1> <h1>Minecraft Punishments</h1>
</div> </div>
@ -10,15 +10,15 @@
<section class="darkmodeSection"> <section class="darkmodeSection">
<section class="columnSection"> <section class="columnSection">
<div class="detailsBackButton"> <div class="detailsBackButton">
<ng-container *ngIf="punishment === undefined"> @if (punishment === undefined) {
<p>Loading...</p> <p>Loading...</p>
</ng-container> }
<a [routerLink]="['/bans']">< Back</a> <a [routerLink]="['/bans']">< Back</a>
</div> </div>
</section> </section>
<section class="columnSection center"> <section class="columnSection center">
<ng-container *ngIf="punishment"> @if (punishment) {
<div> <div>
<span class="tag tagInfo" <span class="tag tagInfo"
[ngClass]="{ [ngClass]="{
@ -38,72 +38,72 @@
{{ this.historyFormat.isActive(punishment) ? 'Active' : 'Inactive' }} {{ this.historyFormat.isActive(punishment) ? 'Active' : 'Inactive' }}
</span> </span>
</div> </div>
</ng-container> }
</section> </section>
<section class="columnSection"> <section class="columnSection">
<div class="columnContainer"> <div class="columnContainer">
<div class="columnParagraph"> <div class="columnParagraph">
<ng-container *ngIf="punishment"> @if (punishment) {
<div class="playerContainer"> <div class="playerContainer">
<h2>Player</h2> <h2>Player</h2>
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.uuid, '150')" <img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.uuid, '150')"
width="150" width="150"
height="150" height="150"
alt="{{punishment.username}}'s Minecraft skin" alt="{{punishment.username}}'s Minecraft skin"
> >
<h3 class="detailsUsername">{{ punishment.username }}</h3> <h3 class="detailsUsername">{{ punishment.username }}</h3>
</div> </div>
</ng-container> }
</div>
</div> </div>
</div> <div class="columnContainer">
<div class="columnContainer"> <div class="columnParagraph">
<div class="columnParagraph"> @if (punishment) {
<ng-container *ngIf="punishment"> <div class="playerContainer">
<div class="playerContainer"> <h2>Moderator</h2>
<h2>Moderator</h2> <img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.punishedByUuid, '150')"
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.punishedByUuid, '150')" width="150"
width="150" height="150"
height="150" alt="{{punishment.punishedBy}}'s Minecraft skin"
alt="{{punishment.punishedBy}}'s Minecraft skin" >
> <h3 class="detailsUsername">{{ punishment.punishedBy }}</h3>
<h3 class="detailsUsername">{{ punishment.punishedBy }}</h3> </div>
}
</div> </div>
</ng-container> </div>
</div> <div class="columnContainer">
</div> <div class="columnParagraph">
<div class="columnContainer"> @if (punishment) {
<div class="columnParagraph"> <div class="detailsInfo">
<ng-container *ngIf="punishment"> <h2>Reason</h2>
<div class="detailsInfo"> <p>{{ punishment.reason | removeTrailingPeriod }}</p>
<h2>Reason</h2> </div>
<p>{{ punishment.reason | removeTrailingPeriod }}</p> }
</div> </div>
</ng-container> </div>
</div> <div class="columnContainer">
</div> <div class="columnParagraph">
<div class="columnContainer"> @if (punishment) {
<div class="columnParagraph"> <div class="detailsInfo">
<ng-container *ngIf="punishment"> <h2>Date</h2>
<div class="detailsInfo"> <p>{{ this.historyFormat.getPunishmentTime(punishment) }}</p>
<h2>Date</h2> </div>
<p>{{ this.historyFormat.getPunishmentTime(punishment) }}</p> }
</div> </div>
</ng-container> </div>
</div> </section>
</div> </section>
</section> </main>
</section>
</main>
</ng-container>
<section class="columnSection">
<ng-container *ngIf="punishment">
<span>Expires</span>
<span>{{ this.historyFormat.getExpiredTime(punishment) }}</span>
<ng-container *ngIf="punishment.removedBy !== undefined && punishment.removedBy.length > 0">
<span>Un{{ this.historyFormat.getType(punishment).toLocaleLowerCase() }} reason</span>
<span>{{ punishment.removedReason == null ? 'No reason specified' : punishment.removedReason }}</span>
</ng-container> </ng-container>
</ng-container>
</section>
<section class="columnSection">
@if (punishment) {
<span>Expires</span>
<span>{{ this.historyFormat.getExpiredTime(punishment) }}</span>
@if (punishment.removedBy !== undefined && punishment.removedBy.length > 0) {
<span>Un{{ this.historyFormat.getType(punishment).toLocaleLowerCase() }} reason</span>
<span>{{ punishment.removedReason == null ? 'No reason specified' : punishment.removedReason }}</span>
}
}
</section>

View File

@ -1,6 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {HistoryService, PunishmentHistory} from '@api'; import {HistoryService, PunishmentHistory} from '@api';
import {NgClass, NgIf, NgOptimizedImage} from '@angular/common'; import { NgClass, NgOptimizedImage } from '@angular/common';
import {RemoveTrailingPeriodPipe} from '@pipes/RemoveTrailingPeriodPipe'; import {RemoveTrailingPeriodPipe} from '@pipes/RemoveTrailingPeriodPipe';
import {HistoryFormatService} from '../history-format.service'; import {HistoryFormatService} from '../history-format.service';
import {ActivatedRoute, RouterLink} from '@angular/router'; import {ActivatedRoute, RouterLink} from '@angular/router';
@ -10,13 +10,12 @@ import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
selector: 'app-details', selector: 'app-details',
imports: [ imports: [
NgIf,
NgOptimizedImage, NgOptimizedImage,
RemoveTrailingPeriodPipe, RemoveTrailingPeriodPipe,
HeaderComponent, HeaderComponent,
RouterLink, RouterLink,
NgClass NgClass
], ],
templateUrl: './details.component.html', templateUrl: './details.component.html',
styleUrl: './details.component.scss' styleUrl: './details.component.scss'
}) })

View File

@ -1,53 +1,55 @@
<ng-container *ngIf="history.length === 0"> @if (history.length === 0) {
<p>No history found</p> <p>No history found</p>
</ng-container> }
<ng-container *ngIf="history.length > 0"> @if (history.length > 0) {
<table [cellSpacing]="0"> <table [cellSpacing]="0">
<div class="historyTableHead"> <div class="historyTableHead">
<thead> <thead>
<tr> <tr>
<th class="historyType">Type</th> <th class="historyType">Type</th>
<th class="historyPlayer">Player</th> <th class="historyPlayer">Player</th>
<th class="historyPlayer">Banned By</th> <th class="historyPlayer">Banned By</th>
<th class="historyReason">Reason</th> <th class="historyReason">Reason</th>
<th class="historyDate">Date</th> <th class="historyDate">Date</th>
<th class="historyDate">Expires</th> <th class="historyDate">Expires</th>
</tr> </tr>
</thead> </thead>
</div> </div>
<div> <div>
<tbody> <tbody>
<tr class="historyPlayerRow" *ngFor="let entry of history"> @for (entry of history; track entry) {
<td class="historyType" (click)="showDetailedPunishment(entry)"> <tr class="historyPlayerRow">
{{ this.historyFormat.getType(entry) }} <td class="historyType" (click)="showDetailedPunishment(entry)">
</td> {{ this.historyFormat.getType(entry) }}
<td class="historyPlayer" (click)="setSearch(entry.username, 'player')"> </td>
<div class="playerContainer"> <td class="historyPlayer" (click)="setSearch(entry.username, 'player')">
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(entry.uuid)" width="25" height="25" <div class="playerContainer">
alt="{{entry.username}}'s Minecraft skin"> <img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(entry.uuid)" width="25" height="25"
<span class="username">{{ entry.username }}</span> alt="{{entry.username}}'s Minecraft skin">
</div> <span class="username">{{ entry.username }}</span>
</td> </div>
<td class="historyPlayer" (click)="setSearch(entry.punishedBy, 'staff')"> </td>
<div class="playerContainer"> <td class="historyPlayer" (click)="setSearch(entry.punishedBy, 'staff')">
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(entry.punishedByUuid)" width="25" height="25" <div class="playerContainer">
alt="{{entry.punishedBy}}'s Minecraft skin"> <img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(entry.punishedByUuid)" width="25" height="25"
<span>{{ entry.punishedBy }}</span> alt="{{entry.punishedBy}}'s Minecraft skin">
</div> <span>{{ entry.punishedBy }}</span>
</td> </div>
<td class="historyReason" (click)="showDetailedPunishment(entry)"> </td>
{{ entry.reason | removeTrailingPeriod }} <td class="historyReason" (click)="showDetailedPunishment(entry)">
</td> {{ entry.reason | removeTrailingPeriod }}
<td class="historyDate" (click)="showDetailedPunishment(entry)"> </td>
{{ this.historyFormat.getPunishmentTime(entry) }} <td class="historyDate" (click)="showDetailedPunishment(entry)">
</td> {{ this.historyFormat.getPunishmentTime(entry) }}
<td class="historyDate" (click)="showDetailedPunishment(entry)"> </td>
{{ this.historyFormat.getExpiredTime(entry) }} <td class="historyDate" (click)="showDetailedPunishment(entry)">
</td> {{ this.historyFormat.getExpiredTime(entry) }}
</tr> </td>
</tbody> </tr>
</div> }
</table> </tbody>
</ng-container> </div>
</table>
}

View File

@ -1,7 +1,7 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {BASE_PATH, HistoryService, PunishmentHistory} from '@api'; import {BASE_PATH, HistoryService, PunishmentHistory} from '@api';
import {catchError, map, Observable, shareReplay} from 'rxjs'; import {catchError, map, Observable, shareReplay} from 'rxjs';
import {NgForOf, NgIf, NgOptimizedImage} from '@angular/common'; import { NgOptimizedImage } from '@angular/common';
import {CookieService} from 'ngx-cookie-service'; import {CookieService} from 'ngx-cookie-service';
import {RemoveTrailingPeriodPipe} from '@pipes/RemoveTrailingPeriodPipe'; import {RemoveTrailingPeriodPipe} from '@pipes/RemoveTrailingPeriodPipe';
import {HttpErrorResponse} from '@angular/common/http'; import {HttpErrorResponse} from '@angular/common/http';
@ -13,11 +13,9 @@ import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-history', selector: 'app-history',
imports: [ imports: [
NgIf,
NgForOf,
NgOptimizedImage, NgOptimizedImage,
RemoveTrailingPeriodPipe RemoveTrailingPeriodPipe
], ],
templateUrl: './history.component.html', templateUrl: './history.component.html',
styleUrl: './history.component.scss', styleUrl: './history.component.scss',
providers: [ providers: [

View File

@ -1,15 +1,14 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ScrollService} from '@services/scroll.service'; import {ScrollService} from '@services/scroll.service';
import {CommonModule} from '@angular/common';
import {HeaderComponent} from '@header/header.component'; import {HeaderComponent} from '@header/header.component';
@Component({ @Component({
selector: 'app-vote', selector: 'app-vote',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
HeaderComponent HeaderComponent
], ],
templateUrl: './vote.component.html', templateUrl: './vote.component.html',
styleUrl: './vote.component.scss' styleUrl: './vote.component.scss'
}) })

View File

@ -1,13 +1,11 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {CommonModule} from '@angular/common';
@Component({ @Component({
selector: 'app-copy-ip', selector: 'app-copy-ip',
templateUrl: './copy-ip.component.html', templateUrl: './copy-ip.component.html',
standalone: true, standalone: true,
imports: [ imports: [],
CommonModule
],
styleUrl: './copy-ip.component.scss' styleUrl: './copy-ip.component.scss'
}) })
export class CopyIpComponent { export class CopyIpComponent {

View File

@ -4,18 +4,26 @@
<mat-form-field appearance="fill" style="width: 100%"> <mat-form-field appearance="fill" style="width: 100%">
<mat-label>Enter your code</mat-label> <mat-label>Enter your code</mat-label>
<input matInput formControlName="code" type="text" (keyup)="onKeyUp()"> <input matInput formControlName="code" type="text" (keyup)="onKeyUp()">
<mat-error *ngIf="loginForm.get('code')?.errors?.['required']"> @if (loginForm.get('code')?.errors?.['required']) {
Code is required <mat-error>
</mat-error> Code is required
<mat-error *ngIf="loginForm.get('code')?.errors?.['minlength']"> </mat-error>
Code must be 8 characters }
</mat-error> @if (loginForm.get('code')?.errors?.['minlength']) {
<mat-error *ngIf="loginForm.get('code')?.errors?.['maxlength']"> <mat-error>
Code cannot exceed 8 characters Code must be 8 characters
</mat-error> </mat-error>
<mat-error *ngIf="loginForm.get('code')?.errors?.['pattern']"> }
Code contains invalid characters @if (loginForm.get('code')?.errors?.['maxlength']) {
</mat-error> <mat-error>
Code cannot exceed 8 characters
</mat-error>
}
@if (loginForm.get('code')?.errors?.['pattern']) {
<mat-error>
Code contains invalid characters
</mat-error>
}
</mat-form-field> </mat-form-field>
</form> </form>
</div> </div>

View File

@ -4,7 +4,7 @@ import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/
import {MatButtonModule} from '@angular/material/button'; import {MatButtonModule} from '@angular/material/button';
import {MatInputModule} from '@angular/material/input'; import {MatInputModule} from '@angular/material/input';
import {MatFormFieldModule} from '@angular/material/form-field'; import {MatFormFieldModule} from '@angular/material/form-field';
import {NgIf} from '@angular/common';
import {MatSnackBar} from '@angular/material/snack-bar'; import {MatSnackBar} from '@angular/material/snack-bar';
import {AuthService} from '@services/auth.service'; import {AuthService} from '@services/auth.service';
@ -18,9 +18,8 @@ import {AuthService} from '@services/auth.service';
MatFormFieldModule, MatFormFieldModule,
MatDialogTitle, MatDialogTitle,
MatDialogContent, MatDialogContent,
MatDialogActions, MatDialogActions
NgIf ],
],
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrl: './login.component.scss' styleUrl: './login.component.scss'
}) })

View File

@ -2,13 +2,11 @@ import {Component, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {ThemeService} from './theme.service'; import {ThemeService} from './theme.service';
import {THEME_MODE} from '@custom-types/constant'; import {THEME_MODE} from '@custom-types/constant';
import {CommonModule} from '@angular/common';
@Component({ @Component({
standalone: true, standalone: true,
imports: [ imports: [],
CommonModule,
],
selector: 'app-theme', selector: 'app-theme',
templateUrl: './theme.component.html', templateUrl: './theme.component.html',
styleUrl: './theme.component.scss' styleUrl: './theme.component.scss'