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 @@ -
- + + [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