feat static pages system with dynamic footer and safe html rendering
This commit is contained in:
18
src/app/pages/static-page/static-page.component.html
Normal file
18
src/app/pages/static-page/static-page.component.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<main class="static-page page-container">
|
||||
@if (loading()) {
|
||||
<section class="static-page__state">{{ 'app.connecting' | translate }}</section>
|
||||
} @else if (notFound()) {
|
||||
<section class="static-page__state">
|
||||
<h1>404</h1>
|
||||
<p>Страница не найдена</p>
|
||||
<a [routerLink]="'/' | langRoute">На главную</a>
|
||||
</section>
|
||||
} @else {
|
||||
<article class="static-page__content">
|
||||
@if (title()) {
|
||||
<h1>{{ title() }}</h1>
|
||||
}
|
||||
<div class="static-page__html" [innerHTML]="safeHtml()"></div>
|
||||
</article>
|
||||
}
|
||||
</main>
|
||||
39
src/app/pages/static-page/static-page.component.scss
Normal file
39
src/app/pages/static-page/static-page.component.scss
Normal file
@@ -0,0 +1,39 @@
|
||||
.static-page {
|
||||
min-height: 45vh;
|
||||
}
|
||||
|
||||
.static-page__state {
|
||||
text-align: center;
|
||||
padding: 2rem 0;
|
||||
color: var(--text-secondary, #667a77);
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary, #1e3c38);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color, #497671);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.static-page__content {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
|
||||
h1 {
|
||||
color: var(--text-primary, #1e3c38);
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.static-page__html {
|
||||
color: var(--text-primary, #1e3c38);
|
||||
line-height: 1.6;
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
}
|
||||
82
src/app/pages/static-page/static-page.component.ts
Normal file
82
src/app/pages/static-page/static-page.component.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { ChangeDetectionStrategy, Component, SecurityContext, inject, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
import { StaticPageResolverService } from '../../core/config/static-page-resolver.service';
|
||||
import { LanguageService } from '../../services/language.service';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-static-page',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink, TranslatePipe, LangRoutePipe],
|
||||
templateUrl: './static-page.component.html',
|
||||
styleUrls: ['./static-page.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class StaticPageComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly sanitizer = inject(DomSanitizer);
|
||||
private readonly staticPageResolver = inject(StaticPageResolverService);
|
||||
private readonly languageService = inject(LanguageService);
|
||||
|
||||
readonly loading = signal(true);
|
||||
readonly notFound = signal(false);
|
||||
readonly title = signal('');
|
||||
readonly safeHtml = signal<SafeHtml>(this.sanitizer.bypassSecurityTrustHtml(''));
|
||||
|
||||
constructor() {
|
||||
this.route.paramMap.subscribe(params => {
|
||||
const keyFromParam = params.get('key');
|
||||
const staticPath = params.get('staticPath');
|
||||
|
||||
if (keyFromParam) {
|
||||
this.loadByKey(keyFromParam);
|
||||
return;
|
||||
}
|
||||
|
||||
if (staticPath) {
|
||||
this.loadByPath(`/${staticPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.notFound.set(true);
|
||||
this.loading.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
private loadByKey(key: string): void {
|
||||
this.loading.set(true);
|
||||
this.notFound.set(false);
|
||||
|
||||
this.staticPageResolver.resolveByKey(key, this.languageService.currentLanguage()).subscribe(page => {
|
||||
this.applyPage(page?.title ?? '', page?.html ?? '', !page);
|
||||
});
|
||||
}
|
||||
|
||||
private loadByPath(path: string): void {
|
||||
this.loading.set(true);
|
||||
this.notFound.set(false);
|
||||
|
||||
this.staticPageResolver.resolveByRoute(path, this.languageService.currentLanguage()).subscribe(page => {
|
||||
this.applyPage(page?.title ?? '', page?.html ?? '', !page);
|
||||
});
|
||||
}
|
||||
|
||||
private applyPage(title: string, html: string, notFound: boolean): void {
|
||||
if (notFound) {
|
||||
this.title.set('');
|
||||
this.safeHtml.set(this.sanitizer.bypassSecurityTrustHtml(''));
|
||||
this.notFound.set(true);
|
||||
this.loading.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const sanitized = this.sanitizer.sanitize(SecurityContext.HTML, html) ?? '';
|
||||
this.title.set(title);
|
||||
this.safeHtml.set(this.sanitizer.bypassSecurityTrustHtml(sanitized));
|
||||
this.notFound.set(false);
|
||||
this.loading.set(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user