Ver a proveniência

user zones

master
Daniel há 9 meses
ascendente
cometimento
701c6f4279
35 ficheiros alterados com 1920 adições e 8 eliminações
  1. +1
    -1
      angular/openapi.json
  2. +477
    -0
      angular/openapi.yaml
  3. +6
    -1
      angular/src/app/_components/_abstract/abstract-data-form-component.ts
  4. +7
    -1
      angular/src/app/_components/list/list.component.ts
  5. +16
    -0
      angular/src/app/_forms/apiForms.ts
  6. +58
    -0
      angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.html
  7. +0
    -0
      angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.scss
  8. +23
    -0
      angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.spec.ts
  9. +194
    -0
      angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.ts
  10. +12
    -0
      angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.html
  11. +0
    -0
      angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.scss
  12. +23
    -0
      angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.spec.ts
  13. +102
    -0
      angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.ts
  14. +1
    -0
      angular/src/app/_views/user-zone/user-zone.component.html
  15. +0
    -0
      angular/src/app/_views/user-zone/user-zone.component.scss
  16. +23
    -0
      angular/src/app/_views/user-zone/user-zone.component.spec.ts
  17. +10
    -0
      angular/src/app/_views/user-zone/user-zone.component.ts
  18. +5
    -0
      angular/src/app/_views/user/user-detail/user-detail.component.html
  19. +13
    -3
      angular/src/app/_views/zone/zone-detail/zone-detail.component.html
  20. +6
    -0
      angular/src/app/app.module.ts
  21. +4
    -0
      angular/src/app/core/api/v1/.openapi-generator/FILES
  22. +3
    -1
      angular/src/app/core/api/v1/api/api.ts
  23. +541
    -0
      angular/src/app/core/api/v1/api/userZone.service.ts
  24. +23
    -0
      angular/src/app/core/api/v1/model/apiUserZonesGetCollection200Response.ts
  25. +3
    -0
      angular/src/app/core/api/v1/model/models.ts
  26. +24
    -0
      angular/src/app/core/api/v1/model/userZone.ts
  27. +29
    -0
      angular/src/app/core/api/v1/model/userZoneJsonld.ts
  28. +4
    -1
      angular/src/assets/i18n/en.json
  29. +35
    -0
      httpdocs/migrations/Version20250605145642.php
  30. +31
    -0
      httpdocs/migrations/Version20250606081404.php
  31. +78
    -0
      httpdocs/src/ApiResource/UserZoneApi.php
  32. +47
    -0
      httpdocs/src/Entity/UserZone.php
  33. +58
    -0
      httpdocs/src/Mapper/UserZoneApiToEntityMapper.php
  34. +48
    -0
      httpdocs/src/Mapper/UserZoneEntityToApiMapper.php
  35. +15
    -0
      httpdocs/src/Repository/UserZoneRepository.php

+ 1
- 1
angular/openapi.json
A apresentação das diferenças no ficheiro foi suprimida por ser demasiado grande
Ver ficheiro


+ 477
- 0
angular/openapi.yaml Ver ficheiro

