This commit is contained in:
2024-12-09 17:44:56 +01:00
parent 77115f9da0
commit b8d00a24d0
17 changed files with 1561 additions and 60 deletions

1
.vscode/launch.json vendored
View File

@@ -7,7 +7,6 @@
"request": "launch",
"url": "http://localhost:8100",
"webRoot": "${workspaceFolder}/www",
"preLaunchTask": "ng serve",
"sourceMaps": true,
"trace": true
},

View File

@@ -5,5 +5,11 @@
<CleanCommand>
</CleanCommand>
<StartupCommand>ionic serve</StartupCommand>
<BuildCommand>
</BuildCommand>
<ProductionBuildCommand>
</ProductionBuildCommand>
<BuildOutputFolder>
</BuildOutputFolder>
</PropertyGroup>
</Project>

41
gulpfile.js Normal file
View File

@@ -0,0 +1,41 @@
const gulp = require('gulp');
const ftp = require('basic-ftp');
const log = require('fancy-log');
const dotenv = require('dotenv');
const path = require('path');
const fs = require('fs');
// Laden der Umgebungsvariablen aus der .env-Datei (optional)
dotenv.config();
// Deploy Task mit basic-ftp
gulp.task('deploy', async function () {
const client = new ftp.Client();
client.ftp.verbose = true; // Aktiviert detaillierte Logs
try {
// Zugriff auf die FTP-Verbindung
await client.access({
host: process.env.FTP_HOST || 'ftps.verag.ag',
user: process.env.FTP_USER || 'daniel',
password: process.env.FTP_PASS || 'debug',
secure: true, // Aktiviert FTPS (erfordert PROT P)
secureOptions: {
rejectUnauthorized: false // Nur verwenden, wenn Ihr Server ein selbstsigniertes Zertifikat verwendet
}
});
// Wechseln in das Zielverzeichnis
await client.ensureDir(process.env.FTP_DEST || '/Websites/avisotv.app.verag.ag');
await client.cd(process.env.FTP_DEST || '/Websites/avisotv.app.verag.ag');
// Rekursives Hochladen des Inhalts des 'www'-Verzeichnisses
await client.uploadFromDir('www');
log('Deployment erfolgreich abgeschlossen.');
}
catch (err) {
log.error('Deployment fehlgeschlagen:', err);
}
client.close();
});

1380
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -48,10 +48,14 @@
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"basic-ftp": "^5.0.5",
"dotenv": "^16.4.7",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^48.2.1",
"eslint-plugin-prefer-arrow": "1.2.2",
"fancy-log": "^2.0.0",
"gulp": "^5.0.0",
"jasmine-core": "~5.1.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.4.0",
@@ -59,7 +63,8 @@
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.4.0"
"typescript": "~5.4.0",
"vinyl-ftp": "^0.6.1"
},
"description": "An Ionic project"
}

View File

@@ -4,7 +4,7 @@
Header
====================================================== -->
<ion-header>
<!-- Ihr Header-Inhalt -->
</ion-header>
<!-- ======================================================
@@ -73,7 +73,7 @@
</div>
<div *ngIf="aviso.avisoTVHinweis"
[ngClass]="getImageClassButtomLeft(aviso.avisoTVHinweis)"
class="blinking-image">
class="blinking-image bottom-left-image-problem">
<img [src]="getTvHinweisImgSrc(aviso.avisoTVHinweis)" alt="Aviso Hinweis" />
</div>
<div *ngIf="aviso.lkW_fertig && aviso.avisoTVHinweis == '' " class="bottom-left-image-round">
@@ -84,10 +84,10 @@
<ng-template #showAvisoHinweis>
<div class="flex-container">
<div class="flex-container-hinweis" >
<div class="lkwnr" style="margin-top: 1%; margin-bottom: 1%"
appAutoFontSize
[maxFontSizePercentage]="35">
[maxFontSizePercentage]="30">
{{ aviso.avisoTVHinweis }}
</div>
<div class="ion-text-center">

