diff --git a/angular/src/app/_views/trip/trip-detail/trip-detail.component.html b/angular/src/app/_views/trip/trip-detail/trip-detail.component.html index 3bf0ed6..fdb48ba 100644 --- a/angular/src/app/_views/trip/trip-detail/trip-detail.component.html +++ b/angular/src/app/_views/trip/trip-detail/trip-detail.component.html @@ -9,7 +9,6 @@
@@ -33,10 +32,10 @@
- } \ No newline at end of file diff --git a/angular/src/app/_views/trip/trip-detail/trip-detail.component.ts b/angular/src/app/_views/trip/trip-detail/trip-detail.component.ts index 52789c6..65b8dc2 100644 --- a/angular/src/app/_views/trip/trip-detail/trip-detail.component.ts +++ b/angular/src/app/_views/trip/trip-detail/trip-detail.component.ts @@ -24,34 +24,15 @@ import {TranslateService} from "@ngx-translate/core"; templateUrl: './trip-detail.component.html', styleUrl: './trip-detail.component.scss' }) -export class TripDetailComponent implements OnInit, AfterViewInit { +export class TripDetailComponent implements OnInit { protected trip!: TripJsonld; - protected readonly FormMode = FormMode; - protected originalUserTrips: UserTripJsonld[] = []; - protected tripLocations: TripLocationJsonld[] = []; - protected userTrips: UserTripJsonld[] = []; - protected userTripEvents: UserTripEventJsonld[] = []; protected users: UserJsonld[] = []; - protected locationForms: FormGroup[] = []; - protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations(); - protected userForms: FormGroup[] = []; - protected userColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefUsers(); - protected originalTripLocations: TripLocation[] = []; - - - @ViewChildren(SearchSelectComponent) searchSelects!: QueryList; constructor( private tripService: TripService, - private tripLocationService: TripLocationService, - private locationService: LocationService, - private userTripService: UserTripService, - private userTripEventService: UserTripEventService, - private userService: UserService, protected appHelperService: AppHelperService, protected translateService: TranslateService, private route: ActivatedRoute, - private fb: FormBuilder ) {} ngOnInit() { @@ -59,268 +40,8 @@ export class TripDetailComponent implements OnInit, AfterViewInit { this.tripService.tripsIdGet(params['id']).subscribe( data => { this.trip = data; - this.loadTripLocations(); - this.loadUserTrips(); - this.loadUserTripEvents(); } ); }); } - - ngAfterViewInit() { - // Reinitialize search selects when they change - this.searchSelects.changes.subscribe(components => { - components.forEach((component: SearchSelectComponent) => { - // Force search selects to initialize - if (component.dataSet) { - component.ngAfterViewInit(); - } - }); - }); - } - - loadTripLocations() { - this.tripLocationService.tripLocationsGetCollection( - 1, - 200, - this.trip !== undefined ? this.trip.id : undefined, - ).subscribe( - data => { - this.tripLocations = data.member; - // Create a form for each trip location - this.locationForms = []; - this.originalTripLocations = JSON.parse(JSON.stringify(this.tripLocations)); - this.tripLocations.forEach((tripLocation) => { - this.locationForms.push(this.createLocationForm(tripLocation.location?.id ?? null)); - }); - } - ); - } - - createLocationForm(locationIri: string | null): FormGroup { - return this.fb.group({ - location: [locationIri] - }); - } - - createUserForm(): FormGroup { - return this.fb.group({ - user: [null] - }); - } - - getLocations = (page: number, pageSize: number, term?: string): Observable => { - return this.locationService.locationsGetCollection(page, pageSize, term); - } - - getUsers = (page: number, pageSize: number, term?: string): Observable => { - // Sammeln Sie alle aktuell ausgewählten Benutzer-IDs (sowohl gespeicherte als auch nicht gespeicherte) - const assignedUserIds: string[] = []; - - // IDs aus bestehenden UserTrips (mit gültiger ID) - this.userTrips - .filter(ut => ut.user && ut.user.id) - .forEach(ut => assignedUserIds.push(this.appHelperService.extractId(ut.user?.id!))); - - // IDs aus aktuellen Formularwerten (auch für noch nicht gespeicherte Einträge) - this.userForms.forEach(form => { - const userValue = form.get('user')?.value; - if (userValue) { - assignedUserIds.push(this.appHelperService.extractId(userValue)); - } - }); - - // Filtere Benutzer, die bereits ausgewählt sind (gespeichert oder nicht) - return this.userService.usersGetCollection( - page, - pageSize, - undefined, - undefined, - term, - '{"isPilot":true}' - ).pipe( - map(response => { - response.member = response.member.filter(user => - !assignedUserIds.includes(this.appHelperService.extractId(user.id!)) - ); - return response; - }) - ); - } - - onUserSelectChange(index: number) { - // Erzwingen Sie eine Aktualisierung aller anderen SearchSelect-Komponenten - setTimeout(() => { - if (this.searchSelects) { - this.searchSelects.forEach((component, i) => { - // Überspringen Sie das aktuelle SearchSelect (es muss nicht aktualisiert werden) - if (i !== index) { - component.ngAfterViewInit(); - } - }); - } - }); - } - - onFormUpdate(event: FormSubmitEvent) { - if (event.status === ModalStatus.Submitted && event.data) { - this.trip = event.data; - } - } - - addNewUserTrip() { - // Erstelle ein unvollständiges Objekt (ohne user-Property) - const newUserTrip: UserTripJsonld = { - tripIri: this.trip.id!, - userIri: null, - completed: false, - approved: false, - }; - - // Füge es als UserTripJsonld hinzu - this.userTrips.push(newUserTrip as UserTripJsonld); - this.userForms.push(this.createUserForm()); - - // Rest unverändert... - setTimeout(() => { - if (this.searchSelects) { - const lastSelect = this.searchSelects.last; - if (lastSelect) { - lastSelect.ngAfterViewInit(); - } - } - }); - } - - loadUserTrips() { - this.userTripService.userTripsGetCollection( - 1, - 200, - this.trip !== undefined ? this.trip.id : undefined, - ).subscribe({ - next: (data) => { - this.userTrips = data.member; - this.originalUserTrips = [...data.member]; // Kopie der ursprünglichen UserTrips speichern - - // Formulare für jeden UserTrip erstellen - this.userForms = []; - this.userTrips.forEach((userTrip, index) => { - const form = this.createUserForm(); - - // Formularwerte initialisieren - if (userTrip.userIri || (userTrip.user && userTrip.user.id)) { - form.get('user')?.setValue(userTrip.userIri || userTrip.user?.id); - } - - this.userForms.push(form); - }); - }, - error: (error) => { - console.error('Fehler beim Laden der Benutzerzuweisungen:', error); - } - }); - } - - loadUserTripEvents() { - this.userTripEventService.userTripEventsGetCollection( - 1, - 200, - undefined, - undefined, - this.trip.dbId!, - ).subscribe({ - next: (data) => { - this.userTripEvents = data.member; - } - }) - } - - saveAllUserTrips() { - // Aktuelle IDs speichern, um später gelöschte Einträge zu identifizieren - let originalUserTripIds: string[] = []; - - // Zuerst alle existierenden UserTrips vom Server holen - this.userTripService.userTripsGetCollection( - 1, 200, this.trip.dbId?.toString() - ).subscribe({ - next: (existingUserTrips) => { - // IDs der existierenden UserTrips speichern - originalUserTripIds = existingUserTrips.member - .filter(userTrip => userTrip.id) - .map(userTrip => this.appHelperService.extractId(userTrip.id!)); - - // Aktualisieren der user objects in unserem userTrips-Array - this.userTrips.forEach((userTrip, index) => { - const userFormValue = this.userForms[index].get('user')?.value; - - // User setzen, wenn verfügbar - if (userFormValue) { - if (typeof userFormValue === 'string') { - userTrip.userIri = userFormValue; - } - } - }); - - // Filtern: Nur UserTrips mit gültigen User-Zuweisungen behalten - const validUserTrips = this.userTrips.filter(ut => ut.userIri || (ut.user && ut.user.id)); - - if (validUserTrips.length === 0 && this.userTrips.length > 0) { - window.alert('Bitte wähle für jeden Eintrag einen Benutzer aus oder entferne ungenutzte Einträge.'); - return; - } - - // Array für alle Operationen erstellen - const allPromises: Promise[] = []; - - // 1. Neue UserTrips erstellen und existierende aktualisieren - validUserTrips.forEach(userTrip => { - if (userTrip.id) { - // Existierenden UserTrip aktualisieren - const id = this.appHelperService.extractId(userTrip.id); - - // ID aus der Liste der zu löschenden IDs entfernen - const idIndex = originalUserTripIds.indexOf(id); - if (idIndex > -1) { - originalUserTripIds.splice(idIndex, 1); - } - - // Update-Promise hinzufügen - allPromises.push( - firstValueFrom(this.userTripService.userTripsIdPatch( - id, - this.appHelperService.convertJsonldToJson(userTrip) - )) - ); - } else { - // Neuen UserTrip erstellen - allPromises.push( - firstValueFrom(this.userTripService.userTripsPost(userTrip)) - ); - } - }); - - // 2. Gelöschte UserTrips von der Datenbank entfernen - originalUserTripIds.forEach(id => { - allPromises.push( - firstValueFrom(this.userTripService.userTripsIdDelete(id)) - ); - }); - - // Alle Operationen ausführen - Promise.all(allPromises) - .then(() => { - // Nach dem Speichern alle UserTrips neu laden - this.loadUserTrips(); - }) - .catch(error => { - console.error('Fehler beim Speichern der Benutzerzuweisungen:', error); - window.alert('Beim Speichern der Benutzerzuweisungen ist ein Fehler aufgetreten. Bitte versuche es erneut.'); - }); - }, - error: (error) => { - console.error('Fehler beim Laden der existierenden Benutzerzuweisungen:', error); - window.alert('Die aktuellen Benutzerzuweisungen konnten nicht geladen werden. Bitte versuche es erneut.'); - } - }); - } } \ No newline at end of file diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.html b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.html new file mode 100644 index 0000000..dbcd157 --- /dev/null +++ b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.html @@ -0,0 +1,72 @@ +
+ @if (!isEditMode()) { +
+

{{ ('basic.create') | translate }} {{ 'model.event' | translate }}

+
+ } @else { +
+

{{ ('basic.edit') | translate }} {{ 'model.trip' | translate }}: {{ data?.event?.name }}

+
+ } +
+ @if (data !== undefined) { +
+ +
+ + + + +
+
+ + + + +
+
+ +
+
+ + +
+
+ } +
+ +
+
+ + + @if (isEditMode()) { + + } +
+
+
\ No newline at end of file diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.scss b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.spec.ts b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.spec.ts new file mode 100644 index 0000000..c53b4cc --- /dev/null +++ b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserTripEventFormComponent } from './user-trip-event-form.component'; + +describe('UserTripEventFormComponent', () => { + let component: UserTripEventFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserTripEventFormComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(UserTripEventFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.ts b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.ts new file mode 100644 index 0000000..604effe --- /dev/null +++ b/angular/src/app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component.ts @@ -0,0 +1,80 @@ +import { Component } from '@angular/core'; +import { + EventService, LocationService, + UserTripEventJsonld, + UserTripEventService, UserTripJsonld, +} from "@app/core/api/v1"; +import {tripForm, userTripEventForm} from "@app/_forms/apiForms"; +import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component"; +import {AppHelperService} from "@app/_helpers/app-helper.service"; +import {TranslateService} from "@ngx-translate/core"; +import {Router} from "@angular/router"; +import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; +import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; +import {ListColDefinition} from "@app/_components/list/list-col-definition"; + +@Component({ + selector: 'app-user-trip-event-form', + templateUrl: './user-trip-event-form.component.html', + styleUrl: './user-trip-event-form.component.scss' +}) +export class UserTripEventFormComponent extends AbstractDataFormComponent { + + protected readonly SearchSelectComponent = SearchSelectComponent; + protected readonly userTripEventForm = userTripEventForm; + protected userTrip?: UserTripJsonld; + protected eventColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefEvents(); + protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations(); + + constructor( + protected userTripEventService: UserTripEventService, + protected eventService: EventService, + protected locationService: LocationService, + appHelperService: AppHelperService, + translateService: TranslateService, + router: Router + ) { + super( + userTripEventForm, + appHelperService, + (data: UserTripEventJsonld) => { + return this.userTripEventService.userTripEventsPost(data); + }, + (id: string | number, data: UserTripEventJsonld) => + this.userTripEventService.userTripEventsIdPatch( + id.toString(), + this.appHelperService.convertJsonldToJson(data) + ), + (id: string | number) => this.userTripEventService.userTripEventsIdDelete(id.toString()), + translateService, + router + ); + + //this.redirectAfterDelete = '/' + ROUTE_USER_TRIPS; + } + + override ngOnInit() { + super.ngOnInit(); + this.form.get('userTripIri')?.setValue(this.userTrip?.id!); + } + + getEvents: ListGetDataFunctionType = ( + index: number, + pageSize: number, + term?: string, + ) => { + return this.eventService.eventsGetCollection( + index, + pageSize, + term + ); + } + + getLocations: ListGetDataFunctionType = (index: number, pageSize: number, term?: string) => { + return this.locationService.locationsGetCollection( + index, + pageSize, + term, + ); + } +} diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.html b/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.html index 6bc7320..b571502 100644 --- a/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.html +++ b/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.html @@ -2,6 +2,10 @@ diff --git a/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.ts b/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.ts index e20dfd0..6092f16 100644 --- a/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.ts +++ b/angular/src/app/_views/user-trip-event/user-trip-event-list/user-trip-event-list.component.ts @@ -1,10 +1,14 @@ import {Component, Input, ViewChild} from '@angular/core'; import {ListComponent} from "@app/_components/list/list.component"; import {ListColDefinition} from "@app/_components/list/list-col-definition"; -import {TripJsonld, UserTripEventService} from "@app/core/api/v1"; +import {TripJsonld, UserTripEventService, UserTripJsonld} from "@app/core/api/v1"; import {AppHelperService} from "@app/_helpers/app-helper.service"; import {FilterBarComponent} from "@app/_components/filter-bar/filter-bar.component"; import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; +import { + UserTripEventFormComponent +} from "@app/_views/user-trip-event/user-trip-event-form/user-trip-event-form.component"; +import {Observable} from "rxjs"; @Component({ selector: 'app-user-trip-event-list', @@ -13,9 +17,13 @@ import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-funct }) export class UserTripEventListComponent { @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; + @Input() public userTrip?: UserTripJsonld; @Input() public trip?: TripJsonld; + @Input() public showCreateButton: boolean; + protected readonly userTripEventFormComponent = UserTripEventFormComponent; protected listColDefinitions!: ListColDefinition[]; + protected dataFormComponentData: any; constructor( private userTripEventService: UserTripEventService, @@ -75,10 +83,13 @@ export class UserTripEventListComponent { filterType: FilterBarComponent.FILTER_TYPE_DATE, } as ListColDefinition, ]; + this.showCreateButton = true; } ngOnInit() { - + this.dataFormComponentData = { + userTrip: this.userTrip, + }; } ngAfterViewInit(): void { @@ -93,11 +104,15 @@ export class UserTripEventListComponent { return this.userTripEventService.userTripEventsGetCollection( index, pageSize, - undefined, + this.userTrip !== undefined ? this.userTrip.id! : undefined, undefined, this.trip !== undefined ? this.trip.dbId! : undefined, this.listComponent.getFilterJsonString(), this.listComponent.getSortingJsonString() ); } + + get deleteItemFunction(): (id: string) => Observable { + return (id: string) => this.userTripEventService.userTripEventsIdDelete(id); + } } diff --git a/angular/src/app/_views/user-trip/user-trip-detail/user-trip-detail.component.html b/angular/src/app/_views/user-trip/user-trip-detail/user-trip-detail.component.html index f0c1a58..d12284e 100644 --- a/angular/src/app/_views/user-trip/user-trip-detail/user-trip-detail.component.html +++ b/angular/src/app/_views/user-trip/user-trip-detail/user-trip-detail.component.html @@ -15,91 +15,11 @@
-

{{ 'user_trip.events' | translate }}

- -
-
-
- - - -
- -
- - - -
- -
- -
- -
-
- -
- -
- -
-
- -
- - -
- -
- -
-
-
- -
-
- -
-
- -
-
- -
-
+ +
diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts index 64fa27c..a081ff0 100644 --- a/angular/src/app/app.module.ts +++ b/angular/src/app/app.module.ts @@ -73,6 +73,7 @@ import { UserFormComponent } from './_views/user/user-form/user-form.component'; import { ImageUploadComponent } from './_components/image-upload/image-upload.component'; import { TripLocationListComponent } from './_views/trip/trip-location-list/trip-location-list.component'; import { TripLocationFormComponent } from './_views/trip/trip-location-form/trip-location-form.component'; +import { UserTripEventFormComponent } from './_views/user-trip-event/user-trip-event-form/user-trip-event-form.component'; registerLocaleData(localeDe, 'de-DE'); @@ -171,6 +172,7 @@ export function HttpLoaderFactory(http: HttpClient) { ImageUploadComponent, TripLocationListComponent, TripLocationFormComponent, + UserTripEventFormComponent, ], providers: [ {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, diff --git a/angular/src/assets/i18n/en.json b/angular/src/assets/i18n/en.json index b8fbb79..34ded97 100644 --- a/angular/src/assets/i18n/en.json +++ b/angular/src/assets/i18n/en.json @@ -75,6 +75,7 @@ "trip_location": "Itinerary location", "user": "User", "user_trip": "Pilotage", + "user_trip_event": "Pilotage event", "vessel": "Vessel", "zone": "Zone" }, @@ -89,7 +90,7 @@ "customer_reference": "Customer reference", "end_date": "End date", "end_location": "End location", - "events": "Events", + "events": "Events (accumulated)", "is_arrival": "Arrival", "is_departure": "Departure", "is_transit": "Transit",