CHORE: setup
Some checks failed
Quality Check / Linting (push) Successful in 25s
Build Application / build (push) Failing after 31s
Build Application / build-docker (push) Has been skipped
Build Application / release (push) Has been skipped

This commit is contained in:
Snoweuph 2025-02-02 15:48:46 +01:00
commit 34e60696b0
Signed by: snoweuph
GPG key ID: BEFC41DA223CEC55
31 changed files with 16999 additions and 0 deletions

View file

@ -0,0 +1,29 @@
name: Feature
title: '[Feature]: '
about: 'Vorlage Für ein Feature Ticket'
ref: 'trunk'
body:
- type: input
id: ticket
attributes:
label: Ticket
description: Für Welches Ticket ist diese Pull Request?
placeholder: TD-1
validations:
required: true
- type: textarea
id: beschreibung
attributes:
label: Beschreibung
description: Was hast du genau gemacht in diesem Ticket?
placeholder: ...
validations:
required: true
- type: textarea
id: more
attributes:
label: Weitere Infos
description: Gibt es noch etwas das ich wissen muss um das Ticket zu Reviewn?
placeholder: ...
validations:
required: false

View file

@ -0,0 +1,3 @@
FROM httpd:2.4
ADD web /usr/local/apache2/htdocs/

View file

@ -0,0 +1,80 @@
name: Build Application
on:
push:
tags:
- 'v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?'
- 'v*'
jobs:
build:
runs-on: stable
container:
image: git.euph.dev/actions/runner-basic:latest
steps:
- name: "Checkout"
uses: "https://git.euph.dev/actions/checkout@v3"
- name: "Install Angular CLI"
run: sudo npm i -g @angular/cli
- name: "Install Dependencies"
run: npm ci
- name: Build Bundle
run: ng build
- name: Upload Binary as Artifact
uses: "https://git.euph.dev/actions/upload-artifact@v3"
with:
name: web
path: dist/tower-defence-administration/browser/*
build-docker:
runs-on: docker
needs:
- build
steps:
- name: "Checkout"
uses: "https://git.euph.dev/actions/checkout@v3"
- name: Download artifact from previous job
uses: "https://git.euph.dev/actions/download-artifact@v3"
with:
name: web
path: .forgejo/workflows/web
- name: Login to Registry
uses: "https://git.euph.dev/actions/docker-login@v3"
with:
registry: git.euph.dev
username: ${{ secrets.DEPLOY_USER }}
password: ${{ secrets.DEPLOY_SECRET }}
- name: Build and push Web Image
uses: "https://git.euph.dev/actions/docker-build-push@v5"
with:
context: ".forgejo/workflows/"
push: true
tags: |
git.euph.dev/towerdefence/web-administration:${{ github.ref_name }}
${{ contains(github.ref_name, 'rc') == false && 'git.euph.dev/towerdefence/web-administration:latest' || '' }}
release:
runs-on: stable
container:
image: git.euph.dev/actions/runner-basic:latest
needs:
- build
- build-docker
steps:
- name: Create Release
uses: "https://git.euph.dev/actions/release@v2"
with:
tag: ${{ github.ref_name }}
token: ${{ secrets.DEPLOY_TOKEN }}
prerelease: ${{ contains( github.ref_name, "rc") }}
release-notes: |
# Tower Defence - Administration ${{ github.ref_name }}
Run this release with docker like this:
\`\`\`sh
docker run --rm -p 4200:80 git.euph.dev/towerdefence/web-administration:${{ github.ref_name }}
\`\`\`
It will be available under [\`localhost:4200\`](localhost:4200)
<br><br>
For more information read the [Documentation](https://git.euph.dev/TowerDefence/Dokumentation/wiki/Administration/Config)

28
.forgejo/workflows/qs.yml Normal file
View file

@ -0,0 +1,28 @@
name: "Quality Check"
on:
- push
- pull_request
jobs:
linting:
name: "Linting"
runs-on: stable
container:
image: "git.euph.dev/actions/runner-basic:latest"
steps:
- name: "Checkout"
uses: "https://git.euph.dev/actions/checkout@v3"
- uses: actions/cache@v3
with:
path: ~/.node_modules
key: ${{ runner.os }}-${{ hashFiles('package-lock.json', 'eslint.config.mjs', '.stylelintrc', '.stylelintignore') }}
restore-keys: ${{ runner.os }}-
- name: "NPM install"
run: npm i
- name: "Linting TS"
run: npm run lint:ts
- name: "Linting SCSS"
run: npm run lint:scss

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
* text=auto eol=lf

42
.gitignore vendored Normal file
View file

@ -0,0 +1,42 @@
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
# Generated
src/app/core/server/**/*
openapitools.json