View File

@@ -91,7 +91,7 @@ ion-title {
ion-icon {
vertical-align: middle;
font-size: calc(var(--tile-height-vh) * 0.12);
font-size: calc(var(--tile-height-vh) * 0.15);
margin-right: -3px;
margin-left: 0.1em;
margin-bottom:0.1em;
@@ -267,6 +267,19 @@ ion-icon {
align-items: center;
justify-content: center;
width: 100%;
row-gap: var(--tile-row-gap);
}
.flex-container > div:first-child {
height: 100%;
}
.flex-container-hinweis {
display: flex;
flex-direction: column;
align-items: center;
}

View File

@@ -27,7 +27,6 @@ interface AvisoResolvedData {
arrivals: AvisoArrivalsResponse;
}
interface CssVariables {
tileWidthPercent: string;
tileHeightVh: string;
@@ -54,7 +53,7 @@ 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' },
'fehlt': { class: 'fehlt', icon: 'time', color: 'danger', text: 'Dokument Fehlt' },
'default': { class: 'status-default', icon: 'help-circle', color: 'medium', text: 'Unbekannt' }
'default': { class: 'status-default', icon: 'help-circle', color: 'medium', text: 'Unbekannt' }
};
// Neues Interface für die Anzeige der Fixzeilen
@@ -80,10 +79,7 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
@HostBinding('style.--tile-title-font-size') tileTitleFontSize = '5vh';
@HostBinding('style.--tile-font-size-date-time') tileFontSizeDateTime = '5vh';
@HostBinding('style.--text-balken-height-vh') textBalkenHeightVh = '10vh';
@HostBinding('style.--tile-row-gap') tileRowGapinPercent = '10%';
@HostBinding('style.--tile-row-gap') tileRowGapinPercent = '10px';
progressBarValue: number = 0;
private progressBarSubscription: Subscription = new Subscription();
@@ -168,11 +164,11 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
});
this.route.paramMap.subscribe(params => {
this.standort = params.get('standort') || 'SUB';
this.standortID = parseInt(params.get('standortID') || '1', 10);
this.standort = params.get('standort') || '';
});
this.route.queryParamMap.subscribe(queryParams => {
this.standort = queryParams.get('standort') || 'NEU';
this.seiten = queryParams.get('seiten') === 'true';
this.onlyOK = queryParams.get('onlyOK') === 'true';
});
@@ -188,11 +184,17 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
// Avisos für Testzwecke modifizieren
this.arrivals.forEach(aviso => {
if (aviso.lkW_Nr === '10AKN963') {
if (aviso.lkW_Nr === '34HG827') {
aviso.lkW_Nr = '10AKN96310AKN96310AKN96310AKN963';
}
});
this.arrivals.forEach(aviso => {
if (aviso.lkW_Nr === 'OOLU9267058') {
aviso.avisoTVHinweis = 'URGENT';
}
});
this.paginateArrivals();
this.updateAvisoStatesAndCycles();
this.cdr.detectChanges();
@@ -235,10 +237,17 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
this.totalArrivals = data.totalCount;
this.loadingArrivals = false;
this.arrivals.forEach(aviso => {
// Beispiel: Setze avisoTVHinweis für ein bestimmtes Aviso
if (aviso.lkW_Nr === '10AKN963') {
aviso.lkW_Nr = '10AKN96310AKN96310AKN96310AKN963';
}
this.arrivals.forEach(aviso => {
if (aviso.lkW_Nr === '34HG827') {
aviso.lkW_Nr = '10AKN96310AKN96310AKN96310AKN963';
}
});
this.arrivals.forEach(aviso => {
if (aviso.lkW_Nr === 'OOLU9267058') {
aviso.avisoTVHinweis = 'URGENT';
}
});
});
this.paginateArrivals();
this.updateAvisoStatesAndCycles();
@@ -396,7 +405,7 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
tileFontSizeDateTime: `${settings.kachelFontSizeDateTime}vh`,
tileSeitenwechselInSek: `${settings.seitenwechselInSek}s`,
textBalkenHeightVh: `${settings.textBalkenHeightInPercent}vh`,
tileRowGapinPercent: `${settings.kachelRowGapInPercent}%`,
tileRowGapinPercent: `${settings.kachelRowGapInPercent}px`,
};
if (this.currentCssVariables && this.hasCssVariablesChanged(newCssVariables)) {
@@ -413,7 +422,6 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
}
}
private hasCssVariablesChanged(newVars: CssVariables): boolean {
return Object.keys(newVars).some(key => (newVars as any)[key] !== (this.currentCssVariables as any)[key]);
}
@@ -422,7 +430,7 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
this.loadingTvSettings = true;
try {
const data: TvSettings[] = await lastValueFrom(
this.avisoService.getAvisoTvSettings(this.avisoTvTextSettings[0]?.standortID || this.standortID).pipe(
this.avisoService.getAvisoTvSettings(this.avisoTvTextSettings[0].standortID || this.standortID).pipe(
tap((data: TvSettings[]) => {
this.avisoTvSettings = data;
this.loadingTvSettings = false;
@@ -432,7 +440,6 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
)
);
} catch {
// Fehler wird bereits in handleSettingsError behandelt
}
}
@@ -575,7 +582,11 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
(windowWidth - containerPaddingTotal + gutterHorizontal) / (tileWidth + gutterHorizontal)
) || 1;
const htmltext = this.totalArrivals > 0 ? (settings.textBalkenHeightInPercent / 100) * windowHeight : 0;
// **Änderung beginnt hier**
const htmltext = (this.avisoTvTextSettings && this.avisoTvTextSettings.length > 0 && this.totalArrivals > 0)
? (settings.textBalkenHeightInPercent / 100) * windowHeight
: 0;
// **Änderung endet hier**
// Verfügbare Höhe für Kacheln unter Verwendung von gutterVertical
const availableHeightForTiles =
@@ -601,8 +612,6 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
if (this.currentPageIndex >= this.pages.length) {
this.currentPageIndex = 0;
}
}
// Automatisches Wechseln der Seiten alle seitenwechselInSek Sekunden
@@ -652,7 +661,6 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
}
}
/**
* Event Listener für Fenstergrößenänderungen, um die Paginierung anzupassen
*/
@@ -816,6 +824,8 @@ export class AvisoPage implements OnInit, OnDestroy, AfterViewInit {
return 'problem';
} else if (lowercaseHinweis === 'passport') {
return 'passport';
} else if (lowercaseHinweis != '') {
return 'problem';
} else {
return '';
}

