Refactor HTML and configuration files for improved structure and consistency

- Updated videos.html to enhance readability and maintainability.
- Refactored webpack.config.js for better organization and clarity.
- Cleaned up TypeScript configuration files (tsconfig.app.json, tsconfig.json, tsconfig.spec.json) for consistency in formatting.
- Adjusted docker-compose.yaml for improved formatting and readability.
This commit is contained in:
Marek Lesko
2025-08-05 06:35:56 +00:00
parent 83ca026a55
commit 02116aa3df
312 changed files with 45638 additions and 45628 deletions

View File

@@ -1,34 +1,34 @@
import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
import { AppConfigService } from './services/config.service';
import { ApiEndpointInterceptor } from './services/http.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes),
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
{
provide: HTTP_INTERCEPTORS,
useClass: DefaultOAuthInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiEndpointInterceptor,
multi: true,
},
provideHttpClient(withInterceptorsFromDi()),
provideOAuthClient({
resourceServer: {
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me','https://beta.e-dias.sk/'],
sendAccessToken: true,
},
}),
]
};
import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
import { AppConfigService } from './services/config.service';
import { ApiEndpointInterceptor } from './services/http.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes),
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
{
provide: HTTP_INTERCEPTORS,
useClass: DefaultOAuthInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiEndpointInterceptor,
multi: true,
},
provideHttpClient(withInterceptorsFromDi()),
provideOAuthClient({
resourceServer: {
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me','https://beta.e-dias.sk/'],
sendAccessToken: true,
},
}),
]
};

View File

@@ -1 +1 @@
<router-outlet />
<router-outlet />

View File

@@ -1,9 +1,9 @@
import { CanActivateFn } from '@angular/router';
import { inject } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(OAuthService);
return authService.hasValidAccessToken(); // returns boolean, Promise, or Observable
};
import { CanActivateFn } from '@angular/router';
import { inject } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(OAuthService);
return authService.hasValidAccessToken(); // returns boolean, Promise, or Observable
};

View File

@@ -1,20 +1,20 @@
import { Routes } from '@angular/router';
import { Login } from './login/login';
import { authGuard } from './app.route.guard';
export const routes: Routes = [
{
path: 'login',
component: Login,
},
{
path: 'content',
children: [
{
path: '',
loadComponent: () => import('./content/content').then(m => m.Content),
canActivate: [authGuard],
}
],
}
];
import { Routes } from '@angular/router';
import { Login } from './login/login';
import { authGuard } from './app.route.guard';
export const routes: Routes = [
{
path: 'login',
component: Login,
},
{
path: 'content',
children: [
{
path: '',
loadComponent: () => import('./content/content').then(m => m.Content),
canActivate: [authGuard],
}
],
}
];

View File

@@ -1,25 +1,25 @@
import { provideZonelessChangeDetection } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { App } from './app';
describe('App', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [App],
providers: [provideZonelessChangeDetection()]
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(App);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it('should render title', () => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Web');
});
});
import { provideZonelessChangeDetection } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { App } from './app';
describe('App', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [App],
providers: [provideZonelessChangeDetection()]
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(App);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it('should render title', () => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Web');
});
});

View File

@@ -1,31 +1,31 @@
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { APP_INITIALIZER, Component, inject, OnInit, provideAppInitializer } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router';
import { DefaultOAuthInterceptor, OAuthService } from 'angular-oauth2-oidc';
import { AppConfigService } from './services/config.service';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
providers: [
OAuthService,
],
templateUrl: './app.html',
styleUrl: './app.scss'
})
export class App implements OnInit {
protected title = 'Web';
constructor(private readonly as: OAuthService, private readonly router: Router) {
this.as.configure({
issuer: 'https://identity.lesko.me',
redirectUri: window.location.origin + '/login',
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
scope: 'openid profile email',
responseType: 'code',
timeoutFactor: 0.01,
});
}
ngOnInit(): void {
this.as.loadDiscoveryDocumentAndLogin().then(() => this.router.navigate(['login']));
}
}
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { APP_INITIALIZER, Component, inject, OnInit, provideAppInitializer } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router';
import { DefaultOAuthInterceptor, OAuthService } from 'angular-oauth2-oidc';
import { AppConfigService } from './services/config.service';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
providers: [
OAuthService,
],
templateUrl: './app.html',
styleUrl: './app.scss'
})
export class App implements OnInit {
protected title = 'Web';
constructor(private readonly as: OAuthService, private readonly router: Router) {
this.as.configure({
issuer: 'https://identity.lesko.me',
redirectUri: window.location.origin + '/login',
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
scope: 'openid profile email',
responseType: 'code',
timeoutFactor: 0.01,
});
}
ngOnInit(): void {
this.as.loadDiscoveryDocumentAndLogin().then(() => this.router.navigate(['login']));
}
}