@@ -2984,6 +2984,398 @@ paths:
$ref: '#/components/schemas/UserTripEvent'
required: true
deprecated: false
/api/user_zones:
get:
operationId: api_user_zones_get_collection
tags:
- UserZone
responses:
'200':
description: 'UserZone collection'
content:
application/ld+json:
schema:
type: object
properties:
member: { type: array, items: { $ref: '#/components/schemas/UserZone.jsonld' } }
totalItems: { type: integer, minimum: 0 }
view: { type: object, properties: { '@id': { type: string, format: iri-reference }, '@type': { type: string }, first: { type: string, format: iri-reference }, last: { type: string, format: iri-reference }, previous: { type: string, format: iri-reference }, next: { type: string, format: iri-reference } }, example: { '@id': string, type: string, first: string, last: string, previous: string, next: string } }
search: { type: object, properties: { '@type': { type: string }, template: { type: string }, variableRepresentation: { type: string }, mapping: { type: array, items: { type: object, properties: { '@type': { type: string }, variable: { type: string }, property: { type: [string, 'null'] }, required: { type: boolean } } } } } }
required:
- member
'403':
description: Forbidden
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
summary: 'Retrieves the collection of UserZone resources.'
description: 'Retrieves the collection of UserZone resources.'
parameters:
-
name: page
in: query
description: 'The collection page number'
required: false
deprecated: false
allowEmptyValue: true
schema:
type: integer
default: 1
style: form
explode: false
allowReserved: false
-
name: itemsPerPage
in: query
description: 'The number of items per page'
required: false
deprecated: false
allowEmptyValue: true
schema:
type: integer
default: 50
minimum: 0
maximum: 200
style: form
explode: false
allowReserved: false
-
name: user
in: query
description: ''
required: false
deprecated: false
allowEmptyValue: false
schema:
type: string
style: form
explode: false
allowReserved: false
-
name: 'user[]'
in: query
description: ''
required: false
deprecated: false
allowEmptyValue: false
schema:
type: array
items:
type: string
style: form
explode: true
allowReserved: false
-
name: zone
in: query
description: ''
required: false
deprecated: false
allowEmptyValue: false
schema:
type: string
style: form
explode: false
allowReserved: false
-
name: 'zone[]'
in: query
description: ''
required: false
deprecated: false
allowEmptyValue: false
schema:
type: array
items:
type: string
style: form
explode: true
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
description: ''
required: false
deprecated: false
allowEmptyValue: true
schema:
type: string
style: form
explode: false
allowReserved: false
deprecated: false
post:
operationId: api_user_zones_post
tags:
- UserZone
responses:
'201':
description: 'UserZone resource created'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/UserZone.jsonld'
links: { }
'400':
description: 'Invalid input'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
'422':
description: 'An error occurred'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/ConstraintViolation.jsonld-jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/ConstraintViolation-json'
application/json:
schema:
$ref: '#/components/schemas/ConstraintViolation-json'
links: { }
'403':
description: Forbidden
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
summary: 'Creates a UserZone resource.'
description: 'Creates a UserZone resource.'
parameters: []
requestBody:
description: 'The new UserZone resource'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/UserZone.jsonld'
required: true
deprecated: false
'/api/user_zones/{id}':
get:
operationId: api_user_zones_id_get
tags:
- UserZone
responses:
'200':
description: 'UserZone resource'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/UserZone.jsonld'
'403':
description: Forbidden
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
'404':
description: 'Not found'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
summary: 'Retrieves a UserZone resource.'
description: 'Retrieves a UserZone resource.'
parameters:
-
name: id
in: path
description: 'UserZone identifier'
required: true
deprecated: false
allowEmptyValue: false
schema:
type: string
style: simple
explode: false
allowReserved: false
deprecated: false
delete:
operationId: api_user_zones_id_delete
tags:
- UserZone
responses:
'204':
description: 'UserZone resource deleted'
'403':
description: Forbidden
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
'404':
description: 'Not found'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
summary: 'Removes the UserZone resource.'
description: 'Removes the UserZone resource.'
parameters:
-
name: id
in: path
description: 'UserZone identifier'
required: true
deprecated: false
allowEmptyValue: false
schema:
type: string
style: simple
explode: false
allowReserved: false
deprecated: false
patch:
operationId: api_user_zones_id_patch
tags:
- UserZone
responses:
'200':
description: 'UserZone resource updated'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/UserZone.jsonld'
links: { }
'400':
description: 'Invalid input'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
'422':
description: 'An error occurred'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/ConstraintViolation.jsonld-jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/ConstraintViolation-json'
application/json:
schema:
$ref: '#/components/schemas/ConstraintViolation-json'
links: { }
'403':
description: Forbidden
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
'404':
description: 'Not found'
content:
application/ld+json:
schema:
$ref: '#/components/schemas/Error.jsonld'
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
application/json:
schema:
$ref: '#/components/schemas/Error'
links: { }
summary: 'Updates the UserZone resource.'
description: 'Updates the UserZone resource.'
parameters:
-
name: id
in: path
description: 'UserZone identifier'
required: true
deprecated: false
allowEmptyValue: false
schema:
type: string
style: simple
explode: false
allowReserved: false
requestBody:
description: 'The updated UserZone resource'
content:
application/merge-patch+json:
schema:
$ref: '#/components/schemas/UserZone'
required: true
deprecated: false
/api/vessels:
get:
operationId: api_vessels_get_collection
@@ -4912,6 +5304,89 @@ components:
- eventIri
- locationIri
- date
UserZone:
type: object
description: ''
deprecated: false
properties:
dbId:
readOnly: true
type:
- integer
- 'null'
user:
readOnly: true
type: string
format: iri-reference
example: 'https://example.com/'
userIri:
type:
- string
- 'null'
format: iri-reference
example: 'https://example.com/'
zone:
readOnly: true
type: string
format: iri-reference
example: 'https://example.com/'
zoneIri:
type:
- string
- 'null'
format: iri-reference
example: 'https://example.com/'
UserZone.jsonld:
type: object
description: ''
deprecated: false
properties:
'@context':
readOnly: true
oneOf:
-
type: string
-
type: object
properties:
'@vocab':
type: string
hydra:
type: string
enum: ['http://www.w3.org/ns/hydra/core#']
required:
- '@vocab'
- hydra
additionalProperties: true
'@id':
readOnly: true
type: string
'@type':
readOnly: true
type: string
dbId:
readOnly: true
type:
- integer
- 'null'
user:
readOnly: true
$ref: '#/components/schemas/User.jsonld'
userIri:
type:
- string
- 'null'
format: iri-reference
example: 'https://example.com/'
zone:
readOnly: true
$ref: '#/components/schemas/Zone.jsonld'
zoneIri:
type:
- string
- 'null'
format: iri-reference
example: 'https://example.com/'
Vessel:
type: object
description: ''
@@ -5167,6 +5642,8 @@ tags:
name: UserTrip
-
name: UserTripEvent
-
name: UserZone
-
name: Vessel
-


+ 6
- 1
angular/src/app/_components/_abstract/abstract-data-form-component.ts Ver ficheiro

@@ -27,6 +27,7 @@ export abstract class AbstractDataFormComponent<T extends { [key: string]: any }
@Input() redirectAfterDelete?: string;
@Output() submit = new EventEmitter<FormSubmitEvent<T>>();
@Output() deleted: EventEmitter<void> = new EventEmitter<void>();
@Input() isInModal: boolean = false;
protected id?: string;
protected form!: FormGroup;

