| @@ -4183,10 +4183,6 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| customerReference: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| startLocation: | |||
| readOnly: true | |||
| type: string | |||
| @@ -4280,10 +4276,6 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| customerReference: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| startLocation: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/Location.jsonld' | |||
| @@ -4352,14 +4344,15 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| isArrival: | |||
| type: boolean | |||
| isTransit: | |||
| type: boolean | |||
| isDeparture: | |||
| type: boolean | |||
| date: | |||
| type: string | |||
| arrivalDateTime: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: date-time | |||
| departureDateTime: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: date-time | |||
| createdAt: | |||
| readOnly: true | |||
| @@ -4370,7 +4363,6 @@ components: | |||
| required: | |||
| - tripIri | |||
| - locationIri | |||
| - date | |||
| TripLocation.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -4420,14 +4412,15 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| isArrival: | |||
| type: boolean | |||
| isTransit: | |||
| type: boolean | |||
| isDeparture: | |||
| type: boolean | |||
| date: | |||
| type: string | |||
| arrivalDateTime: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: date-time | |||
| departureDateTime: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: date-time | |||
| createdAt: | |||
| readOnly: true | |||
| @@ -4438,7 +4431,6 @@ components: | |||
| required: | |||
| - tripIri | |||
| - locationIri | |||
| - date | |||
| User: | |||
| type: object | |||
| description: '' | |||
| @@ -1,4 +1,4 @@ | |||
| import { Directive, EventEmitter, Input, Output, OnInit } from '@angular/core'; | |||
| import {Directive, EventEmitter, Input, Output, OnInit, AfterViewInit} from '@angular/core'; | |||
| import { FormGroup } from '@angular/forms'; | |||
| import { Observable } from 'rxjs'; | |||
| import { Router } from '@angular/router'; | |||
| @@ -20,7 +20,7 @@ export interface FormSubmitEvent<T> { | |||
| } | |||
| @Directive() | |||
| export abstract class AbstractDataFormComponent<T extends { [key: string]: any }> implements OnInit { | |||
| export abstract class AbstractDataFormComponent<T extends { [key: string]: any }> implements OnInit, AfterViewInit { | |||
| @Input() data?: T; | |||
| @Input() mode: FormMode = FormMode.Create; | |||
| @Input() id?: string | number; | |||
| @@ -51,6 +51,9 @@ export abstract class AbstractDataFormComponent<T extends { [key: string]: any } | |||
| } | |||
| } | |||
| ngAfterViewInit() { | |||
| } | |||
| protected getNewDataSet(): T { | |||
| return {} as T; | |||
| } | |||
| @@ -5,6 +5,6 @@ | |||
| </div> | |||
| <div class="col-6"> | |||
| <label for="{{ inputId }}-time">{{ label }} ({{ 'basic.time' | translate }}):</label> | |||
| <input type="time" id="{{ inputId }}-time" class="form-control" formControlName="time" step="1" [readonly]="readonly"> | |||
| <input type="time" id="{{ inputId }}-time" class="form-control" formControlName="time" [step]="showSeconds ? 1 : 60" [readonly]="readonly"> | |||
| </div> | |||
| </div> | |||
| @@ -11,6 +11,7 @@ export class DatetimePickerComponent implements OnInit { | |||
| @Input() inputId: string = 'myId'; | |||
| @Input() initialValue: string | null = null; | |||
| @Input() readonly: boolean = false; | |||
| @Input() showSeconds: boolean = false; | |||
| @Output() dateTimeChange = new EventEmitter<string | null>(); | |||
| form: FormGroup; | |||
| @@ -46,25 +47,48 @@ export class DatetimePickerComponent implements OnInit { | |||
| return date.toLocaleDateString('en-CA'); | |||
| } | |||
| private formatTime(date: Date): string { | |||
| return date.toLocaleTimeString('en-GB', { hour12: false }); | |||
| } | |||
| private formatTime(date: Date): string { | |||
| if (this.showSeconds) { | |||
| return date.toLocaleTimeString('en-GB', { hour12: false }); | |||
| } else { | |||
| // Nur Stunden und Minuten zurückgeben | |||
| return date.toLocaleTimeString('en-GB', { | |||
| hour12: false, | |||
| hour: '2-digit', | |||
| minute: '2-digit' | |||
| }); | |||
| } | |||
| } | |||
| private emitDateTime() { | |||
| const { date, time } = this.form.value; | |||
| if (date && time) { | |||
| const [year, month, day] = date.split('-'); | |||
| private emitDateTime() { | |||
| const { date, time } = this.form.value; | |||
| if (date && time) { | |||
| const [year, month, day] = date.split('-'); | |||
| const [hours, minutes, seconds] = time.split(':'); | |||
| const dateTime = new Date(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes), Number(seconds)); | |||
| // Parse Zeit je nach Format (mit oder ohne Sekunden) | |||
| let hours, minutes, seconds; | |||
| if (this.showSeconds && time.split(':').length > 2) { | |||
| [hours, minutes, seconds] = time.split(':'); | |||
| } else { | |||
| [hours, minutes] = time.split(':'); | |||
| seconds = '00'; | |||
| } | |||
| // Format the date to match the loaded format | |||
| const formattedDate = dateTime.toLocaleString('sv-SE', { timeZone: 'Europe/Berlin' }).replace(' ', 'T') + '+02:00'; | |||
| const dateTime = new Date( | |||
| Number(year), | |||
| Number(month) - 1, | |||
| Number(day), | |||
| Number(hours), | |||
| Number(minutes), | |||
| Number(seconds || 0) | |||
| ); | |||
| //console.log('Emitting datetime:', formattedDate); | |||
| this.dateTimeChange.emit(formattedDate); | |||
| } else { | |||
| //console.log('Emitting null datetime'); | |||
| this.dateTimeChange.emit(null); | |||
| // Format the date to match the loaded format | |||
| const formattedDate = dateTime.toLocaleString('sv-SE', { timeZone: 'Europe/Berlin' }).replace(' ', 'T') + '+02:00'; | |||
| this.dateTimeChange.emit(formattedDate); | |||
| } else { | |||
| this.dateTimeChange.emit(null); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -29,6 +29,7 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| @Input() public onRowSelectedFunction!: Function; | |||
| @Input() public onUpdateBooleanStateFunction!: ListUpdateElementFunctionType; | |||
| @Input() public dataFormComponent!: Type<AbstractDataFormComponent<any>>; | |||
| @Input() public dataFormComponentData?: any; | |||
| @Input() public searchable: boolean; | |||
| @Input() public showDetailButton: boolean; | |||
| @Input() public showPosition: boolean; | |||
| @@ -122,6 +123,9 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| this.setupAutoRefresh(); | |||
| } | |||
| ngAfterViewInit(): void { | |||
| } | |||
| private setupAutoRefresh(): void { | |||
| this.clearAutoRefresh(); | |||
| if (this.refreshIntervalSeconds && this.refreshIntervalSeconds > 0) { | |||
| @@ -205,9 +209,6 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| return visibility; | |||
| } | |||
| ngAfterViewInit(): void { | |||
| } | |||
| getData = (): void => { | |||
| this.getDataFunction( | |||
| this.pagingComponent.getPageIndex(), | |||
| @@ -392,7 +393,7 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| public onCreateData() { | |||
| this.appHelperService.openModal( | |||
| this.dataFormComponent, | |||
| null, | |||
| this.dataFormComponentData, | |||
| this.getData | |||
| ); | |||
| } | |||
| @@ -99,7 +99,6 @@ export const tripForm = new FormGroup({ | |||
| vessel: new FormControl(null, []), | |||
| vesselIri: new FormControl(null, [Validators.required]), | |||
| pilotageReference: new FormControl(null, []), | |||
| customerReference: new FormControl(null, []), | |||
| startLocation: new FormControl(null, []), | |||
| startLocationIri: new FormControl(null, [Validators.required]), | |||
| endLocation: new FormControl(null, []), | |||
| @@ -116,7 +115,6 @@ export const tripJsonldForm = new FormGroup({ | |||
| vessel: new FormControl(null, []), | |||
| vesselIri: new FormControl(null, [Validators.required]), | |||
| pilotageReference: new FormControl(null, []), | |||
| customerReference: new FormControl(null, []), | |||
| startLocation: new FormControl(null, []), | |||
| startLocationIri: new FormControl(null, [Validators.required]), | |||
| endLocation: new FormControl(null, []), | |||
| @@ -134,10 +132,8 @@ export const tripLocationForm = new FormGroup({ | |||
| tripIri: new FormControl(null, [Validators.required]), | |||
| location: new FormControl(null, []), | |||
| locationIri: new FormControl(null, [Validators.required]), | |||
| isArrival: new FormControl(null, []), | |||
| isTransit: new FormControl(null, []), | |||
| isDeparture: new FormControl(null, []), | |||
| date: new FormControl(null, [Validators.required]), | |||
| arrivalDateTime: new FormControl(null, []), | |||
| departureDateTime: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -147,10 +143,8 @@ export const tripLocationJsonldForm = new FormGroup({ | |||
| tripIri: new FormControl(null, [Validators.required]), | |||
| location: new FormControl(null, []), | |||
| locationIri: new FormControl(null, [Validators.required]), | |||
| isArrival: new FormControl(null, []), | |||
| isTransit: new FormControl(null, []), | |||
| isDeparture: new FormControl(null, []), | |||
| date: new FormControl(null, [Validators.required]), | |||
| arrivalDateTime: new FormControl(null, []), | |||
| departureDateTime: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -47,6 +47,7 @@ export class AppHelperService { | |||
| public openModal(component: any, data: any, callback?: (callbackParam?: any) => void, callbackParam?: any): Promise<ModalStatus> { | |||
| const modalRef = this.modalService.open(component); | |||
| console.log(data); | |||
| for (const key in data) { | |||
| modalRef.componentInstance[key] = data[key]; | |||
| } | |||
| @@ -16,106 +16,10 @@ | |||
| <mat-tab label="{{ 'trip.itinerary' | translate }}"> | |||
| <div> | |||
| <h4 class="mb-4">{{ 'trip.itinerary_locations' | translate }}</h4> | |||
| <div *ngFor="let tripLocation of tripLocations; let i = index" class="p-2 mb-2 changing-list"> | |||
| <div class="row"> | |||
| <div class="col-12 col-md-4 mb-1"> | |||
| <label [for]="'location_' + i" class="form-label">Location*:</label> | |||
| <app-search-select | |||
| [formId]="'location'" | |||
| [formLabelLangKey]="'model.location'" | |||
| [documentForm]="locationForms[i]" | |||
| [getDataFunction]="getLocations" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="locationColDefinitions" | |||
| [dataSet]="tripLocation.location" | |||
| > | |||
| </app-search-select> | |||
| </div> | |||
| <div class="col-12 col-md-2 mb-1"> | |||
| <label class="form-label">trip.date (Date):</label> | |||
| <div> | |||
| <input | |||
| type="date" | |||
| class="form-control" | |||
| [value]="formatDateForInput(tripLocation.date)" | |||
| (change)="onDateInputChange($event, i)" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div class="col-12 col-md-2 mb-1"> | |||
| <label class="form-label">trip.date (Time):</label> | |||
| <div> | |||
| <input | |||
| type="time" | |||
| class="form-control" | |||
| [value]="formatTimeForInput(tripLocation.date)" | |||
| (change)="onTimeInputChange($event, i)" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div class="col-12 col-md-2 mb-1 d-flex align-items-end"> | |||
| <div class="form-check"> | |||
| <input | |||
| class="form-check-input" | |||
| type="checkbox" | |||
| [id]="'isArrival_' + i" | |||
| [checked]="tripLocation.isArrival" | |||
| (change)="onIsArrivalChange($event, i)" | |||
| > | |||
| <label class="form-check-label" [for]="'isArrival_' + i"> | |||
| {{ 'trip.is_arrival' | translate }} | |||
| </label> | |||
| </div> | |||
| <div class="form-check"> | |||
| <input | |||
| class="form-check-input" | |||
| type="checkbox" | |||
| [id]="'isTransit_' + i" | |||
| [checked]="tripLocation.isTransit" | |||
| (change)="onIsTransitChange($event, i)" | |||
| > | |||
| <label class="form-check-label" [for]="'isTransit_' + i"> | |||
| {{ 'trip.is_transit' | translate }} | |||
| </label> | |||
| </div> | |||
| <div class="form-check"> | |||
| <input | |||
| class="form-check-input" | |||
| type="checkbox" | |||
| [id]="'isDeparture_' + i" | |||
| [checked]="tripLocation.isDeparture" | |||
| (change)="onIsDepartureChange($event, i)" | |||
| > | |||
| <label class="form-check-label" [for]="'isDeparture_' + i"> | |||
| {{ 'trip.is_departure' | translate }} | |||
| </label> | |||
| </div> | |||
| </div> | |||
| <div class="col-12 col-md-2 mb-1 d-flex align-items-end"> | |||
| <button type="button" class="btn btn-danger mb-3" (click)="removeTripLocation(i)">X</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <button type="button" class="btn btn-primary" (click)="addNewTripLocation()">+</button> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <button type="button" class="btn btn-primary" (click)="saveAllTripLocations()"> | |||
| {{ 'basic.save' | translate }} | |||
| </button> | |||
| </div> | |||
| </div> | |||
| <app-trip-location-list | |||
| [trip]="trip" | |||
| > | |||
| </app-trip-location-list> | |||
| </div> | |||
| </mat-tab> | |||
| <mat-tab label="{{ 'trip.assigned_users' | translate }}"> | |||
| @@ -137,10 +41,6 @@ | |||
| > | |||
| </app-search-select> | |||
| </div> | |||
| <div class="col-12 col-md-2 d-flex align-items-end"> | |||
| <button type="button" class="btn btn-danger mb-3" (click)="removeUserTrip(i)">X</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -168,74 +168,6 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| } | |||
| } | |||
| formatDateForInput(dateString: string): string { | |||
| if (!dateString) return ''; | |||
| const date = new Date(dateString); | |||
| return date.toISOString().split('T')[0]; | |||
| } | |||
| formatTimeForInput(dateString: string): string { | |||
| if (!dateString) return ''; | |||
| const date = new Date(dateString); | |||
| return date.toTimeString().slice(0, 5); | |||
| } | |||
| onDateInputChange(event: Event, index: number) { | |||
| const input = event.target as HTMLInputElement; | |||
| const currentDate = new Date(this.tripLocations[index].date || new Date()); | |||
| const [year, month, day] = input.value.split('-').map(Number); | |||
| currentDate.setFullYear(year, month - 1, day); | |||
| this.tripLocations[index].date = currentDate.toISOString(); | |||
| } | |||
| onTimeInputChange(event: Event, index: number) { | |||
| const input = event.target as HTMLInputElement; | |||
| const currentDate = new Date(this.tripLocations[index].date || new Date()); | |||
| const [hours, minutes] = input.value.split(':').map(Number); | |||
| currentDate.setHours(hours, minutes); | |||
| this.tripLocations[index].date = currentDate.toISOString(); | |||
| } | |||
| onIsArrivalChange(event: Event, index: number) { | |||
| const checkbox = event.target as HTMLInputElement; | |||
| this.tripLocations[index].isArrival = checkbox.checked; | |||
| } | |||
| onIsTransitChange(event: Event, index: number) { | |||
| const checkbox = event.target as HTMLInputElement; | |||
| this.tripLocations[index].isTransit = checkbox.checked; | |||
| } | |||
| onIsDepartureChange(event: Event, index: number) { | |||
| const checkbox = event.target as HTMLInputElement; | |||
| this.tripLocations[index].isDeparture = checkbox.checked; | |||
| } | |||
| addNewTripLocation() { | |||
| // Create a new empty trip location | |||
| const newTripLocation: TripLocationJsonld = { | |||
| tripIri: this.trip.id!, | |||
| date: new Date().toISOString(), | |||
| isArrival: false, | |||
| locationIri: null | |||
| }; | |||
| this.tripLocations.push(newTripLocation); | |||
| this.locationForms.push(this.createLocationForm(null)); | |||
| // Force update in the next event loop to properly initialize the search-select | |||
| setTimeout(() => { | |||
| if (this.searchSelects) { | |||
| const lastSelect = this.searchSelects.last; | |||
| if (lastSelect) { | |||
| lastSelect.ngAfterViewInit(); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| addNewUserTrip() { | |||
| // Erstelle ein unvollständiges Objekt (ohne user-Property) | |||
| const newUserTrip: UserTripJsonld = { | |||
| @@ -303,110 +235,6 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| }) | |||
| } | |||
| removeTripLocation(index: number): void { | |||
| this.translateService.get('basic.delete_confirm').subscribe((confirmMessage: string) => { | |||
| if (!confirm(confirmMessage)) { | |||
| return; | |||
| } | |||
| // Just remove from arrays; deletion happens later in saveAllTripLocations() | |||
| this.tripLocations.splice(index, 1); | |||
| this.locationForms.splice(index, 1); | |||
| }); | |||
| } | |||
| removeUserTrip(index: number) { | |||
| this.translateService.get('basic.delete_confirm').subscribe((confirmMessage: string) => { | |||
| if (!confirm(confirmMessage)) { | |||
| return; | |||
| } | |||
| // Nur aus dem Array entfernen, tatsächliches Löschen erfolgt beim Speichern | |||
| this.userTrips.splice(index, 1); | |||
| this.userForms.splice(index, 1); | |||
| }); | |||
| } | |||
| saveAllTripLocations(): void { | |||
| // A) DELETE: find which original dbIds are missing → delete those | |||
| const originalDbIds = this.originalTripLocations | |||
| .map(o => o.dbId) | |||
| // narrow type to number (filter out null/undefined) | |||
| .filter((id): id is number => id != null); | |||
| const currentDbIds = this.tripLocations | |||
| .map(t => t.dbId) | |||
| .filter((id): id is number => id != null); | |||
| const dbIdsToDelete = originalDbIds.filter(id => !currentDbIds.includes(id)); | |||
| dbIdsToDelete.forEach(dbId => { | |||
| this.tripLocationService | |||
| .tripLocationsIdDelete(dbId.toString()) | |||
| .subscribe({ | |||
| next: () => console.log(`TripLocation ${dbId} deleted.`), | |||
| error: err => console.error(`Error deleting TripLocation ${dbId}:`, err) | |||
| }); | |||
| }); | |||
| // B) UPSERT: create or update remaining entries | |||
| this.tripLocations.forEach((tripLocation, index) => { | |||
| const form = this.locationForms[index]; | |||
| const locationVal = form.get('location')?.value; | |||
| const dbId = tripLocation.dbId; | |||
| const isNew = dbId == null; // no dbId → brand new | |||
| // only for existing entries compare against snapshot | |||
| let locationChanged = false; | |||
| let modelChanged = false; | |||
| if (!isNew) { | |||
| const original = this.originalTripLocations[index]; | |||
| locationChanged = locationVal !== original.locationIri; | |||
| modelChanged = ( | |||
| tripLocation.date !== original.date || | |||
| tripLocation.isArrival !== original.isArrival || | |||
| tripLocation.isTransit !== original.isTransit || | |||
| tripLocation.isDeparture !== original.isDeparture | |||
| ); | |||
| } | |||
| // skip if neither new nor changed | |||
| if (!(isNew || locationChanged || modelChanged)) { | |||
| return; | |||
| } | |||
| // validate a location was chosen | |||
| if (!locationVal) { | |||
| console.error(`Location missing for entry #${index}`); | |||
| return; | |||
| } | |||
| if (typeof locationVal === 'string') { | |||
| tripLocation.locationIri = locationVal; | |||
| } | |||
| // always ensure the parent trip IRI is set | |||
| tripLocation.tripIri = this.trip?.id ?? null; | |||
| // choose correct API call | |||
| const save$ = isNew | |||
| ? this.tripLocationService.tripLocationsPost(tripLocation) | |||
| : this.tripLocationService.tripLocationsIdPatch( | |||
| dbId!.toString(), | |||
| this.appHelperService.convertJsonldToJson(tripLocation) | |||
| ); | |||
| // execute save and log result | |||
| save$.subscribe({ | |||
| next: saved => { | |||
| console.log(`TripLocation #${index} ${isNew ? 'created' : 'updated'}.`); | |||
| }, | |||
| error: err => { | |||
| console.error(`Error saving TripLocation #${index}:`, err); | |||
| } | |||
| }); | |||
| }); | |||
| // C) Finally: reset original snapshot to current state | |||
| this.originalTripLocations = JSON.parse(JSON.stringify(this.tripLocations)); | |||
| } | |||
| saveAllUserTrips() { | |||
| // Aktuelle IDs speichern, um später gelöschte Einträge zu identifizieren | |||
| let originalUserTripIds: string[] = []; | |||
| @@ -49,10 +49,6 @@ | |||
| </app-search-select> | |||
| <input id="endLocationIri" type="hidden" formControlName="endLocationIri" required/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="customerReference" class="form-label">{{ 'trip.customer_reference' | translate }}:</label> | |||
| <input type="text" class="form-control" id="customerReference" formControlName="customerReference"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <app-datetime-picker | |||
| [label]="'trip.start_date' | translate" | |||
| @@ -65,7 +61,7 @@ | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <app-datetime-picker | |||
| [label]="'trip.end_date' | translate" | |||
| [inputId]="'startDate'" | |||
| [inputId]="'endDate'" | |||
| [initialValue]="tripForm.get('endDate')?.value ?? null" | |||
| (dateTimeChange)="onDateChange($event, 'endDate')" | |||
| ></app-datetime-picker> | |||
| @@ -32,14 +32,6 @@ export class TripListComponent { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'customerReference', | |||
| text: 'trip.customer_reference', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'customerReference', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'vessel', | |||
| text: 'trip.vessel', | |||
| @@ -0,0 +1,57 @@ | |||
| <div class="spt-container"> | |||
| @if (!isEditMode()) { | |||
| <div class="spt-headline d-flex justify-content-between align-items-start"> | |||
| <h2>{{ ('basic.new') | translate }} {{ 'model.trip_location' | translate }}</h2> | |||
| </div> | |||
| } | |||
| <div class="spt-form"> | |||
| <form [formGroup]="tripLocationForm" (ngSubmit)="onSubmit()"> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <label for="locationIri" class="form-label">{{ 'trip.start_location' | translate }}*:</label> | |||
| <app-search-select #locationSearchSelect | |||
| [formId]="'locationIri'" | |||
| [formLabelLangKey]="'model.location'" | |||
| [documentForm]="form" | |||
| [getDataFunction]="getLocations" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="locationColDefinitions" | |||
| [dataSet]="data?.location" | |||
| > | |||
| </app-search-select> | |||
| <input id="locationIri" type="hidden" formControlName="locationIri" required/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <app-datetime-picker | |||
| [label]="'trip_location.arrival_date_time' | translate" | |||
| [inputId]="'arrivalDateTime'" | |||
| [initialValue]="tripLocationForm.get('arrivalDateTime')?.value ?? null" | |||
| (dateTimeChange)="onDateChange($event, 'arrivalDateTime')" | |||
| ></app-datetime-picker> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <app-datetime-picker | |||
| [label]="'trip_location.departure_date_time' | translate" | |||
| [inputId]="'departureDateTime'" | |||
| [initialValue]="tripLocationForm.get('departureDateTime')?.value ?? null" | |||
| (dateTimeChange)="onDateChange($event, 'departureDateTime')" | |||
| ></app-datetime-picker> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid"> | |||
| {{ 'basic.save' | translate }} | |||
| </button> | |||
| @if (isEditMode()) { | |||
| <button type="button" class="ms-3 btn btn-primary" (click)="onDelete()"> | |||
| {{ 'basic.delete' | translate }} {{ 'model.trip' | translate }} | |||
| </button> | |||
| } | |||
| </div> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { TripLocationFormComponent } from './trip-location-form.component'; | |||
| describe('TripLocationFormComponent', () => { | |||
| let component: TripLocationFormComponent; | |||
| let fixture: ComponentFixture<TripLocationFormComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [TripLocationFormComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(TripLocationFormComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,72 @@ | |||
| import {Component, Input} from '@angular/core'; | |||
| import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component"; | |||
| import { | |||
| LocationService, TripJsonld, | |||
| TripLocationJsonld, | |||
| TripLocationService, | |||
| } from "@app/core/api/v1"; | |||
| import {AppHelperService} from "@app/_helpers/app-helper.service"; | |||
| import {TranslateService} from "@ngx-translate/core"; | |||
| import {Router} from "@angular/router"; | |||
| import {ROUTE_BASE_DATA} from "@app/app-routing.module"; | |||
| import {tripLocationForm} from "@app/_forms/apiForms"; | |||
| import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; | |||
| import {ListColDefinition} from "@app/_components/list/list-col-definition"; | |||
| import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; | |||
| @Component({ | |||
| selector: 'app-trip-location-form', | |||
| templateUrl: './trip-location-form.component.html', | |||
| styleUrl: './trip-location-form.component.scss' | |||
| }) | |||
| export class TripLocationFormComponent extends AbstractDataFormComponent<TripLocationJsonld> { | |||
| @Input() public trip!: TripJsonld; | |||
| @Input() public arrivalDateTime?: string; | |||
| @Input() public departureDateTime?: string; | |||
| protected readonly SearchSelectComponent = SearchSelectComponent; | |||
| protected locationColDefinitions: ListColDefinition[]; | |||
| constructor( | |||
| private tripLocationService: TripLocationService, | |||
| private locationService: LocationService, | |||
| private appHelperService: AppHelperService, | |||
| translateService: TranslateService, | |||
| router: Router | |||
| ) { | |||
| super( | |||
| tripLocationForm, | |||
| (data: TripLocationJsonld) => { | |||
| return this.tripLocationService.tripLocationsPost(data); | |||
| }, | |||
| (id: string | number, data: TripLocationJsonld) => | |||
| this.tripLocationService.tripLocationsIdPatch( | |||
| id.toString(), | |||
| this.appHelperService.convertJsonldToJson(data) | |||
| ), | |||
| (id: string | number) => this.tripLocationService.tripLocationsIdDelete(id.toString()), | |||
| translateService, | |||
| router | |||
| ); | |||
| this.redirectAfterDelete = '/' + ROUTE_BASE_DATA; | |||
| this.locationColDefinitions = SearchSelectComponent.getDefaultColDefLocations(); | |||
| } | |||
| override ngOnInit() { | |||
| super.ngOnInit(); | |||
| this.form.get('tripIri')?.setValue(this.trip.id); | |||
| this.form.get('arrivalDateTime')?.setValue(this.arrivalDateTime); | |||
| this.form.get('departureDateTime')?.setValue(this.departureDateTime); | |||
| } | |||
| getLocations: ListGetDataFunctionType = (index: number, pageSize: number, term?: string) => { | |||
| return this.locationService.locationsGetCollection( | |||
| index, | |||
| pageSize, | |||
| term | |||
| ); | |||
| } | |||
| protected readonly tripLocationForm = tripLocationForm; | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| <div class="spt-container"> | |||
| <app-list #listComponent | |||
| [listId]="'tripLocationList'" | |||
| [getDataFunction]="getData" | |||
| [listColDefinitions]="listColDefinitions" | |||
| [dataFormComponent]="tripLocationFormComponent" | |||
| [dataFormComponentData]="dataFormComponentData" | |||
| ></app-list> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { TripLocationListComponent } from './trip-location-list.component'; | |||
| describe('TripLocationListComponent', () => { | |||
| let component: TripLocationListComponent; | |||
| let fixture: ComponentFixture<TripLocationListComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [TripLocationListComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(TripLocationListComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,127 @@ | |||
| import {Component, Input, Type, ViewChild} from '@angular/core'; | |||
| import {ListComponent} from "@app/_components/list/list.component"; | |||
| import {ListColDefinition} from "@app/_components/list/list-col-definition"; | |||
| import {TripJsonld, TripLocationService} 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 {TripLocationFormComponent} from "@app/_views/trip/trip-location-form/trip-location-form.component"; | |||
| import {map, tap} from "rxjs/operators"; | |||
| @Component({ | |||
| selector: 'app-trip-location-list', | |||
| templateUrl: './trip-location-list.component.html', | |||
| styleUrl: './trip-location-list.component.scss' | |||
| }) | |||
| export class TripLocationListComponent { | |||
| @Input() public trip!: TripJsonld; | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| protected tripLocationFormComponent = TripLocationFormComponent; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| protected dataFormComponentData: any; | |||
| constructor( | |||
| private tripLocationService: TripLocationService, | |||
| protected appHelperService: AppHelperService, | |||
| ) { | |||
| this.listColDefinitions = [ | |||
| { | |||
| name: 'location', | |||
| text: 'model.location', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'location', | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'zone', | |||
| text: 'model.zone', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'location', | |||
| field: 'zoneName', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'arrivalDateTime', | |||
| text: 'trip_location.arrival_date_time', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'arrivalDateTime', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'departureDateTime', | |||
| text: 'trip_location.departure_date_time', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'departureDateTime', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| ]; | |||
| } | |||
| ngOnInit() { | |||
| this.dataFormComponentData = { | |||
| trip: this.trip, | |||
| arrivalDateTime: new Date().toISOString(), | |||
| departureDateTime: new Date(new Date().setHours(new Date().getHours() + 1)) | |||
| }; | |||
| } | |||
| ngAfterViewInit(): void { | |||
| this.listComponent.getData(); | |||
| } | |||
| getData: ListGetDataFunctionType = ( | |||
| index: number, | |||
| pageSize: number, | |||
| term?: string, | |||
| ) => { | |||
| return this.tripLocationService.tripLocationsGetCollection( | |||
| index, | |||
| pageSize, | |||
| this.trip.id, | |||
| undefined, | |||
| this.listComponent.getFilterJsonString(), | |||
| this.listComponent.getSortingJsonString() | |||
| ).pipe( | |||
| map(response => { | |||
| // Set default arrival and departure time before return | |||
| let arrivalDateTime = new Date().toISOString(); | |||
| let departureDateTime = new Date(new Date().setHours(new Date().getHours() + 1)).toISOString(); | |||
| if (response.member && response.member.length > 0) { | |||
| const lastEntry = response.member[response.member.length - 1]; | |||
| if (lastEntry.departureDateTime) { | |||
| const departureDate = new Date(lastEntry.departureDateTime); | |||
| departureDate.setDate(departureDate.getDate() + 1); | |||
| arrivalDateTime = departureDate.toISOString(); | |||
| const arrivalDate = new Date(arrivalDateTime); | |||
| arrivalDate.setHours(arrivalDate.getHours() + 1); | |||
| departureDateTime = arrivalDate.toISOString(); | |||
| } | |||
| } | |||
| this.dataFormComponentData = { | |||
| trip: this.trip, | |||
| arrivalDateTime: arrivalDateTime, | |||
| departureDateTime: departureDateTime | |||
| }; | |||
| return response; | |||
| }) | |||
| ); | |||
| } | |||
| } | |||
| @@ -71,6 +71,8 @@ import { UserTripEventComponent } from './_views/user-trip-event/user-trip-event | |||
| import { UserTripEventListComponent } from './_views/user-trip-event/user-trip-event-list/user-trip-event-list.component'; | |||
| 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'; | |||
| registerLocaleData(localeDe, 'de-DE'); | |||
| @@ -167,6 +169,8 @@ export function HttpLoaderFactory(http: HttpClient) { | |||
| UserTripEventListComponent, | |||
| UserFormComponent, | |||
| ImageUploadComponent, | |||
| TripLocationListComponent, | |||
| TripLocationFormComponent, | |||
| ], | |||
| providers: [ | |||
| {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, | |||
| @@ -19,7 +19,6 @@ export interface Trip { | |||
| readonly vessel?: string; | |||
| vesselIri: string | null; | |||
| readonly pilotageReference?: string | null; | |||
| customerReference?: string | null; | |||
| readonly startLocation?: string; | |||
| startLocationIri: string | null; | |||
| readonly endLocation?: string; | |||
| @@ -24,7 +24,6 @@ export interface TripJsonld { | |||
| readonly vessel?: VesselJsonld; | |||
| vesselIri: string | null; | |||
| readonly pilotageReference?: string | null; | |||
| customerReference?: string | null; | |||
| readonly startLocation?: LocationJsonld; | |||
| startLocationIri: string | null; | |||
| readonly endLocation?: LocationJsonld; | |||
| @@ -22,10 +22,8 @@ export interface TripLocation { | |||
| tripIri: string | null; | |||
| location?: Location; | |||
| locationIri: string | null; | |||
| isArrival?: boolean; | |||
| isTransit?: boolean; | |||
| isDeparture?: boolean; | |||
| date: string; | |||
| arrivalDateTime?: string | null; | |||
| departureDateTime?: string | null; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -25,10 +25,8 @@ export interface TripLocationJsonld { | |||
| tripIri: string | null; | |||
| location?: LocationJsonld; | |||
| locationIri: string | null; | |||
| isArrival?: boolean; | |||
| isTransit?: boolean; | |||
| isDeparture?: boolean; | |||
| date: string; | |||
| arrivalDateTime?: string | null; | |||
| departureDateTime?: string | null; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -43,6 +43,11 @@ | |||
| "events": "Events", | |||
| "completed": "Completed" | |||
| }, | |||
| "trip_location": | |||
| { | |||
| "arrival_date_time": "ETA", | |||
| "departure_date_time": "ETD" | |||
| }, | |||
| "user_trip": | |||
| { | |||
| "view": "Pilotage", | |||
| @@ -67,6 +72,7 @@ | |||
| "vessel": "Vessel", | |||
| "shipping_company": "Shipping Company", | |||
| "trip": "Trip", | |||
| "trip_location": "Itinerary location", | |||
| "user": "User", | |||
| "user_trip": "Pilotage", | |||
| "event": "Event" | |||
| @@ -0,0 +1,41 @@ | |||
| <?php | |||
| declare(strict_types=1); | |||
| namespace DoctrineMigrations; | |||
| use Doctrine\DBAL\Schema\Schema; | |||
| use Doctrine\Migrations\AbstractMigration; | |||
| /** | |||
| * Auto-generated Migration: Please modify to your needs! | |||
| */ | |||
| final class Version20250507154018 extends AbstractMigration | |||
| { | |||
| public function getDescription(): string | |||
| { | |||
| return ''; | |||
| } | |||
| public function up(Schema $schema): void | |||
| { | |||
| // this up() migration is auto-generated, please modify it to your needs | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip DROP customer_reference | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip_location ADD arrival_date_time DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', ADD departure_date_time DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', DROP is_arrival, DROP date, DROP is_transit, DROP is_departure | |||
| SQL); | |||
| } | |||
| public function down(Schema $schema): void | |||
| { | |||
| // this down() migration is auto-generated, please modify it to your needs | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip_location ADD is_arrival TINYINT(1) NOT NULL, ADD date DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)', ADD is_transit TINYINT(1) NOT NULL, ADD is_departure TINYINT(1) NOT NULL, DROP arrival_date_time, DROP departure_date_time | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip ADD customer_reference VARCHAR(255) DEFAULT NULL | |||
| SQL); | |||
| } | |||
| } | |||
| @@ -81,8 +81,6 @@ class TripApi | |||
| #[ApiProperty(writable: false)] | |||
| public ?string $pilotageReference = null; | |||
| public ?string $customerReference = null; | |||
| /** | |||
| * @var LocationApi | |||
| */ | |||
| @@ -40,7 +40,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||
| security: 'is_granted("ROLE_ADMIN")' | |||
| ) | |||
| ], | |||
| order: ['date' => 'ASC'], | |||
| order: ['arrivalDateTime' => 'ASC', 'departureDateTime' => 'ASC'], | |||
| security: 'is_granted("ROLE_USER")', | |||
| provider: EntityToDtoStateProvider::class, | |||
| processor: EntityClassDtoStateProcessor::class, | |||
| @@ -62,9 +62,9 @@ class TripLocationApi | |||
| * @var TripApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: true, | |||
| writable: false, | |||
| readableLink: true, | |||
| writableLink: true, | |||
| writableLink: false, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| @@ -82,9 +82,9 @@ class TripLocationApi | |||
| * @var LocationApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: true, | |||
| writable: false, | |||
| readableLink: true, | |||
| writableLink: true, | |||
| writableLink: false, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| @@ -98,14 +98,9 @@ class TripLocationApi | |||
| #[ApiProperty(writable: true)] | |||
| public ?LocationApi $locationIri = null; | |||
| public bool $isArrival = false; | |||
| public ?\DateTimeImmutable $arrivalDateTime = null; | |||
| public bool $isTransit = false; | |||
| public bool $isDeparture = false; | |||
| #[Assert\NotBlank] | |||
| public \DateTimeImmutable $date; | |||
| public ?\DateTimeImmutable $departureDateTime = null; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| @@ -22,9 +22,6 @@ class Trip | |||
| #[ORM\JoinColumn(nullable: false)] | |||
| private Vessel $vessel; | |||
| #[ORM\Column(length: 255, nullable: true)] | |||
| private ?string $customerReference = null; | |||
| #[ORM\ManyToOne(targetEntity: Location::class)] | |||
| #[ORM\JoinColumn(name: 'start_location_id', nullable: false)] | |||
| private Location $startLocation; | |||
| @@ -24,26 +24,19 @@ class TripLocation | |||
| #[ORM\JoinColumn(nullable: false)] | |||
| private Location $location; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isArrival = true; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?DateTimeImmutable $arrivalDateTime = null; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isTransit = true; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isDeparture = true; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $date; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?DateTimeImmutable $departureDateTime = null; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| public function __construct(Trip $trip, Location $location, DateTimeImmutable $date) | |||
| public function __construct(Trip $trip, Location $location) | |||
| { | |||
| $this->trip = $trip; | |||
| $this->location = $location; | |||
| $this->date = $date; | |||
| $this->createdAt = new DateTimeImmutable(); | |||
| } | |||
| @@ -74,45 +67,24 @@ class TripLocation | |||
| return $this; | |||
| } | |||
| public function getDate(): DateTimeImmutable | |||
| { | |||
| return $this->date; | |||
| } | |||
| public function setDate(DateTimeImmutable $date): self | |||
| { | |||
| $this->date = $date; | |||
| return $this; | |||
| } | |||
| public function isArrival(): bool | |||
| { | |||
| return $this->isArrival; | |||
| } | |||
| public function setIsArrival(bool $isArrival): void | |||
| { | |||
| $this->isArrival = $isArrival; | |||
| } | |||
| public function isTransit(): bool | |||
| public function getArrivalDateTime(): ?DateTimeImmutable | |||
| { | |||
| return $this->isTransit; | |||
| return $this->arrivalDateTime; | |||
| } | |||
| public function setIsTransit(bool $isTransit): void | |||
| public function setArrivalDateTime(?DateTimeImmutable $arrivalDateTime): void | |||
| { | |||
| $this->isTransit = $isTransit; | |||
| $this->arrivalDateTime = $arrivalDateTime; | |||
| } | |||
| public function isDeparture(): bool | |||
| public function getDepartureDateTime(): ?DateTimeImmutable | |||
| { | |||
| return $this->isDeparture; | |||
| return $this->departureDateTime; | |||
| } | |||
| public function setIsDeparture(bool $isDeparture): void | |||
| public function setDepartureDateTime(?DateTimeImmutable $departureDateTime): void | |||
| { | |||
| $this->isDeparture = $isDeparture; | |||
| $this->departureDateTime = $departureDateTime; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| @@ -73,7 +73,6 @@ class TripApiToEntityMapper implements MapperInterface | |||
| assert($dto instanceof TripApi); | |||
| assert($entity instanceof Trip); | |||
| $entity->setCustomerReference($dto->customerReference); | |||
| $entity->setStartDate($dto->startDate); | |||
| $entity->setEndDate($dto->endDate); | |||
| $entity->setNote($dto->note); | |||
| @@ -38,7 +38,6 @@ class TripEntityToApiMapper implements MapperInterface | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->pilotageReference = "P-" . $entity->getId() . "-" . $entity->getStartDate()->format('Y'); | |||
| $dto->customerReference = $entity->getCustomerReference(); | |||
| $dto->startDate = $entity->getStartDate(); | |||
| $dto->endDate = $entity->getEndDate(); | |||
| $dto->note = $entity->getNote(); | |||
| @@ -49,7 +49,7 @@ class TripLocationApiToEntityMapper implements MapperInterface | |||
| throw new \Exception('Location not found'); | |||
| } | |||
| return new TripLocation($trip, $location, $dto->date); | |||
| return new TripLocation($trip, $location); | |||
| } | |||
| public function populate(object $from, object $to, array $context): object | |||
| @@ -67,10 +67,8 @@ class TripLocationApiToEntityMapper implements MapperInterface | |||
| $entity->setLocation($location); | |||
| } | |||
| $entity->setIsArrival($dto->isArrival); | |||
| $entity->setIsTransit($dto->isTransit); | |||
| $entity->setIsDeparture($dto->isDeparture); | |||
| $entity->setDate($dto->date); | |||
| $entity->setArrivalDateTime($dto->arrivalDateTime); | |||
| $entity->setDepartureDateTime($dto->departureDateTime); | |||
| return $entity; | |||
| } | |||
| @@ -37,10 +37,8 @@ class TripLocationEntityToApiMapper implements MapperInterface | |||
| assert($dto instanceof TripLocationApi); | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->date = $entity->getDate(); | |||
| $dto->isArrival = $entity->isArrival(); | |||
| $dto->isTransit = $entity->isTransit(); | |||
| $dto->isDeparture = $entity->isDeparture(); | |||
| $dto->arrivalDateTime = $entity->getArrivalDateTime(); | |||
| $dto->departureDateTime = $entity->getDepartureDateTime(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->tripIri = $dto->trip = $this->microMapper->map($entity->getTrip(), TripApi::class, [ | |||