View File

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

View File

@@ -1,22 +1,22 @@
import { JsonPipe } from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, isDevMode, signal } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { AppConfigService } from '../services/config.service';
@Component({
selector: 'app-content',
imports: [JsonPipe],
templateUrl: './content.html',
styleUrl: './content.scss'
})
export class Content {
data = signal({});
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
httpClient.get('/api/product')
.subscribe(data => {
this.data.set(data);
});
}
}
import { JsonPipe } from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, isDevMode, signal } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { AppConfigService } from '../services/config.service';
@Component({
selector: 'app-content',
imports: [JsonPipe],
templateUrl: './content.html',
styleUrl: './content.scss'
})
export class Content {
data = signal({});
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
httpClient.get('/api/product')
.subscribe(data => {
this.data.set(data);
});
}
}

View File

@@ -1,2 +1,2 @@
Logging in...

View File

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

View File

@@ -1,33 +1,33 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
@Component({
selector: 'app-login',
templateUrl: './login.html',
styleUrl: './login.scss'
})
export class Login implements OnInit {
constructor(readonly as: OAuthService, readonly router: Router) { }
ngOnInit(): void {
if (this.as.hasValidAccessToken() && this.as.hasValidIdToken()) {
this.getUserInfo();
} else {
this.as.events.subscribe(event => {
if (event.type === 'token_received')
if (this.as.hasValidIdToken()) {
this.getUserInfo();
}
})
}
}
getUserInfo(): void {
this.as.loadUserProfile().then(value => {
console.log('User profile loaded:', value);
this.router.navigate(['/content']);
});
}
}
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
@Component({
selector: 'app-login',
templateUrl: './login.html',
styleUrl: './login.scss'
})
export class Login implements OnInit {
constructor(readonly as: OAuthService, readonly router: Router) { }
ngOnInit(): void {
if (this.as.hasValidAccessToken() && this.as.hasValidIdToken()) {
this.getUserInfo();
} else {
this.as.events.subscribe(event => {
if (event.type === 'token_received')
if (this.as.hasValidIdToken()) {
this.getUserInfo();
}
})
}
}
getUserInfo(): void {
this.as.loadUserProfile().then(value => {
console.log('User profile loaded:', value);
this.router.navigate(['/content']);
});
}
}

View File

@@ -1,31 +1,31 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AppConfigService {
private config: any;
public loaded: boolean = false;
constructor() { }
loadConfig(): Observable<any> {
return new Observable(observer => {
fetch('/config.json')
.then(async response => {
if (!response.ok) {
throw new Error(`Could not load config.json: ${response.statusText}`);
}
this.config = await response.json();
this.loaded = true;
observer.next(this.config);
observer.complete();
})
.catch(error => observer.error(error));
});
}
get setting() {
return this.config;
}
}
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AppConfigService {
private config: any;
public loaded: boolean = false;
constructor() { }
loadConfig(): Observable<any> {
return new Observable(observer => {
fetch('/config.json')
.then(async response => {
if (!response.ok) {
throw new Error(`Could not load config.json: ${response.statusText}`);
}
this.config = await response.json();
this.loaded = true;
observer.next(this.config);
observer.complete();
})
.catch(error => observer.error(error));
});
}
get setting() {
return this.config;
}
}

View File

@@ -1,25 +1,25 @@
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AppConfigService } from './config.service';
@Injectable({ providedIn: 'root' })
export class ApiEndpointInterceptor implements HttpInterceptor {
constructor(private readonly configService: AppConfigService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.prependUrl(req, next);
}
prependUrl(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const apiEndpoint = this.configService.setting.apiEndpoint;
if (apiEndpoint === undefined || !this.configService.loaded)
throw new Error('API endpoint is not defined or config not loaded');
const isRelative = !/^https?:\/\//i.test(req.url);
const url = isRelative ? `${apiEndpoint.replace(/\/$/, '')}/${req.url.replace(/^\//, '')}` : req.url;
const cloned = req.clone({ url });
console.trace('ApiEndpointInterceptor hit:', url);
return next.handle(cloned);
}
}
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AppConfigService } from './config.service';
@Injectable({ providedIn: 'root' })
export class ApiEndpointInterceptor implements HttpInterceptor {
constructor(private readonly configService: AppConfigService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.prependUrl(req, next);
}
prependUrl(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const apiEndpoint = this.configService.setting.apiEndpoint;
if (apiEndpoint === undefined || !this.configService.loaded)
throw new Error('API endpoint is not defined or config not loaded');
const isRelative = !/^https?:\/\//i.test(req.url);
const url = isRelative ? `${apiEndpoint.replace(/\/$/, '')}/${req.url.replace(/^\//, '')}` : req.url;
const cloned = req.clone({ url });
console.trace('ApiEndpointInterceptor hit:', url);
return next.handle(cloned);
}
}