@@ -99,7 +100,11 @@ export abstract class AbstractDataFormComponent<T extends { [key: string]: any }
this.deleteFn!(this.id!).subscribe({
next: () => {
this.deleted.emit();
if (this.redirectAfterDelete && this.router) {
this.submit.emit({
status: ModalStatus.Submitted,
data: null
});
if (!this.isInModal && this.redirectAfterDelete && this.router) {
this.router.navigate([this.redirectAfterDelete]);
}
},


+ 7
- 1
angular/src/app/_components/list/list.component.ts Ver ficheiro

@@ -434,6 +434,11 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy {
delete this.dataFormComponentData.data;
}

this.dataFormComponentData = {
...this.dataFormComponentData,
isInModal: true,
};

this.appHelperService.openModal(
this.dataFormComponent,
this.dataFormComponentData,
@@ -449,7 +454,8 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy {
// Create a new object instead of modifying the existing one
this.dataFormComponentData = {
...this.dataFormComponentData,
data: element
data: element,
isInModal: true,
};
this.appHelperService.openModal(
this.dataFormComponent,


+ 16
- 0
angular/src/app/_forms/apiForms.ts Ver ficheiro

@@ -244,6 +244,22 @@ export const userTripEventJsonldForm = new FormGroup({
createdAt: new FormControl(null, [])
});

export const userZoneForm = new FormGroup({
dbId: new FormControl(null, []),
user: new FormControl(null, []),
userIri: new FormControl(null, []),
zone: new FormControl(null, []),
zoneIri: new FormControl(null, [])
});

export const userZoneJsonldForm = new FormGroup({
dbId: new FormControl(null, []),
user: new FormControl(null, []),
userIri: new FormControl(null, []),
zone: new FormControl(null, []),
zoneIri: new FormControl(null, [])
});

export const vesselForm = new FormGroup({
dbId: new FormControl(null, []),
name: new FormControl(null, [Validators.required]),


+ 58
- 0
angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.html Ver ficheiro

@@ -0,0 +1,58 @@
<div class="spt-container">
<div class="spt-form">
@if (data !== undefined) {
<form [formGroup]="userZoneForm" (ngSubmit)="onSubmit()">
@if (user) {
<div>{{ 'base_data.pilot' | translate }}: {{ user.fullName }}</div>
} @else {
<div class="row">
<label for="userIri" class="form-label">{{ 'base_data.pilot' | translate }}*:</label>
<app-search-select #userSearchSelect
[formId]="'userIri'"
[formLabelLangKey]="'model.user'"
[documentForm]="userZoneForm"
[getDataFunction]="getUsers"
[displayedDataField]="'fullName'"
[listColDefinitions]="userColDefinitions"
[dataSet]="user"
>
</app-search-select>
<input id="userIri" type="hidden" formControlName="userIri" required/>
</div>
}
@if (zone) {
<div>{{ 'model.zone' | translate }}: {{ zone.name }}</div>
} @else {
<div class="col-12 mb-3">
<label for="zoneIri" class="form-label">{{ 'model.zone' | translate }}*:</label>
<app-search-select #zoneSearchSelect
[formId]="'zoneIri'"
[formLabelLangKey]="'model.zone'"
[documentForm]="userZoneForm"
[getDataFunction]="getZones"
[displayedDataField]="'name'"
[listColDefinitions]="zoneColDefinitions"
[dataSet]="zone"
>
</app-search-select>
<input id="zoneIri" type="hidden" formControlName="zoneIri" required/>
</div>
}
</form>
}
</div>

<div class="row">
<div class="col-12 mb-3">
<button type="submit" class="btn btn-primary" (click)="onSubmit()">
{{ 'basic.save' | translate }}
</button>

@if (isEditMode()) {
<button type="button" class="ms-3 btn btn-primary" (click)="onDelete()">
{{ 'basic.delete' | translate }} {{ 'model.user_trip' | translate }}
</button>
}
</div>
</div>
</div>

+ 0
- 0
angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.scss Ver ficheiro


+ 23
- 0
angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.spec.ts Ver ficheiro

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { UserZoneFormComponent } from './user-zone-form.component';

describe('UserZoneFormComponent', () => {
let component: UserZoneFormComponent;
let fixture: ComponentFixture<UserZoneFormComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserZoneFormComponent]
})
.compileComponents();
fixture = TestBed.createComponent(UserZoneFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 194
- 0
angular/src/app/_views/user-zone/user-zone-form/user-zone-form.component.ts Ver ficheiro

@@ -0,0 +1,194 @@
import { Component } from '@angular/core';
import {
UserJsonld,
UserService,
UserZoneJsonld, UserZoneService,
ZoneJsonld, ZoneService
} from "@app/core/api/v1";
import {userZoneForm} from "@app/_forms/apiForms";
import {ListColDefinition} from "@app/_components/list/list-col-definition";
import {AppHelperService} from "@app/_helpers/app-helper.service";
import {TranslateService} from "@ngx-translate/core";
import {Router} from "@angular/router";
import {SearchSelectComponent} from "@app/_components/search-select/search-select.component";
import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type";
import {of, switchMap} from "rxjs";
import {map} from "rxjs/operators";
import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component";

@Component({
selector: 'app-user-zone-form',
templateUrl: './user-zone-form.component.html',
styleUrl: './user-zone-form.component.scss'
})
export class UserZoneFormComponent extends AbstractDataFormComponent<UserZoneJsonld> {
protected readonly userZoneForm = userZoneForm;
protected userColDefinitions: ListColDefinition[];
protected zoneColDefinitions: ListColDefinition[];
protected user?: UserJsonld;
protected zone?: ZoneJsonld;

constructor(
protected userZoneService: UserZoneService,
protected userService: UserService,
protected zoneService: ZoneService,
appHelperService: AppHelperService,
translateService: TranslateService,
router: Router
) {
super(
userZoneForm,
appHelperService,
(data: UserZoneJsonld) => this.userZoneService.userZonesPost(this.appHelperService.convertJsonldToJson(data)),
(id: string | number, data: UserZoneJsonld) =>
this.userZoneService.userZonesIdPatch(
id.toString(),
this.appHelperService.convertJsonldToJson(data)
),
(id: string | number) => userZoneService.userZonesIdDelete(id.toString()),
translateService,
router
);
this.userColDefinitions = SearchSelectComponent.getDefaultColDefUsers();
this.zoneColDefinitions = SearchSelectComponent.getDefaultColDefZones();
}

override ngOnInit() {
super.ngOnInit();

// Setze User und Zone aus den übergebenen Daten
if (this.data?.user && !this.user) {
this.user = this.data?.user;
}
if (this.data?.zone && !this.zone) {
this.zone = this.data?.zone;
}

// Validierung: Mindestens User oder Zone muss vorgegeben sein
if (!this.user && !this.zone) {
throw new Error('UserZoneFormComponent: Either user or zone has to be given');
}

// Beide gleichzeitig vorgegeben ist auch nicht erlaubt (würde keinen Sinn machen)
if (this.user && this.zone) {
throw new Error('UserZoneFormComponent: Either user or zone has to be given');
}

// Setze die FormControl-Werte wenn vorgegeben
if (this.zone && !this.data!.zoneIri!) {
this.data!.zoneIri = this.zone.id!;
this.form.get('zoneIri')?.setValue(this.zone.id!);
}
if (this.user && !this.data!.userIri!) {
this.data!.userIri = this.user.id!;
this.form.get('userIri')?.setValue(this.user.id!);
}
}

getUsers: ListGetDataFunctionType = (
index: number,
pageSize: number,
term?: string,
) => {
// Hole alle Benutzer mit isPilot=true
return this.userService.usersGetCollection(
index,
pageSize,
undefined,
undefined,
term,
'{"isPilot":true}'
).pipe(
switchMap(usersResponse => {
// Wenn keine Zone vorhanden ist, gib alle Benutzer zurück
if (!this.zone?.id) {
return of(usersResponse);
}

// Hole alle UserZones für diese Zone
return this.userZoneService.userZonesGetCollection(
1,
100,
undefined, // user
undefined, // user2
this.zone.id, // zone
undefined,
).pipe(
map(userZonesResponse => {
// Extrahiere die User-IDs aus den UserZones
const usedUserIds = new Set(
userZonesResponse.member?.map(
(userZone: UserZoneJsonld) => userZone.userIri
) || []
);

// Filtere die Benutzer, die noch nicht zugeordnet sind
if (usersResponse.member) {
usersResponse.member = usersResponse.member.filter(
(user: UserJsonld) => !usedUserIds.has(user.id!)
);
// Aktualisiere die totalItems Anzahl
if (usersResponse.totalItems) {
usersResponse.totalItems = usersResponse.member.length;
}
}

return usersResponse;
})
);
})
);
}

getZones: ListGetDataFunctionType = (
index: number,
pageSize: number,
term?: string,
) => {
return this.zoneService.zonesGetCollection(
index,
pageSize,
undefined,
undefined,
term
).pipe(
switchMap(zonesResponse => {
// Wenn kein User vorhanden ist, gib alle Zonen zurück
if (!this.user?.id) {
return of(zonesResponse);
}

// Hole alle UserZones für diesen User
return this.userZoneService.userZonesGetCollection(
1,
100,
this.user.id, // user
undefined, // user2
undefined // zone
).pipe(
map(userZonesResponse => {
// Extrahiere die Zone-IDs aus den UserZones
const usedZoneIds = new Set(
userZonesResponse.member?.map(
(userZone: UserZoneJsonld) => userZone.zoneIri
) || []
);

// Filtere die Zonen, die noch nicht zugeordnet sind
if (zonesResponse.member) {
zonesResponse.member = zonesResponse.member.filter(
(zone: ZoneJsonld) => !usedZoneIds.has(zone.id!)
);
// Aktualisiere die totalItems Anzahl
if (zonesResponse.totalItems) {
zonesResponse.totalItems = zonesResponse.member.length;
}
}

return zonesResponse;
})
);
})
);
}
}

+ 12
- 0
angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.html Ver ficheiro

@@ -0,0 +1,12 @@
<div class="spt-container">
<app-list #listComponent
[listId]="'userZoneList'"
[getDataFunction]="getData"
[listColDefinitions]="listColDefinitions"
[dataFormComponent]="userTripLocationFormComponent"
[dataFormComponentData]="dataFormComponentData"
[deleteItemFunction]="deleteItemFunction"
[showCreateButton]="showCreateButton"
[showDetailButton]="false"
></app-list>
</div>

+ 0
- 0
angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.scss Ver ficheiro


+ 23
- 0
angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.spec.ts Ver ficheiro

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { UserZoneListComponent } from './user-zone-list.component';

describe('UserZoneListComponent', () => {
let component: UserZoneListComponent;
let fixture: ComponentFixture<UserZoneListComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserZoneListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(UserZoneListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 102
- 0
angular/src/app/_views/user-zone/user-zone-list/user-zone-list.component.ts Ver ficheiro

@@ -0,0 +1,102 @@
import {Component, Input, ViewChild} from '@angular/core';
import {UserJsonld, UserZoneService, ZoneJsonld} from "@app/core/api/v1";
import {ListComponent} from "@app/_components/list/list.component";
import {ListColDefinition} from "@app/_components/list/list-col-definition";
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 {Observable} from "rxjs";
import {UserZoneFormComponent} from "@app/_views/user-zone/user-zone-form/user-zone-form.component";

@Component({
selector: 'app-user-zone-list',
templateUrl: './user-zone-list.component.html',
styleUrl: './user-zone-list.component.scss'
})
export class UserZoneListComponent {
@Input() public user?: UserJsonld;
@Input() public zone?: ZoneJsonld;
@Input() public showCreateButton: boolean;
@ViewChild("listComponent", {static: false}) listComponent!: ListComponent;

protected readonly userTripLocationFormComponent = UserZoneFormComponent;
protected listColDefinitions!: ListColDefinition[];
protected dataFormComponentData: any;

constructor(
private userZoneService: UserZoneService,
protected appHelperService: AppHelperService,
) {
this.showCreateButton = true;
this.listColDefinitions = [
{
name: 'userFirstname',
text: 'users.firstname',
type: ListComponent.COLUMN_TYPE_TEXT_BOLD,
field: 'firstName',
subResource: 'user',
sortable: true,
sortingSubResource: 'user',
sortingFieldName: 'firstName',
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'userLastname',
text: 'users.lastname',
type: ListComponent.COLUMN_TYPE_TEXT_BOLD,
field: 'lastName',
subResource: 'user',
sortable: true,
sortingSubResource: 'user',
sortingFieldName: 'lastName',
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'zoneName',
text: 'model.zone',
type: ListComponent.COLUMN_TYPE_TEXT,
field: 'name',
subResource: 'zone',
sortable: true,
sortingSubResource: 'zone',
sortingFieldName: 'name',
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
];
}

ngOnInit() {
this.dataFormComponentData = {};
if (this.zone) {
this.dataFormComponentData['zone'] = this.zone;
}
if (this.user) {
this.dataFormComponentData['user'] = this.user;
}
}

ngAfterViewInit(): void {
this.listComponent.getData();
}

getData: ListGetDataFunctionType = (
index: number,
pageSize: number,
term?: string,
) => {
return this.userZoneService.userZonesGetCollection(
index,
pageSize,
this.user ? this.user.id : undefined,
undefined,
this.zone ? this.zone.id : undefined,
undefined,
this.listComponent.getFilterJsonString(),
this.listComponent.getSortingJsonString()
);
}

get deleteItemFunction(): (id: string) => Observable<any> {
return (id: string) => this.userZoneService.userZonesIdDelete(id);
}
}

+ 1
- 0
angular/src/app/_views/user-zone/user-zone.component.html Ver ficheiro

@@ -0,0 +1 @@
<p>user-zone works!</p>

+ 0
- 0
angular/src/app/_views/user-zone/user-zone.component.scss Ver ficheiro


+ 23
- 0
angular/src/app/_views/user-zone/user-zone.component.spec.ts Ver ficheiro

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { UserZoneComponent } from './user-zone.component';

describe('UserZoneComponent', () => {
let component: UserZoneComponent;
let fixture: ComponentFixture<UserZoneComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserZoneComponent]
})
.compileComponents();
fixture = TestBed.createComponent(UserZoneComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 10
- 0
angular/src/app/_views/user-zone/user-zone.component.ts Ver ficheiro

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-user-zone',
templateUrl: './user-zone.component.html',
styleUrl: './user-zone.component.scss'
})
export class UserZoneComponent {

}

+ 5
- 0
angular/src/app/_views/user/user-detail/user-detail.component.html Ver ficheiro

@@ -15,5 +15,10 @@
[user]="user"
></app-user-trip-list>
</mat-tab>
<mat-tab label="{{ 'model.user_zones' | translate }}">
<app-user-zone-list
[user]="user"
></app-user-zone-list>
</mat-tab>
</mat-tab-group>
</div>

+ 13
- 3
angular/src/app/_views/zone/zone-detail/zone-detail.component.html Ver ficheiro

@@ -1,7 +1,17 @@
@if (zone) {
<div class="spt-container">
<app-zone-form
[data]="zone"
></app-zone-form>
<mat-tab-group>
<mat-tab label="{{ 'basic.details' | translate }}">
<app-zone-form
[data]="zone"
></app-zone-form>
</mat-tab>
<mat-tab label="{{ 'model.user_zones' | translate }}">
<app-user-zone-list
[zone]="zone"
></app-user-zone-list>
</mat-tab>
</mat-tab-group>

</div>
}

+ 6
- 0
angular/src/app/app.module.ts Ver ficheiro

@@ -74,6 +74,9 @@ import { ImageUploadComponent } from './_components/image-upload/image-upload.co
import { TripLocationListComponent } from './_views/trip/trip-location-list/trip-location-list.component';
import { TripLocationFormComponent } from './_views/trip/trip-location-form/trip-location-form.component';
import { UserTripEventFormComponent } from './_views/user-trip-event/user-trip-event-form/user-trip-event-form.component';
import { UserZoneListComponent } from '@app/_views/user-zone/user-zone-list/user-zone-list.component';
import { UserZoneComponent } from './_views/user-zone/user-zone.component';
import { UserZoneFormComponent } from './_views/user-zone/user-zone-form/user-zone-form.component';

registerLocaleData(localeDe, 'de-DE');

@@ -173,6 +176,9 @@ export function HttpLoaderFactory(http: HttpClient) {
TripLocationListComponent,
TripLocationFormComponent,
UserTripEventFormComponent,
UserZoneListComponent,
UserZoneComponent,
UserZoneFormComponent,
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true},


+ 4
- 0
angular/src/app/core/api/v1/.openapi-generator/FILES Ver ficheiro

@@ -12,6 +12,7 @@ api/tripLocation.service.ts
api/user.service.ts
api/userTrip.service.ts
api/userTripEvent.service.ts
api/userZone.service.ts
api/vessel.service.ts
api/zone.service.ts
configuration.ts
@@ -29,6 +30,7 @@ model/apiTripLocationsGetCollection200Response.ts
model/apiTripsGetCollection200Response.ts
model/apiUserTripEventsGetCollection200Response.ts
model/apiUserTripsGetCollection200Response.ts
model/apiUserZonesGetCollection200Response.ts
model/apiUsersGetCollection200Response.ts
model/apiVesselsGetCollection200Response.ts
model/apiZonesGetCollection200Response.ts
@@ -58,6 +60,8 @@ model/userTrip.ts
model/userTripEvent.ts
model/userTripEventJsonld.ts
model/userTripJsonld.ts
model/userZone.ts
model/userZoneJsonld.ts
model/vessel.ts
model/vesselJsonld.ts
model/zone.ts


+ 3
- 1
angular/src/app/core/api/v1/api/api.ts Ver ficheiro

@@ -18,8 +18,10 @@ export * from './userTrip.service';
import { UserTripService } from './userTrip.service';
export * from './userTripEvent.service';
import { UserTripEventService } from './userTripEvent.service';
export * from './userZone.service';
import { UserZoneService } from './userZone.service';
export * from './vessel.service';
import { VesselService } from './vessel.service';
export * from './zone.service';
import { ZoneService } from './zone.service';
export const APIS = [AuthService, EventService, LocationService, MediaObjectService, ShippingCompanyService, TripService, TripLocationService, UserService, UserTripService, UserTripEventService, VesselService, ZoneService];
export const APIS = [AuthService, EventService, LocationService, MediaObjectService, ShippingCompanyService, TripService, TripLocationService, UserService, UserTripService, UserTripEventService, UserZoneService, VesselService, ZoneService];

+ 541
- 0
angular/src/app/core/api/v1/api/userZone.service.ts Ver ficheiro

@@ -0,0 +1,541 @@
/**
* Imaq Platform
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpParameterCodec, HttpContext
} from '@angular/common/http';
import { CustomHttpParameterCodec } from '../encoder';
import { Observable } from 'rxjs';

// @ts-ignore
import { ApiUserZonesGetCollection200Response } from '../model/apiUserZonesGetCollection200Response';
// @ts-ignore
import { ConstraintViolationJson } from '../model/constraintViolationJson';
// @ts-ignore
import { ConstraintViolationJsonldJsonld } from '../model/constraintViolationJsonldJsonld';
// @ts-ignore
import { ErrorJsonld } from '../model/errorJsonld';
// @ts-ignore
import { UserZone } from '../model/userZone';
// @ts-ignore
import { UserZoneJsonld } from '../model/userZoneJsonld';

// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';



@Injectable({
providedIn: 'root'
})
export class UserZoneService {

protected basePath = 'http://localhost';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();
public encoder: HttpParameterCodec;

constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string|string[], @Optional() configuration: Configuration) {
if (configuration) {
this.configuration = configuration;
}
if (typeof this.configuration.basePath !== 'string') {
if (Array.isArray(basePath) && basePath.length > 0) {
basePath = basePath[0];
}

if (typeof basePath !== 'string') {
basePath = this.basePath;
}
this.configuration.basePath = basePath;
}
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
}


// @ts-ignore
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
if (typeof value === "object" && value instanceof Date === false) {
httpParams = this.addToHttpParamsRecursive(httpParams, value);
} else {
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
}
return httpParams;
}

private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
if (value == null) {
return httpParams;
}

if (typeof value === "object") {
if (Array.isArray(value)) {
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
} else if (value instanceof Date) {
if (key != null) {
httpParams = httpParams.append(key, (value as Date).toISOString().substring(0, 10));
} else {
throw Error("key may not be null if value is Date");
}
} else {
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
httpParams, value[k], key != null ? `${key}.${k}` : k));
}
} else if (key != null) {
httpParams = httpParams.append(key, value);
} else {
throw Error("key may not be null if value is not object or array");
}
return httpParams;
}

/**
* Retrieves the collection of UserZone resources.
* Retrieves the collection of UserZone resources.
* @param page The collection page number
* @param itemsPerPage The number of items per page
* @param user
* @param user2
* @param zone
* @param zone2
* @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 userZonesGetCollection(page?: number, itemsPerPage?: number, user?: string, user2?: Array<string>, zone?: string, zone2?: Array<string>, customJsonFilter?: string, customJsonOrder?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<ApiUserZonesGetCollection200Response>;
public userZonesGetCollection(page?: number, itemsPerPage?: number, user?: string, user2?: Array<string>, zone?: string, zone2?: Array<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<ApiUserZonesGetCollection200Response>>;
public userZonesGetCollection(page?: number, itemsPerPage?: number, user?: string, user2?: Array<string>, zone?: string, zone2?: Array<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<ApiUserZonesGetCollection200Response>>;
public userZonesGetCollection(page?: number, itemsPerPage?: number, user?: string, user2?: Array<string>, zone?: string, zone2?: Array<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) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>page, 'page');
}
if (itemsPerPage !== undefined && itemsPerPage !== null) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>itemsPerPage, 'itemsPerPage');
}
if (user !== undefined && user !== null) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>user, 'user');
}
if (user2) {
user2.forEach((element) => {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>element, 'user[]');
})
}
if (zone !== undefined && zone !== null) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>zone, 'zone');
}
if (zone2) {
zone2.forEach((element) => {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>element, 'zone[]');
})
}
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');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (JWT) required
localVarCredential = this.configuration.lookupCredential('JWT');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/ld+json',
'application/problem+json',
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/api/user_zones`;
return this.httpClient.request<ApiUserZonesGetCollection200Response>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
params: localVarQueryParameters,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

/**
* Removes the UserZone resource.
* Removes the UserZone resource.
* @param id UserZone identifier
* @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 userZonesIdDelete(id: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any>;
public userZonesIdDelete(id: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<any>>;
public userZonesIdDelete(id: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<any>>;
public userZonesIdDelete(id: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (id === null || id === undefined) {
throw new Error('Required parameter id was null or undefined when calling userZonesIdDelete.');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (JWT) required
localVarCredential = this.configuration.lookupCredential('JWT');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/ld+json',
'application/problem+json',
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/api/user_zones/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
return this.httpClient.request<any>('delete', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

/**
* Retrieves a UserZone resource.
* Retrieves a UserZone resource.
* @param id UserZone identifier
* @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 userZonesIdGet(id: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<UserZoneJsonld>;
public userZonesIdGet(id: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<UserZoneJsonld>>;
public userZonesIdGet(id: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<UserZoneJsonld>>;
public userZonesIdGet(id: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (id === null || id === undefined) {
throw new Error('Required parameter id was null or undefined when calling userZonesIdGet.');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (JWT) required
localVarCredential = this.configuration.lookupCredential('JWT');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/ld+json',
'application/problem+json',
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/api/user_zones/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
return this.httpClient.request<UserZoneJsonld>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

/**
* Updates the UserZone resource.
* Updates the UserZone resource.
* @param id UserZone identifier
* @param userZone The updated UserZone resource
* @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 userZonesIdPatch(id: string, userZone: UserZone, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<UserZoneJsonld>;
public userZonesIdPatch(id: string, userZone: UserZone, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<UserZoneJsonld>>;
public userZonesIdPatch(id: string, userZone: UserZone, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<UserZoneJsonld>>;
public userZonesIdPatch(id: string, userZone: UserZone, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (id === null || id === undefined) {
throw new Error('Required parameter id was null or undefined when calling userZonesIdPatch.');
}
if (userZone === null || userZone === undefined) {
throw new Error('Required parameter userZone was null or undefined when calling userZonesIdPatch.');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (JWT) required
localVarCredential = this.configuration.lookupCredential('JWT');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/ld+json',
'application/problem+json',
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


// to determine the Content-Type header
const consumes: string[] = [
'application/merge-patch+json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
}

let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/api/user_zones/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
return this.httpClient.request<UserZoneJsonld>('patch', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: userZone,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

/**
* Creates a UserZone resource.
* Creates a UserZone resource.
* @param userZoneJsonld The new UserZone resource
* @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 userZonesPost(userZoneJsonld: UserZoneJsonld, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<UserZoneJsonld>;
public userZonesPost(userZoneJsonld: UserZoneJsonld, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<UserZoneJsonld>>;
public userZonesPost(userZoneJsonld: UserZoneJsonld, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<UserZoneJsonld>>;
public userZonesPost(userZoneJsonld: UserZoneJsonld, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/ld+json' | 'application/problem+json' | 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (userZoneJsonld === null || userZoneJsonld === undefined) {
throw new Error('Required parameter userZoneJsonld was null or undefined when calling userZonesPost.');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (JWT) required
localVarCredential = this.configuration.lookupCredential('JWT');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/ld+json',
'application/problem+json',
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


// to determine the Content-Type header
const consumes: string[] = [
'application/ld+json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
}

let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/api/user_zones`;
return this.httpClient.request<UserZoneJsonld>('post', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: userZoneJsonld,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

}

+ 23
- 0
angular/src/app/core/api/v1/model/apiUserZonesGetCollection200Response.ts Ver ficheiro

@@ -0,0 +1,23 @@
/**
* Imaq Platform
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { UserZoneJsonld } from './userZoneJsonld';
import { ApiEventsGetCollection200ResponseSearch } from './apiEventsGetCollection200ResponseSearch';
import { ApiEventsGetCollection200ResponseView } from './apiEventsGetCollection200ResponseView';


export interface ApiUserZonesGetCollection200Response {
member: Array<UserZoneJsonld>;
totalItems?: number;
view?: ApiEventsGetCollection200ResponseView;
search?: ApiEventsGetCollection200ResponseSearch;
}


+ 3
- 0
angular/src/app/core/api/v1/model/models.ts Ver ficheiro

@@ -9,6 +9,7 @@ export * from './apiTripLocationsGetCollection200Response';
export * from './apiTripsGetCollection200Response';
export * from './apiUserTripEventsGetCollection200Response';
export * from './apiUserTripsGetCollection200Response';
export * from './apiUserZonesGetCollection200Response';
export * from './apiUsersGetCollection200Response';
export * from './apiVesselsGetCollection200Response';
export * from './apiZonesGetCollection200Response';
@@ -37,6 +38,8 @@ export * from './userTrip';
export * from './userTripEvent';
export * from './userTripEventJsonld';
export * from './userTripJsonld';
export * from './userZone';
export * from './userZoneJsonld';
export * from './vessel';
export * from './vesselJsonld';
export * from './zone';


+ 24
- 0
angular/src/app/core/api/v1/model/userZone.ts Ver ficheiro

@@ -0,0 +1,24 @@
/**
* Imaq Platform
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/


/**
*
*/
export interface UserZone {
readonly dbId?: number | null;
readonly user?: string;
userIri?: string | null;
readonly zone?: string;
zoneIri?: string | null;
}


+ 29
- 0
angular/src/app/core/api/v1/model/userZoneJsonld.ts Ver ficheiro

@@ -0,0 +1,29 @@
/**
* Imaq Platform
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { UserJsonld } from './userJsonld';
import { ConstraintViolationJsonldJsonldContext } from './constraintViolationJsonldJsonldContext';
import { ZoneJsonld } from './zoneJsonld';


/**
*
*/
export interface UserZoneJsonld {
readonly id?: string;
readonly xType?: string;
readonly dbId?: number | null;
readonly user?: UserJsonld;
userIri?: string | null;
readonly zone?: ZoneJsonld;
zoneIri?: string | null;
}


+ 4
- 1
angular/src/assets/i18n/en.json Ver ficheiro

@@ -4,7 +4,8 @@
"shipping_companies": "Shipping companies",
"vessels": "Vessels",
"view": "Base data",
"zones": "Zones"
"zones": "Zones",
"pilot": "Pilot"
},
"basic": {
"account": "Account",
@@ -76,6 +77,8 @@
"user": "User",
"user_trip": "Pilotage",
"user_trip_event": "Pilotage event",
"user_zone": "User zone",
"user_zones": "User zones",
"vessel": "Vessel",
"zone": "Zone"
},


+ 35
- 0
httpdocs/migrations/Version20250605145642.php Ver ficheiro

@@ -0,0 +1,35 @@
<?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 Version20250605145642 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('CREATE TABLE user_zone (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, zone_id INT NOT NULL, INDEX IDX_DA6A8CCEA76ED395 (user_id), INDEX IDX_DA6A8CCE9F2C3FAB (zone_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE user_zone ADD CONSTRAINT FK_DA6A8CCEA76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE user_zone ADD CONSTRAINT FK_DA6A8CCE9F2C3FAB FOREIGN KEY (zone_id) REFERENCES zone (id) ON DELETE CASCADE');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE user_zone DROP FOREIGN KEY FK_DA6A8CCEA76ED395');
$this->addSql('ALTER TABLE user_zone DROP FOREIGN KEY FK_DA6A8CCE9F2C3FAB');
$this->addSql('DROP TABLE user_zone');
}
}

+ 31
- 0
httpdocs/migrations/Version20250606081404.php Ver ficheiro

@@ -0,0 +1,31 @@
<?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 Version20250606081404 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('CREATE UNIQUE INDEX unique_user_zone ON user_zone (zone_id, user_id)');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP INDEX unique_user_zone ON user_zone');
}
}

+ 78
- 0
httpdocs/src/ApiResource/UserZoneApi.php Ver ficheiro

@@ -0,0 +1,78 @@
<?php

namespace App\ApiResource;

use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Entity\UserZone;
use App\Filter\CustomJsonFilter;
use App\Filter\CustomJsonOrderFilter;
use App\State\EntityClassDtoStateProcessor;
use App\State\EntityToDtoStateProvider;
use Symfony\Component\PropertyInfo\Type;

#[ApiResource(
shortName: 'UserZone',
operations: [
new Get(security: 'is_granted("ROLE_USER")'),
new GetCollection(security: 'is_granted("ROLE_USER")'),
new Post(security: 'is_granted("ROLE_ADMIN")'),
new Patch(security: 'is_granted("ROLE_ADMIN")'),
new Delete(security: 'is_granted("ROLE_ADMIN")')
],
security: 'is_granted("ROLE_USER")',
provider: EntityToDtoStateProvider::class,
processor: EntityClassDtoStateProcessor::class,
stateOptions: new Options(entityClass: UserZone::class),
)]

#[ApiFilter(SearchFilter::class, properties: [
'user' => 'exact',
'zone' => 'exact',
])]
#[ApiFilter(CustomJsonFilter::class)]
#[ApiFilter(CustomJsonOrderFilter::class)]
class UserZoneApi
{
#[ApiProperty(readable: false, writable: false, identifier: true)]
public ?int $id = null;

#[ApiProperty(writable: false)]
public ?int $dbId = null;

/**
* @var UserApi
*/
#[ApiProperty(
writable: false,
readableLink: true,
writableLink: false,
builtinTypes: [new Type('object', class: UserApi::class)]
)]
public ?UserApi $user = null;

