Compare commits

..

No commits in common. "643545a18a6e929bd30f51b5cd30b4f016004dcb" and "43b75b8e746dbe3ece19672a5a3e91957efd8d1d" have entirely different histories.

17 changed files with 59 additions and 480 deletions

View File

@ -1,28 +0,0 @@
package com.alttd.altitudeweb.controllers.application;
import com.alttd.altitudeweb.api.AppealsApi;
import com.alttd.altitudeweb.model.AppealResponseDto;
import com.alttd.altitudeweb.model.DiscordAppealDto;
import com.alttd.altitudeweb.model.MinecraftAppealDto;
import com.alttd.altitudeweb.model.UpdateMailDto;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.server.ResponseStatusException;
public class AppealController implements AppealsApi {
@Override
public ResponseEntity<MinecraftAppealDto> submitDiscordAppeal(DiscordAppealDto discordAppealDto) {
throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Discord appeals are not yet supported");
}
@Override
public ResponseEntity<AppealResponseDto> submitMinecraftAppeal(MinecraftAppealDto minecraftAppealDto) {
throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Minecraft appeals are not yet supported");
}
@Override
public ResponseEntity<AppealResponseDto> updateMail(UpdateMailDto updateMailDto) {
throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Updating mail is not yet supported");
}
}

View File

@ -1,22 +0,0 @@
package com.alttd.altitudeweb.controllers.login;
import com.alttd.altitudeweb.api.LoginApi;
import com.alttd.altitudeweb.model.AddLoginDto;
import com.alttd.altitudeweb.model.LoginDataDto;
import com.alttd.altitudeweb.model.LoginResultDto;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.server.ResponseStatusException;
public class LoginController implements LoginApi {
@Override
public ResponseEntity<Void> addLogin(AddLoginDto addLoginDto) {
throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Adding login is not yet supported");
}
@Override
public ResponseEntity<LoginResultDto> login(LoginDataDto loginDataDto) {
throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Logging in is not yet supported");
}
}

View File

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

View File

@ -6,104 +6,57 @@
</div>
</app-header>
<main>
<section class="darkmodeSection">
<section class="columnSection">
<div class="detailsBackButton">
<ng-container *ngIf="punishment === undefined">
<p>Loading...</p>
</ng-container>
<a [routerLink]="['/bans']">< Back</a>
</div>
</section>
<section class="columnSection center">
<ng-container *ngIf="punishment">
<div>
<span class="tag tagInfo"
[ngClass]="{
'tagPermanent': this.historyFormat.isPermanent(punishment),
'tagExpired': !this.historyFormat.isPermanent(punishment)
}">
{{ this.historyFormat.getType(punishment) }}
</span>
</div>
<div>
<span
class="tag tagInfo"
[ngClass]="{
'tagActive': this.historyFormat.isActive(punishment),
'tagInactive': !this.historyFormat.isActive(punishment)
}">
{{ this.historyFormat.isActive(punishment) ? 'Active' : 'Inactive' }}
</span>
</div>
</ng-container>
</section>
<section class="columnSection">
<div class="columnContainer">
<div class="columnParagraph">
<ng-container *ngIf="punishment">
<div class="playerContainer">
<h2>Player</h2>
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.uuid, '150')"
width="150"
height="150"
alt="{{punishment.username}}'s Minecraft skin"
>
<h3 class="detailsUsername">{{ punishment.username }}</h3>
</div>
</ng-container>
</div>
</div>
<div class="columnContainer">
<div class="columnParagraph">
<ng-container *ngIf="punishment">
<div class="playerContainer">
<h2>Moderator</h2>
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.punishedByUuid, '150')"
width="150"
height="150"
alt="{{punishment.punishedBy}}'s Minecraft skin"
>
<h3 class="detailsUsername">{{ punishment.punishedBy }}</h3>
</div>
</ng-container>
</div>
</div>
<div class="columnContainer">
<div class="columnParagraph">
<ng-container *ngIf="punishment">
<div class="detailsInfo">
<h2>Reason</h2>
<p>{{ punishment.reason | removeTrailingPeriod }}</p>
</div>
</ng-container>
</div>
</div>
<div class="columnContainer">
<div class="columnParagraph">
<ng-container *ngIf="punishment">
<div class="detailsInfo">
<h2>Date</h2>
<p>{{ this.historyFormat.getPunishmentTime(punishment) }}</p>
</div>
</ng-container>
</div>
</div>
</section>
</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 *ngIf="punishment === undefined">
<p>Loading...</p>
</ng-container>
</section>
<ng-container *ngIf="punishment">
<table [cellSpacing]="0">
<div>
<p>type: {{ this.historyFormat.getType(punishment) }}</p>
<p>is active: {{ this.historyFormat.isActive(punishment) }}</p>
<tbody>
<tr>
<td>Player</td>
<td>
<div class="playerContainer">
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.uuid)" width="25" height="25"
alt="{{punishment.username}}'s Minecraft skin">
<span class="username">{{ punishment.username }}</span>
</div>
</td>
</tr>
<tr>
<td>Moderator</td>
<td>
<div class="playerContainer">
<img class="avatar" [ngSrc]="this.historyFormat.getAvatarUrl(punishment.punishedByUuid)" width="25"
height="25"
alt="{{punishment.punishedBy}}'s Minecraft skin">
<span class="username">{{ punishment.punishedBy }}</span>
</div>
</td>
</tr>
<tr>
<td>Reason</td>
<td>{{ punishment.reason | removeTrailingPeriod }}</td>
</tr>
<tr>
<td>Date</td>
<td>{{ this.historyFormat.getPunishmentTime(punishment) }}</td>
</tr>
<tr>
<td>Expires</td>
<td>{{ this.historyFormat.getExpiredTime(punishment) }}</td>
</tr>
<ng-container *ngIf="punishment.removedBy !== undefined && punishment.removedBy.length > 0">
<tr>
<td>Un{{ this.historyFormat.getType(punishment).toLocaleLowerCase() }} reason</td>
<td>{{ punishment.removedReason == null ? 'No reason specified' : punishment.removedReason }}</td>
</tr>
</ng-container>
</tbody>
</div>
</table>
</ng-container>
</ng-container>

