diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index a477ecd..64e7075 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -1,19 +1,26 @@
+
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
+import { AvisoResolver } from './pages/aviso/aviso.resolver'; // Importieren Sie den Resolver
const routes: Routes = [
{
path: 'home',
- loadChildren: () => import('./pages/home/home.module').then( m => m.HomePageModule)
+ loadChildren: () => import('./pages/home/home.module').then(m => m.HomePageModule)
},
{
path: 'aviso',
- loadChildren: () => import('./pages/aviso/aviso.module').then( m => m.AvisoPageModule)
+ loadChildren: () => import('./pages/aviso/aviso.module').then(m => m.AvisoPageModule),
+ resolve: { avisoData: AvisoResolver } // Hinzufügen des Resolvers zur Route
},
{
path: '',
redirectTo: 'aviso',
pathMatch: 'full'
+ },
+ {
+ path: '**',
+ redirectTo: 'aviso'
}
];
diff --git a/src/app/pages/aviso/aviso-routing.module.ts b/src/app/pages/aviso/aviso-routing.module.ts
index 1a39cee..fcba62f 100644
--- a/src/app/pages/aviso/aviso-routing.module.ts
+++ b/src/app/pages/aviso/aviso-routing.module.ts
@@ -1,12 +1,14 @@
+
import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
-
+import { RouterModule, Routes } from '@angular/router';
import { AvisoPage } from './aviso.page';
+import { AvisoResolver } from './aviso.resolver'; // Pfad anpassen
const routes: Routes = [
{
path: '',
- component: AvisoPage
+ component: AvisoPage,
+ resolve: { avisoData: AvisoResolver }
}
];
@@ -14,4 +16,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
-export class AvisoPageRoutingModule {}
+export class AvisoPageRoutingModule { }
diff --git a/src/app/pages/aviso/aviso.module.ts b/src/app/pages/aviso/aviso.module.ts
index 9df1bf6..776f4df 100644
--- a/src/app/pages/aviso/aviso.module.ts
+++ b/src/app/pages/aviso/aviso.module.ts
@@ -1,14 +1,14 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
+import { AvisoPage } from './aviso.page';
import { IonicModule } from '@ionic/angular';
import { AvisoPageRoutingModule } from './aviso-routing.module';
import { AutoResizeTextDirective } from '../../directives/auto-resize-text.directive';
-import { AvisoPage } from './aviso.page';
-import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({
imports: [
diff --git a/src/app/pages/aviso/aviso.page.html b/src/app/pages/aviso/aviso.page.html
index 2b1a311..5d7bb5c 100644
--- a/src/app/pages/aviso/aviso.page.html
+++ b/src/app/pages/aviso/aviso.page.html
@@ -1,14 +1,10 @@
-
-
-
-
- Ankünfte ({{ totalArrivals }}) Seite {{ currentPageIndex + 1 }} von {{ pages.length }}
-
-
+
+
+
@@ -28,10 +24,14 @@
- 0">
-
0">
+
+ [ngClass]="getStatusClass(aviso.status, aviso.lkW_fertig)">
+
+
+ {{ getOverallIndex(i) }}
+
{{ aviso.lkW_Nr }}
@@ -44,7 +44,7 @@
{{ aviso.ankunft }}
-
+
{{ aviso.dauer }}
@@ -56,6 +56,7 @@
+
@@ -70,27 +71,45 @@
+
+
+ {{ currentDate | date: 'HH:mm:ss' }}
+ {{ currentDate | date: ' dd.MM.yyyy' }}
+
+
+
+
+
+
+
+ ({{ totalArrivals }})
{{ currentPageIndex + 1 }} / {{ pages.length }}
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
diff --git a/src/app/pages/aviso/aviso.page.scss b/src/app/pages/aviso/aviso.page.scss
index 8098bba..ab9ad47 100644
--- a/src/app/pages/aviso/aviso.page.scss
+++ b/src/app/pages/aviso/aviso.page.scss
@@ -1,89 +1,54 @@
-
-
ion-content {
--background: #f0f0f0; /* Heller Hintergrund für besseren Kontrast */
}
-.title-card {
- background-color: #3880ff; /* Beispiel: Blaue Hintergrundfarbe */
- color: white;
- text-align: center;
-}
-
-ion-card-content p {
- font-size: 1.8em; /* Größere Schriftgröße für die Inhalte */
- margin: 10px 0;
-}
-
.grid-container {
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(15%, 1fr)); /* Feste Mindestbreite */
- gap: 1%; /* Abstand zwischen den Kacheln */
- padding: 0px; /* Optional: Innenabstand */
- justify-content: center; /* Zentriert die Kacheln */
- }
+ grid-template-columns: repeat(auto-fill, minmax(var(--tile-width-percent), 1fr));
+ row-gap: 1vh;
+ column-gap: 1vh;
+ padding: 0px;
+ justify-content: center;
+}
.arrival-card {
- width: 95%; /* Feste Breite */
- height: 24vh; /* Feste Höhe */
- border-radius: 15px; /* Abgerundete Ecken für ein moderneres Aussehen */
+ height: var(--tile-height-vh);
+ border-radius: 15px;
transition: box-shadow 0.3s, transform 0.3s;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ margin: 0;
+ padding: 0em;
+ box-sizing: border-box; /* Padding wird in der Höhe berücksichtigt */
+ animation: fadeIn 0.2s ease-in-out; /* Kürzere Animationsdauer */
}
.htmltext {
- height: 30vh;
+ height: var(--text-balken-height-vh);
width: 100%;
white-space: pre-line;
transition: box-shadow 0.3s, transform 0.3s;
}
-ion-content {
- ion-grid.htmltext {
- height: 30vh;
- }
-}
-
-
-
ion-icon {
vertical-align: middle;
- font-size: 1.2em; /* Größere Icons für bessere Sichtbarkeit */
+ font-size: calc(var(--tile-height-vh) * 0.18); /* Anpassung der Icon-Größe */
+ margin-right: 0.3em; /* Abstand zwischen Icon und Text */
}
/* Statusklassen */
-.statusLKW_Erfasst {
- border-left: 10px solid #2dd36f; /* Grün */
-}
-
-.statusLKW_Freigegeben {
- border-left: 10px solid #3880ff; /* Blau */
-}
-
-.statusLKW_LKW_neu {
- border-left: 10px solid #f78c40; /* Orange */
+.lkwfertig {
+ border-left: 10px solid green;
+ background-color: #e6ffe6; /* Leicht grüner Hintergrund für "fertig" */
}
+.statusLKW_LKW_neu,
.statusLKW_Ankunft {
- border-left: 10px solid #f78c40; /* Orange */
-}
-
-.statusLKW_Vorbereitet {
- border-left: 10px solid #c8c8c8; /* Grau */
-}
-
-.statusLKW_Vorgeschrieben {
- border-left: 10px solid #a259ff; /* Violett */
-}
-
-.status-default {
- border-left: 10px solid #c8c8c8; /* Grau */
-}
+ }
/* Animationen für Ankunftskarten */
-.arrival-card {
- animation: fadeIn 0.5s ease-in-out;
-}
-
@keyframes fadeIn {
from {
opacity: 0;
@@ -96,54 +61,138 @@ ion-icon {
}
}
-@media (min-width: 1200px) {
+/* Typografie */
+ion-title {
+ font-size: calc(var(--tile-height-vh) * 0.24); /* 4% der Kachelhöhe */
+ font-weight: bold;
+ color: #003680;
+}
+
+.title {
+ font-size: calc(var(--tile-height-vh) * 0.24); /* 4% der Kachelhöhe */
+ font-weight: bold;
+ color: #003680;
+}
+
+ion-card-title {
+ font-size: calc(var(--tile-height-vh) * 0.06); /* Erhöht auf 6% der Kachelhöhe */
+ margin: 0; /* Abstand unter dem Titel */
+ text-align: center;
+ white-space: nowrap; /* Erlaubt Zeilenumbrüche */
+ overflow-wrap: normal; /* Bricht lange Wörter um */
+ color: #002050; /* Dunkleres Blau für besseren Kontrast */
+}
+
+ion-card-content p {
+ font-size: calc(var(--tile-height-vh) * 0.04); /* Erhöht auf 4% der Kachelhöhe */
+ margin: 0;
+ text-align: center;
+ white-space: nowrap; /* Erlaubt Zeilenumbrüche */
+ overflow-wrap: normal; /* Bricht lange Wörter um */
+ line-height: 1.5; /* Verbesserte Lesbarkeit */
+ color: #333; /* Dunkle Schriftfarbe für besseren Kontrast */
+}
+
+.centered-content p {
+ margin-bottom: 0.5em; /* Abstand zwischen den Absätzen */
+}
+
+/* Icon-Text-Gruppe */
+.icon-text-group {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0.5em;
+}
+
+.icon-text-group ion-icon {
+ margin-right: 0.5em;
+}
+
+/* Mobile Geräte */
+@media (max-width: 599px) {
+ .arrival-card {
+ height: auto; /* Höhe passt sich dem Inhalt an */
+ }
+
ion-card-title {
- font-size: 3.5em;
+ font-size: calc(var(--tile-height-vh) * 0.08);
}
ion-card-content p {
- font-size: 2em;
+ font-size: calc(var(--tile-height-vh) * 0.05);
}
}
-ion-text p {
- font-size: 2em;
-}
+/* Tablets */
+@media (min-width: 600px) and (max-width: 1199px) {
+ ion-card-title {
+ font-size: var(--tile-title-font-size);
+ }
-.card-title {
- display: flex;
- justify-content: space-between;
- align-items: center;
- font-size: 2.5em;
- font-weight: bold;
-}
-
-.card-title ion-icon {
- margin-left: auto;
-}
-
-ion-footer {
- background-color: #ffffff;
- border-top: 1px solid #c8c8c8;
-}
-
-ion-toolbar {
- --padding-start: 0;
- --padding-end: 0;
-}
-
-ion-title {
- font-size: 1.6em;
- font-weight: bold;
- color: #3880ff;
-}
-
-@media (max-width: 600px) {
- ion-title {
- font-size: 1.4em;
+ ion-card-content p {
+ font-size: var(--tile-font-size-date-time);
}
}
+
+/* Desktops */
+@media (min-width: 1200px) {
+ ion-card-title {
+ font-size: var(--tile-title-font-size);
+ }
+
+ ion-card-content p {
+ font-size: var(--tile-font-size-date-time);
+ }
+}
+
+.logo {
+ max-height: calc(var(--tile-height-vh) * 0.40);
+ object-fit: contain;
+}
+
+.logobar {
+ max-height: 10vh;
+}
+
+.custom-progress-bar {
+ --progress-background: #003680; /* Fortschrittsfarbe (gefüllter Teil) */
+ --background: #e0e0e0; /* Hintergrundfarbe der Leiste */
+ --buffer-background: #003680; /* Hintergrundfarbe des Puffers */
+}
+.card-number {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ font-size: calc(var(--tile-height-vh) * 0.18);
+ font-weight: bold;
+ background-color: transparent;
+ padding: 2px 5px;
+ border-radius: 3px;
+}
+/* Versteckt die Buttons und zeigt nur den Indikator-Strich an */
+.custom-segment-button {
+ --color: transparent; /* Text unsichtbar machen */
+ --background: #003680; /* Hintergrund des Buttons transparent */
+ min-height: 0;
+ padding: 0;
+ margin: 0;
+ border: none;
+ width: 200px;
+ --indicator-color: transparent;
+}
+
+/* Styling für das ion-segment */
+.custom-segment {
+ --background: transparent;
+ height: 0.4vh;
+ position: relative;
+ margin: 0;
+ padding: 0;
+
+}
+
+
diff --git a/src/app/pages/aviso/aviso.page.ts b/src/app/pages/aviso/aviso.page.ts
index 525274e..d398f0e 100644
--- a/src/app/pages/aviso/aviso.page.ts
+++ b/src/app/pages/aviso/aviso.page.ts
@@ -1,383 +1,439 @@
+// src/app/pages/aviso/aviso.page.ts
+
import {
- Component,OnInit,OnDestroy,HostListener,ChangeDetectorRef
+ Component,
+ OnInit,
+ OnDestroy,
+ HostListener,
+ ChangeDetectorRef,
+ HostBinding
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { AvisoService, AvisoArrivalsResponse } from '../../services/aviso.service';
-import { AvisoDto } from '../../services/aviso.dto';
-import { AvisoTvSettingsDto } from '../../services/aviso-tv-settings.dto';
-import { ToastController } from '@ionic/angular';
-import { interval, Subject } from 'rxjs';
-import { switchMap, takeUntil, startWith } from 'rxjs/operators';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
-
+import { interval, Subject, throwError, lastValueFrom, Subscription } from 'rxjs';
+import { switchMap, takeUntil, distinctUntilChanged, tap, catchError, map, take } from 'rxjs/operators';
+
+import { AvisoService, AvisoArrivalsResponse } from '../../services/aviso.service';
+import { AvisoDto, TvSettings } from '../../services/aviso.dto';
+import { AvisoTvTextSettingsDto } from '../../services/aviso-tv-settings.dto';
+
+// Schnittstelle für die aufgelösten Daten vom Resolver
+interface AvisoResolvedData {
+ avisoTvTextSettings: AvisoTvTextSettingsDto[];
+ avisoTvSettings: TvSettings[];
+ arrivals: AvisoArrivalsResponse;
+}
+
+interface AvisoPageData {
+ avisoData: AvisoResolvedData;
+}
+
+interface CssVariables {
+ tileWidthPercent: string;
+ tileHeightVh: string;
+ tileTitleFontSize: string;
+ tileFontSizeDateTime: string;
+ tileSeitenwechselInSek: string;
+ textBalkenHeightVh: string;
+}
+
+const ARRIVALS_INTERVAL_MS = 10000;
+const TVTEXTSETTINGS_INTERVAL_MS = 60000;
+const TVSETTINGS_INTERVAL_MS = 10000;
+const TOGGLE_DIV_INTERVAL_MS = 5000;
+
+interface StatusInfo {
+ class: string;
+ icon: string;
+ color: string;
+ text: string;
+}
+
+const STATUS_MAP: { [key: string]: StatusInfo } = {
+ '3': { class: 'statusLKW_Ankunft', icon: 'time', color: 'medium', text: 'Ankunft' },
+ 'lkwfertig': { class: 'lkwfertig', icon: 'time', color: 'warning', text: 'Ankunft' },
+ 'default': { class: 'status-default', icon: 'help-circle', color: 'medium', text: 'Unbekannt' }
+};
+
+// Neues Interface für die Anzeige der Fixzeilen
+interface SettingDisplayData {
+ nonEmptyFixeZeilen: {
+ sanitizedHtml: SafeHtml;
+ textAlign: string;
+ }[];
+ currentDivIndex: number;
+}
+
@Component({
selector: 'app-aviso',
templateUrl: './aviso.page.html',
styleUrls: ['./aviso.page.scss'],
})
export class AvisoPage implements OnInit, OnDestroy {
-
-
- standort: string = '';
- seiten: boolean = false;
- onlyOK: boolean = false;
-
+
+ // HostBindings für CSS-Variablen
+ @HostBinding('style.--tile-width-percent') tileWidthPercent = '30vw';
+ @HostBinding('style.--tile-height-vh') tileHeightVh = '20vh';
+ @HostBinding('style.--tile-title-font-size') tileTitleFontSize = '2vh';
+ @HostBinding('style.--tile-font-size-date-time') tileFontSizeDateTime = '1vh';
+ @HostBinding('style.--text-balken-height-vh') textBalkenHeightVh = '5vh';
+
+ progressBarValue: number = 0;
+ private progressBarSubscription: Subscription = new Subscription();
+
+
+ currentDate: Date = new Date();
+ private dateSubscription: Subscription = new Subscription();
+
+ // Standort- und Filterinformationen
+ standort = '';
+ standortID = 0;
+ seiten = false;
+ onlyOK = false;
+
// Datenmodelle
arrivals: AvisoDto[] = [];
- avisoTvSettings: AvisoTvSettingsDto[] = []; // Neues Datenmodell
+ avisoTvTextSettings: AvisoTvTextSettingsDto[] = [];
+ avisoTvSettings: TvSettings[] = [];
// Paginierung
pages: AvisoDto[][] = [];
- currentPageIndex: number = 0;
- tilesPerPage: number = 0;
+ currentPageIndex = 0;
+ tilesPerPage = 0;
- // Ladezustand
- loadingArrivals: boolean = false;
- loadingSettings: boolean = false; // Ladezustand für Einstellungen
+ // Ladezustände
+ loadingArrivals = false;
+ loadingTextSettings = false;
+ loadingTvSettings = false;
- // Gesamtanzahl
- totalArrivals: number = 0;
- totalSettings: number = 0; // Gesamtanzahl für Einstellungen
+ // Gesamtanzahlen
+ totalArrivals = 0;
+ totalTextSettings = 0;
- // Fehlernachricht
- errorMessage: string = '';
- settingsErrorMessage: string = ''; // Fehlernachricht für Einstellungen
+ // Fehlermeldungen
+ errorMessage = '';
+ settingsErrorMessage = '';
- // Subjects zum Beenden der Subscriptions
+ // Sonstige Variablen
private destroy$ = new Subject();
- private pageRotation$ = new Subject(); // Optional, für separate Page Rotation
-
- // Feste Kachelgrößen (entsprechend den CSS-Einstellungen)
- private readonly tileWidth: number = 450; // in px
- private readonly tileHeight: number = 100; // in px
- private readonly gutter: number = 0; // Abstand zwischen den Kacheln in px
- private readonly containerPadding: number = 0; // Innenabstand des Grid-Containers in px
- public fontSettings: {textAlign: string}[] = [];
private toggleDivInterval: any;
- showFirstDiv: boolean = true;
+ private currentCssVariables: CssVariables | null = null;
+
+ // Neues Array für die Anzeige der Fixzeilen
+ settingDisplayData: SettingDisplayData[] = [];
constructor(
private route: ActivatedRoute,
private avisoService: AvisoService,
- private toastController: ToastController,
private cdr: ChangeDetectorRef,
private sanitizer: DomSanitizer
) { }
-
-
/**
- * Sanitizes HTML, extracts font size and text align from span elements,
- * and stores them in dataset attributes and the fontSettings array.
- * @param html Das zu sanitizende HTML
- * @param index Index der Einstellung zur Zuordnung der Stilinformationen
- * @returns Sanitized HTML als SafeHtml
- */
- sanitizeHtml(html: string, index: number): SafeHtml {
- const parser = new DOMParser();
- const doc = parser.parseFromString(html, 'text/html');
- const spans = doc.querySelectorAll('div');
-
- spans.forEach(span => {
- const fontSize = span.style.fontSize;
-
- if (fontSize) {
-
- let fontSizePx: number;
- if (fontSize.endsWith('pt')) {
- fontSizePx = parseFloat(fontSize) * 1.333; // Umrechnung von pt zu px
- } else if (fontSize.endsWith('px')) {
- fontSizePx = parseFloat(fontSize);
- } else {
- // Andere Einheiten oder Standardfall
- fontSizePx = parseFloat(fontSize);
- }
-
- const textAlign = span.style.textAlign || 'left';
-
- // Speichern der ursprünglichen Schriftgröße und Textausrichtung
- this.fontSettings[index] = {
- textAlign: textAlign
- };
-
- // Speichern in dataset
- span.dataset['originalFontSizePx'] = fontSizePx.toString();
- span.dataset['originalTextAlign'] = textAlign;
-
- // Debugging: Loggen der ursprünglichen Schriftgröße
- console.log(`Original Font Size for span: "${span.textContent}" = ${fontSizePx}px`);
- } else {
- // Falls keine Schriftgröße definiert ist
- console.log(`No inline font size found for span: "${span.textContent}"`);
- }
-
- // Entfernen der Inline-Schriftgröße
- span.style.fontSize = '';
-
- // Hinzufügen der Klasse für die dynamische Anpassung
- span.classList.add('dynamic-font-size');
- });
-
- // Debugging: Loggen des bearbeiteten HTML
- console.log('Processed HTML:', doc.body.innerHTML);
-
- return this.sanitizer.bypassSecurityTrustHtml(doc.body.innerHTML);
+ * Konvertiert eine Schriftgröße in verschiedene Einheiten zu Pixel.
+ * @param fontSize Die Schriftgröße als String (z.B. '12pt', '16px')
+ * @returns Die Schriftgröße in Pixel
+ */
+ private convertToPx(fontSize: string): number {
+ if (fontSize.endsWith('pt')) {
+ return parseFloat(fontSize) * 1.333;
+ } else if (fontSize.endsWith('px')) {
+ return parseFloat(fontSize);
+ } else {
+ return parseFloat(fontSize);
+ }
}
- getTextAlign(index: number): string {
- const settings = this.fontSettings[index];
- return settings ? settings.textAlign : 'left';
- }
-
-
ngOnInit() {
- this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((params) => {
- this.standort = params['standort'] || 'SUB';
- this.seiten = params['seiten'] === 'true' || false;
- this.onlyOK = params['onlyOK'] === 'true' || false;
-
- // Initiales Laden der Daten
- this.loadArrivals();
- this.loadAvisoTvSettings();
- this.startDivToggle();
+ this.currentDate = new Date();
+ // Aktualisieren Sie das Datum jede Sekunde
+ this.dateSubscription = interval(1000).subscribe(() => {
+ this.currentDate = new Date();
});
- interval(1000000) // 10000 Millisekunden = 10 Sekunden
+ this.route.paramMap.subscribe(params => {
+ this.standort = params.get('standort') || 'SUB';
+ this.standortID = parseInt(params.get('standortID') || '1', 10);
+ });
+
+ this.route.queryParamMap.subscribe(queryParams => {
+ this.seiten = queryParams.get('seiten') === 'true';
+ this.onlyOK = queryParams.get('onlyOK') === 'true';
+ });
+
+ // Zugriff auf die vom Resolver bereitgestellten Daten
+ this.route.data.pipe(takeUntil(this.destroy$)).subscribe((resolvedData) => {
+ const data = (resolvedData as any)['avisoData'] as AvisoResolvedData;
+
+ this.avisoTvTextSettings = data.avisoTvTextSettings;
+ this.avisoTvSettings = data.avisoTvSettings;
+ this.arrivals = data.arrivals.avisos;
+ this.totalArrivals = data.arrivals.totalCount;
+
+ // Process the HTML settings
+ this.preprocessHtmlSettings();
+
+ // Setzen der CSS-Variablen
+ this.setCSSVariables();
+
+ // Starten der Div-Umschaltung
+ this.startDivToggle();
+
+ // Starten der Seitenrotation
+ this.paginateArrivals();
+ this.startPageRotation();
+ });
+
+
+ // Automatisches Aktualisieren der Arrivals alle 10 Sekunden
+ interval(ARRIVALS_INTERVAL_MS)
.pipe(
- startWith(0), // Sofortiger Start ohne Warten
switchMap(() => {
- // Nur den Ladeindikator anzeigen, wenn keine Daten vorhanden sind
this.loadingArrivals = this.arrivals.length === 0;
this.errorMessage = '';
return this.avisoService.getArrivals(this.standort, this.seiten, this.onlyOK);
}),
+ distinctUntilChanged((prev, curr) => this.arrivalsAreEqual(prev.avisos, curr.avisos)),
takeUntil(this.destroy$)
)
.subscribe(
- (data: AvisoArrivalsResponse) => { // Typisierung der empfangenen Daten
- console.log('Received arrivals data:', data); // Zum Debuggen
+ (data: AvisoArrivalsResponse) => {
this.arrivals = data.avisos;
this.totalArrivals = data.totalCount;
this.loadingArrivals = false;
this.paginateArrivals();
- this.cdr.detectChanges(); // Manuelle Change Detection
+ this.cdr.detectChanges();
},
(error) => {
- console.error('Fehler beim Laden der Arrivals:', error);
- this.presentToast(`Fehler beim Laden der Arrivals: ${error}`);
this.errorMessage = 'Fehler beim Laden der Arrivals. Bitte versuche es später erneut.';
this.loadingArrivals = false;
}
);
-
- // Automatisches Aktualisieren der TV-Einstellungen alle 10 Sekunden
- interval(1000000) // 10000 Millisekunden = 10 Sekunden
+ // Automatisches Aktualisieren der TV Settings alle 10 Sekunden
+ interval(TVSETTINGS_INTERVAL_MS)
.pipe(
- startWith(0),
- switchMap(() => {
- this.loadingSettings = this.avisoTvSettings.length === 0;
- this.settingsErrorMessage = '';
- return this.avisoService.getAvisoTvSettings(this.standort);
- }),
+ switchMap(() => this.loadAvisoTvSettings()),
takeUntil(this.destroy$)
)
- .subscribe(
- (data: AvisoTvSettingsDto[]) => { // Typisierung als Array
- console.log('Received TV settings data:', data);
- this.avisoTvSettings = data;
- this.totalSettings = data.length; // Setze totalSettings auf die Länge des Arrays
- this.loadingSettings = false;
- this.cdr.detectChanges(); // Manuelle Change Detection
+ .subscribe();
- // Debugging: Überprüfe jede Einstellung
- this.avisoTvSettings.forEach(setting => {
- console.log(`Setting ID: ${setting.tvTextBezeichnungID}, isActive: ${setting.isActive}, position: ${setting.position}, fixeZeile1: ${setting.fixeZeile1}`);
- });
- },
- (error) => {
- console.error('Fehler beim Laden der TV Settings:', error);
- this.presentToast(`Fehler beim Laden der TV Settings: ${error}`);
- this.settingsErrorMessage = 'Fehler beim Laden der TV Settings. Bitte versuche es später erneut.';
- this.loadingSettings = false;
- }
- );
-
- // Starte die Page Rotation einmal nach dem Initialen Laden
- // Optional: Falls du separate Subjects für Page Rotation verwendest
- // this.startPageRotation();
+ // Automatisches Aktualisieren der TV Text Settings alle 60 Sekunden
+ interval(TVTEXTSETTINGS_INTERVAL_MS)
+ .pipe(
+ switchMap(() => this.loadAvisoTvTextSettings()),
+ takeUntil(this.destroy$)
+ )
+ .subscribe();
}
+
+ private startProgressBar(seitenwechselInSek: number): void {
+ // Falls eine vorherige Subscription existiert, beenden wir sie
+ if (this.progressBarSubscription) {
+ this.progressBarSubscription.unsubscribe();
+ }
+
+ // Setzen des Fortschrittswerts auf 0
+ this.progressBarValue = 0;
+
+ const progressBarIntervalMs = 100; // Aktualisierung alle 100ms
+ const totalSteps = Math.floor((seitenwechselInSek * 1000) / progressBarIntervalMs);
+
+ this.progressBarSubscription = interval(progressBarIntervalMs)
+ .pipe(
+ take(totalSteps),
+ map((step) => (step + 1) / totalSteps),
+ takeUntil(this.destroy$)
+ )
+ .subscribe((progress) => {
+ this.progressBarValue = progress;
+ this.cdr.detectChanges();
+ });
+ }
+
+ getOverallIndex(i: number): number {
+ let count = 0;
+ for (let j = 0; j < this.currentPageIndex; j++) {
+ count += this.pages[j].length;
+ }
+ return count + i + 1;
+ }
+
+
+ private preprocessHtmlSettings() {
+ this.settingDisplayData = this.avisoTvTextSettings.map((setting, index) => {
+ const nonEmptyFixeZeilen = [];
+
+ // Verarbeiten von fixeZeile1
+ if (setting.fixeZeile1) {
+ const { sanitizedHtml, textAlign } = this.processHtml(setting.fixeZeile1, index);
+ nonEmptyFixeZeilen.push({ sanitizedHtml, textAlign });
+ }
+
+ // Verarbeiten von fixeZeile2
+ if (setting.fixeZeile2) {
+ const { sanitizedHtml, textAlign } = this.processHtml(setting.fixeZeile2, index);
+ nonEmptyFixeZeilen.push({ sanitizedHtml, textAlign });
+ }
+
+ // Verarbeiten von fixeZeile3
+ if (setting.fixeZeile3) {
+ const { sanitizedHtml, textAlign } = this.processHtml(setting.fixeZeile3, index);
+ nonEmptyFixeZeilen.push({ sanitizedHtml, textAlign });
+ }
+
+ return {
+ nonEmptyFixeZeilen,
+ currentDivIndex: 0
+ };
+ });
+ }
+
+ private processHtml(html: string, index: number): { sanitizedHtml: SafeHtml; textAlign: string } {
+ // Vermeide das Modifizieren des HTML-Inhalts, um die Formatierung zu erhalten
+ const sanitizedHtml = this.sanitizer.bypassSecurityTrustHtml(html);
+
+ // Extrahiere text-align aus dem ersten Div
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(html, 'text/html');
+ const firstDiv = doc.querySelector('div');
+ let textAlign = 'left';
+ if (firstDiv) {
+ textAlign = firstDiv.style.textAlign || 'left';
+ }
+ return { sanitizedHtml, textAlign };
+ }
ngOnDestroy() {
- // Beenden aller Subscriptions, um Speicherlecks zu vermeiden
this.destroy$.next();
this.destroy$.complete();
- // Beende auch die Page Rotation Subscription, falls du separate Subjects verwendest
- // this.pageRotation$.next();
- // this.pageRotation$.complete();
- }
+ if (this.toggleDivInterval) {
+ clearInterval(this.toggleDivInterval);
+ }
- /**
- * Lädt die Ankünfte (Arrivals) von der API.
- */
- loadArrivals() {
- this.loadingArrivals = true;
- this.avisoService
- .getArrivals(this.standort, this.seiten, this.onlyOK)
- .pipe(takeUntil(this.destroy$))
- .subscribe(
- (data: AvisoArrivalsResponse) => {
- console.log('Received arrivals data:', data);
- this.arrivals = data.avisos;
- this.totalArrivals = data.totalCount;
- this.loadingArrivals = false;
- this.paginateArrivals();
- this.cdr.detectChanges();
- },
- (error) => {
- console.error('Fehler beim Laden der Arrivals:', error);
- this.presentToast(`Fehler beim Laden der Arrivals: ${error}`);
- this.errorMessage = 'Fehler beim Laden der Arrivals. Bitte versuche es später erneut.';
- this.loadingArrivals = false;
- }
- );
- }
+ if (this.progressBarSubscription) {
+ this.progressBarSubscription.unsubscribe();
+ }
- /**
- * Lädt die Aviso TV Einstellungen von der API.
- */
- loadAvisoTvSettings() {
- this.loadingSettings = true;
- this.avisoService
- .getAvisoTvSettings(this.standort)
- .pipe(takeUntil(this.destroy$))
- .subscribe(
- (data: AvisoTvSettingsDto[]) => { // Typisierung als Array
- console.log('Received TV settings data:', data); // Zum Debuggen
- this.avisoTvSettings = data;
- this.totalSettings = data.length; // Setze totalSettings auf die Länge des Arrays
- this.loadingSettings = false;
- this.cdr.detectChanges(); // Manuelle Change Detection
- showFirstDiv: true // Initialisiere alle auf true
-
- // Debugging: Überprüfe jede Einstellung
- this.avisoTvSettings.forEach(setting => {
- console.log(`Setting ID: ${setting.tvTextBezeichnungID}, isActive: ${setting.isActive}, position: ${setting.position}, fixeZeile1: ${setting.fixeZeile1}`);
- });
- },
- (error) => {
- console.error('Fehler beim Laden der TV Settings:', error);
- this.presentToast(`Fehler beim Laden der TV Settings: ${error}`);
- this.settingsErrorMessage = 'Fehler beim Laden der TV Settings. Bitte versuche es später erneut.';
- this.loadingSettings = false;
- }
- );
- }
-
- startDivToggle() {
- this.toggleDivInterval = setInterval(() => {
- this.showFirstDiv = !this.showFirstDiv;
- this.cdr.detectChanges(); // Manuelle Change Detection, falls nötig
- }, 5000); // 5000 Millisekunden = 5 Sekunden
- }
- /**
- * Lädt Arrivals und TV-Einstellungen basierend auf aktuellen Filtern.
- */
- applyFilters() {
- this.loadArrivals();
- this.loadAvisoTvSettings();
- }
-
- /**
- * Zeigt eine Toast-Nachricht an.
- * @param message Die Nachricht, die angezeigt werden soll.
- */
- async presentToast(message: string) {
- const toast = await this.toastController.create({
- message: message,
- duration: 3000,
- position: 'bottom',
- });
- toast.present();
- }
-
- // Methoden zur Bestimmung von Statusklassen und -farben
- getStatusClass(status: number): string {
- switch (status) {
- case 0:
- return 'statusLKW_Erfasst';
- case 1:
- return 'statusLKW_Freigegeben';
- case 2:
- return 'statusLKW_LKW_neu';
- case 3:
- return 'statusLKW_Ankunft';
- case 4:
- return 'statusLKW_Vorbereitet';
- case 5:
- return 'statusLKW_Vorgeschrieben';
- default:
- return 'status-default';
+ if (this.dateSubscription) {
+ this.dateSubscription.unsubscribe();
}
}
+
+ private setCSSVariables(): void {
+ if (this.avisoTvSettings && this.avisoTvSettings.length > 0) {
+ const settings = this.avisoTvSettings[0];
+ const newCssVariables: CssVariables = {
+ tileWidthPercent: `${settings.kachelWidthInPercent}vw`,
+ tileHeightVh: `${settings.kachelHeightInPercent}vh`,
+ tileTitleFontSize: `${settings.kachelFontSizeLkwNummer}vh`,
+ tileFontSizeDateTime: `${settings.kachelFontSizeDateTime}vh`,
+ tileSeitenwechselInSek: `${settings.seitenwechselInSek}s`,
+ textBalkenHeightVh: `${settings.textBalkenHeightInPercent}vh`,
+ };
+
+ if (this.currentCssVariables && this.hasCssVariablesChanged(newCssVariables)) {
+ this.reloadPageOnce();
+ return;
+ }
+
+ Object.assign(this, newCssVariables);
+ this.currentCssVariables = newCssVariables;
+ } else {
+ console.warn('avisoTvSettings ist nicht verfügbar oder leer');
+ }
+ }
+
+ private hasCssVariablesChanged(newVars: CssVariables): boolean {
+ return Object.keys(newVars).some(key => (newVars as any)[key] !== (this.currentCssVariables as any)[key]);
+ }
+
+ private async loadAvisoTvSettings(): Promise {
+ this.loadingTvSettings = true;
+ try {
+ const data: TvSettings[] = await lastValueFrom(
+ this.avisoService.getAvisoTvSettings(this.avisoTvTextSettings[0]?.standortID || this.standortID).pipe(
+ tap((data: TvSettings[]) => {
+ this.avisoTvSettings = data;
+ this.loadingTvSettings = false;
+ this.setCSSVariables();
+ }),
+ catchError((error: any) => this.handleSettingsError(error, 'TV Settings'))
+ )
+ );
+ } catch {
+ // Fehler wird bereits in handleSettingsError behandelt
+ }
+ }
+
+ private async loadAvisoTvTextSettings(): Promise {
+ this.loadingTextSettings = true;
+ try {
+ const data: AvisoTvTextSettingsDto[] = await lastValueFrom(
+ this.avisoService.getAvisoTvTextSettings(this.standort).pipe(
+ tap((data: AvisoTvTextSettingsDto[]) => {
+ this.avisoTvTextSettings = data;
+ this.totalTextSettings = data.length;
+ this.loadingTextSettings = false;
+ // Process the new HTML settings
+ this.preprocessHtmlSettings();
+ }),
+ catchError((error: any) => this.handleSettingsError(error, 'TV Text Settings'))
+ )
+ );
+ } catch {
+ // Fehler wird bereits in handleSettingsError behandelt
+ }
+ }
+
+ private handleSettingsError(error: any, context: string) {
+ console.error(`Fehler beim Laden der ${context}:`, error);
+ this.settingsErrorMessage = `Fehler beim Laden der ${context}. Bitte versuche es später erneut.`;
+ this.loadingTvSettings = false;
+ this.loadingTextSettings = false;
+ return throwError(error);
+ }
+
+ private startDivToggle(): void {
+ const shouldToggle = this.settingDisplayData.some(data => data.nonEmptyFixeZeilen.length > 1);
+
+ if (shouldToggle) {
+ this.toggleDivInterval = setInterval(() => {
+ this.settingDisplayData.forEach(data => {
+ if (data.nonEmptyFixeZeilen.length > 1) {
+ data.currentDivIndex = (data.currentDivIndex + 1) % data.nonEmptyFixeZeilen.length;
+ }
+ });
+ this.cdr.detectChanges();
+ }, TOGGLE_DIV_INTERVAL_MS);
+ } else {
+ // Initialize currentDivIndex to 0
+ this.settingDisplayData.forEach(data => data.currentDivIndex = 0);
+ }
+ }
+
+ // Status-Methoden mithilfe des STATUS_MAP
+ getStatusClass(status: number, lkwFertig: boolean): string {
+ if (lkwFertig) {
+ return STATUS_MAP['lkwfertig'].class;
+ }
+ return STATUS_MAP[status.toString()]?.class || STATUS_MAP['default'].class;
+ }
+
+
getStatusIcon(status: number): string {
- switch (status) {
- case 0:
- return 'checkmark-circle'; // Erfasst
- case 1:
- return 'checkmark-circle'; // Freigegeben
- case 2:
- return 'help-circle'; // LKW n.e.
- case 3:
- return 'time'; // Ankunft
- case 4:
- return 'construct'; // Vorbereitet
- case 5:
- return 'bookmarks'; // Vorgeschrieben
- default:
- return 'help-circle'; // Unbekannt
- }
+ return STATUS_MAP[status.toString()]?.icon || STATUS_MAP['default'].icon;
}
getStatusColor(status: number): string {
- switch (status) {
- case 0:
- return 'success'; // Erfasst - Grün
- case 1:
- return 'primary'; // Freigegeben - Blau
- case 2:
- return 'warning'; // LKW n.e. - Gelb/Orange
- case 3:
- return 'warning'; // Ankunft - Gelb/Orange
- case 4:
- return 'secondary'; // Vorbereitet - Grau
- case 5:
- return 'tertiary'; // Vorgeschrieben - Violett
- default:
- return 'medium'; // Unbekannt - Grau
- }
+ return STATUS_MAP[status.toString()]?.color || STATUS_MAP['default'].color;
}
getStatusText(status: number): string {
- switch (status) {
- case 0:
- return 'Erfasst';
- case 1:
- return 'Freigegeben';
- case 2:
- return 'LKW n.e.';
- case 3:
- return 'Ankunft';
- case 4:
- return 'Vorbereitet';
- case 5:
- return 'Vorgeschrieben';
- default:
- return 'Unbekannt';
- }
+ return STATUS_MAP[status.toString()]?.text || STATUS_MAP['default'].text;
}
/**
@@ -386,99 +442,155 @@ export class AvisoPage implements OnInit, OnDestroy {
* @returns Eine CSS-Klassen-String
*/
getPositionClass(position: string): string {
- const pos = position.toLowerCase(); // Konvertiere zu Kleinbuchstaben
- switch (pos) {
- case 'top':
- return 'position-top';
- case 'middle':
- return 'position-middle';
- case 'left':
- return 'position-left';
- case 'right':
- return 'position-right';
- default:
- return '';
+ const pos = position.toLowerCase();
+ const positionClasses: { [key: string]: string } = {
+ 'top': 'position-top',
+ 'middle': 'position-middle',
+ 'left': 'position-left',
+ 'right': 'position-right'
+ };
+ return positionClasses[pos] || '';
+ }
+
+ private reloadPageOnce(): void {
+ if (!sessionStorage.getItem('pageReloaded')) {
+ sessionStorage.setItem('pageReloaded', 'true');
+ window.location.reload();
+ } else {
+ sessionStorage.removeItem('pageReloaded');
}
}
// Paginierung der Arrivals
- paginateArrivals() {
- // Berechnung der verfügbaren Breite und Höhe
- const windowWidth = window.innerWidth;
- const windowHeight = window.innerHeight;
- // Definiere die Prozentsätze für Layout-Parameter
- const titleHeightPercent = 5; // z.B. 10% der Fensterhöhe
- const htmltextPercent = this.totalArrivals > 0 ? 30 : 0;
-
- const containerPaddingPercent = 0; // z.B. 5% der Fensterbreite
- const gutterPercent = 1;
- const tileWidthPercent = 15; // z.B. 20% der Fensterbreite
- const tileHeightPercent = 23; // z.B. 25% der Fensterhöhe
-
-
-
- const containerPadding = (containerPaddingPercent / 100) * windowWidth;
- const gutter = (gutterPercent / 100) * windowWidth;
- const tileWidth = (tileWidthPercent / 100) * windowWidth;
- const tileHeight = (tileHeightPercent / 100) * windowHeight;
-
- // Berechnung der verfügbaren Breite für die Kacheln
- const containerPaddingTotal = containerPadding * 2; // Links und rechts
- const columns = Math.floor((windowWidth - containerPaddingTotal + gutter) / (tileWidth + gutter));
-
- // Berechnung der verfügbaren Höhe für die Kacheln
- const titleHeight = (titleHeightPercent / 100) * windowHeight;
- let htmltext = 0;
- if (this.totalArrivals > 0) {
- htmltext = (htmltextPercent / 100) * windowHeight;
+ private paginateArrivals(): void {
+ if (!this.avisoTvSettings || this.avisoTvSettings.length === 0) {
+ return;
}
- const availableHeightForTiles = windowHeight - htmltext - titleHeight - containerPadding * 2 - gutter * (columns > 1 ? columns : 0);
+ const settings = this.avisoTvSettings[0];
+ const windowWidth = window.outerWidth;
+ const windowHeight = window.outerHeight;
- // Berechnung der maximal möglichen Kacheln pro Spalte
- const rows = Math.floor((availableHeightForTiles + gutter) / (tileHeight + gutter));
+ const tileWidth = (settings.kachelWidthInPercent / 100) * windowWidth;
+ const tileHeight = (settings.kachelHeightInPercent / 100) * windowHeight;
+ const logo = (10 / 100) * windowHeight;
+
+ // Definieren Sie separate horizontale und vertikale Gutter
+ const gutterHorizontal = (1 / 100) * windowHeight;
+ const gutterVertical = (1 / 100) * windowHeight;
+
+ const containerPadding = (0 / 100) * windowHeight;
+
+ const containerPaddingTotal = containerPadding * 2;
+
+ // Berechnung der Spalten unter Verwendung von gutterHorizontal
+ const columns = Math.floor(
+ (windowWidth - containerPaddingTotal + gutterHorizontal) / (tileWidth + gutterHorizontal)
+ ) || 1;
+
+ const htmltext = this.totalArrivals > 0 ? (settings.textBalkenHeightInPercent / 100) * windowHeight : 0;
+
+ // Verfügbare Höhe für Kacheln unter Verwendung von gutterVertical
+ const availableHeightForTiles =
+ windowHeight -
+ logo -
+ htmltext -
+ containerPadding * 2 -
+ gutterVertical * (columns > 1 ? columns : 0);
+
+ // Berechnung der Reihen unter Verwendung von gutterVertical
+ const rows = Math.floor(
+ (availableHeightForTiles + gutterVertical) / (tileHeight + gutterVertical)
+ ) || 1;
- // Berechnung der Kacheln pro Seite
this.tilesPerPage = columns * rows;
-
- // Sicherstellen, dass mindestens eine Kachel pro Seite angezeigt wird
this.tilesPerPage = this.tilesPerPage > 0 ? this.tilesPerPage : 1;
- console.log('Columns:', columns);
- console.log('Rows:', rows);
- console.log('Tiles per Page:', this.tilesPerPage);
-
- // Aufteilung der Arrivals in Seiten
this.pages = [];
for (let i = 0; i < this.arrivals.length; i += this.tilesPerPage) {
this.pages.push(this.arrivals.slice(i, i + this.tilesPerPage));
}
- // Reset der aktuellen Seite, wenn nötig
if (this.currentPageIndex >= this.pages.length) {
this.currentPageIndex = 0;
}
-
- console.log('Total Pages:', this.pages.length);
}
- // Automatisches Wechseln der Seiten alle 10 Sekunden
- startPageRotation() {
- interval(10000) // 10000 Millisekunden = 10 Sekunden
- .pipe(takeUntil(this.destroy$))
- .subscribe(() => {
- if (this.pages.length > 0) {
- this.currentPageIndex = (this.currentPageIndex + 1) % this.pages.length;
- console.log('Wechsel zu Seite:', this.currentPageIndex + 1);
- }
- });
+
+ // Automatisches Wechseln der Seiten alle seitenwechselInSek Sekunden
+ private startPageRotation(): void {
+ if (!this.avisoTvSettings || this.avisoTvSettings.length === 0) {
+ console.warn('avisoTvSettings ist nicht verfügbar oder leer');
+ return;
+ }
+
+ const seitenwechselInSek = this.avisoTvSettings[0].seitenwechselInSek;
+ console.log('Seitenwechselintervall (Sek):', seitenwechselInSek);
+
+ if (typeof seitenwechselInSek === 'number' && seitenwechselInSek > 0) {
+ const intervalMs = seitenwechselInSek * 1000;
+ console.log('Seitenwechselintervall (ms):', intervalMs);
+
+ // Starten Sie den Fortschrittsbalken
+ this.startProgressBar(seitenwechselInSek);
+
+ interval(intervalMs)
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(() => {
+ if (this.pages.length > 0) {
+ this.currentPageIndex = (this.currentPageIndex + 1) % this.pages.length;
+ console.log('Wechsel zu Seite:', this.currentPageIndex + 1);
+ this.cdr.detectChanges();
+
+ // Fortschrittsbalken neu starten
+ this.startProgressBar(seitenwechselInSek);
+ } else {
+ console.warn('Keine Seiten verfügbar zum Wechseln');
+ }
+ });
+ } else {
+ console.warn('seitenwechselInSek ist ungültig:', seitenwechselInSek);
+ }
}
+
/**
* Event Listener für Fenstergrößenänderungen, um die Paginierung anzupassen
*/
- @HostListener('window:resize', ['$event'])
- onResize(event: Event) {
+ @HostListener('window:resize')
+ onResize(): void {
this.paginateArrivals();
}
+
+ /**
+ * Vergleicht zwei Arrivals-Arrays, um festzustellen, ob sie gleich sind.
+ * @param a Erstes Arrivals-Array
+ * @param b Zweites Arrivals-Array
+ * @returns `true`, wenn beide Arrays gleich sind, ansonsten `false`
+ */
+ private arrivalsAreEqual(a: AvisoDto[], b: AvisoDto[]): boolean {
+ if (a.length !== b.length) {
+ return false;
+ }
+
+ for (let i = 0; i < a.length; i++) {
+ if (
+ a[i].avisoID !== b[i].avisoID ||
+ a[i].status !== b[i].status ||
+ a[i].lkW_Nr !== b[i].lkW_Nr ||
+ a[i].ankunft !== b[i].ankunft ||
+ a[i].dauer !== b[i].dauer ||
+ a[i].letzterMitarbeiter !== b[i].letzterMitarbeiter ||
+ a[i].weiterleitungTextTV !== b[i].weiterleitungTextTV ||
+ a[i].imEx !== b[i].imEx ||
+ a[i].zollDigitalEingereicht !== b[i].zollDigitalEingereicht ||
+ a[i].buero !== b[i].buero ||
+ a[i].avisoTVHinweis !== b[i].avisoTVHinweis
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
diff --git a/src/app/pages/aviso/aviso.resolver.ts b/src/app/pages/aviso/aviso.resolver.ts
new file mode 100644
index 0000000..b7f1407
--- /dev/null
+++ b/src/app/pages/aviso/aviso.resolver.ts
@@ -0,0 +1,52 @@
+// src/app/resolvers/aviso.resolver.ts
+
+import { Injectable } from '@angular/core';
+import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
+import { Observable, forkJoin, of } from 'rxjs';
+import { catchError } from 'rxjs/operators';
+import { AvisoService, AvisoArrivalsResponse } from '../../services/aviso.service';
+import { AvisoTvTextSettingsDto, TvSettings } from '../../services/aviso.dto';
+
+interface AvisoResolvedData {
+ avisoTvTextSettings: AvisoTvTextSettingsDto[];
+ avisoTvSettings: TvSettings[];
+ arrivals: AvisoArrivalsResponse;
+}
+
+@Injectable({
+ providedIn: 'root',
+})
+export class AvisoResolver implements Resolve {
+ constructor(private avisoService: AvisoService) { }
+
+ resolve(
+ route: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot
+ ): Observable {
+ const standort = route.paramMap.get('standort') || 'SUB';
+ const seiten = route.queryParamMap.get('seiten') === 'true';
+ const onlyOK = route.queryParamMap.get('onlyOK') === 'true';
+ const standortID = parseInt(route.paramMap.get('standortID') || '1', 10);
+
+ return forkJoin({
+ avisoTvTextSettings: this.avisoService.getAvisoTvTextSettings(standort).pipe(
+ catchError(error => {
+ console.error('Fehler beim Laden der TV Text Settings', error);
+ return of([]);
+ })
+ ),
+ avisoTvSettings: this.avisoService.getAvisoTvSettings(standortID).pipe(
+ catchError(error => {
+ console.error('Fehler beim Laden der TV Settings', error);
+ return of([]);
+ })
+ ),
+ arrivals: this.avisoService.getArrivals(standort, seiten, onlyOK).pipe(
+ catchError(error => {
+ console.error('Fehler beim Laden der Arrivals', error);
+ return of({ avisos: [], totalCount: 0 });
+ })
+ )
+ });
+ }
+}
diff --git a/src/app/services/aviso-tv-settings.dto.ts b/src/app/services/aviso-tv-settings.dto.ts
index cc1e17f..396f617 100644
--- a/src/app/services/aviso-tv-settings.dto.ts
+++ b/src/app/services/aviso-tv-settings.dto.ts
@@ -1,4 +1,4 @@
-export interface AvisoTvSettingsDto {
+export interface AvisoTvTextSettingsDto {
tvTextBezeichnungID: number;
standortID: number;
tvTextBezeichnung: string;
diff --git a/src/app/services/aviso.dto.ts b/src/app/services/aviso.dto.ts
index c3212b4..e47d84e 100644
--- a/src/app/services/aviso.dto.ts
+++ b/src/app/services/aviso.dto.ts
@@ -2,6 +2,7 @@ export interface AvisoDto {
avisoID: number;
status: number;
lkW_Nr: string;
+ lkW_fertig: boolean;
ankunft: string | null;
dauer: string;
letzterMitarbeiter: string;
@@ -11,3 +12,40 @@ export interface AvisoDto {
buero: string;
avisoTVHinweis: string;
}
+
+export interface TvSettings {
+ TvSettingID: number;
+ StandortID: number;
+ kachelWidthInPercent: number;
+ kachelHeightInPercent: number;
+ kachelFontSizeLkwNummer: number;
+ kachelFontSizeDateTime: number;
+ seitenwechselInSek: number;
+ textBalkenHeightInPercent: number;
+ logo: string;
+}
+
+export interface AvisoTvTextSettingsDto {
+ tvTextBezeichnungID: number;
+ standortID: number;
+ tvTextBezeichnung: string;
+ standort: string;
+ position: string;
+ fixeZeile1?: string;
+ fixeZeile2?: string;
+ fixeZeile3?: string;
+ art?: string;
+ startDate?: string | null;
+ endDate?: string | null;
+ startTime?: string | null;
+ endTime?: string | null;
+ isRecurring: boolean;
+ isMonday: boolean;
+ isTuesday: boolean;
+ isWednesday: boolean;
+ isThursday: boolean;
+ isFriday: boolean;
+ isSaturday: boolean;
+ isSunday: boolean;
+ isActive: boolean;
+}
diff --git a/src/app/services/aviso.service.ts b/src/app/services/aviso.service.ts
index f26e3d9..e4c8c5b 100644
--- a/src/app/services/aviso.service.ts
+++ b/src/app/services/aviso.service.ts
@@ -2,8 +2,8 @@ import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
-import { AvisoDto } from './aviso.dto'; // Importiere das Interface
-import { AvisoTvSettingsDto } from './aviso-tv-settings.dto'; // Importiere das neue Interface
+import { AvisoDto, TvSettings } from './aviso.dto'; // Importiere das Interface
+import { AvisoTvTextSettingsDto } from './aviso-tv-settings.dto'; // Importiere das neue Interface
// Definiere die Response Interfaces
export interface AvisoArrivalsResponse {
@@ -45,10 +45,18 @@ export class AvisoService {
/**
* Holt die Aviso TV Einstellungen basierend auf dem übergebenen Standort.
* @param standort Standort zur Filterung der Einstellungen.
- * @returns Ein Observable von AvisoTvSettingsDto[].
+ * @returns Ein Observable von AvisoTvTextSettingsDto[].
*/
- getAvisoTvSettings(standort: string): Observable {
- return this.http.get(`${this.baseUrl}/${standort}`)
+ getAvisoTvTextSettings(standort: string): Observable {
+ return this.http.get(`${this.baseUrl}/${standort}`)
+ .pipe(
+ tap(data => console.log('AvisoService received TV Text settings data:', data)), // Logge die empfangenen Daten
+ catchError(this.handleError)
+ );
+ }
+
+ getAvisoTvSettings(standortID: number): Observable {
+ return this.http.get(`${this.baseUrl}/AvisoTvSettings/Standort/${standortID}`)
.pipe(
tap(data => console.log('AvisoService received TV settings data:', data)), // Logge die empfangenen Daten
catchError(this.handleError)
diff --git a/src/assets/Logos/verag.png b/src/assets/Logos/verag.png
new file mode 100644
index 0000000..a87a0f0
Binary files /dev/null and b/src/assets/Logos/verag.png differ