#[ApiProperty(writable: true)]
public ?UserApi $userIri = null;

/**
* @var ZoneApi
*/
#[ApiProperty(
writable: false,
readableLink: true,
writableLink: false,
builtinTypes: [new Type('object', class: ZoneApi::class)]
)]
public ?ZoneApi $zone = null;

#[ApiProperty(writable: true)]
public ?ZoneApi $zoneIri = null;
}

+ 47
- 0
httpdocs/src/Entity/UserZone.php Ver ficheiro

@@ -0,0 +1,47 @@
<?php

namespace App\Entity;

use App\Repository\UserZoneRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: UserZoneRepository::class)]
#[ORM\UniqueConstraint(name: "unique_user_zone", columns: ["zone_id", "user_id"])]
class UserZone
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column(type: 'integer')]
private int $id;

#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
private ?User $user = null;

#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
private ?Zone $zone = null;

public function getId(): int
{
return $this->id;
}

public function getUser(): ?User
{
return $this->user;
}

public function setUser(?User $user): void
{
$this->user = $user;
}

public function getZone(): ?Zone
{
return $this->zone;
}

public function setZone(?Zone $zone): void
{
$this->zone = $zone;
}
}

+ 58
- 0
httpdocs/src/Mapper/UserZoneApiToEntityMapper.php Ver ficheiro