View File

@@ -1,7 +1,8 @@
// aviso-resolver.service.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 { catchError, switchMap } from 'rxjs/operators';
import { AvisoService, AvisoArrivalsResponse } from '../../services/aviso.service';
import { AvisoTvTextSettingsDto, TvSettings } from '../../services/aviso.dto';
@@ -21,30 +22,65 @@ export class AvisoResolver implements Resolve<AvisoResolvedData> {
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<AvisoResolvedData> {
const standort = route.paramMap.get('standort') || 'SUB';
const standort = route.queryParamMap.get('standort') || '';
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 });
})
)
});
if (!standort) {
console.error('Standort-Parameter fehlt.');
return of({
avisoTvTextSettings: [],
avisoTvSettings: [],
arrivals: { avisos: [], totalCount: 0 }
} as AvisoResolvedData);
}
return this.avisoService.getStandortID(standort).pipe(
catchError(error => {
console.error('Fehler beim Abrufen der StandortID', error);
return of(null);
}),
switchMap(result => {
if (!result || !result.standortID) {
console.error('StandortID konnte nicht abgerufen werden.');
return of({
avisoTvTextSettings: [],
avisoTvSettings: [],
arrivals: { avisos: [], totalCount: 0 }
} as AvisoResolvedData);
}
const standortID = result.standortID;
return forkJoin({
avisoTvTextSettings: this.avisoService.getAvisoTvTextSettings(standort).pipe(
catchError(error => {
console.error('Fehler beim Laden der TV Text Settings', error);
return of([] as AvisoTvTextSettingsDto[]);
})
),
avisoTvSettings: this.avisoService.getAvisoTvSettings(standortID).pipe(
catchError(error => {
console.error('Fehler beim Laden der TV Settings', error);
return of([] as TvSettings[]);
})
),
arrivals: this.avisoService.getArrivals(standort, seiten, onlyOK).pipe(
catchError(error => {
console.error('Fehler beim Laden der Arrivals', error);
return of({ avisos: [], totalCount: 0 } as AvisoArrivalsResponse);
})
)
});
}),
catchError(error => {
console.error('Allgemeiner Fehler im Resolver', error);
return of({
avisoTvTextSettings: [],
avisoTvSettings: [],
arrivals: { avisos: [], totalCount: 0 }
} as AvisoResolvedData);
})
);
}
}

