| @@ -1685,6 +1685,18 @@ paths: | |||
| style: form | |||
| explode: true | |||
| allowReserved: false | |||
| - | |||
| name: tripId | |||
| in: query | |||
| description: 'Filter UserTripEvents by Trip ID' | |||
| required: false | |||
| deprecated: false | |||
| allowEmptyValue: false | |||
| schema: | |||
| type: integer | |||
| style: form | |||
| explode: false | |||
| allowReserved: false | |||
| - | |||
| name: custom_json_filter | |||
| in: query | |||
| @@ -2327,6 +2339,9 @@ components: | |||
| type: string | |||
| code: | |||
| type: string | |||
| zoneName: | |||
| readOnly: true | |||
| type: string | |||
| isZone: | |||
| type: boolean | |||
| isPlace: | |||
| @@ -2389,6 +2404,9 @@ components: | |||
| type: string | |||
| code: | |||
| type: string | |||
| zoneName: | |||
| readOnly: true | |||
| type: string | |||
| isZone: | |||
| type: boolean | |||
| isPlace: | |||
| @@ -2405,31 +2423,6 @@ components: | |||
| - zoneIri | |||
| - name | |||
| - code | |||
| MediaObject: | |||
| type: object | |||
| description: '' | |||
| deprecated: false | |||
| properties: | |||
| id: | |||
| readOnly: true | |||
| type: integer | |||
| file: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: binary | |||
| filePath: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| createdBy: | |||
| $ref: '#/components/schemas/User' | |||
| createdAt: | |||
| readOnly: true | |||
| type: string | |||
| format: date-time | |||
| required: | |||
| - file | |||
| MediaObject.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -2849,11 +2842,16 @@ components: | |||
| lastName: | |||
| type: string | |||
| image: | |||
| anyOf: | |||
| - | |||
| $ref: '#/components/schemas/MediaObject' | |||
| - | |||
| type: 'null' | |||
| readOnly: true | |||
| type: string | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| imageIri: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| imageUrl: | |||
| readOnly: true | |||
| type: | |||
| @@ -2867,7 +2865,9 @@ components: | |||
| password: | |||
| writeOnly: true | |||
| description: 'The plaintext password when being set or changed.' | |||
| type: string | |||
| type: | |||
| - string | |||
| - 'null' | |||
| active: | |||
| type: boolean | |||
| roles: | |||
| @@ -2931,11 +2931,14 @@ components: | |||
| lastName: | |||
| type: string | |||
| image: | |||
| anyOf: | |||
| - | |||
| $ref: '#/components/schemas/MediaObject.jsonld' | |||
| - | |||
| type: 'null' | |||
| readOnly: true | |||
| $ref: '#/components/schemas/MediaObject.jsonld' | |||
| imageIri: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| imageUrl: | |||
| readOnly: true | |||
| type: | |||
| @@ -2949,7 +2952,9 @@ components: | |||
| password: | |||
| writeOnly: true | |||
| description: 'The plaintext password when being set or changed.' | |||
| type: string | |||
| type: | |||
| - string | |||
| - 'null' | |||
| active: | |||
| type: boolean | |||
| roles: | |||
| @@ -3164,6 +3169,11 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| user: | |||
| readOnly: true | |||
| type: string | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| date: | |||
| type: string | |||
| format: date-time | |||
| @@ -3242,6 +3252,9 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| user: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/User.jsonld' | |||
| date: | |||
| type: string | |||
| format: date-time | |||
| @@ -15,6 +15,7 @@ export const locationForm = new FormGroup({ | |||
| zoneIri: new FormControl(null, [Validators.required]), | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| zoneName: new FormControl(null, []), | |||
| isZone: new FormControl(null, []), | |||
| isPlace: new FormControl(null, []), | |||
| isPort: new FormControl(null, []), | |||
| @@ -27,20 +28,13 @@ export const locationJsonldForm = new FormGroup({ | |||
| zoneIri: new FormControl(null, [Validators.required]), | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| zoneName: new FormControl(null, []), | |||
| isZone: new FormControl(null, []), | |||
| isPlace: new FormControl(null, []), | |||
| isPort: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| export const mediaObjectForm = new FormGroup({ | |||
| id: new FormControl(null, []), | |||
| file: new FormControl(null, [Validators.required]), | |||
| filePath: new FormControl(null, []), | |||
| createdBy: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| export const mediaObjectJsonldForm = new FormGroup({ | |||
| dbId: new FormControl(null, []), | |||
| contentUrl: new FormControl(null, []), | |||
| @@ -125,6 +119,7 @@ export const userForm = new FormGroup({ | |||
| referenceId: new FormControl(null, [Validators.required]), | |||
| lastName: new FormControl(null, [Validators.required]), | |||
| image: new FormControl(null, []), | |||
| imageIri: new FormControl(null, []), | |||
| imageUrl: new FormControl(null, []), | |||
| fullName: new FormControl(null, []), | |||
| password: new FormControl(null, []), | |||
| @@ -140,6 +135,7 @@ export const userJsonldForm = new FormGroup({ | |||
| referenceId: new FormControl(null, [Validators.required]), | |||
| lastName: new FormControl(null, [Validators.required]), | |||
| image: new FormControl(null, []), | |||
| imageIri: new FormControl(null, []), | |||
| imageUrl: new FormControl(null, []), | |||
| fullName: new FormControl(null, []), | |||
| password: new FormControl(null, []), | |||
| @@ -186,6 +182,7 @@ export const userTripEventForm = new FormGroup({ | |||
| eventIri: new FormControl(null, [Validators.required]), | |||
| location: new FormControl(null, []), | |||
| locationIri: new FormControl(null, [Validators.required]), | |||
| user: new FormControl(null, []), | |||
| date: new FormControl(null, [Validators.required]), | |||
| note: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| @@ -199,6 +196,7 @@ export const userTripEventJsonldForm = new FormGroup({ | |||
| eventIri: new FormControl(null, [Validators.required]), | |||
| location: new FormControl(null, []), | |||
| locationIri: new FormControl(null, [Validators.required]), | |||
| user: new FormControl(null, []), | |||
| date: new FormControl(null, [Validators.required]), | |||
| note: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| @@ -127,6 +127,14 @@ | |||
| </div> | |||
| </div> | |||
| </mat-tab> | |||
| <mat-tab label="{{ 'trip.events' | translate }}"> | |||
| <div> | |||
| <app-user-trip-event-list | |||
| [trip]="trip" | |||
| > | |||
| </app-user-trip-event-list> | |||
| </div> | |||
| </mat-tab> | |||
| </mat-tab-group> | |||
| } | |||
| @@ -7,7 +7,7 @@ import { | |||
| TripService, | |||
| LocationService, | |||
| LocationJsonld, | |||
| UserTripService, UserService, UserTripJsonld, UserJsonld | |||
| UserTripService, UserService, UserTripJsonld, UserJsonld, UserTripEventJsonld, UserTripEventService | |||
| } from "@app/core/api/v1"; | |||
| import { AppHelperService } from "@app/_helpers/app-helper.service"; | |||
| import { ActivatedRoute } from "@angular/router"; | |||
| @@ -29,6 +29,7 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| protected originalUserTrips: UserTripJsonld[] = []; | |||
| protected tripLocations: TripLocationJsonld[] = []; | |||
| protected userTrips: UserTripJsonld[] = []; | |||
| protected userTripEvents: UserTripEventJsonld[] = []; | |||
| protected users: UserJsonld[] = []; | |||
| protected locationForms: FormGroup[] = []; | |||
| protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations(); | |||
| @@ -42,6 +43,7 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| private tripLocationService: TripLocationService, | |||
| private locationService: LocationService, | |||
| private userTripService: UserTripService, | |||
| private userTripEventService: UserTripEventService, | |||
| private userService: UserService, | |||
| protected appHelperService: AppHelperService, | |||
| private route: ActivatedRoute, | |||
| @@ -54,7 +56,8 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| data => { | |||
| this.trip = data; | |||
| this.loadTripLocations(); | |||
| this.loadUserTrips(); // Verwenden Sie die neue loadUserTrips-Methode | |||
| this.loadUserTrips(); | |||
| this.loadUserTripEvents(); | |||
| } | |||
| ); | |||
| }); | |||
| @@ -263,6 +266,20 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| }); | |||
| } | |||
| loadUserTripEvents() { | |||
| this.userTripEventService.userTripEventsGetCollection( | |||
| 1, | |||
| 200, | |||
| undefined, | |||
| undefined, | |||
| this.trip.dbId!, | |||
| ).subscribe({ | |||
| next: (data) => { | |||
| this.userTripEvents = data.member; | |||
| } | |||
| }) | |||
| } | |||
| removeTripLocation(index: number) { | |||
| const tripLocationId = this.tripLocations[index].id; | |||
| @@ -0,0 +1,7 @@ | |||
| <div class="spt-container"> | |||
| <app-list #listComponent | |||
| [listId]="'userTripEventList'" | |||
| [getDataFunction]="getData" | |||
| [listColDefinitions]="listColDefinitions" | |||
| ></app-list> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { UserTripEventListComponent } from './user-trip-event-list.component'; | |||
| describe('UserTripEventListComponent', () => { | |||
| let component: UserTripEventListComponent; | |||
| let fixture: ComponentFixture<UserTripEventListComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [UserTripEventListComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(UserTripEventListComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,103 @@ | |||
| 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 {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"; | |||
| @Component({ | |||
| selector: 'app-user-trip-event-list', | |||
| templateUrl: './user-trip-event-list.component.html', | |||
| styleUrl: './user-trip-event-list.component.scss' | |||
| }) | |||
| export class UserTripEventListComponent { | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| @Input() public trip?: TripJsonld; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| constructor( | |||
| private userTripEventService: UserTripEventService, | |||
| protected appHelperService: AppHelperService, | |||
| ) { | |||
| this.listColDefinitions = [ | |||
| { | |||
| name: 'eventName', | |||
| text: 'model.event', | |||
| type: ListComponent.COLUMN_TYPE_TEXT_BOLD, | |||
| subResource: 'event', | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'user', | |||
| text: 'model.user', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'user', | |||
| field: 'fullName', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'location', | |||
| text: 'model.location', | |||
| type: ListComponent.COLUMN_TYPE_TEXT_BOLD, | |||
| field: 'name', | |||
| subResource: 'location', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'zone', | |||
| text: 'model.zone', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'zoneName', | |||
| subResource: 'location', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'date', | |||
| text: 'basic.date', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'date', | |||
| 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() { | |||
| } | |||
| ngAfterViewInit(): void { | |||
| this.listComponent.getData(); | |||
| } | |||
| getData: ListGetDataFunctionType = ( | |||
| index: number, | |||
| pageSize: number, | |||
| term?: string, | |||
| ) => { | |||
| return this.userTripEventService.userTripEventsGetCollection( | |||
| index, | |||
| pageSize, | |||
| undefined, | |||
| undefined, | |||
| this.trip !== undefined ? this.trip.dbId! : undefined, | |||
| this.listComponent.getFilterJsonString(), | |||
| this.listComponent.getSortingJsonString() | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <p>user-trip-event works!</p> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { UserTripEventComponent } from './user-trip-event.component'; | |||
| describe('UserTripEventComponent', () => { | |||
| let component: UserTripEventComponent; | |||
| let fixture: ComponentFixture<UserTripEventComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [UserTripEventComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(UserTripEventComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,10 @@ | |||
| import { Component } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-user-trip-event', | |||
| templateUrl: './user-trip-event.component.html', | |||
| styleUrl: './user-trip-event.component.scss' | |||
| }) | |||
| export class UserTripEventComponent { | |||
| } | |||
| @@ -78,11 +78,6 @@ export class UserTripFormComponent extends AbstractDataFormComponent<UserTripJso | |||
| } | |||
| } | |||
| getFileNameFromUrl(url: string | null | undefined): string { | |||
| if (!url) return ''; | |||
| return url.split('/').pop() || ''; | |||
| } | |||
| markSignatureForRemoval(): void { | |||
| // Speichere die aktuelle signatureIri, um sie später zu löschen | |||
| this.signatureToDelete = this.form.get('signatureIri')?.value; | |||
| @@ -4,6 +4,16 @@ | |||
| </div> | |||
| <mat-tab-group> | |||
| <mat-tab label="{{ 'basic.details' | translate }}"> | |||
| <app-user-form | |||
| [data]="user" | |||
| [mode]="FormMode.Edit" | |||
| [id]="appHelperService.extractId(user.id!)" | |||
| (submit)="onFormUpdate($event)" | |||
| > | |||
| </app-user-form> | |||
| <div class="card contacts-detail"> | |||
| <div class="card-body row"> | |||
| <div class="spt-col col-12 col-sm-6 col-lg-8"> | |||
| @@ -3,6 +3,7 @@ import {UserJsonld, UserService} from "@app/core/api/v1"; | |||
| import {AccountService} from "@app/_services"; | |||
| import {AppHelperService} from "@app/_helpers/app-helper.service"; | |||
| import {ActivatedRoute} from "@angular/router"; | |||
| import {FormMode} from "@app/_components/_abstract/abstract-data-form-component"; | |||
| @Component({ | |||
| selector: 'app-user-detail', | |||
| @@ -54,4 +55,6 @@ export class UserDetailComponent implements OnInit, AfterViewInit { | |||
| this.isCurrentUser = this.appHelperService.extractId(this.user.id) == user?.id; | |||
| } | |||
| } | |||
| protected readonly FormMode = FormMode; | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| <div class="spt-container"> | |||
| @if (!isEditMode()) { | |||
| <div class="spt-headline d-flex justify-content-between align-items-start"> | |||
| <h2>{{ ('basic.new') | translate }} {{ 'model.user' | translate }}</h2> | |||
| </div> | |||
| } | |||
| <div class="spt-form"> | |||
| <form [formGroup]="userForm" (ngSubmit)="onSubmit()"> | |||
| <div class="mb-3"> | |||
| <label for="email" class="form-label">{{ 'users.email' | translate }}:</label> | |||
| <input type="text" class="form-control" id="email" formControlName="email"/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="lastName" class="form-label">{{ 'users.lastname' | translate }}:</label> | |||
| <input type="text" class="form-control" id="lastName" formControlName="lastName"/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="referenceId" class="form-label">{{ 'users.pilotIdNo' | translate }}:</label> | |||
| <input type="text" class="form-control" id="referenceId" formControlName="referenceId"/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="password" class="form-label">{{ 'users.password' | translate }}:</label> | |||
| <input type="text" class="form-control" id="password" formControlName="password"/> | |||
| </div> | |||
| <div class="flex gap-2"> | |||
| <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> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { UserFormComponent } from './user-form.component'; | |||
| describe('UserFormComponent', () => { | |||
| let component: UserFormComponent; | |||
| let fixture: ComponentFixture<UserFormComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [UserFormComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(UserFormComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,40 @@ | |||
| import { Component } from '@angular/core'; | |||
| import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component"; | |||
| import {UserJsonld, UserService} 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_USERS} from "@app/app-routing.module"; | |||
| import {userForm} from "@app/_forms/apiForms"; | |||
| @Component({ | |||
| selector: 'app-user-form', | |||
| templateUrl: './user-form.component.html', | |||
| styleUrl: './user-form.component.scss' | |||
| }) | |||
| export class UserFormComponent extends AbstractDataFormComponent<UserJsonld> { | |||
| protected readonly userForm = userForm; | |||
| constructor( | |||
| private userService: UserService, | |||
| private appHelperService: AppHelperService, | |||
| translateService: TranslateService, | |||
| router: Router | |||
| ) { | |||
| super( | |||
| userForm, | |||
| (data: UserJsonld) => this.userService.usersPost(data), | |||
| (id: string | number, data: UserJsonld) => | |||
| this.userService.usersIdPatch( | |||
| id.toString(), | |||
| this.appHelperService.convertJsonldToJson(data) | |||
| ), | |||
| (id: string | number) => this.userService.usersIdDelete(id.toString()), | |||
| translateService, | |||
| router | |||
| ); | |||
| this.redirectAfterDelete = '/' + ROUTE_USERS; | |||
| } | |||
| } | |||
| @@ -67,6 +67,9 @@ import { UserTripComponent } from './_views/user-trip/user-trip.component'; | |||
| import { UserTripListComponent } from './_views/user-trip/user-trip-list/user-trip-list.component'; | |||
| import { UserTripDetailComponent } from './_views/user-trip/user-trip-detail/user-trip-detail.component'; | |||
| import { UserTripFormComponent } from './_views/user-trip/user-trip-form/user-trip-form.component'; | |||
| import { UserTripEventComponent } from './_views/user-trip-event/user-trip-event.component'; | |||
| 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'; | |||
| registerLocaleData(localeDe, 'de-DE'); | |||
| @@ -159,6 +162,9 @@ export function HttpLoaderFactory(http: HttpClient) { | |||
| UserTripListComponent, | |||
| UserTripDetailComponent, | |||
| UserTripFormComponent, | |||
| UserTripEventComponent, | |||
| UserTripEventListComponent, | |||
| UserFormComponent, | |||
| ], | |||
| providers: [ | |||
| {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, | |||
| @@ -39,7 +39,6 @@ model/eventJsonldContext.ts | |||
| model/eventJsonldContextOneOf.ts | |||
| model/location.ts | |||
| model/locationJsonld.ts | |||
| model/mediaObject.ts | |||
| model/mediaObjectJsonld.ts | |||
| model/models.ts | |||
| model/shippingCompany.ts | |||
| @@ -49,9 +48,7 @@ model/tripJsonld.ts | |||
| model/tripLocation.ts | |||
| model/tripLocationJsonld.ts | |||
| model/user.ts | |||
| model/userImage.ts | |||
| model/userJsonld.ts | |||
| model/userJsonldImage.ts | |||
| model/userTrip.ts | |||
| model/userTripEvent.ts | |||
| model/userTripEventJsonld.ts | |||
| @@ -102,15 +102,16 @@ export class UserTripEventService { | |||
| * @param itemsPerPage The number of items per page | |||
| * @param userTrip | |||
| * @param userTrip2 | |||
| * @param tripId Filter UserTripEvents by Trip ID | |||
| * @param customJsonFilter | |||
| * @param customJsonOrder | |||
| * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. | |||
| * @param reportProgress flag to report request and response progress. | |||
| */ | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, customJsonFilter?: string, customJsonOrder?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<ApiUserTripEventsGetCollection200Response>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, customJsonFilter?: string, customJsonOrder?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<ApiUserTripEventsGetCollection200Response>>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, customJsonFilter?: string, customJsonOrder?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<ApiUserTripEventsGetCollection200Response>>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, customJsonFilter?: string, customJsonOrder?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<any> { | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, tripId?: number, customJsonFilter?: string, customJsonOrder?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<ApiUserTripEventsGetCollection200Response>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, tripId?: number, customJsonFilter?: string, customJsonOrder?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<ApiUserTripEventsGetCollection200Response>>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, tripId?: number, customJsonFilter?: string, customJsonOrder?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<ApiUserTripEventsGetCollection200Response>>; | |||
| public userTripEventsGetCollection(page?: number, itemsPerPage?: number, userTrip?: string, userTrip2?: Array<string>, tripId?: number, customJsonFilter?: string, customJsonOrder?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json', context?: HttpContext, transferCache?: boolean}): Observable<any> { | |||
| let localVarQueryParameters = new HttpParams({encoder: this.encoder}); | |||
| if (page !== undefined && page !== null) { | |||
| @@ -131,6 +132,10 @@ export class UserTripEventService { | |||
| <any>element, 'userTrip[]'); | |||
| }) | |||
| } | |||
| if (tripId !== undefined && tripId !== null) { | |||
| localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, | |||
| <any>tripId, 'tripId'); | |||
| } | |||
| if (customJsonFilter !== undefined && customJsonFilter !== null) { | |||
| localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, | |||
| <any>customJsonFilter, 'custom_json_filter'); | |||
| @@ -20,6 +20,7 @@ export interface Location { | |||
| zoneIri: string | null; | |||
| name: string; | |||
| code: string; | |||
| readonly zoneName?: string; | |||
| isZone?: boolean; | |||
| isPlace?: boolean; | |||
| isPort?: boolean; | |||
| @@ -25,6 +25,7 @@ export interface LocationJsonld { | |||
| zoneIri: string | null; | |||
| name: string; | |||
| code: string; | |||
| readonly zoneName?: string; | |||
| isZone?: boolean; | |||
| isPlace?: boolean; | |||
| isPort?: boolean; | |||
| @@ -19,7 +19,6 @@ export * from './eventJsonldContext'; | |||
| export * from './eventJsonldContextOneOf'; | |||
| export * from './location'; | |||
| export * from './locationJsonld'; | |||
| export * from './mediaObject'; | |||
| export * from './mediaObjectJsonld'; | |||
| export * from './shippingCompany'; | |||
| export * from './shippingCompanyJsonld'; | |||
| @@ -28,9 +27,7 @@ export * from './tripJsonld'; | |||
| export * from './tripLocation'; | |||
| export * from './tripLocationJsonld'; | |||
| export * from './user'; | |||
| export * from './userImage'; | |||
| export * from './userJsonld'; | |||
| export * from './userJsonldImage'; | |||
| export * from './userTrip'; | |||
| export * from './userTripEvent'; | |||
| export * from './userTripEventJsonld'; | |||
| @@ -9,7 +9,6 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { UserImage } from './userImage'; | |||
| /** | |||
| @@ -21,13 +20,14 @@ export interface User { | |||
| firstName: string; | |||
| referenceId: string; | |||
| lastName: string; | |||
| image?: UserImage; | |||
| readonly image?: string; | |||
| imageIri?: string | null; | |||
| readonly imageUrl?: string | null; | |||
| readonly fullName?: string | null; | |||
| /** | |||
| * The plaintext password when being set or changed. | |||
| */ | |||
| password?: string; | |||
| password?: string | null; | |||
| active?: boolean; | |||
| roles?: Array<string>; | |||
| readonly createdAt?: string | null; | |||
| @@ -9,7 +9,7 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { UserJsonldImage } from './userJsonldImage'; | |||
| import { MediaObjectJsonld } from './mediaObjectJsonld'; | |||
| import { EventJsonldContext } from './eventJsonldContext'; | |||
| @@ -25,13 +25,14 @@ export interface UserJsonld { | |||
| firstName: string; | |||
| referenceId: string; | |||
| lastName: string; | |||
| image?: UserJsonldImage; | |||
| readonly image?: MediaObjectJsonld; | |||
| imageIri?: string | null; | |||
| readonly imageUrl?: string | null; | |||
| readonly fullName?: string | null; | |||
| /** | |||
| * The plaintext password when being set or changed. | |||
| */ | |||
| password?: string; | |||
| password?: string | null; | |||
| active?: boolean; | |||
| roles?: Array<string>; | |||
| readonly createdAt?: string | null; | |||
| @@ -23,6 +23,7 @@ export interface UserTripEvent { | |||
| eventIri: string | null; | |||
| readonly location?: string; | |||
| locationIri: string | null; | |||
| readonly user?: string; | |||
| date: string; | |||
| note?: string | null; | |||
| readonly createdAt?: string | null; | |||
| @@ -10,6 +10,7 @@ | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { UserTripJsonld } from './userTripJsonld'; | |||
| import { UserJsonld } from './userJsonld'; | |||
| import { EventJsonld } from './eventJsonld'; | |||
| import { EventJsonldContext } from './eventJsonldContext'; | |||
| import { LocationJsonld } from './locationJsonld'; | |||
| @@ -29,6 +30,7 @@ export interface UserTripEventJsonld { | |||
| eventIri: string | null; | |||
| readonly location?: LocationJsonld; | |||
| locationIri: string | null; | |||
| readonly user?: UserJsonld; | |||
| date: string; | |||
| note?: string | null; | |||
| readonly createdAt?: string | null; | |||
| @@ -34,7 +34,8 @@ | |||
| "remove_itinerary_location": "Remove itinerary location", | |||
| "save_itinerary": "Save itinerary", | |||
| "assigned_users": "Assigned Users (User Trips)", | |||
| "save_user_assignments": "Save user assignments" | |||
| "save_user_assignments": "Save user assignments", | |||
| "events": "Events" | |||
| }, | |||
| "user_trip": | |||
| { | |||
| @@ -119,7 +120,8 @@ | |||
| "firstname": "Firstname", | |||
| "lastname": "Lastname", | |||
| "userTrips": "User trips", | |||
| "pilotIdNo": "#Pilot id" | |||
| "pilotIdNo": "#Pilot id", | |||
| "password": "Password" | |||
| }, | |||
| "form": | |||
| { | |||
| @@ -84,6 +84,9 @@ class LocationApi | |||
| #[Assert\NotBlank] | |||
| public string $code; | |||
| #[ApiProperty(writable: false)] | |||
| public string $zoneName; | |||
| public bool $isZone; | |||
| public bool $isPlace; | |||
| @@ -23,6 +23,7 @@ use App\Filter\CustomJsonOrderFilter; | |||
| use App\Filter\UserNameSearchFilter; | |||
| use App\State\EntityClassDtoStateProcessor; | |||
| use App\State\EntityToDtoStateProvider; | |||
| use Symfony\Component\PropertyInfo\Type; | |||
| use Symfony\Component\Validator\Constraints as Assert; | |||
| #[ApiResource( | |||
| @@ -75,7 +76,24 @@ class UserApi | |||
| #[Assert\NotBlank] | |||
| public string $lastName; | |||
| public ?MediaObject $image = null; | |||
| /** | |||
| * @var MediaObjectApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: false, | |||
| readableLink: true, | |||
| writableLink: false, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| class: MediaObjectApi::class, | |||
| ) | |||
| ] | |||
| )] | |||
| public ?MediaObjectApi $image = null; | |||
| #[ApiProperty(writable: true)] | |||
| public ?MediaObjectApi $imageIri = null; | |||
| #[ApiProperty(writable: false)] | |||
| public ?string $imageUrl = null; | |||
| @@ -16,6 +16,7 @@ use App\Entity\UserTrip; | |||
| use App\Entity\UserTripEvent; | |||
| use App\Filter\CustomJsonFilter; | |||
| use App\Filter\CustomJsonOrderFilter; | |||
| use App\Filter\UserTripEventFilter; | |||
| use App\State\EntityClassDtoStateProcessor; | |||
| use App\State\EntityToDtoStateProvider; | |||
| use Symfony\Component\Validator\Constraints as Assert; | |||
| @@ -41,6 +42,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||
| security: 'is_granted("ROLE_ADMIN")' | |||
| ) | |||
| ], | |||
| order: ['date' => 'ASC'], | |||
| security: 'is_granted("ROLE_USER")', | |||
| provider: EntityToDtoStateProvider::class, | |||
| processor: EntityClassDtoStateProcessor::class, | |||
| @@ -48,6 +50,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||
| )] | |||
| #[ApiFilter(SearchFilter::class, properties: ['userTrip' => 'exact'])] | |||
| #[ApiFilter(UserTripEventFilter::class)] | |||
| #[ApiFilter(CustomJsonFilter::class)] | |||
| #[ApiFilter(CustomJsonOrderFilter::class)] | |||
| class UserTripEventApi | |||
| @@ -118,6 +121,22 @@ class UserTripEventApi | |||
| #[ApiProperty(writable: true)] | |||
| public ?LocationApi $locationIri = null; | |||
| /** | |||
| * @var UserApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: false, | |||
| readableLink: true, | |||
| writableLink: false, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| class: UserApi::class, | |||
| ) | |||
| ] | |||
| )] | |||
| public ?UserApi $user = null; | |||
| #[Assert\NotBlank] | |||
| public \DateTimeImmutable $date; | |||
| @@ -0,0 +1,47 @@ | |||
| <?php | |||
| namespace App\Filter; | |||
| use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter; | |||
| use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; | |||
| use ApiPlatform\Metadata\ApiFilter; | |||
| use Doctrine\ORM\QueryBuilder; | |||
| use ApiPlatform\Metadata\Operation; | |||
| #[ApiFilter(UserTripEventFilter::class)] | |||
| class UserTripEventFilter extends AbstractFilter | |||
| { | |||
| protected function filterProperty( | |||
| string $property, | |||
| mixed $value, | |||
| QueryBuilder $queryBuilder, | |||
| QueryNameGeneratorInterface $queryNameGenerator, | |||
| string $resourceClass, | |||
| ?Operation $operation = null, | |||
| array $context = [] | |||
| ): void { | |||
| if ($property !== 'tripId') { | |||
| return; | |||
| } | |||
| $rootAlias = $queryBuilder->getRootAliases()[0]; | |||
| $parameterName = $queryNameGenerator->generateParameterName('tripId'); | |||
| $queryBuilder | |||
| ->join("$rootAlias.userTrip", "userTrip") | |||
| ->join("userTrip.trip", "trip") | |||
| ->andWhere("trip.id = :$parameterName") | |||
| ->setParameter($parameterName, $value); | |||
| } | |||
| public function getDescription(string $resourceClass): array | |||
| { | |||
| return [ | |||
| 'tripId' => [ | |||
| 'property' => 'tripId', | |||
| 'type' => 'int', | |||
| 'required' => false, | |||
| 'description' => 'Filter UserTripEvents by Trip ID', | |||
| ], | |||
| ]; | |||
| } | |||
| } | |||
| @@ -37,6 +37,7 @@ class LocationEntityToApiMapper implements MapperInterface | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->name = $entity->getName(); | |||
| $dto->zoneName = $entity->getZone()->getName(); | |||
| $dto->code = $entity->getCode(); | |||
| $dto->isZone = $entity->isZone(); | |||
| $dto->isPlace = $entity->isPlace(); | |||
| @@ -5,6 +5,7 @@ namespace App\Mapper; | |||
| use App\ApiResource\UserApi; | |||
| use App\Entity\User; | |||
| use App\Entity\Posting; | |||
| use App\Repository\MediaObjectRepository; | |||
| use App\Repository\UserRepository; | |||
| use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; | |||
| use Symfonycasts\MicroMapper\AsMapper; | |||
| @@ -16,6 +17,7 @@ class UserApiToEntityMapper implements MapperInterface | |||
| public function __construct( | |||
| private UserRepository $repository, | |||
| private UserPasswordHasherInterface $userPasswordHasher, | |||
| private MediaObjectRepository $mediaObjectRepository, | |||
| ) | |||
| { | |||
| } | |||
| @@ -48,6 +50,16 @@ class UserApiToEntityMapper implements MapperInterface | |||
| $entity->setPassword($this->userPasswordHasher->hashPassword($entity, $dto->password)); | |||
| } | |||
| if ($dto->imageIri) { | |||
| $image = $this->mediaObjectRepository->find($dto->imageIri->id); | |||
| if (!$image) { | |||
| throw new \Exception('Image not found'); | |||
| } | |||
| $entity->setImage($image); | |||
| } else { | |||
| $entity->setImage(null); | |||
| } | |||
| return $entity; | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ | |||
| namespace App\Mapper; | |||
| use App\ApiResource\MediaObjectApi; | |||
| use App\ApiResource\UserApi; | |||
| use App\Entity\User; | |||
| use App\Service\FileUrlService; | |||
| @@ -42,8 +43,15 @@ class UserEntityToApiMapper implements MapperInterface | |||
| $dto->referenceId = $entity->getReferenceId(); | |||
| $dto->firstName = $entity->getFirstName(); | |||
| $dto->lastName = $entity->getLastName(); | |||
| $dto->image = $entity->getImage(); | |||
| $dto->roles = $entity->getRoles(); | |||
| $dto->imageIri = $dto->image = null; | |||
| if ($entity->getImage() !== null) { | |||
| $dto->imageIri = $dto->image = $this->microMapper->map($entity->getImage(), MediaObjectApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 1, | |||
| ]); | |||
| } | |||
| $dto->imageUrl = $this->fileUrlService->getFileUrl($entity->getImage()); | |||
| $dto->fullName = $entity->getFirstName() . " " . $entity->getLastName(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| @@ -19,8 +19,6 @@ class UserTripApiToEntityMapper implements MapperInterface | |||
| { | |||
| public function __construct( | |||
| private UserTripRepository $repository, | |||
| private TripRepository $tripRepository, | |||
| private UserRepository $userRepository, | |||
| private MediaObjectRepository $mediaObjectRepository, | |||
| private MicroMapperInterface $microMapper | |||
| ) { | |||
| @@ -4,6 +4,7 @@ namespace App\Mapper; | |||
| use App\ApiResource\EventApi; | |||
| use App\ApiResource\LocationApi; | |||
| use App\ApiResource\UserApi; | |||
| use App\ApiResource\UserTripApi; | |||
| use App\ApiResource\UserTripEventApi; | |||
| use App\Entity\UserTripEvent; | |||
| @@ -54,6 +55,10 @@ class UserTripEventEntityToApiMapper implements MapperInterface | |||
| MicroMapperInterface::MAX_DEPTH => 1, | |||
| ]); | |||
| $dto->user = $this->microMapper->map($entity->getUserTrip()->getUser(), UserApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 1, | |||
| ]); | |||
| return $dto; | |||
| } | |||
| } | |||