1
.prettierignore Normal file
View file

@ -0,0 +1 @@
*

3
.stylelintignore Normal file
View file

@ -0,0 +1,3 @@
*.*
!*.css
!*.scss

14
.stylelintrc.json Normal file
View file

@ -0,0 +1,14 @@
{
"extends": "stylelint-config-standard-scss",
"plugins": [
"stylelint-scss"
],
"rules": {
"custom-property-empty-line-before": null,
"declaration-empty-line-before": null,
"media-feature-range-notation": null,
"import-notation": "string",
"scss/no-global-function-names": null,
"no-empty-source": null
}
}

26
Justfile Normal file
View file

@ -0,0 +1,26 @@
_choose:
just --choose
up:
docker compose up -d
ng serve
down:
docker compose down
lint:
-npm run lint:ts:fix
-npm run lint:scss:fix
generate:
#!/bin/sh
API_VERSION="$(cat package.json | jq -r '.api_version')"
API_URL="https://git.euph.dev/TowerDefence/Server/releases/download/$API_VERSION/api.yml"
rm -rf src/app/core/server
mkdir -p src/app/core/server
npx @openapitools/openapi-generator-cli \
generate \
--openapitools src/app/core/openapitools.json \
-i "$API_URL" \
-g typescript-angular \
-o src/app/core/server

1
License.md Normal file
View file

@ -0,0 +1 @@
See License [here](https://git.euph.dev/TowerDefence/.profile/src/branch/main/License.md)

3
Readme.md Normal file
View file

@ -0,0 +1,3 @@
[![QS Badge](https://git.euph.dev/TowerDefence/Administration/actions/workflows/qs.yml/badge.svg?branch=trunk&style=for-the-badge&label=QS)](https://git.euph.dev/TowerDefence/Administration/actions?workflow=qs.yml)
[![Build Badge](https://git.euph.dev/TowerDefence/Administration/actions/workflows/build.yml/badge.svg?style=for-the-badge&label=Build)](https://git.euph.dev/TowerDefence/Administration/actions?workflow=build.yml)
# Tower Defence - Administration

102
angular.json Normal file
View file

@ -0,0 +1,102 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"Tower-Defence-Administration": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/tower-defence-administration",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kB",
"maximumError": "1MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kB",
"maximumError": "8kB"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "Tower-Defence-Administration:build:production"
},
"development": {
"buildTarget": "Tower-Defence-Administration:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
}
}
}
}
}

63
eslint.config.mjs Normal file
View file

@ -0,0 +1,63 @@
import simpleImportSort from "eslint-plugin-simple-import-sort";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import {fileURLToPath} from "node:url";
import js from "@eslint/js";
import {FlatCompat} from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
{
ignores: ["src/app/core/server"],
},
...compat.extends("eslint:recommended", "plugin:@typescript-eslint/strict"),
{
plugins: {
"simple-import-sort": simpleImportSort,
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
globals: {
...globals.browser,
},
parser: tsParser,
ecmaVersion: "latest",
sourceType: "module",
},
rules: {
indent: ["error", 4],
"linebreak-style": ["error", "unix"],
quotes: ["error", "single"],
semi: ["error", "always"],
strict: "error",
"array-bracket-newline": "error",
yoda: "error",
"@typescript-eslint/array-type": [
"error",
{
default: "generic",
},
],
"@typescript-eslint/ban-tslint-comment": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-extraneous-class": "off",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"no-mixed-spaces-and-tabs": "off",
},
},
]

16303
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

57
package.json Normal file
View file

@ -0,0 +1,57 @@
{
"name": "tower-defence-administration",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"lint:ts": "eslint src",
"lint:scss": "stylelint src",
"lint:ts:fix": "eslint src --fix",
"lint:scss:fix": "stylelint src --fix"
},
"private": true,
"dependencies": {
"@angular/animations": "^19.0.0",
"@angular/common": "^19.0.0",
"@angular/compiler": "^19.0.0",
"@angular/core": "^19.0.0",
"@angular/forms": "^19.0.0",
"@angular/material": "^19.1.2",
"@angular/platform-browser": "^19.0.0",
"@angular/platform-browser-dynamic": "^19.0.0",
"@angular/router": "^19.0.0",
"angular-auth-oidc-client": "^19.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.0.5",
"@angular/cli": "^19.0.5",
"@angular/compiler-cli": "^19.0.0",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.19.0",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^8.22.0",
"@typescript-eslint/parser": "^8.22.0",
"eslint": "^9.19.0",
"eslint-plugin-autofix": "^2.2.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"globals": "^15.14.0",
"jasmine-core": "~5.4.0",
"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",
"stylelint": "^16.14.1",
"stylelint-config-standard-scss": "^14.0.0",
"stylelint-scss": "^6.11.0",
"typescript": "~5.6.2"
},
"api_version": "v0.0.0-rc.2",
"volta": {
"node": "22.13.1"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,4 @@
<button (click)="login()">PAIN</button>
<button (click)="logout()">ASS</button>
<p>{{ test()|json }}</p>
<router-outlet />

View file

View file

@ -0,0 +1,30 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it('should have the \'Tower-Defence-Administration\' title', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('Tower-Defence-Administration');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Tower-Defence-Administration');
});
});