View File

@@ -23,6 +23,7 @@ export interface TvSettings {
kachelRowGapInPercent: number;
seitenwechselInSek: number;
textBalkenHeightInPercent: number;
lineHeight: number;
logo: string;
}
@@ -50,3 +51,7 @@ export interface AvisoTvTextSettingsDto {
isSunday: boolean;
isActive: boolean;
}
export interface StandorteTV {
StandortID: number;
Standort: string;
}

View File

@@ -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, TvSettings } from './aviso.dto'; // Importiere das Interface
import { AvisoTvTextSettingsDto } from './aviso-tv-settings.dto'; // Importiere das neue Interface
import { AvisoDto, TvSettings } from './aviso.dto';
import { AvisoTvTextSettingsDto } from './aviso-tv-settings.dto';
import { environment } from '../../environments/environment';
// Definiere die Response Interfaces
@@ -36,7 +36,7 @@ export class AvisoService {
.set('seiten', seiten.toString())
.set('onlyOK', onlyOK.toString());
return this.http.get<AvisoArrivalsResponse>(`${this.baseUrl}/arrivals`, { params })
return this.http.get<AvisoArrivalsResponse>(`${this.baseUrl}/Aviso/arrivals`, { params })
.pipe(
tap(data => console.log('AvisoService received arrivals data:', data)), // Logge die empfangenen Daten
catchError(this.handleError)
@@ -49,9 +49,9 @@ export class AvisoService {
* @returns Ein Observable von AvisoTvTextSettingsDto[].
*/
getAvisoTvTextSettings(standort: string): Observable<AvisoTvTextSettingsDto[]> {
return this.http.get<AvisoTvTextSettingsDto[]>(`${this.baseUrl}/${standort}`)
return this.http.get<AvisoTvTextSettingsDto[]>(`${this.baseUrl}/AvisoTv/${standort}`)
.pipe(
tap(data => console.log('AvisoService received TV Text settings data:', data)), // Logge die empfangenen Daten
tap(data => console.log('AvisoService received TV Text settings data:', data)),
catchError(this.handleError)
);
}
@@ -94,4 +94,12 @@ export class AvisoService {
}
return throwError(errorMessage);
}
getStandortID(standort: string): Observable<{ standortID: number }> {
return this.http.get<{ standortID: number }>(`${this.baseUrl}/AvisoTv/StandortID/${standort}`)
.pipe(
tap(data => console.log('AvisoService received StandortID:', data)),
catchError(this.handleError)
);
}
}

BIN
src/assets/Logos/atilla.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
src/assets/Logos/imex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@@ -4,7 +4,7 @@
export const environment = {
production: false,
baseUrl: 'https://localhost:7063/api/Aviso'
baseUrl: 'https://localhost:7063/api'
};