@@ -0,0 +1,58 @@
<?php

namespace App\Mapper;

use App\ApiResource\UserZoneApi;
use App\Entity\UserZone;
use App\Repository\UserRepository;
use App\Repository\UserZoneRepository;
use App\Repository\ZoneRepository;
use Symfonycasts\MicroMapper\AsMapper;
use Symfonycasts\MicroMapper\MapperInterface;

#[AsMapper(from: UserZoneApi::class, to: UserZone::class)]
class UserZoneApiToEntityMapper implements MapperInterface
{
public function __construct(
private readonly UserZoneRepository $userZoneRepository,
private readonly UserRepository $userRepository,
private readonly ZoneRepository $zoneRepository
) {}

public function load(object $from, string $toClass, array $context): object
{
$dto = $from;
assert($dto instanceof UserZoneApi);

$entity = $dto->id ? $this->userZoneRepository->find($dto->id) : new UserZone();
if ($dto->id && !$entity) {
throw new \Exception('UserZone not found');
}

return $entity;
}

public function populate(object $from, object $to, array $context): object
{
assert($from instanceof UserZoneApi);
assert($to instanceof UserZone);

if ($from->userIri) {
$user = $this->userRepository->find($from->userIri->id);
if (!$user) {
throw new \Exception('User not found');
}
$to->setUser($user);
}

if ($from->zoneIri) {
$zone = $this->zoneRepository->find($from->zoneIri->id);
if (!$zone) {
throw new \Exception('Zone not found');
}
$to->setZone($zone);
}

return $to;
}
}

