Compare commits

..

23 Commits

Author SHA1 Message Date
Tomasi Patrick
674ed9e8e8
Merge pull request #29 from TomasiDeveloping/update
Update
2026-02-17 14:30:38 +01:00
Tomasi - Developing
4e02e114c1 fix 2026-02-17 14:29:59 +01:00
Tomasi - Developing
3545994bbf v1.2.0 2026-02-17 14:23:49 +01:00
Tomasi - Developing
b04ad8c9b3 fix 2026-02-17 14:19:23 +01:00
Tomasi - Developing
27ea4cf182 zone.js 2026-02-17 13:59:16 +01:00
Tomasi - Developing
f32c41f900 sweetalert2 2026-02-17 13:56:44 +01:00
Tomasi - Developing
2566e02897 ngx-toastr 2026-02-17 13:54:25 +01:00
Tomasi - Developing
e91daa881d ngx-spinner 2026-02-17 13:49:59 +01:00
Tomasi - Developing
ffa1cc6189 ngx-mask 2026-02-17 13:47:10 +01:00
Tomasi - Developing
1af95c1905 ngx-countup 2026-02-17 13:44:16 +01:00
Tomasi - Developing
9b4d22e8be karma-jasmine-html-reporter 2026-02-17 13:41:41 +01:00
Tomasi - Developing
5788bd7c23 jasmine-core 2026-02-17 13:39:11 +01:00
Tomasi - Developing
15be92ea1a bootswatch 2026-02-17 13:36:16 +01:00
Tomasi - Developing
c57900d9c1 bootstrap-icons 2026-02-17 13:33:40 +01:00
Tomasi - Developing
d2021acca7 bootstrap 2026-02-17 13:30:24 +01:00
Tomasi - Developing
4d5f994a96 ag-charts-angular 2026-02-17 13:27:56 +01:00
Tomasi - Developing
76caaea9c5 @types/jasmine 2026-02-17 13:25:27 +01:00
Tomasi - Developing
b1b179775a @sweetalert2/theme-dark 2026-02-17 13:22:31 +01:00
Tomasi - Developing
9f1d1fc071 @ng-bootstrap/ng-bootstrap 2026-02-17 13:19:03 +01:00
Tomasi - Developing
3c91001dd2 ng update @angular/core@21 @angular/cli@21 2026-02-17 13:16:29 +01:00
Tomasi - Developing
ef4c9d643a ng update @angular/core@20 @angular/cli@20 2026-02-17 13:07:59 +01:00
Tomasi - Developing
4d47336e2b ng update @angular/core@19 @angular/cli@19 2026-02-17 13:02:28 +01:00
Tomasi - Developing
3f7aea2e67 .net 10 and fix 2026-02-17 12:56:33 +01:00
77 changed files with 6170 additions and 9304 deletions

View File

@ -1,17 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -1,6 +1,6 @@
using Api.Helpers;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace Api.Configurations;
@ -30,34 +30,19 @@ public static class SwaggerExtension
});
// Configures Bearer token authentication for Swagger
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
{
Description = @"JWT Authorization header using the Bearer scheme.
Enter 'Bearer' [space] and then your token in the text input below.
Example: 'Bearer 12345abcdef'",
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme
});
// Adds security requirements for Bearer token authentication
options.AddSecurityRequirement(new OpenApiSecurityRequirement
options.AddSecurityRequirement(document => new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = JwtBearerDefaults.AuthenticationScheme
},
Scheme = "Oauth2",
Name = JwtBearerDefaults.AuthenticationScheme,
In = ParameterLocation.Header
},
new List<string>()
}
[new OpenApiSecuritySchemeReference(JwtBearerDefaults.AuthenticationScheme, document)] = []
});
});
}

View File

@ -1,4 +1,4 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace Api.Helpers;

View File

@ -3,6 +3,7 @@ using Api.Middleware;
using Application;
using Database;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Serilog;
using Utilities.Classes;
@ -24,7 +25,6 @@ try
.WriteTo.File(logPath, rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true);
});
builder.Services.AddDatabase(builder.Configuration);
builder.Services.AddApplication();
@ -54,6 +54,8 @@ try
app.UseStaticFiles();
app.UseDefaultFiles();
app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

View File

@ -1,11 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="DataTransferObjects\Alliance\" />
<Folder Include="Classes\" />

View File

