| @@ -9,7 +9,6 @@ | |||
| <div> | |||
| <app-trip-form | |||
| [data]="trip" | |||
| (submit)="onFormUpdate($event)" | |||
| ></app-trip-form> | |||
| </div> | |||
| </mat-tab> | |||
| @@ -33,10 +32,10 @@ | |||
| <div> | |||
| <app-user-trip-event-list | |||
| [trip]="trip" | |||
| [showCreateButton]="false" | |||
| > | |||
| </app-user-trip-event-list> | |||
| </div> | |||
| </mat-tab> | |||
| </mat-tab-group> | |||
| } | |||
| @@ -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<SearchSelectComponent>; | |||
| 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<any> => { | |||
| return this.locationService.locationsGetCollection(page, pageSize, term); | |||
| } | |||
| getUsers = (page: number, pageSize: number, term?: string): Observable<any> => { | |||
| // 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<TripJsonld>) { | |||
| 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<any>[] = []; | |||
| // 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.'); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| <div class="spt-container"> | |||
| @if (!isEditMode()) { | |||
| <div class="spt-headline d-flex justify-content-between align-items-start"> | |||
| <h2>{{ ('basic.create') | translate }} {{ 'model.event' | translate }}</h2> | |||
| </div> | |||
| } @else { | |||
| <div class="spt-headline d-flex justify-content-between align-items-start"> | |||
| <h2>{{ ('basic.edit') | translate }} {{ 'model.trip' | translate }}: {{ data?.event?.name }}</h2> | |||
| </div> | |||
| } | |||
| <div class="spt-form"> | |||
| @if (data !== undefined) { | |||
| <form [formGroup]="userTripEventForm" (ngSubmit)="onSubmit()"> | |||
| <input id="userTripIri" type="hidden" formControlName="userTripIri" required/> | |||
| <div class="col-12 mb-3"> | |||
| <label for="eventIri" class="form-label">{{ 'model.event' | translate }}*:</label> | |||
| <app-search-select #eventSearchSelect | |||
| [formId]="'eventIri'" | |||
| [formLabelLangKey]="'model.event'" | |||
| [documentForm]="form" | |||
| [getDataFunction]="getEvents" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="eventColDefinitions" | |||
| [dataSet]="data.event" | |||
| > | |||
| </app-search-select> | |||
| <input id="eventIri" type="hidden" formControlName="eventIri" required/> | |||
| </div> | |||
| <div class="col-12 mb-3"> | |||
| <label for="locationIri" class="form-label">{{ 'model.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]="'common.date' | translate" | |||
| [inputId]="'startDate'" | |||
| [initialValue]="form.get('date')?.value ?? null" | |||
| (dateTimeChange)="onDateChange($event, 'date')" | |||
| ></app-datetime-picker> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="note" class="form-label">{{ 'common.note' | translate }}:</label> | |||
| <textarea class="form-control" id="note" formControlName="note"></textarea> | |||
| </div> | |||
| </form> | |||
| } | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <button type="submit" class="btn btn-primary" (click)="onSubmit()"> | |||
| {{ 'basic.save' | translate }} | |||
| </button> | |||
| @if (isEditMode()) { | |||
| <button type="button" class="ms-3 btn btn-primary" (click)="onDelete()"> | |||
| {{ 'basic.delete' | translate }} {{ 'model.user_trip_event' | translate }} | |||
| </button> | |||
| } | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -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<UserTripEventFormComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [UserTripEventFormComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(UserTripEventFormComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -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<UserTripEventJsonld> { | |||
| 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, | |||
| ); | |||
| } | |||
| } | |||
| @@ -2,6 +2,10 @@ | |||
| <app-list #listComponent | |||
| [listId]="'userTripEventList'" | |||
| [getDataFunction]="getData" | |||
| [showCreateButton]="showCreateButton" | |||
| [listColDefinitions]="listColDefinitions" | |||
| [dataFormComponent]="userTripEventFormComponent" | |||
| [dataFormComponentData]="dataFormComponentData" | |||
| [deleteItemFunction]="deleteItemFunction" | |||
| ></app-list> | |||
| </div> | |||
| @@ -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<any> { | |||
| return (id: string) => this.userTripEventService.userTripEventsIdDelete(id); | |||
| } | |||
| } | |||
| @@ -15,91 +15,11 @@ | |||
| </mat-tab> | |||
| <mat-tab label="{{ 'user_trip.events' | translate }}"> | |||
| <div> | |||
| <h4 class="mb-4">{{ 'user_trip.events' | translate }}</h4> | |||
| <div *ngFor="let userTripEvent of userTripEvents; let i = index" class="p-2 mb-2 changing-list"> | |||
| <div class="row"> | |||
| <div class="col-12 col-md-6 mb-3"> | |||
| <label [for]="'event_' + i" class="form-label">{{ 'model.event' | translate }}*:</label> | |||
| <app-search-select | |||
| [formId]="'eventIri'" | |||
| [formLabelLangKey]="'model.event'" | |||
| [documentForm]="eventForms[i]" | |||
| [getDataFunction]="getEvents" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="eventColDefinitions" | |||
| [dataSet]="userTripEvent.event" | |||
| > | |||
| </app-search-select> | |||
| </div> | |||
| <div class="col-12 col-md-6 mb-3"> | |||
| <label [for]="'location_' + i" class="form-label">{{ 'model.location' | translate }}*:</label> | |||
| <app-search-select | |||
| [formId]="'locationIri'" | |||
| [formLabelLangKey]="'model.location'" | |||
| [documentForm]="eventForms[i]" | |||
| [getDataFunction]="getLocations" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="locationColDefinitions" | |||
| [dataSet]="userTripEvent.location" | |||
| > | |||
| </app-search-select> | |||
| </div> | |||
| <div class="col-12 col-md-3 mb-1"> | |||
| <label class="form-label">{{ 'user_trip.event_date' | translate }} ({{ 'common.date' | translate }}):</label> | |||
| <div> | |||
| <input | |||
| type="date" | |||
| class="form-control" | |||
| [value]="formatDateForInput(userTripEvent.date)" | |||
| (change)="onDateInputChange($event, i)" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div class="col-12 col-md-3 mb-1"> | |||
| <label class="form-label">{{ 'user_trip.event_date' | translate }} ({{ 'common.time' | translate }}):</label> | |||
| <div> | |||
| <input | |||
| type="time" | |||
| class="form-control" | |||
| [value]="formatTimeForInput(userTripEvent.date)" | |||
| (change)="onTimeInputChange($event, i)" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div class="col-12 col-md-4 mb-1"> | |||
| <label [for]="'note_' + i" class="form-label">{{ 'common.note' | translate }}:</label> | |||
| <textarea | |||
| class="form-control" | |||
| [id]="'note_' + i" | |||
| rows="2" | |||
| [(ngModel)]="userTripEvent.note" | |||
| ></textarea> | |||
| </div> | |||
| <div class="col-12 col-md-2 mb-1 d-flex align-items-end"> | |||
| <button type="button" class="btn btn-danger" (click)="removeUserTripEvent(i)">X</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <button type="button" class="btn btn-primary" (click)="addNewUserTripEvent()">+</button> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <button type="button" class="btn btn-primary" (click)="saveAllUserTripEvents()"> | |||
| {{ 'basic.save' | translate }} | |||
| </button> | |||
| </div> | |||
| </div> | |||
| <app-user-trip-event-list | |||
| [userTrip]="userTrip" | |||
| [showCreateButton]="true" | |||
| > | |||
| </app-user-trip-event-list> | |||
| </div> | |||
| </mat-tab> | |||
| </mat-tab-group> | |||
| @@ -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}, | |||
| @@ -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", | |||