View File

@ -1,68 +0,0 @@
.detailsBackButton {
font-family: open-sans, sans-serif;
}
.columnSection {
padding-top: 30px;
}
h2 {
text-align: center;
}
h3 {
text-align: center;
}
.avatar {
padding: 10px 0;
}
.detailsUsername {
font-size: 1.2em;
font-family: 'opensans-bold', sans-serif;
}
.detailsInfo {
padding-top: 50px;
}
.detailsInfo p {
text-align: center;
}
.tag {
display: inline-block;
padding: 5px 10px;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 0.25rem;
font-family: 'opensans-bold', sans-serif;
}
.tagInfo {
margin: 0 20px;
font-size: 1.1em;
}
.tagActive {
color: #FFFFFF;
background-color: #EE5555;
}
.tagInactive {
color: #FFFFFF;
background-color: #F79720;
}
.tagPermanent {
color: #FFFFFF;
background-color: #EE5555;
}
.tagExpired {
color: #FFFFFF;
background-color: #777777
}

View File

@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {HistoryService, PunishmentHistory} from '../../../api';
import {NgClass, NgIf, NgOptimizedImage} from '@angular/common';
import {NgIf, NgOptimizedImage} from '@angular/common';
import {RemoveTrailingPeriodPipe} from '../../util/RemoveTrailingPeriodPipe';
import {HistoryFormatService} from '../history-format.service';
import {ActivatedRoute, RouterLink} from '@angular/router';
import {ActivatedRoute} from '@angular/router';
import {catchError, map} from 'rxjs';
import {HeaderComponent} from '../../header/header.component';
@ -13,9 +13,7 @@ import {HeaderComponent} from '../../header/header.component';
NgIf,
NgOptimizedImage,
RemoveTrailingPeriodPipe,
HeaderComponent,
RouterLink,
NgClass
HeaderComponent
],
templateUrl: './details.component.html',
styleUrl: './details.component.scss'

View File

@ -22,19 +22,9 @@ export class HistoryFormatService {
}
public isActive(entry: PunishmentHistory): boolean {
if (entry.removedBy !== null) {
return false;
}
if (entry.expiryTime <= 0) {
return true;
}
return entry.expiryTime > Date.now();
}
public isPermanent(entry: PunishmentHistory): boolean {
return entry.expiryTime <= 0;
}
public getType(entry: PunishmentHistory): string {
return entry.type.charAt(0).toUpperCase() + entry.type.slice(1);
}
@ -58,11 +48,11 @@ export class HistoryFormatService {
}) + " " + suffix;
}
public getAvatarUrl(entry: string, size: string = '25'): string {
public getAvatarUrl(entry: string): string {
let uuid = entry.replace('-', '');
if (uuid === 'C') {
uuid = "f78a4d8dd51b4b3998a3230f2de0c670"
}
return `https://crafatar.com/avatars/${uuid}?size=${size}&overlay`;
return `https://crafatar.com/avatars/${uuid}?size=25&overlay`;
}
}