@ -1,6 +1,6 @@
using System.Reflection;
using Application.Helpers;
using Application.Helpers;
using Application.Interfaces;
using Application.Profiles;
using Application.Repositories;
using Application.Services;
using Microsoft.Extensions.DependencyInjection;
@ -13,7 +13,7 @@ public static class ApplicationDependencyInjection
{
public static IServiceCollection AddApplication(this IServiceCollection services)
{
services.AddAutoMapper(Assembly.GetExecutingAssembly());
services.AddAutoMapper(_ => {}, typeof(AllianceProfile));
services.AddScoped<IAllianceRepository, AllianceRepository>();
services.AddScoped<IAdmonitionRepository, AdmonitionRepository>();

View File

@ -1,11 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.DataProtection" />
<PackageReference Include="Microsoft.AspNetCore.Identity" />

View File

@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

View File

@ -3,37 +3,33 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="MailKit" Version="4.11.0" />
<PackageVersion Include="MailKit" Version="4.15.0" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.3" />
<PackageVersion Include="Octokit" Version="14.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.1" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4" />
<PackageVersion Include="AutoMapper" Version="14.0.0" />
<PackageVersion Include="ExcelDataReader" Version="3.7.0" />
<PackageVersion Include="ExcelDataReader.DataSet" Version="3.7.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="8.1.1" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="10.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.9" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.3" />
<PackageVersion Include="AutoMapper" Version="16.0.0" />
<PackageVersion Include="ExcelDataReader" Version="3.8.0" />
<PackageVersion Include="ExcelDataReader.DataSet" Version="3.8.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.3" />
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="10.1.3" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.1" />
<PackageVersion Include="AspNetCore.HealthChecks.SqlServer" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageVersion Include="Azure.Identity" Version="1.13.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Serilog" Version="4.2.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="Azure.Identity" Version="1.17.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.3" />
<PackageVersion Include="Serilog" Version="4.3.1" />
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageVersion Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.3" />
</ItemGroup>
</Project>

View File

@ -25,6 +25,16 @@ All beta versions (0.x.x) can be found here →
---
### **[1.2.0]** *2026-02-17* 🚀
#### 🛠 Changed
- **Platform Upgrade**
The application has been upgraded to the latest platform versions:
- Backend: **.NET 10**
- Frontend: **Angular 21**
These upgrades improve performance, security, and future compatibility with upcoming features.
### **[1.1.0]** *2026-02-09* 🚀
#### ✨ Added
- **Desert Storm Player Sorting in Info Dialog**

View File

@ -21,7 +21,7 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"builder": "@angular/build:application",
"options": {
"outputPath": "dist/ui",
"index": "src/index.html",
@ -75,7 +75,7 @@
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "Ui:build:production"
@ -87,13 +87,13 @@
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"builder": "@angular/build:extract-i18n",
"options": {
"buildTarget": "Ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"builder": "@angular/build:karma",
"options": {
"polyfills": [
"zone.js",
@ -114,5 +114,31 @@
}
}
}
},
"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

@ -1,4 +1,4 @@
module.exports = function (config) {
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
@ -7,7 +7,7 @@
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {

13927
Ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "ui",
"version": "0.0.0",
"version": "1.2.0",
"scripts": {
"ng": "ng",
"start": "ng serve --host=127.0.0.1",
@ -10,46 +10,46 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^18.2.7",
"@angular/common": "^18.2.7",
"@angular/compiler": "^18.2.7",
"@angular/core": "^18.2.7",
"@angular/forms": "^18.2.7",
"@angular/platform-browser": "^18.2.7",
"@angular/platform-browser-dynamic": "^18.2.7",
"@angular/router": "^18.2.7",
"@angular/animations": "^21.1.4",
"@angular/common": "^21.1.4",
"@angular/compiler": "^21.1.4",
"@angular/core": "^21.1.4",
"@angular/forms": "^21.1.4",
"@angular/platform-browser": "^21.1.4",
"@angular/platform-browser-dynamic": "^21.1.4",
"@angular/router": "^21.1.4",
"@auth0/angular-jwt": "^5.2.0",
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
"@ng-bootstrap/ng-bootstrap": "^20.0.0",
"@popperjs/core": "^2.11.8",
"@sweetalert2/theme-dark": "^5.0.18",
"ag-charts-angular": "^11.0.4",
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.3",
"bootswatch": "^5.3.3",
"@sweetalert2/theme-dark": "^5.0.27",
"ag-charts-angular": "^13.1.0",
"bootstrap": "^5.3.8",
"bootstrap-icons": "^1.13.1",
"bootswatch": "^5.3.8",
"jest-editor-support": "*",
"moment": "^2.30.1",
"ngx-countup": "^13.2.0",
"ngx-mask": "^19.0.6",
"ngx-countup": "^21.0.0",
"ngx-mask": "^21.0.1",
"ngx-pagination": "^6.0.3",
"ngx-spinner": "^17.0.0",
"ngx-toastr": "^19.0.0",
"ngx-spinner": "^21.0.0",
"ngx-toastr": "^20.0.5",
"rxjs": "~7.8.0",
"sweetalert2": "^11.22.4",
"sweetalert2": "^11.26.18",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
"zone.js": "~0.16.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.2.8",
"@angular/cli": "^18.2.8",
"@angular/compiler-cli": "^18.2.7",
"@angular/localize": "^18.2.7",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.3.0",
"@angular/build": "^21.1.4",
"@angular/cli": "^21.1.4",
"@angular/compiler-cli": "^21.1.4",
"@angular/localize": "^21.1.4",
"@types/jasmine": "~6.0.0",
"jasmine-core": "~6.0.1",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.5.4"
"karma-jasmine-html-reporter": "~2.2.0",
"typescript": "~5.9.3"
}
}

View File

@ -9,7 +9,8 @@ import {environment} from "../../../environments/environment";
@Component({
selector: 'app-email-confirmation',
templateUrl: './email-confirmation.component.html',
styleUrl: './email-confirmation.component.css'
styleUrl: './email-confirmation.component.css',
standalone: false
})
export class EmailConfirmationComponent implements OnInit {

View File

@ -9,7 +9,8 @@ import {environment} from "../../../environments/environment";
@Component({
selector: 'app-forgot-password',
templateUrl: './forgot-password.component.html',
styleUrl: './forgot-password.component.css'
styleUrl: './forgot-password.component.css',
standalone: false
})
export class ForgotPasswordComponent {

View File

@ -80,13 +80,15 @@
</div>
</form>
</div>
<div class="alliance-counter" *ngIf="allianceCount !== null">
@if (allianceCount !== null) {
<div class="alliance-counter">
<span>Currently </span>
<span class="count">
<span [countUp]="allianceCount"></span>
</span>
<span> alliances use the tool</span>
</div>
}
</div>
<footer class="footer d-flex flex-wrap justify-content-center justify-content-md-between align-items-center px-3 py-3 mt-auto shadow-sm gap-2 small text-center">

View File

@ -12,7 +12,8 @@ import {StatService} from "../../services/stat.service";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrl: './login.component.css'
styleUrl: './login.component.css',
standalone: false
})
export class LoginComponent implements OnInit {

View File

@ -91,10 +91,14 @@
class="input-group-text eye-icon bi"></i>
</span>
<!-- Password Invalid Feedback -->
<div *ngIf="f['password'].invalid && (f['password'].dirty || !f['password'].untouched )"
@if (f['password'].invalid && (f['password'].dirty || !f['password'].untouched )) {
<div
class="invalid-feedback">
<p *ngIf="f['password'].hasError('required')">Password is required</p>
<div *ngIf="!f['password'].hasError('required')">
@if (f['password'].hasError('required')) {
<p>Password is required</p>
}
@if (!f['password'].hasError('required')) {
<div>
<div [ngClass]="f['password'].hasError('hasNumber') ? 'text-danger': 'text-success'">
<i
[ngClass]="f['password'].hasError('hasNumber') ? 'bi bi-x-square-fill' : 'bi bi-check-square-fill'"></i>
@ -121,7 +125,9 @@
Must contain special characters
</div>
</div>
}
</div>
}
</div>
<div class="form-floating is-invalid mb-3">
@ -134,12 +140,18 @@
<label for="confirmPassword">Confirm Password</label>
</div>
<!-- Confirm Password Invalid Feedback -->
<div *ngIf="f['confirmPassword'].invalid && (f['confirmPassword'].dirty || !f['confirmPassword'].untouched )"
@if (f['confirmPassword'].invalid && (f['confirmPassword'].dirty || !f['confirmPassword'].untouched )) {
<div
class="invalid-feedback">
<p *ngIf="f['confirmPassword'].hasError('required')">Confirmation is required</p>
@if (f['confirmPassword'].hasError('required')) {
<p>Confirmation is required</p>
}
@if (f['confirmPassword'].hasError('passwordMismatch')) {
<p
*ngIf="f['confirmPassword'].hasError('passwordMismatch')">Passwords do not match</p>
>Passwords do not match</p>
}
</div>
}
<div class="d-grid gap-2 col-6 mx-auto">
<button [disabled]="registerForm.invalid" type="submit" class="btn btn-success">Register</button>

View File

@ -10,7 +10,8 @@ import {environment} from "../../../environments/environment";
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrl: './register.component.css'
styleUrl: './register.component.css',
standalone: false
})
export class RegisterComponent implements OnInit {

View File

@ -51,9 +51,13 @@
<span (click)="isInputText = !isInputText" class="input-group-text eye-icon">
<i [ngClass]="isInputText ? 'bi-eye-slash-fill' : 'bi-eye-fill'" class="bi"></i>
</span>
<div *ngIf="password?.hasError && (password?.dirty || !password?.untouched)" class="invalid-feedback">
<p *ngIf="password?.hasError('required')">Password is required</p>
<div *ngIf="!password?.hasError('required')">
@if (password?.hasError && (password?.dirty || !password?.untouched)) {
<div class="invalid-feedback">
@if (password?.hasError('required')) {
<p>Password is required</p>
}
@if (!password?.hasError('required')) {
<div>
<div [ngClass]="password?.hasError('hasNumber') ? 'text-danger': 'text-success'">
<i [ngClass]="password?.hasError('hasNumber') ? 'bi bi-x-square-fill' : 'bi bi-check-square-fill'"></i>
Must have at least 1 number!
@ -76,7 +80,9 @@
Must contain at least 1 special character!
</div>
</div>
}
</div>
}
</div>
</div>
@ -89,10 +95,16 @@
<span (click)="isInputText = !isInputText" class="input-group-text eye-icon">
<i [ngClass]="isInputText ? 'bi-eye-slash-fill' : 'bi-eye-fill'" class="bi"></i>
</span>
<div *ngIf="confirmPassword?.errors && (confirmPassword?.dirty || !confirmPassword?.untouched)" class="invalid-feedback">
<p *ngIf="confirmPassword?.hasError('required')">Repeat password is required</p>
<p *ngIf="confirmPassword?.hasError('passwordMismatch')">Passwords do not match</p>
@if (confirmPassword?.errors && (confirmPassword?.dirty || !confirmPassword?.untouched)) {
<div class="invalid-feedback">
@if (confirmPassword?.hasError('required')) {
<p>Repeat password is required</p>
}
@if (confirmPassword?.hasError('passwordMismatch')) {
<p>Passwords do not match</p>
}
</div>
}
</div>
</div>

View File

@ -9,7 +9,8 @@ import {ResetPasswordModel} from "../../models/resetPassword.model";
@Component({
selector: 'app-reset-password',
templateUrl: './reset-password.component.html',
styleUrl: './reset-password.component.css'
styleUrl: './reset-password.component.css',
standalone: false
})
export class ResetPasswordComponent implements OnInit {

View File

@ -98,10 +98,14 @@
class="input-group-text eye-icon bi"></i>
</span>
<!-- Password Invalid Feedback -->
<div *ngIf="f['password'].invalid && (f['password'].dirty || !f['password'].untouched )"
@if (f['password'].invalid && (f['password'].dirty || !f['password'].untouched )) {
<div
class="invalid-feedback">
<p *ngIf="f['password'].hasError('required')">Required</p>
<div *ngIf="!f['password'].hasError('required')">
@if (f['password'].hasError('required')) {
<p>Required</p>
}
@if (!f['password'].hasError('required')) {
<div>
<div [ngClass]="f['password'].hasError('hasNumber') ? 'text-danger': 'text-success'">
<i
[ngClass]="f['password'].hasError('hasNumber') ? 'bi bi-x-square-fill' : 'bi bi-check-square-fill'"></i>
@ -128,7 +132,9 @@
special
</div>
</div>
}
</div>
}
</div>
<div class="form-floating is-invalid mb-3">
@ -141,12 +147,18 @@
<label for="confirmPassword">Confirm Password</label>
</div>
<!-- Confirm Password Invalid Feedback -->
<div *ngIf="f['confirmPassword'].invalid && (f['confirmPassword'].dirty || !f['confirmPassword'].untouched )"
@if (f['confirmPassword'].invalid && (f['confirmPassword'].dirty || !f['confirmPassword'].untouched )) {
<div
class="invalid-feedback">
<p *ngIf="f['confirmPassword'].hasError('required')">Confirmation password is required</p>
@if (f['confirmPassword'].hasError('required')) {
<p>Confirmation password is required</p>
}
@if (f['confirmPassword'].hasError('passwordMismatch')) {
<p
*ngIf="f['confirmPassword'].hasError('passwordMismatch')">Passwords do not match</p>
>Passwords do not match</p>
}
</div>
}
<div class="d-flex justify-content-between">
<button type="button" (click)="onCancel()" class="btn btn-warning">Cancel</button>

View File

@ -10,7 +10,8 @@ import {environment} from "../../../environments/environment";
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrl: './sign-up.component.css'
styleUrl: './sign-up.component.css',
standalone: false
})
export class SignUpComponent {

View File

@ -4,7 +4,8 @@ import {AuthenticationService} from "./services/authentication.service";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.css'
styleUrl: './app.component.css',
standalone: false
})
export class AppComponent implements OnInit {
title = 'Last War - Player Management';

View File

@ -65,9 +65,10 @@ import { CustomEventCategoryComponent } from './pages/custom-event/custom-event-
import { CustomEventLeaderboardComponent } from './pages/custom-event/custom-event-leaderboard/custom-event-leaderboard.component';
import { CustomEventEventsComponent } from './pages/custom-event/custom-event-events/custom-event-events.component';
import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
import {CountUpModule} from "ngx-countup";
import { PlayerSquadsComponent } from './pages/player-squads/player-squads.component';
import { SquadEditModalComponent } from './modals/squad-edit-modal/squad-edit-modal.component';
import {CommonModule} from "@angular/common";
import {CountUpDirective} from "ngx-countup";
@NgModule({
declarations: [
@ -126,6 +127,7 @@ import { SquadEditModalComponent } from './modals/squad-edit-modal/squad-edit-mo
SquadEditModalComponent
],
imports: [
CommonModule,
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
@ -146,7 +148,7 @@ import { SquadEditModalComponent } from './modals/squad-edit-modal/squad-edit-mo
AgCharts,
NgxMaskDirective,
NgxMaskPipe,
CountUpModule
CountUpDirective
],
providers: [
provideNgxMask(),

View File

@ -3,7 +3,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-under-development',
templateUrl: './under-development.component.html',
styleUrl: './under-development.component.css'
styleUrl: './under-development.component.css',
standalone: false
})
export class UnderDevelopmentComponent {

View File

@ -2,7 +2,8 @@ import {Pipe, PipeTransform} from '@angular/core';
import moment from "moment";
@Pipe({
name: 'week'
name: 'week',
standalone: false
})
export class WeekPipe implements PipeTransform {

View File

@ -7,7 +7,8 @@ import {FormArray, FormControl, FormGroup, Validators} from "@angular/forms";
@Component({
selector: 'app-custom-event-participants-model',
templateUrl: './custom-event-participants-model.component.html',
styleUrl: './custom-event-participants-model.component.css'
styleUrl: './custom-event-participants-model.component.css',
standalone: false
})
export class CustomEventParticipantsModelComponent implements OnInit {

View File

@ -6,7 +6,8 @@ import {PlayerModel} from "../../models/player.model";
@Component({
selector: 'app-desert-storm-participants-modal',
templateUrl: './desert-storm-participants-modal.component.html',
styleUrl: './desert-storm-participants-modal.component.css'
styleUrl: './desert-storm-participants-modal.component.css',
standalone: false
})
export class DesertStormParticipantsModalComponent implements OnInit {

View File

@ -10,7 +10,8 @@ import {environment} from "../../../environments/environment";
@Component({
selector: 'app-invite-user-modal',
templateUrl: './invite-user-modal.component.html',
styleUrl: './invite-user-modal.component.css'
styleUrl: './invite-user-modal.component.css',
standalone: false
})
export class InviteUserModalComponent implements OnInit {

View File

@ -6,7 +6,8 @@ import {PlayerModel} from "../../models/player.model";
@Component({
selector: 'app-marshal-guard-modal',
templateUrl: './marshal-guard-modal.component.html',
styleUrl: './marshal-guard-modal.component.css'
styleUrl: './marshal-guard-modal.component.css',
standalone: false
})
export class MarshalGuardModalComponent implements OnInit {

View File

@ -10,7 +10,8 @@ import Swal from "sweetalert2";
@Component({
selector: 'app-player-admonition-modal',
templateUrl: './player-admonition-modal.component.html',
styleUrl: './player-admonition-modal.component.css'
styleUrl: './player-admonition-modal.component.css',
standalone: false
})
export class PlayerAdmonitionModalComponent implements OnInit {

View File

@ -7,7 +7,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-player-dismiss-information-modal',
templateUrl: './player-dismiss-information-modal.component.html',
styleUrl: './player-dismiss-information-modal.component.css'
styleUrl: './player-dismiss-information-modal.component.css',
standalone: false
})
export class PlayerDismissInformationModalComponent implements OnInit {

View File

@ -10,7 +10,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-player-edit-modal',
templateUrl: './player-edit-modal.component.html',
styleUrl: './player-edit-modal.component.css'
styleUrl: './player-edit-modal.component.css',
standalone: false
})
export class PlayerEditModalComponent implements OnInit {

View File

@ -8,7 +8,8 @@ import {PlayerService} from "../../services/player.service";
@Component({
selector: 'app-player-excel-import-modal',
templateUrl: './player-excel-import-modal.component.html',
styleUrl: './player-excel-import-modal.component.css'
styleUrl: './player-excel-import-modal.component.css',
standalone: false
})
export class PlayerExcelImportModalComponent {

View File

@ -10,7 +10,8 @@ import Swal from "sweetalert2";
@Component({
selector: 'app-player-note-modal',
templateUrl: './player-note-modal.component.html',
styleUrl: './player-note-modal.component.css'
styleUrl: './player-note-modal.component.css',
standalone: false
})
export class PlayerNoteModalComponent implements OnInit {

View File

@ -10,7 +10,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-squad-edit-modal',
templateUrl: './squad-edit-modal.component.html',
styleUrl: './squad-edit-modal.component.css'
styleUrl: './squad-edit-modal.component.css',
standalone: false
})
export class SquadEditModalComponent implements OnInit {

View File

@ -8,7 +8,8 @@ import {FormControl, FormGroup, Validators} from "@angular/forms";
@Component({
selector: 'app-user-edit-modal',
templateUrl: './user-edit-modal.component.html',
styleUrl: './user-edit-modal.component.css'
styleUrl: './user-edit-modal.component.css',
standalone: false
})
export class UserEditModalComponent implements OnInit {

View File

@ -10,7 +10,8 @@ import {VsDuelLeagueModel} from "../../models/vsDuelLeague.model";
@Component({
selector: 'app-vs-duel-edit-modal',
templateUrl: './vs-duel-create-modal.component.html',
styleUrl: './vs-duel-create-modal.component.css'
styleUrl: './vs-duel-create-modal.component.css',
standalone: false
})
export class VsDuelCreateModalComponent implements OnInit {

View File

@ -6,7 +6,8 @@ import {PlayerModel} from "../../models/player.model";
@Component({
selector: 'app-zombie-siege-participants-modal',
templateUrl: './zombie-siege-participants-modal.component.html',
styleUrl: './zombie-siege-participants-modal.component.css'
styleUrl: './zombie-siege-participants-modal.component.css',
standalone: false
})
export class ZombieSiegeParticipantsModalComponent implements OnInit {

View File

@ -78,7 +78,8 @@
</ul>
<!-- User menu (visible only when user is logged in) -->
<div *ngIf="loggedInUser" class="login">
@if (loggedInUser) {
<div class="login">
<ul class="navbar-nav me-auto">
<li ngbDropdown display="dynamic" class="nav-item" role="presentation">
<button type="button" class="nav-link" ngbDropdownToggle>
@ -95,13 +96,16 @@
</li>
</ul>
</div>
}
<!-- Login button (visible only when user is not logged in) -->
<div *ngIf="!loggedInUser" class="d-flex login" routerLink="/login">
@if (!loggedInUser) {
<div class="d-flex login" routerLink="/login">
<button (click)="isShown = false" class="btn btn-secondary" routerLink="/login"><i
class="bi bi-box-arrow-right"></i> Login
</button>
</div>
}
</div>
</div>
</nav>

View File

@ -7,7 +7,8 @@ import {environment} from "../../environments/environment";
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrl: './navigation.component.css'
styleUrl: './navigation.component.css',
standalone: false
})
export class NavigationComponent implements OnInit, OnDestroy {

View File

@ -11,7 +11,8 @@ import {AuthenticationService} from "../../services/authentication.service";
@Component({
selector: 'app-account',
templateUrl: './account.component.html',
styleUrl: './account.component.css'
styleUrl: './account.component.css',
standalone: false
})
export class AccountComponent implements OnInit{

View File

@ -16,7 +16,7 @@
}
.api-key-input-group {
max-width: 420px; // Begrenzung der Breite des Input-Feldes
max-width: 420px;
}
.api-key-input {

View File

@ -7,7 +7,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-alliance-api-key',
templateUrl: './alliance-api-key.component.html',
styleUrl: './alliance-api-key.component.css'
styleUrl: './alliance-api-key.component.css',
standalone: false
})
export class AllianceApiKeyComponent implements OnInit {

View File

@ -11,7 +11,8 @@ import {JwtTokenService} from "../../../services/jwt-token.service";
@Component({
selector: 'app-alliance-user-administration',
templateUrl: './alliance-user-administration.component.html',
styleUrl: './alliance-user-administration.component.css'
styleUrl: './alliance-user-administration.component.css',
standalone: false
})
export class AllianceUserAdministrationComponent implements OnInit {

View File

@ -9,7 +9,8 @@ import {JwtTokenService} from "../../services/jwt-token.service";
@Component({
selector: 'app-alliance',
templateUrl: './alliance.component.html',
styleUrl: './alliance.component.css'
styleUrl: './alliance.component.css',
standalone: false
})
export class AllianceComponent implements OnInit {

View File

@ -11,7 +11,8 @@ import {JwtTokenService} from "../../services/jwt-token.service";
@Component({
selector: 'app-change-password',
templateUrl: './change-password.component.html',
styleUrl: './change-password.component.css'
styleUrl: './change-password.component.css',
standalone: false
})
export class ChangePasswordComponent {

View File

@ -13,7 +13,8 @@ import Swal from "sweetalert2";
@Component({
selector: 'app-custom-event-category',
templateUrl: './custom-event-category.component.html',
styleUrl: './custom-event-category.component.css'
styleUrl: './custom-event-category.component.css',
standalone: false
})
export class CustomEventCategoryComponent implements OnInit {
isCreateCustomEventCategory: any;

View File

@ -6,7 +6,8 @@ import {CustomEventDetailModel} from "../../../models/customEvent.model";
@Component({
selector: 'app-custom-event-detail',
templateUrl: './custom-event-detail.component.html',
styleUrl: './custom-event-detail.component.css'
styleUrl: './custom-event-detail.component.css',
standalone: false
})
export class CustomEventDetailComponent implements OnInit {

View File

@ -19,7 +19,8 @@ import {forkJoin, Observable} from "rxjs";
@Component({
selector: 'app-custom-event-events',
templateUrl: './custom-event-events.component.html',
styleUrl: './custom-event-events.component.css'
styleUrl: './custom-event-events.component.css',
standalone: false
})
export class CustomEventEventsComponent implements OnInit {

View File

@ -12,7 +12,8 @@ import {
@Component({
selector: 'app-custom-event-leaderboard',
templateUrl: './custom-event-leaderboard.component.html',
styleUrl: './custom-event-leaderboard.component.css'
styleUrl: './custom-event-leaderboard.component.css',
standalone: false
})
export class CustomEventLeaderboardComponent implements OnInit {

View File

@ -4,7 +4,8 @@ import {Component} from '@angular/core';
@Component({
selector: 'app-custom-event',
templateUrl: './custom-event.component.html',
styleUrl: './custom-event.component.css'
styleUrl: './custom-event.component.css',
standalone: false
})
export class CustomEventComponent {

View File

@ -6,7 +6,8 @@ import {DesertStormDetailModel} from "../../../models/desertStorm.model";
@Component({
selector: 'app-desert-storm-detail',
templateUrl: './desert-storm-detail.component.html',
styleUrl: './desert-storm-detail.component.css'
styleUrl: './desert-storm-detail.component.css',
standalone: false
})
export class DesertStormDetailComponent implements OnInit {

View File

@ -21,7 +21,8 @@ import {forkJoin, Observable} from "rxjs";
@Component({
selector: 'app-desert-storm',
templateUrl: './desert-storm.component.html',
styleUrl: './desert-storm.component.css'
styleUrl: './desert-storm.component.css',
standalone: false
})
export class DesertStormComponent implements OnInit {

View File

@ -13,7 +13,8 @@ import {
@Component({
selector: 'app-dismiss-player',
templateUrl: './dismiss-player.component.html',
styleUrl: './dismiss-player.component.css'
styleUrl: './dismiss-player.component.css',
standalone: false
})
export class DismissPlayerComponent implements OnInit {

View File

@ -8,7 +8,8 @@ import {Router} from "@angular/router";
@Component({
selector: 'app-feedback',
templateUrl: './feedback.component.html',
styleUrl: './feedback.component.css'
styleUrl: './feedback.component.css',
standalone: false
})
export class FeedbackComponent implements OnInit {

View File

@ -3,7 +3,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-imprint',
templateUrl: './imprint.component.html',
styleUrl: './imprint.component.css'
styleUrl: './imprint.component.css',
standalone: false
})
export class ImprintComponent {

View File

@ -6,7 +6,8 @@ import {MarshalGuardDetailModel} from "../../../models/marshalGuard.model";
@Component({
selector: 'app-marshal-guard-detail',
templateUrl: './marshal-guard-detail.component.html',
styleUrl: './marshal-guard-detail.component.css'
styleUrl: './marshal-guard-detail.component.css',
standalone: false
})
export class MarshalGuardDetailComponent implements OnInit {

View File

@ -24,7 +24,8 @@ import {forkJoin, Observable} from "rxjs";
@Component({
selector: 'app-marshal-guard',
templateUrl: './marshal-guard.component.html',
styleUrl: './marshal-guard.component.css'
styleUrl: './marshal-guard.component.css',
standalone: false
})
export class MarshalGuardComponent implements OnInit {

View File

@ -8,7 +8,8 @@ import {PlayerMvpModel} from "../../models/player.model";
@Component({
selector: 'app-mvp',
templateUrl: './mvp.component.html',
styleUrl: './mvp.component.css'
styleUrl: './mvp.component.css',
standalone: false
})
export class MvpComponent implements OnInit {

View File

@ -3,7 +3,8 @@ import {Component} from '@angular/core';
@Component({
selector: 'app-player-info-custom-event',
templateUrl: './player-info-custom-event.component.html',
styleUrl: './player-info-custom-event.component.css'
styleUrl: './player-info-custom-event.component.css',
standalone: false
})
export class PlayerInfoCustomEventComponent {

View File

@ -3,7 +3,8 @@ import {Component} from '@angular/core';
@Component({
selector: 'app-player-info-desert-storm',
templateUrl: './player-info-desert-storm.component.html',
styleUrl: './player-info-desert-storm.component.css'
styleUrl: './player-info-desert-storm.component.css',
standalone: false
})
export class PlayerInfoDesertStormComponent {

View File

@ -6,7 +6,8 @@ import {MarshalGuardParticipantModel} from "../../../models/marshalGuardParticip
@Component({
selector: 'app-player-info-marshal-guard',
templateUrl: './player-info-marshal-guard.component.html',
styleUrl: './player-info-marshal-guard.component.css'
styleUrl: './player-info-marshal-guard.component.css',
standalone: false
})
export class PlayerInfoMarshalGuardComponent {

View File

@ -9,7 +9,8 @@ import {ToastrService} from "ngx-toastr";
selector: 'app-player-info-vs-duel',
templateUrl: './player-info-vs-duel.component.html',
styleUrl: './player-info-vs-duel.component.css',
providers: [DatePipe]
providers: [DatePipe],
standalone: false
})
export class PlayerInfoVsDuelComponent {
@ -24,9 +25,7 @@ export class PlayerInfoVsDuelComponent {
options: AgChartOptions = {
title: {
text: 'Weekly Points'
},
title: { text: 'Weekly Points' },
data: [],
series: [
{
@ -39,22 +38,21 @@ export class PlayerInfoVsDuelComponent {
fill: 'blue'
}
],
axes: [
{
axes: {
y: {
type: 'number',
position: 'left',
label: {
formatter: (params: any) => {
return params.value.toLocaleString('en-US')
}
}
formatter: (params: any) => params.value.toLocaleString('en-US'),
},
{
},
x: {
type: 'category',
position: 'bottom',
}
]
}
},
},
};
getData(take: number) {
const chartData: {date: string, points: number}[] = [];

View File

@ -10,7 +10,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-player-information',
templateUrl: './player-information.component.html',
styleUrl: './player-information.component.css'
styleUrl: './player-information.component.css',
standalone: false
})
export class PlayerInformationComponent implements OnInit {

View File

@ -9,7 +9,8 @@ import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-player-squads',
templateUrl: './player-squads.component.html',
styleUrl: './player-squads.component.css'
styleUrl: './player-squads.component.css',
standalone: false
})
export class PlayerSquadsComponent implements OnInit {

View File

@ -20,7 +20,8 @@ import {
@Component({
selector: 'app-player',
templateUrl: './player.component.html',
styleUrl: './player.component.css'
styleUrl: './player.component.css',
standalone: false
})
export class PlayerComponent implements OnInit {

View File

@ -7,7 +7,8 @@ import {VsDuelDetailModel} from "../../../models/vsDuel.model";
@Component({
selector: 'app-vs-duel-detail',
templateUrl: './vs-duel-detail.component.html',
styleUrl: './vs-duel-detail.component.css'
styleUrl: './vs-duel-detail.component.css',
standalone: false
})
export class VsDuelDetailComponent implements OnInit {

View File

@ -13,7 +13,8 @@ import {VsDuelLeagueModel} from "../../../models/vsDuelLeague.model";
@Component({
selector: 'app-vs-duel-edit',
templateUrl: './vs-duel-edit.component.html',
styleUrl: './vs-duel-edit.component.css'
styleUrl: './vs-duel-edit.component.css',
standalone: false
})
export class VsDuelEditComponent implements OnInit {

View File

@ -12,7 +12,8 @@ import {Router} from "@angular/router";
selector: 'app-vs-duel',
templateUrl: './vs-duel.component.html',
styleUrl: './vs-duel.component.css',
providers: [WeekPipe]
providers: [WeekPipe],
standalone: false
})
export class VsDuelComponent implements OnInit {

View File

@ -6,7 +6,8 @@ import {ZombieSiegeService} from "../../../services/zombie-siege.service";
@Component({
selector: 'app-zombie-siege-detail',
templateUrl: './zombie-siege-detail.component.html',
styleUrl: './zombie-siege-detail.component.css'
styleUrl: './zombie-siege-detail.component.css',
standalone: false
})
export class ZombieSiegeDetailComponent implements OnInit {

View File

@ -24,6 +24,7 @@ import {PagedResponseModel} from "../../models/pagedResponse.model";
selector: 'app-zombie-siege',
templateUrl: './zombie-siege.component.html',
styleUrl: './zombie-siege.component.css',
standalone: false
})
export class ZombieSiegeComponent implements OnInit {

View File

@ -1,9 +1,14 @@
/// <reference types="@angular/localize" />
import { provideZoneChangeDetection } from "@angular/core";
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
import { ModuleRegistry, AllCommunityModule } from 'ag-charts-community';
ModuleRegistry.registerModules([AllCommunityModule]);
platformBrowserDynamic()
.bootstrapModule(AppModule, {
applicationProviders: [provideZoneChangeDetection()],
})
.catch(err => console.error(err));

View File

@ -14,15 +14,11 @@
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
]
"useDefineForClassFields": false
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,

View File

@ -1,20 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Constants\" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="MailKit" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="Octokit" />
</ItemGroup>