29
src/app/app.component.ts Normal file
View file

@ -0,0 +1,29 @@
import { AsyncPipe, JsonPipe } from '@angular/common';
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { AdminService } from '@core/server';
import { AuthService } from './core/auth/auth.service';
@Component({
selector: 'app-root',
imports: [RouterOutlet, JsonPipe, AsyncPipe],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
constructor(
private api: AdminService,
private auth: AuthService
){
}
test() {
return this.api.configuration;
}
login(){
this.auth.login();
}
logout(){
this.auth.logout();
}
}

32
src/app/app.config.ts Normal file
View file

@ -0,0 +1,32 @@
import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideRouter } from '@angular/router';
import { BASE_PATH, Configuration} from '@core/server';
import { LogLevel, provideAuth, } from 'angular-auth-oidc-client';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideAnimationsAsync(),
provideRouter(routes),
provideHttpClient(),
Configuration,
provideAuth({
config: {
authority: 'https://keycloak.szut.dev/auth/realms/szut',
redirectUrl: window.location.origin,
postLogoutRedirectUri: window.location.origin,
clientId: 'employee-management-service',
scope: 'openid profile email offline_access',
responseType: 'code',
silentRenew: true,
useRefreshToken: true,
logLevel: LogLevel.Error,
}
}),
{ provide: BASE_PATH, useValue: 'http://localhost:8080/api/v1' }
]
};

3
src/app/app.routes.ts Normal file
View file

@ -0,0 +1,3 @@
import { Routes } from '@angular/router';
export const routes: Routes = [];

6
src/app/core/auth/UserData.d.ts vendored Normal file
View file

@ -0,0 +1,6 @@
interface UserData {
username: string,
verified: boolean
}
export default UserData;

View file

@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { CanActivate, GuardResult, MaybeAsync, RedirectCommand, Router } from '@angular/router';
import UserData from '@core/auth/UserData';
import { Configuration } from '@core/server';
import { OidcSecurityService } from 'angular-auth-oidc-client';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService implements CanActivate {
public $user: BehaviorSubject<UserData | undefined>;
constructor(
private readonly oidcSecurityService: OidcSecurityService,
protected apiConfig: Configuration,
private router: Router
) {
this.$user = new BehaviorSubject<UserData | undefined>(undefined);
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated, userData, accessToken }) => {
apiConfig.credentials = {JWTAuth: accessToken};
const isLoggedIn = isAuthenticated && userData != null && accessToken != '';
this.$user.next(isLoggedIn ? {
username: userData.preferred_username,
verified: userData.email_verified
} : undefined);
});
}
canActivate(): MaybeAsync<GuardResult> {
return new Observable((publish) => {
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated }) => {
publish.next(isAuthenticated ? true : new RedirectCommand(this.router.parseUrl('/')));
});
});
}
login() {
this.oidcSecurityService.authorize();
}
logout() {
this.oidcSecurityService.logoff().subscribe(() => { });
}
}

13
src/index.html Normal file
View file

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>TowerDefenceAdministration</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

6
src/main.ts Normal file
View file

@ -0,0 +1,6 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from '@app/app.component';
import { appConfig } from '@app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));

1
src/styles.scss Normal file
View file

@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

15
tsconfig.app.json Normal file
View file

@ -0,0 +1,15 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts"
],
"include": [
"src/**/*.d.ts"
]
}

43
tsconfig.json Normal file
View file

@ -0,0 +1,43 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"isolatedModules": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
],
"paths": {
"@/*": [
"./src/*"
],
"@app/*": [
"./src/app/*"
],
"@core/*": [
"./src/app/core/*"
]
}
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

15
tsconfig.spec.json Normal file
View file

@ -0,0 +1,15 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}