| @@ -1937,6 +1937,18 @@ paths: | |||
| style: form | |||
| explode: false | |||
| allowReserved: false | |||
| - | |||
| name: custom_json_filter | |||
| in: query | |||
| description: '' | |||
| required: false | |||
| deprecated: false | |||
| allowEmptyValue: false | |||
| schema: | |||
| type: string | |||
| style: form | |||
| explode: false | |||
| allowReserved: false | |||
| - | |||
| name: custom_json_order | |||
| in: query | |||
| @@ -3947,6 +3959,8 @@ components: | |||
| type: boolean | |||
| isPort: | |||
| type: boolean | |||
| isStartEnd: | |||
| type: boolean | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -4012,6 +4026,8 @@ components: | |||
| type: boolean | |||
| isPort: | |||
| type: boolean | |||
| isStartEnd: | |||
| type: boolean | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -4171,10 +4187,6 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| captainName: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| startLocation: | |||
| readOnly: true | |||
| type: string | |||
| @@ -4207,6 +4219,8 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| completed: | |||
| type: boolean | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -4270,10 +4284,6 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| captainName: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| startLocation: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/Location.jsonld' | |||
| @@ -4302,6 +4312,8 @@ components: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| completed: | |||
| type: boolean | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -4342,6 +4354,10 @@ components: | |||
| example: 'https://example.com/' | |||
| isArrival: | |||
| type: boolean | |||
| isTransit: | |||
| type: boolean | |||
| isDeparture: | |||
| type: boolean | |||
| date: | |||
| type: string | |||
| format: date-time | |||
| @@ -4406,6 +4422,10 @@ components: | |||
| example: 'https://example.com/' | |||
| isArrival: | |||
| type: boolean | |||
| isTransit: | |||
| type: boolean | |||
| isDeparture: | |||
| type: boolean | |||
| date: | |||
| type: string | |||
| format: date-time | |||
| @@ -4471,6 +4491,8 @@ components: | |||
| type: boolean | |||
| active: | |||
| type: boolean | |||
| isPilot: | |||
| type: boolean | |||
| roles: | |||
| readOnly: true | |||
| type: array | |||
| @@ -4489,6 +4511,7 @@ components: | |||
| - lastName | |||
| - isAdmin | |||
| - active | |||
| - isPilot | |||
| User.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -4562,6 +4585,8 @@ components: | |||
| type: boolean | |||
| active: | |||
| type: boolean | |||
| isPilot: | |||
| type: boolean | |||
| roles: | |||
| readOnly: true | |||
| type: array | |||
| @@ -4580,6 +4605,7 @@ components: | |||
| - lastName | |||
| - isAdmin | |||
| - active | |||
| - isPilot | |||
| UserTrip: | |||
| type: object | |||
| description: '' | |||
| @@ -4618,6 +4644,8 @@ components: | |||
| - 'null' | |||
| completed: | |||
| type: boolean | |||
| approved: | |||
| type: boolean | |||
| signature: | |||
| readOnly: true | |||
| type: string | |||
| @@ -4649,6 +4677,7 @@ components: | |||
| - tripIri | |||
| - userIri | |||
| - completed | |||
| - approved | |||
| UserTrip.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -4706,6 +4735,8 @@ components: | |||
| - 'null' | |||
| completed: | |||
| type: boolean | |||
| approved: | |||
| type: boolean | |||
| signature: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/MediaObject.jsonld' | |||
| @@ -4735,6 +4766,7 @@ components: | |||
| - tripIri | |||
| - userIri | |||
| - completed | |||
| - approved | |||
| UserTripEvent: | |||
| type: object | |||
| description: '' | |||
| @@ -4905,6 +4937,30 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| length: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| breadth: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| draft: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| grossTonnage: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| imoNo: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| callSign: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -4961,6 +5017,30 @@ components: | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| length: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| breadth: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| draft: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| grossTonnage: | |||
| type: | |||
| - number | |||
| - 'null' | |||
| imoNo: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| callSign: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -88,7 +88,7 @@ export abstract class AbstractDataFormComponent<T extends { [key: string]: any } | |||
| return; | |||
| } | |||
| this.translateService.get('basic.delete_confirm').subscribe((confirmMessage: string) => { | |||
| this.translateService.get('basic.delete_confirm_related').subscribe((confirmMessage: string) => { | |||
| if (confirm(confirmMessage)) { | |||
| this.deleteFn!(this.id!).subscribe({ | |||
| next: () => { | |||
| @@ -124,6 +124,46 @@ export class SearchSelectComponent implements OnInit, AfterViewInit { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_zone', | |||
| text: 'location.is_zone', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isZone', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_place', | |||
| text: 'location.is_place', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPlace', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_port', | |||
| text: 'location.is_port', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPort', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_start_end', | |||
| text: 'location.is_start_end', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isStartEnd', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| ]; | |||
| } | |||
| @@ -204,6 +244,54 @@ export class SearchSelectComponent implements OnInit, AfterViewInit { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'length', | |||
| text: 'vessel.length', | |||
| type: ListComponent.COLUMN_TYPE_NUMBER, | |||
| field: 'length', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_NUMBER, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'breadth', | |||
| text: 'vessel.breadth', | |||
| type: ListComponent.COLUMN_TYPE_NUMBER, | |||
| field: 'breadth', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_NUMBER, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'draft', | |||
| text: 'vessel.draft', | |||
| type: ListComponent.COLUMN_TYPE_NUMBER, | |||
| field: 'draft', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_NUMBER, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'grossTonnage', | |||
| text: 'vessel.grossTonnage', | |||
| type: ListComponent.COLUMN_TYPE_NUMBER, | |||
| field: 'grossTonnage', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_NUMBER, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'imoNo', | |||
| text: 'vessel.imoNo', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'imoNo', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'callSign', | |||
| text: 'vessel.callSign', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'callSign', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| @@ -218,27 +306,61 @@ export class SearchSelectComponent implements OnInit, AfterViewInit { | |||
| public static getDefaultColDefUsers(subResource?: string): ListColDefinition[] { | |||
| return [ | |||
| { | |||
| name: 'fullName', | |||
| text: 'users.full_name', | |||
| name: 'image', | |||
| text: 'basic.image', | |||
| type: ListComponent.COLUMN_TYPE_IMAGE, | |||
| field: 'imageUrl', | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'firstName', | |||
| text: 'users.firstname', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'fullName', | |||
| field: 'firstName', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| }, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'lastName', | |||
| text: 'users.lastname', | |||
| type: ListComponent.COLUMN_TYPE_TEXT_BOLD, | |||
| field: 'lastName', | |||
| sortable: true, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'email', | |||
| text: 'users.email', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| type: ListComponent.COLUMN_TYPE_EMAIL, | |||
| field: 'email', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| }, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'referenceId', | |||
| text: 'users.pilotIdNo', | |||
| type: ListComponent.COLUMN_TYPE_TEXT_BOLD, | |||
| field: 'referenceId', | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'isAdmin', | |||
| text: 'users.is_admin', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isAdmin', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'isPilot', | |||
| text: 'users.is_pilot', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPilot', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'active', | |||
| text: 'users.active', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'active', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| ]; | |||
| } | |||
| @@ -55,6 +55,7 @@ export const locationForm = new FormGroup({ | |||
| isZone: new FormControl(null, []), | |||
| isPlace: new FormControl(null, []), | |||
| isPort: new FormControl(null, []), | |||
| isStartEnd: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -68,6 +69,7 @@ export const locationJsonldForm = new FormGroup({ | |||
| isZone: new FormControl(null, []), | |||
| isPlace: new FormControl(null, []), | |||
| isPort: new FormControl(null, []), | |||
| isStartEnd: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -98,7 +100,6 @@ export const tripForm = new FormGroup({ | |||
| vesselIri: new FormControl(null, [Validators.required]), | |||
| pilotageReference: new FormControl(null, []), | |||
| customerReference: new FormControl(null, []), | |||
| captainName: new FormControl(null, []), | |||
| startLocation: new FormControl(null, []), | |||
| startLocationIri: new FormControl(null, [Validators.required]), | |||
| endLocation: new FormControl(null, []), | |||
| @@ -106,6 +107,7 @@ export const tripForm = new FormGroup({ | |||
| startDate: new FormControl(null, [Validators.required]), | |||
| endDate: new FormControl(null, [Validators.required]), | |||
| note: new FormControl(null, []), | |||
| completed: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -115,7 +117,6 @@ export const tripJsonldForm = new FormGroup({ | |||
| vesselIri: new FormControl(null, [Validators.required]), | |||
| pilotageReference: new FormControl(null, []), | |||
| customerReference: new FormControl(null, []), | |||
| captainName: new FormControl(null, []), | |||
| startLocation: new FormControl(null, []), | |||
| startLocationIri: new FormControl(null, [Validators.required]), | |||
| endLocation: new FormControl(null, []), | |||
| @@ -123,6 +124,7 @@ export const tripJsonldForm = new FormGroup({ | |||
| startDate: new FormControl(null, [Validators.required]), | |||
| endDate: new FormControl(null, [Validators.required]), | |||
| note: new FormControl(null, []), | |||
| completed: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -133,6 +135,8 @@ export const tripLocationForm = new FormGroup({ | |||
| 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]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -144,6 +148,8 @@ export const tripLocationJsonldForm = new FormGroup({ | |||
| 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]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -161,6 +167,7 @@ export const userForm = new FormGroup({ | |||
| password: new FormControl(null, []), | |||
| isAdmin: new FormControl(null, [Validators.required]), | |||
| active: new FormControl(null, [Validators.required]), | |||
| isPilot: new FormControl(null, [Validators.required]), | |||
| roles: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -178,6 +185,7 @@ export const userJsonldForm = new FormGroup({ | |||
| password: new FormControl(null, []), | |||
| isAdmin: new FormControl(null, [Validators.required]), | |||
| active: new FormControl(null, [Validators.required]), | |||
| isPilot: new FormControl(null, [Validators.required]), | |||
| roles: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -190,6 +198,7 @@ export const userTripForm = new FormGroup({ | |||
| userIri: new FormControl(null, [Validators.required]), | |||
| captainName: new FormControl(null, []), | |||
| completed: new FormControl(null, [Validators.required]), | |||
| approved: new FormControl(null, [Validators.required]), | |||
| signature: new FormControl(null, []), | |||
| signatureIri: new FormControl(null, []), | |||
| signatureUrl: new FormControl(null, []), | |||
| @@ -205,6 +214,7 @@ export const userTripJsonldForm = new FormGroup({ | |||
| userIri: new FormControl(null, [Validators.required]), | |||
| captainName: new FormControl(null, []), | |||
| completed: new FormControl(null, [Validators.required]), | |||
| approved: new FormControl(null, [Validators.required]), | |||
| signature: new FormControl(null, []), | |||
| signatureIri: new FormControl(null, []), | |||
| signatureUrl: new FormControl(null, []), | |||
| @@ -246,6 +256,12 @@ export const vesselForm = new FormGroup({ | |||
| code: new FormControl(null, [Validators.required]), | |||
| company: new FormControl(null, []), | |||
| companyIri: new FormControl(null, [Validators.required]), | |||
| length: new FormControl(null, []), | |||
| breadth: new FormControl(null, []), | |||
| draft: new FormControl(null, []), | |||
| grossTonnage: new FormControl(null, []), | |||
| imoNo: new FormControl(null, []), | |||
| callSign: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -255,6 +271,12 @@ export const vesselJsonldForm = new FormGroup({ | |||
| code: new FormControl(null, [Validators.required]), | |||
| company: new FormControl(null, []), | |||
| companyIri: new FormControl(null, [Validators.required]), | |||
| length: new FormControl(null, []), | |||
| breadth: new FormControl(null, []), | |||
| draft: new FormControl(null, []), | |||
| grossTonnage: new FormControl(null, []), | |||
| imoNo: new FormControl(null, []), | |||
| callSign: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -48,6 +48,13 @@ | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| <div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3 switch-widget"> | |||
| <p class="form-label">{{ 'location.is_start_end' | translate }}:</p> | |||
| <label class="switch"> | |||
| <input type="checkbox" formControlName="isStartEnd"> | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| @@ -8,6 +8,7 @@ import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-funct | |||
| import {ROUTE_LOCATIONS} from "@app/app-routing.module"; | |||
| import {Sort} from "@angular/material/sort"; | |||
| import {LocationFormComponent} from "@app/_views/location/location-form/location-form.component"; | |||
| import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; | |||
| @Component({ | |||
| selector: 'app-location-list', | |||
| @@ -26,65 +27,7 @@ export class LocationListComponent implements OnInit, AfterViewInit { | |||
| protected appHelperService: AppHelperService, | |||
| ) { | |||
| this.listColDefinitions = [ | |||
| { | |||
| name: 'name', | |||
| text: 'common.name', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'code', | |||
| text: 'common.code', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'code', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'zone', | |||
| text: 'model.zone', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'zone', | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_zone', | |||
| text: 'location.is_zone', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isZone', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_place', | |||
| text: 'location.is_place', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPlace', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'is_port', | |||
| text: 'location.is_port', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPort', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| ]; | |||
| this.listColDefinitions = SearchSelectComponent.getDefaultColDefLocations(); | |||
| } | |||
| ngOnInit() { | |||
| @@ -70,6 +70,31 @@ | |||
| {{ '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"> | |||
| @@ -7,7 +7,7 @@ import { | |||
| TripService, | |||
| LocationService, | |||
| LocationJsonld, | |||
| UserTripService, UserService, UserTripJsonld, UserJsonld, UserTripEventJsonld, UserTripEventService | |||
| UserTripService, UserService, UserTripJsonld, UserJsonld, UserTripEventJsonld, UserTripEventService, TripLocation | |||
| } from "@app/core/api/v1"; | |||
| import { AppHelperService } from "@app/_helpers/app-helper.service"; | |||
| import { ActivatedRoute } from "@angular/router"; | |||
| @@ -17,6 +17,7 @@ import {firstValueFrom, Observable} from 'rxjs'; | |||
| import { ListColDefinition } from '@app/_components/list/list-col-definition'; | |||
| import { SearchSelectComponent } from '@app/_components/search-select/search-select.component'; | |||
| import {map} from "rxjs/operators"; | |||
| import {TranslateService} from "@ngx-translate/core"; | |||
| @Component({ | |||
| selector: 'app-trip-detail', | |||
| @@ -35,6 +36,8 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations(); | |||
| protected userForms: FormGroup[] = []; | |||
| protected userColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefUsers(); | |||
| protected originalTripLocations: TripLocation[] = []; | |||
| @ViewChildren(SearchSelectComponent) searchSelects!: QueryList<SearchSelectComponent>; | |||
| @@ -46,6 +49,7 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| private userTripEventService: UserTripEventService, | |||
| private userService: UserService, | |||
| protected appHelperService: AppHelperService, | |||
| protected translateService: TranslateService, | |||
| private route: ActivatedRoute, | |||
| private fb: FormBuilder | |||
| ) {} | |||
| @@ -85,16 +89,17 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| this.tripLocations = data.member; | |||
| // Create a form for each trip location | |||
| this.locationForms = []; | |||
| this.tripLocations.forEach(() => { | |||
| this.locationForms.push(this.createLocationForm()); | |||
| this.originalTripLocations = JSON.parse(JSON.stringify(this.tripLocations)); | |||
| this.tripLocations.forEach((tripLocation) => { | |||
| this.locationForms.push(this.createLocationForm(tripLocation.location?.id ?? null)); | |||
| }); | |||
| } | |||
| ); | |||
| } | |||
| createLocationForm(): FormGroup { | |||
| createLocationForm(locationIri: string | null): FormGroup { | |||
| return this.fb.group({ | |||
| location: [null] | |||
| location: [locationIri] | |||
| }); | |||
| } | |||
| @@ -126,7 +131,14 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| }); | |||
| // Filtere Benutzer, die bereits ausgewählt sind (gespeichert oder nicht) | |||
| return this.userService.usersGetCollection(page, pageSize, undefined, term).pipe( | |||
| 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!)) | |||
| @@ -191,6 +203,16 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| 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 = { | |||
| @@ -201,7 +223,7 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| }; | |||
| this.tripLocations.push(newTripLocation); | |||
| this.locationForms.push(this.createLocationForm()); | |||
| this.locationForms.push(this.createLocationForm(null)); | |||
| // Force update in the next event loop to properly initialize the search-select | |||
| setTimeout(() => { | |||
| @@ -219,7 +241,8 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| const newUserTrip: UserTripJsonld = { | |||
| tripIri: this.trip.id!, | |||
| userIri: null, | |||
| completed: false | |||
| completed: false, | |||
| approved: false, | |||
| }; | |||
| // Füge es als UserTripJsonld hinzu | |||
| @@ -280,79 +303,110 @@ export class TripDetailComponent implements OnInit, AfterViewInit { | |||
| }) | |||
| } | |||
| removeTripLocation(index: number) { | |||
| const tripLocationId = this.tripLocations[index].id; | |||
| if (tripLocationId) { | |||
| // If it exists on the server, delete it | |||
| this.tripLocationService.tripLocationsIdDelete(this.appHelperService.extractId(tripLocationId)).subscribe( | |||
| () => { | |||
| this.tripLocations.splice(index, 1); | |||
| this.locationForms.splice(index, 1); | |||
| } | |||
| ); | |||
| } else { | |||
| // If it's only local, just remove it from the array | |||
| 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) { | |||
| // Nur aus dem Array entfernen, tatsächliches Löschen erfolgt beim Speichern | |||
| this.userTrips.splice(index, 1); | |||
| this.userForms.splice(index, 1); | |||
| 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() { | |||
| 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) | |||
| }); | |||
| }); | |||
| // First update the location objects in our tripLocations array | |||
| // B) UPSERT: create or update remaining entries | |||
| this.tripLocations.forEach((tripLocation, index) => { | |||
| const locationFormValue = this.locationForms[index].get('location')?.value; | |||
| 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 | |||
| ); | |||
| } | |||
| // Ensure we have a location | |||
| if (locationFormValue) { | |||
| // If just an ID was set, create a proper location object | |||
| if (typeof locationFormValue === 'string') { | |||
| tripLocation.locationIri = locationFormValue; | |||
| } | |||
| } else { | |||
| // If no location is set, show an error | |||
| // skip if neither new nor changed | |||
| if (!(isNew || locationChanged || modelChanged)) { | |||
| return; | |||
| } | |||
| }); | |||
| // Filter out trip locations that have no location set | |||
| const validTripLocations = this.tripLocations.filter(tl => tl.locationIri); | |||
| if (validTripLocations.length === 0) { | |||
| return; | |||
| } | |||
| // Save all trip locations | |||
| const savePromises = validTripLocations.map(tripLocation => { | |||
| if (tripLocation.id) { | |||
| // Update existing | |||
| return firstValueFrom(this.tripLocationService.tripLocationsIdPatch( | |||
| this.appHelperService.extractId(tripLocation.id), | |||
| this.appHelperService.convertJsonldToJson(tripLocation) | |||
| )); | |||
| } else { | |||
| // Create new | |||
| return firstValueFrom(this.tripLocationService.tripLocationsPost(tripLocation)); | |||
| // 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) | |||
| ); | |||
| Promise.all(savePromises) | |||
| .then(() => { | |||
| // Reload trip locations to get updated data | |||
| this.loadTripLocations(); | |||
| }) | |||
| .catch(error => { | |||
| console.error('Error saving trip locations:', error); | |||
| // 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[] = []; | |||
| @@ -53,10 +53,6 @@ | |||
| <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"> | |||
| <label for="captainName" class="form-label">{{ 'trip.captain_name' | translate }}:</label> | |||
| <input type="text" class="form-control" id="captainName" formControlName="captainName"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <app-datetime-picker | |||
| [label]="'trip.start_date' | translate" | |||
| @@ -60,6 +60,11 @@ export class TripFormComponent extends AbstractDataFormComponent<TripJsonld> { | |||
| } | |||
| getLocations: ListGetDataFunctionType = (index: number, pageSize: number, term?: string) => { | |||
| return this.locationService.locationsGetCollection(index, pageSize, term); | |||
| return this.locationService.locationsGetCollection( | |||
| index, | |||
| pageSize, | |||
| term, | |||
| '{"isStartEnd":true}' | |||
| ); | |||
| } | |||
| } | |||
| @@ -49,14 +49,6 @@ export class TripListComponent { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'captainName', | |||
| text: 'trip.captain_name', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'captainName', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'startLocation', | |||
| text: 'trip.start_location', | |||
| @@ -2,15 +2,11 @@ import { Component, OnInit, AfterViewInit, QueryList, ViewChildren } from '@angu | |||
| import { FormBuilder, FormGroup } from '@angular/forms'; | |||
| import { | |||
| LocationService, | |||
| TripJsonld, | |||
| LocationJsonld, | |||
| UserService, | |||
| UserTripJsonld, | |||
| UserTripService, | |||
| UserTripEventJsonld, | |||
| UserTripEventService, | |||
| EventService, | |||
| EventJsonld | |||
| } from "@app/core/api/v1"; | |||
| import { AppHelperService } from "@app/_helpers/app-helper.service"; | |||
| import { ActivatedRoute } from "@angular/router"; | |||
| @@ -19,8 +15,6 @@ import { ModalStatus } from "@app/_helpers/modal.states"; | |||
| import { firstValueFrom, Observable } from 'rxjs'; | |||
| import { ListColDefinition } from '@app/_components/list/list-col-definition'; | |||
| import { SearchSelectComponent } from '@app/_components/search-select/search-select.component'; | |||
| import { ListComponent } from '@app/_components/list/list.component'; | |||
| import { FilterBarComponent } from "@app/_components/filter-bar/filter-bar.component"; | |||
| @Component({ | |||
| selector: 'app-user-trip-detail', | |||
| @@ -17,6 +17,13 @@ | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| <div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3 switch-widget"> | |||
| <p class="form-label">{{ 'user_trip.approved' | translate }}:</p> | |||
| <label class="switch"> | |||
| <input type="checkbox" formControlName="approved" [disabled]="data.approved"> | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| </div> | |||
| @@ -29,9 +29,9 @@ export class UserTripFormComponent extends AbstractImageFormComponent<UserTripJs | |||
| userTripForm, | |||
| undefined, | |||
| (id: string | number, data: UserTripJsonld) => | |||
| userTripService.userTripsIdPatch( | |||
| this.userTripService.userTripsIdPatch( | |||
| id.toString(), | |||
| appHelperService.convertJsonldToJson(data) | |||
| this.appHelperService.convertJsonldToJson(data) | |||
| ), | |||
| (id: string | number) => userTripService.userTripsIdDelete(id.toString()), | |||
| 'signatureIri', | |||
| @@ -82,6 +82,14 @@ export class UserTripListComponent { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'approved', | |||
| text: 'user_trip.approved', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'approved', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'completedDate', | |||
| text: 'user_trip.completed_at', | |||
| @@ -42,6 +42,13 @@ | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| <div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3 switch-widget"> | |||
| <p class="form-label">{{ 'users.is_pilot' | translate }}:</p> | |||
| <label class="switch"> | |||
| <input type="checkbox" formControlName="isPilot"> | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| </div> | |||
| <app-image-upload | |||
| @@ -65,6 +65,22 @@ export class UserListComponent implements OnInit, AfterViewInit { | |||
| type: ListComponent.COLUMN_TYPE_TEXT_BOLD, | |||
| field: 'referenceId', | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'isAdmin', | |||
| text: 'users.is_admin', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isAdmin', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'isPilot', | |||
| text: 'users.is_pilot', | |||
| type: ListComponent.COLUMN_TYPE_BOOLEAN, | |||
| field: 'isPilot', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_BOOLEAN, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'active', | |||
| text: 'users.active', | |||
| @@ -91,6 +107,7 @@ export class UserListComponent implements OnInit, AfterViewInit { | |||
| undefined, | |||
| undefined, | |||
| term, | |||
| this.listComponent.getFilterJsonString(), | |||
| this.listComponent.getSortingJsonString() | |||
| ); | |||
| } | |||
| @@ -35,6 +35,50 @@ | |||
| <input id="companyIri" type="hidden" formControlName="companyIri"/> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="length" class="form-label">{{ 'vessel.length' | translate }}:</label> | |||
| <input type="number" | |||
| class="form-control" | |||
| id="length" | |||
| formControlName="length"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="breadth" class="form-label">{{ 'vessel.breadth' | translate }}:</label> | |||
| <input type="number" | |||
| class="form-control" | |||
| id="breadth" | |||
| formControlName="breadth"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="draft" class="form-label">{{ 'vessel.draft' | translate }}:</label> | |||
| <input type="number" | |||
| class="form-control" | |||
| id="draft" | |||
| formControlName="draft"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="grossTonnage" class="form-label">{{ 'vessel.grossTonnage' | translate }}:</label> | |||
| <input type="number" | |||
| class="form-control" | |||
| id="grossTonnage" | |||
| formControlName="grossTonnage"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="imoNo" class="form-label">{{ 'vessel.imoNo' | translate }}:</label> | |||
| <input type="text" | |||
| class="form-control" | |||
| id="imoNo" | |||
| formControlName="imoNo"/> | |||
| </div> | |||
| <div class="col-12 col-lg-6 mb-3"> | |||
| <label for="callSign" class="form-label">{{ 'vessel.callSign' | translate }}:</label> | |||
| <input type="text" | |||
| class="form-control" | |||
| id="callSign" | |||
| formControlName="callSign"/> | |||
| </div> | |||
| </div> | |||
| <div class="row"> | |||
| <div class="col-12 mb-3"> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid"> | |||
| @@ -1,12 +1,10 @@ | |||
| import {Component, ViewChild} from '@angular/core'; | |||
| import {ListComponent} from "@app/_components/list/list.component"; | |||
| import {ListColDefinition} from "@app/_components/list/list-col-definition"; | |||
| import {VesselJsonld, VesselService, ZoneJsonld} from "@app/core/api/v1"; | |||
| import {VesselService, ZoneJsonld} from "@app/core/api/v1"; | |||
| import {Router} from "@angular/router"; | |||
| 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 {Sort} from "@angular/material/sort"; | |||
| import {ROUTE_VESSELS, ROUTE_ZONES} from "@app/app-routing.module"; | |||
| import {VesselFormComponent} from "@app/_views/vessel/vessel-form/vessel-form.component"; | |||
| import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; | |||
| @@ -109,14 +109,15 @@ export class UserService { | |||
| * @param firstName | |||
| * @param lastName | |||
| * @param userNameSearch | |||
| * @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 usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonOrder?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<ApiUsersGetCollection200Response>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonOrder?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<ApiUsersGetCollection200Response>>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonOrder?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<ApiUsersGetCollection200Response>>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonOrder?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> { | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonFilter?: string, customJsonOrder?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<ApiUsersGetCollection200Response>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonFilter?: string, customJsonOrder?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<ApiUsersGetCollection200Response>>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonFilter?: string, customJsonOrder?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<ApiUsersGetCollection200Response>>; | |||
| public usersGetCollection(page?: number, itemsPerPage?: number, firstName?: string, lastName?: string, userNameSearch?: string, customJsonFilter?: string, customJsonOrder?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> { | |||
| let localVarQueryParameters = new HttpParams({encoder: this.encoder}); | |||
| if (page !== undefined && page !== null) { | |||
| @@ -139,6 +140,10 @@ export class UserService { | |||
| localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, | |||
| <any>userNameSearch, 'userNameSearch'); | |||
| } | |||
| if (customJsonFilter !== undefined && customJsonFilter !== null) { | |||
| localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, | |||
| <any>customJsonFilter, 'custom_json_filter'); | |||
| } | |||
| if (customJsonOrder !== undefined && customJsonOrder !== null) { | |||
| localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, | |||
| <any>customJsonOrder, 'custom_json_order'); | |||
| @@ -24,6 +24,7 @@ export interface Location { | |||
| isZone?: boolean; | |||
| isPlace?: boolean; | |||
| isPort?: boolean; | |||
| isStartEnd?: boolean; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -28,6 +28,7 @@ export interface LocationJsonld { | |||
| isZone?: boolean; | |||
| isPlace?: boolean; | |||
| isPort?: boolean; | |||
| isStartEnd?: boolean; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -20,7 +20,6 @@ export interface Trip { | |||
| vesselIri: string | null; | |||
| readonly pilotageReference?: string | null; | |||
| customerReference?: string | null; | |||
| captainName?: string | null; | |||
| readonly startLocation?: string; | |||
| startLocationIri: string | null; | |||
| readonly endLocation?: string; | |||
| @@ -28,6 +27,7 @@ export interface Trip { | |||
| startDate: string; | |||
| endDate: string; | |||
| note?: string | null; | |||
| completed?: boolean; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -25,7 +25,6 @@ export interface TripJsonld { | |||
| vesselIri: string | null; | |||
| readonly pilotageReference?: string | null; | |||
| customerReference?: string | null; | |||
| captainName?: string | null; | |||
| readonly startLocation?: LocationJsonld; | |||
| startLocationIri: string | null; | |||
| readonly endLocation?: LocationJsonld; | |||
| @@ -33,6 +32,7 @@ export interface TripJsonld { | |||
| startDate: string; | |||
| endDate: string; | |||
| note?: string | null; | |||
| completed?: boolean; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -23,6 +23,8 @@ export interface TripLocation { | |||
| location?: Location; | |||
| locationIri: string | null; | |||
| isArrival?: boolean; | |||
| isTransit?: boolean; | |||
| isDeparture?: boolean; | |||
| date: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -26,6 +26,8 @@ export interface TripLocationJsonld { | |||
| location?: LocationJsonld; | |||
| locationIri: string | null; | |||
| isArrival?: boolean; | |||
| isTransit?: boolean; | |||
| isDeparture?: boolean; | |||
| date: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -30,6 +30,7 @@ export interface User { | |||
| password?: string | null; | |||
| isAdmin: boolean; | |||
| active: boolean; | |||
| isPilot: boolean; | |||
| roles?: Array<string>; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -34,6 +34,7 @@ export interface UserJsonld { | |||
| password?: string | null; | |||
| isAdmin: boolean; | |||
| active: boolean; | |||
| isPilot: boolean; | |||
| roles?: Array<string>; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -22,6 +22,7 @@ export interface UserTrip { | |||
| userIri: string | null; | |||
| captainName?: string | null; | |||
| completed: boolean; | |||
| approved: boolean; | |||
| readonly signature?: string; | |||
| signatureIri?: string | null; | |||
| readonly signatureUrl?: string | null; | |||
| @@ -28,6 +28,7 @@ export interface UserTripJsonld { | |||
| userIri: string | null; | |||
| captainName?: string | null; | |||
| completed: boolean; | |||
| approved: boolean; | |||
| readonly signature?: MediaObjectJsonld; | |||
| signatureIri?: string | null; | |||
| readonly signatureUrl?: string | null; | |||
| @@ -20,6 +20,12 @@ export interface Vessel { | |||
| code: string; | |||
| readonly company?: string; | |||
| companyIri: string | null; | |||
| length?: number | null; | |||
| breadth?: number | null; | |||
| draft?: number | null; | |||
| grossTonnage?: number | null; | |||
| imoNo?: string | null; | |||
| callSign?: string | null; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -24,6 +24,12 @@ export interface VesselJsonld { | |||
| code: string; | |||
| readonly company?: ShippingCompanyJsonld; | |||
| companyIri: string | null; | |||
| length?: number | null; | |||
| breadth?: number | null; | |||
| draft?: number | null; | |||
| grossTonnage?: number | null; | |||
| imoNo?: string | null; | |||
| callSign?: string | null; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -30,24 +30,27 @@ | |||
| "end_location": "End location", | |||
| "start_date": "Start date", | |||
| "end_date": "End date", | |||
| "is_arrival": "is arrival", | |||
| "is_arrival": "Arrival", | |||
| "is_transit": "Transit", | |||
| "is_departure": "Departure", | |||
| "itinerary": "Itinerary", | |||
| "itinerary_locations": "Itinerary locations", | |||
| "add_itinerary_location": "Add itinerary location", | |||
| "remove_itinerary_location": "Remove itinerary location", | |||
| "save_itinerary": "Save itinerary", | |||
| "assigned_users": "Assigned Users (User Trips)", | |||
| "assigned_users": "Assigned Pilots", | |||
| "save_user_assignments": "Save user assignments", | |||
| "events": "Events" | |||
| }, | |||
| "user_trip": | |||
| { | |||
| "view": "User Trips", | |||
| "view": "Pilotage", | |||
| "events": "Events", | |||
| "completed": "Completed", | |||
| "completed_at": "Completed at", | |||
| "signature": "Signature Image", | |||
| "event_date": "Event date" | |||
| "event_date": "Event date", | |||
| "approved": "Approved" | |||
| }, | |||
| "base_data": | |||
| { | |||
| @@ -64,18 +67,28 @@ | |||
| "shipping_company": "Shipping Company", | |||
| "trip": "Trip", | |||
| "user": "User", | |||
| "user_trip": "User Trip", | |||
| "user_trip": "Pilotage", | |||
| "event": "Event" | |||
| }, | |||
| "location": | |||
| { | |||
| "is_zone": "Is zone", | |||
| "is_place": "Is place", | |||
| "is_port": "Is port" | |||
| "is_zone": "Zone", | |||
| "is_place": "Place", | |||
| "is_port": "Port", | |||
| "is_start_end": "Start/End" | |||
| }, | |||
| "zone": | |||
| { | |||
| }, | |||
| "vessel": | |||
| { | |||
| "length": "Length", | |||
| "breadth": "Breadth", | |||
| "draft": "Draft", | |||
| "grossTonnage": "Gross Tonnage", | |||
| "imoNo": "Imo", | |||
| "callSign": "Call sign" | |||
| }, | |||
| "profile": | |||
| { | |||
| @@ -85,7 +98,7 @@ | |||
| { | |||
| "logout": "Logout", | |||
| "company_name": "Imaq Pilotage", | |||
| "users": "Users", | |||
| "users": "Users / Pilots", | |||
| "new": "New", | |||
| "edit_before": "", | |||
| "edit_after": "Edit", | |||
| @@ -113,26 +126,28 @@ | |||
| "edit": "Edit", | |||
| "save": "Save", | |||
| "delete": "Delete", | |||
| "delete_confirm": "Do you really want to delete this dataset? There might be related data, which makes deletion impossible unless the related data will be removed first!" | |||
| "delete_confirm": "Do you really want to delete this dataset?", | |||
| "delete_confirm_related": "Do you really want to delete this dataset? There might be related data, which makes deletion impossible unless the related data will be removed first!" | |||
| }, | |||
| "users": | |||
| { | |||
| "view": "Users", | |||
| "view": "Users / Pilots", | |||
| "user": "User", | |||
| "email": "Email", | |||
| "full_name": "Name", | |||
| "firstname": "Firstname", | |||
| "lastname": "Lastname", | |||
| "userTrips": "User trips", | |||
| "userTrips": "Pilotage", | |||
| "pilotIdNo": "#Pilot id", | |||
| "password": "Password", | |||
| "active": "Active", | |||
| "image": "Image", | |||
| "is_admin": "Is admin" | |||
| "is_admin": "Admin", | |||
| "is_pilot": "Pilot" | |||
| }, | |||
| "form": | |||
| { | |||
| "mandatory": " is mandatory", | |||
| "mandatory": " Mandatory", | |||
| "email_validation": "Please provide a valid email address", | |||
| "search_placeholder": "Search", | |||
| "no_data": "No datasets found." | |||
| @@ -0,0 +1,65 @@ | |||
| <?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 Version20250428094124 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 location ADD is_start_end TINYINT(1) NOT NULL | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip ADD completed TINYINT(1) NOT NULL, DROP captain_name | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip_location ADD is_transit TINYINT(1) NOT NULL, ADD is_departure TINYINT(1) NOT NULL | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE user ADD is_pilot TINYINT(1) NOT NULL | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE user_trip ADD approved TINYINT(1) NOT NULL | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE vessel ADD length DOUBLE PRECISION DEFAULT NULL, ADD breadth DOUBLE PRECISION DEFAULT NULL, ADD draft DOUBLE PRECISION DEFAULT NULL, ADD gross_tonnage DOUBLE PRECISION DEFAULT NULL, ADD imo_no VARCHAR(255) DEFAULT NULL, ADD call_sign VARCHAR(255) DEFAULT NULL | |||
| SQL); | |||
| } | |||
| public function down(Schema $schema): void | |||
| { | |||
| // this down() migration is auto-generated, please modify it to your needs | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE location DROP is_start_end | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE `user` DROP is_pilot | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE vessel DROP length, DROP breadth, DROP draft, DROP gross_tonnage, DROP imo_no, DROP call_sign | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip_location DROP is_transit, DROP is_departure | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE trip ADD captain_name VARCHAR(255) DEFAULT NULL, DROP completed | |||
| SQL); | |||
| $this->addSql(<<<'SQL' | |||
| ALTER TABLE user_trip DROP approved | |||
| SQL); | |||
| } | |||
| } | |||
| @@ -93,6 +93,8 @@ class LocationApi | |||
| public bool $isPort; | |||
| public bool $isStartEnd; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| } | |||
| @@ -83,8 +83,6 @@ class TripApi | |||
| public ?string $customerReference = null; | |||
| public ?string $captainName = null; | |||
| /** | |||
| * @var LocationApi | |||
| */ | |||
| @@ -133,6 +131,8 @@ class TripApi | |||
| public ?string $note; | |||
| public bool $completed = false; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| } | |||
| @@ -98,7 +98,11 @@ class TripLocationApi | |||
| #[ApiProperty(writable: true)] | |||
| public ?LocationApi $locationIri = null; | |||
| public bool $isArrival; | |||
| public bool $isArrival = false; | |||
| public bool $isTransit = false; | |||
| public bool $isDeparture = false; | |||
| #[Assert\NotBlank] | |||
| public \DateTimeImmutable $date; | |||
| @@ -18,6 +18,7 @@ use ApiPlatform\Metadata\GetCollection; | |||
| use ApiPlatform\Metadata\Patch; | |||
| use ApiPlatform\Metadata\Post; | |||
| use App\Entity\User; | |||
| use App\Filter\CustomJsonFilter; | |||
| use App\Filter\CustomJsonOrderFilter; | |||
| use App\Filter\UserNameSearchFilter; | |||
| use App\State\EntityClassDtoStateProcessor; | |||
| @@ -53,6 +54,7 @@ use Symfony\Component\Validator\Constraints as Assert; | |||
| )] | |||
| #[ApiFilter(SearchFilter::class, properties: ['firstName' => 'ipartial', 'lastName' => 'ipartial'])] | |||
| #[ApiFilter(UserNameSearchFilter::class)] | |||
| #[ApiFilter(CustomJsonFilter::class)] | |||
| #[ApiFilter(CustomJsonOrderFilter::class)] | |||
| class UserApi | |||
| { | |||
| @@ -113,6 +115,9 @@ class UserApi | |||
| #[Assert\NotNull] | |||
| public bool $active = false; | |||
| #[Assert\NotNull] | |||
| public bool $isPilot = false; | |||
| #[ApiProperty(writable: false)] | |||
| public array $roles = []; | |||
| @@ -105,6 +105,9 @@ class UserTripApi | |||
| #[Assert\NotNull] | |||
| public bool $completed = false; | |||
| #[Assert\NotNull] | |||
| public bool $approved = false; | |||
| /** | |||
| * @var MediaObjectApi | |||
| */ | |||
| @@ -84,6 +84,18 @@ class VesselApi | |||
| #[ApiProperty(writable: true)] | |||
| public ?ShippingCompanyApi $companyIri = null; | |||
| public ?float $length = null; | |||
| public ?float $breadth = null; | |||
| public ?float $draft = null; | |||
| public ?float $grossTonnage = null; | |||
| public ?string $imoNo = null; | |||
| public ?string $callSign = null; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| } | |||
| @@ -37,6 +37,9 @@ class Location | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isPort = false; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isStartEnd = false; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| @@ -119,6 +122,16 @@ class Location | |||
| $this->isPort = $isPort; | |||
| } | |||
| public function isStartEnd(): bool | |||
| { | |||
| return $this->isStartEnd; | |||
| } | |||
| public function setIsStartEnd(bool $isStartEnd): void | |||
| { | |||
| $this->isStartEnd = $isStartEnd; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -25,9 +25,6 @@ class Trip | |||
| #[ORM\Column(length: 255, nullable: true)] | |||
| private ?string $customerReference = null; | |||
| #[ORM\Column(length: 255, nullable: true)] | |||
| private ?string $captainName = null; | |||
| #[ORM\ManyToOne(targetEntity: Location::class)] | |||
| #[ORM\JoinColumn(name: 'start_location_id', nullable: false)] | |||
| private Location $startLocation; | |||
| @@ -45,6 +42,9 @@ class Trip | |||
| #[ORM\Column(type: "text", nullable: true)] | |||
| protected ?string $note; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $completed = false; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| @@ -97,17 +97,6 @@ class Trip | |||
| $this->customerReference = $customerReference; | |||
| } | |||
| public function getCaptainName(): ?string | |||
| { | |||
| return $this->captainName; | |||
| } | |||
| public function setCaptainName(?string $captainName): self | |||
| { | |||
| $this->captainName = $captainName; | |||
| return $this; | |||
| } | |||
| public function getStartLocation(): Location | |||
| { | |||
| return $this->startLocation; | |||
| @@ -162,6 +151,16 @@ class Trip | |||
| $this->note = $note; | |||
| } | |||
| public function isCompleted(): bool | |||
| { | |||
| return $this->completed; | |||
| } | |||
| public function setCompleted(bool $completed): void | |||
| { | |||
| $this->completed = $completed; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -27,6 +27,12 @@ class TripLocation | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isArrival = true; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isTransit = true; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isDeparture = true; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $date; | |||
| @@ -89,6 +95,26 @@ class TripLocation | |||
| $this->isArrival = $isArrival; | |||
| } | |||
| public function isTransit(): bool | |||
| { | |||
| return $this->isTransit; | |||
| } | |||
| public function setIsTransit(bool $isTransit): void | |||
| { | |||
| $this->isTransit = $isTransit; | |||
| } | |||
| public function isDeparture(): bool | |||
| { | |||
| return $this->isDeparture; | |||
| } | |||
| public function setIsDeparture(bool $isDeparture): void | |||
| { | |||
| $this->isDeparture = $isDeparture; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -35,6 +35,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface | |||
| #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] | |||
| private ?MediaObject $image = null; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $isPilot = false; | |||
| #[ORM\Column] | |||
| private array $roles = []; | |||
| @@ -180,6 +183,16 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface | |||
| $this->active = $active; | |||
| } | |||
| public function isPilot(): bool | |||
| { | |||
| return $this->isPilot; | |||
| } | |||
| public function setIsPilot(bool $isPilot): void | |||
| { | |||
| $this->isPilot = $isPilot; | |||
| } | |||
| public function getCreatedAt(): ?\DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -37,6 +37,9 @@ class UserTrip | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $completed = false; | |||
| #[ORM\Column(nullable: false)] | |||
| private bool $approved = false; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?DateTimeImmutable $completedDate; | |||
| @@ -124,6 +127,16 @@ class UserTrip | |||
| $this->completed = $completed; | |||
| } | |||
| public function isApproved(): bool | |||
| { | |||
| return $this->approved; | |||
| } | |||
| public function setApproved(bool $approved): void | |||
| { | |||
| $this->approved = $approved; | |||
| } | |||
| public function getUserTripEvents(): Collection | |||
| { | |||
| return $this->userTripEvents; | |||
| @@ -28,6 +28,24 @@ class Vessel | |||
| #[ORM\Column(length: 255, unique: true)] | |||
| private string $code; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?float $length = null; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?float $breadth = null; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?float $draft = null; | |||
| #[ORM\Column(nullable: true)] | |||
| private ?float $grossTonnage = null; | |||
| #[ORM\Column(length: 255, nullable: true)] | |||
| private ?string $imoNo = null; | |||
| #[ORM\Column(length: 255, nullable: true)] | |||
| private ?string $callSign = null; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| @@ -80,6 +98,66 @@ class Vessel | |||
| $this->code = $code; | |||
| } | |||
| public function getLength(): ?float | |||
| { | |||
| return $this->length; | |||
| } | |||
| public function setLength(?float $length): void | |||
| { | |||
| $this->length = $length; | |||
| } | |||
| public function getBreadth(): ?float | |||
| { | |||
| return $this->breadth; | |||
| } | |||
| public function setBreadth(?float $breadth): void | |||
| { | |||
| $this->breadth = $breadth; | |||
| } | |||
| public function getDraft(): ?float | |||
| { | |||
| return $this->draft; | |||
| } | |||
| public function setDraft(?float $draft): void | |||
| { | |||
| $this->draft = $draft; | |||
| } | |||
| public function getGrossTonnage(): ?float | |||
| { | |||
| return $this->grossTonnage; | |||
| } | |||
| public function setGrossTonnage(?float $grossTonnage): void | |||
| { | |||
| $this->grossTonnage = $grossTonnage; | |||
| } | |||
| public function getImoNo(): ?string | |||
| { | |||
| return $this->imoNo; | |||
| } | |||
| public function setImoNo(?string $imoNo): void | |||
| { | |||
| $this->imoNo = $imoNo; | |||
| } | |||
| public function getCallSign(): ?string | |||
| { | |||
| return $this->callSign; | |||
| } | |||
| public function setCallSign(?string $callSign): void | |||
| { | |||
| $this->callSign = $callSign; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -6,6 +6,7 @@ use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter; | |||
| use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; | |||
| use ApiPlatform\Metadata\ApiFilter; | |||
| use ApiPlatform\Metadata\Operation; | |||
| use Doctrine\ORM\Mapping\ClassMetadata; | |||
| use Doctrine\ORM\QueryBuilder; | |||
| use Doctrine\DBAL\Types\Types; | |||
| use Doctrine\ORM\Mapping\ClassMetadataInfo; | |||
| @@ -66,12 +67,12 @@ class CustomJsonFilter extends AbstractFilter | |||
| ->setParameter($parameterName, '%' . $value . '%'); | |||
| } | |||
| private function isValidProperty(ClassMetadataInfo $metadata, string $property): bool | |||
| private function isValidProperty(ClassMetadata $metadata, string $property): bool | |||
| { | |||
| return $metadata->hasField($property) || $metadata->hasAssociation($property); | |||
| } | |||
| private function isAssociation(ClassMetadataInfo $metadata, string $property): bool | |||
| private function isAssociation(ClassMetadata $metadata, string $property): bool | |||
| { | |||
| return $metadata->hasAssociation($property); | |||
| } | |||
| @@ -56,6 +56,7 @@ class LocationApiToEntityMapper implements MapperInterface | |||
| $entity->setIsZone($dto->isZone); | |||
| $entity->setIsPlace($dto->isPlace); | |||
| $entity->setIsPort($dto->isPort); | |||
| $entity->setIsStartEnd($dto->isStartEnd); | |||
| if ($dto->zoneIri) { | |||
| $zone = $this->zoneRepository->find($dto->zoneIri->id); | |||
| @@ -42,6 +42,7 @@ class LocationEntityToApiMapper implements MapperInterface | |||
| $dto->isZone = $entity->isZone(); | |||
| $dto->isPlace = $entity->isPlace(); | |||
| $dto->isPort = $entity->isPort(); | |||
| $dto->isStartEnd = $entity->isStartEnd(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->zoneIri = $dto->zone = $this->microMapper->map($entity->getZone(), ZoneApi::class, [ | |||
| @@ -74,7 +74,6 @@ class TripApiToEntityMapper implements MapperInterface | |||
| assert($entity instanceof Trip); | |||
| $entity->setCustomerReference($dto->customerReference); | |||
| $entity->setCaptainName($dto->captainName); | |||
| $entity->setStartDate($dto->startDate); | |||
| $entity->setEndDate($dto->endDate); | |||
| $entity->setNote($dto->note); | |||
| @@ -39,10 +39,10 @@ class TripEntityToApiMapper implements MapperInterface | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->pilotageReference = "P-" . $entity->getId() . "-" . $entity->getStartDate()->format('Y'); | |||
| $dto->customerReference = $entity->getCustomerReference(); | |||
| $dto->captainName = $entity->getCaptainName(); | |||
| $dto->startDate = $entity->getStartDate(); | |||
| $dto->endDate = $entity->getEndDate(); | |||
| $dto->note = $entity->getNote(); | |||
| $dto->completed = $entity->isCompleted(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| // Map related entities | |||
| @@ -68,6 +68,8 @@ class TripLocationApiToEntityMapper implements MapperInterface | |||
| } | |||
| $entity->setIsArrival($dto->isArrival); | |||
| $entity->setIsTransit($dto->isTransit); | |||
| $entity->setIsDeparture($dto->isDeparture); | |||
| $entity->setDate($dto->date); | |||
| return $entity; | |||
| @@ -39,13 +39,15 @@ class TripLocationEntityToApiMapper implements MapperInterface | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->date = $entity->getDate(); | |||
| $dto->isArrival = $entity->isArrival(); | |||
| $dto->isTransit = $entity->isTransit(); | |||
| $dto->isDeparture = $entity->isDeparture(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->trip = $this->microMapper->map($entity->getTrip(), TripApi::class, [ | |||
| $dto->tripIri = $dto->trip = $this->microMapper->map($entity->getTrip(), TripApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 5, | |||
| ]); | |||
| $dto->location = $this->microMapper->map($entity->getLocation(), LocationApi::class, [ | |||
| $dto->locationIri = $dto->location = $this->microMapper->map($entity->getLocation(), LocationApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 5, | |||
| ]); | |||
| @@ -46,6 +46,7 @@ class UserApiToEntityMapper implements MapperInterface | |||
| $entity->setFirstName($dto->firstName); | |||
| $entity->setLastName($dto->lastName); | |||
| $entity->setActive($dto->active); | |||
| $entity->setIsPilot($dto->isPilot); | |||
| $roles = $entity->getRoles(); | |||
| if ($dto->isAdmin && !in_array(User::ROLE_ADMIN, $roles, true)) { | |||
| @@ -46,6 +46,7 @@ class UserEntityToApiMapper implements MapperInterface | |||
| $dto->roles = $entity->getRoles(); | |||
| $dto->isAdmin = in_array(User::ROLE_ADMIN, $entity->getRoles(), true); | |||
| $dto->active = $entity->isActive(); | |||
| $dto->isPilot = $entity->isPilot(); | |||
| $dto->imageIri = $dto->image = null; | |||
| if ($entity->getImage() !== null) { | |||
| @@ -70,6 +70,7 @@ class UserTripApiToEntityMapper implements MapperInterface | |||
| $entity->setCompletedDate(new \DateTimeImmutable()); | |||
| } | |||
| $entity->setCompleted($dto->completed); | |||
| $entity->setApproved($dto->approved); | |||
| if ($dto->signatureIri) { | |||
| $signature = $this->mediaObjectRepository->find($dto->signatureIri->id); | |||
| @@ -43,6 +43,7 @@ class UserTripEntityToApiMapper implements MapperInterface | |||
| $dto->captainName = $entity->getCaptainName(); | |||
| $dto->signatureUrl = $this->fileUrlService->getFileUrl($entity->getSignature()); | |||
| $dto->completed = $entity->isCompleted(); | |||
| $dto->approved = $entity->isApproved(); | |||
| $dto->completedDate = $entity->getCompletedDate(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| @@ -8,7 +8,6 @@ use App\Repository\VesselRepository; | |||
| use App\Repository\ShippingCompanyRepository; | |||
| use Symfonycasts\MicroMapper\AsMapper; | |||
| use Symfonycasts\MicroMapper\MapperInterface; | |||
| use Symfonycasts\MicroMapper\MicroMapperInterface; | |||
| #[AsMapper(from: VesselApi::class, to: Vessel::class)] | |||
| class VesselApiToEntityMapper implements MapperInterface | |||
| @@ -54,6 +53,12 @@ class VesselApiToEntityMapper implements MapperInterface | |||
| $entity->setName($dto->name); | |||
| $entity->setCode($dto->code); | |||
| $entity->setLength($dto->length); | |||
| $entity->setBreadth($dto->breadth); | |||
| $entity->setDraft($dto->draft); | |||
| $entity->setGrossTonnage($dto->grossTonnage); | |||
| $entity->setImoNo($dto->imoNo); | |||
| $entity->setCallSign($dto->callSign); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| return $entity; | |||
| @@ -38,9 +38,15 @@ class VesselEntityToApiMapper implements MapperInterface | |||
| $dto->dbId = $entity->getId(); | |||
| $dto->name = $entity->getName(); | |||
| $dto->code = $entity->getCode(); | |||
| $dto->length = $entity->getLength(); | |||
| $dto->breadth = $entity->getBreadth(); | |||
| $dto->draft = $entity->getDraft(); | |||
| $dto->grossTonnage = $entity->getGrossTonnage(); | |||
| $dto->imoNo = $entity->getImoNo(); | |||
| $dto->callSign = $entity->getCallSign(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->company = $this->microMapper->map($entity->getCompany(), ShippingCompanyApi::class, [ | |||
| $dto->companyIri = $dto->company = $this->microMapper->map($entity->getCompany(), ShippingCompanyApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 5, | |||
| ]); | |||