+ 48
- 0
httpdocs/src/Mapper/UserZoneEntityToApiMapper.php Ver ficheiro

@@ -0,0 +1,48 @@
<?php

namespace App\Mapper;

use App\ApiResource\UserApi;
use App\ApiResource\UserZoneApi;
use App\ApiResource\ZoneApi;
use App\Entity\UserZone;
use Symfonycasts\MicroMapper\AsMapper;
use Symfonycasts\MicroMapper\MapperInterface;
use Symfonycasts\MicroMapper\MicroMapperInterface;

#[AsMapper(from: UserZone::class, to: UserZoneApi::class)]
class UserZoneEntityToApiMapper implements MapperInterface
{
public function __construct(
private readonly MicroMapperInterface $microMapper
) {}

public function load(object $from, string $toClass, array $context): object
{
$entity = $from;
assert($entity instanceof UserZone);

$dto = new UserZoneApi();
$dto->id = $entity->getId();

return $dto;
}

public function populate(object $from, object $to, array $context): object
{
assert($from instanceof UserZone);
assert($to instanceof UserZoneApi);

$to->dbId = $from->getId();

$to->user = $to->userIri = $this->microMapper->map($from->getUser(), UserApi::class, [
MicroMapperInterface::MAX_DEPTH => 5,
]);

$to->zone = $to->zoneIri = $this->microMapper->map($from->getZone(), ZoneApi::class, [
MicroMapperInterface::MAX_DEPTH => 5,
]);

return $to;
}
}

+ 15
- 0
httpdocs/src/Repository/UserZoneRepository.php Ver ficheiro

@@ -0,0 +1,15 @@
<?php

namespace App\Repository;

use App\Entity\UserZone;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class UserZoneRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, UserZone::class);
}
}

Carregando…
Cancelar
Guardar