View File

@ -1,5 +0,0 @@
<app-forms [currentPage]="'appeal'" [formTitle]="'Minecraft Appeal'">
<div form-content>
</div>
</app-forms>

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppealComponent } from './appeal.component';
describe('AppealComponent', () => {
let component: AppealComponent;
let fixture: ComponentFixture<AppealComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppealComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AppealComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,63 +0,0 @@
import {Component, OnInit} from '@angular/core';
import {FormsComponent} from '../forms.component';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {AppealsService} from '../../../api';
@Component({
selector: 'app-appeal',
imports: [
FormsComponent
],
templateUrl: './appeal.component.html',
styleUrl: './appeal.component.scss'
})
export class AppealComponent implements OnInit {
public form: FormGroup | undefined;
constructor(private fb: FormBuilder, private appealApi: AppealsService) {
}
ngOnInit() {
this.initForm()
}
private initForm() {
this.form = this.fb.group({
name: ['', [Validators.required]],
punishmentId: ['', [Validators.required]],
email: ['', [Validators.required, Validators.email]],
message: ['', [Validators.required, Validators.minLength(10)]]
});
}
public onSubmit() {
if (this.form === undefined) {
console.error('Form is undefined');
return
}
if (this.form.valid) {
console.log('Form submitted:', this.form.value);
// Process form submission here
} 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)) {
console.error('Control [' + control + '] is not a FormGroup');
return;
}
control.markAsTouched({onlySelf: true});
});
}
}
private sendForm(validForm: FormGroup) {
// const appeal: MinecraftAppeal = {
//
// }
// this.appealApi.submitMinecraftAppeal()
}
}

View File

@ -1,12 +0,0 @@
<ng-container>
<app-header [current_page]="currentPage" height="200px" background_image="/public/img/backgrounds/staff.png"
[overlay_gradient]="0.5">
<div class="title" header-content>
<h1>{{ formTitle }}</h1>
</div>
</app-header>
<!-- TODO add form styling in this div-->
<div>
<ng-content select="[form-content]"></ng-content>
</div>
</ng-container>

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsComponent } from './forms.component';
describe('FormsComponent', () => {
let component: FormsComponent;
let fixture: ComponentFixture<FormsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormsComponent]
})
.compileComponents();
fixture = TestBed.createComponent(FormsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,15 +0,0 @@
import {Component, Input} from '@angular/core';
import {HeaderComponent} from '../header/header.component';
@Component({
selector: 'app-forms',
imports: [
HeaderComponent
],
templateUrl: './forms.component.html',
styleUrl: './forms.component.scss'
})
export class FormsComponent {
@Input() formTitle: string = 'Form';
@Input() currentPage: string = 'forms';
}

View File

@ -36,7 +36,3 @@ paths:
$ref: './schemas/forms/appeal/appeal.yml#/MinecraftAppeal'
/appeal/discord-appeal:
$ref: './schemas/forms/appeal/appeal.yml#/DiscordAppeal'
/login/addUserLogin:
$ref: './schemas/login/login.yml#/AddUserLogin'
/login/userLogin:
$ref: './schemas/login/login.yml#/UserLogin'

View File

@ -1,97 +0,0 @@
UserLogin:
post:
tags:
- login
summary: Log in to the site
description: Log in to the site through a code from the server
operationId: login
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginData'
responses:
'200':
description: Logged in
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResult'
'401':
description: Login failed - Invalid credentials
content:
application/json:
schema:
$ref: '../generic/errors.yml#/components/schemas/ApiError'
default:
description: Unexpected error
content:
application/json:
schema:
$ref: '../generic/errors.yml#/components/schemas/ApiError'
AddUserLogin:
post:
tags:
- login
summary: Add a login
description: Add a code, user combination that can be used to log in
operationId: addLogin
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddLogin'
responses:
'200':
description: Success
default:
description: Unexpected error
content:
application/json:
schema:
$ref: '../generic/errors.yml#/components/schemas/ApiError'
components:
schemas:
LoginData:
type: object
required:
- loginCode
properties:
loginCode:
type: string
description: The code to log in
LoginResult:
type: object
required:
- uuid
- userName
- auth
properties:
uuid:
type: string
format: uuid
description: UUID of logged in user
userName:
type: string
description: Name of the logged in user
auth:
type: string
description: Token to use along side requests
AddLogin:
type: object
required:
- loginCode
- uuid
properties:
auth:
type: string
description: Token to verify the sender is allowed to add logins
loginCode:
type: string
description: The code that can be logged in with
uuid:
type: string
format: uuid
description: UUID of the user that will get logged in