| @@ -3078,6 +3078,17 @@ components: | |||||
| - 'null' | - 'null' | ||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| location: | |||||
| readOnly: true | |||||
| type: string | |||||
| format: iri-reference | |||||
| example: 'https://example.com/' | |||||
| locationIri: | |||||
| type: | |||||
| - string | |||||
| - 'null' | |||||
| format: iri-reference | |||||
| example: 'https://example.com/' | |||||
| date: | date: | ||||
| type: string | type: string | ||||
| format: date-time | format: date-time | ||||
| @@ -3094,6 +3105,7 @@ components: | |||||
| required: | required: | ||||
| - userTripIri | - userTripIri | ||||
| - eventIri | - eventIri | ||||
| - locationIri | |||||
| - date | - date | ||||
| UserTripEvent.jsonld: | UserTripEvent.jsonld: | ||||
| type: object | type: object | ||||
| @@ -3146,6 +3158,15 @@ components: | |||||
| - 'null' | - 'null' | ||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| location: | |||||
| readOnly: true | |||||
| $ref: '#/components/schemas/Location.jsonld' | |||||
| locationIri: | |||||
| type: | |||||
| - string | |||||
| - 'null' | |||||
| format: iri-reference | |||||
| example: 'https://example.com/' | |||||
| date: | date: | ||||
| type: string | type: string | ||||
| format: date-time | format: date-time | ||||
| @@ -3162,6 +3183,7 @@ components: | |||||
| required: | required: | ||||
| - userTripIri | - userTripIri | ||||
| - eventIri | - eventIri | ||||
| - locationIri | |||||
| - date | - date | ||||
| Vessel: | Vessel: | ||||
| type: object | type: object | ||||
| @@ -184,6 +184,8 @@ export const userTripEventForm = new FormGroup({ | |||||
| userTripIri: new FormControl(null, [Validators.required]), | userTripIri: new FormControl(null, [Validators.required]), | ||||
| event: new FormControl(null, []), | event: new FormControl(null, []), | ||||
| eventIri: new FormControl(null, [Validators.required]), | eventIri: new FormControl(null, [Validators.required]), | ||||
| location: new FormControl(null, []), | |||||
| locationIri: new FormControl(null, [Validators.required]), | |||||
| date: new FormControl(null, [Validators.required]), | date: new FormControl(null, [Validators.required]), | ||||
| note: new FormControl(null, []), | note: new FormControl(null, []), | ||||
| createdAt: new FormControl(null, []) | createdAt: new FormControl(null, []) | ||||
| @@ -195,6 +197,8 @@ export const userTripEventJsonldForm = new FormGroup({ | |||||
| userTripIri: new FormControl(null, [Validators.required]), | userTripIri: new FormControl(null, [Validators.required]), | ||||
| event: new FormControl(null, []), | event: new FormControl(null, []), | ||||
| eventIri: new FormControl(null, [Validators.required]), | eventIri: new FormControl(null, [Validators.required]), | ||||
| location: new FormControl(null, []), | |||||
| locationIri: new FormControl(null, [Validators.required]), | |||||
| date: new FormControl(null, [Validators.required]), | date: new FormControl(null, [Validators.required]), | ||||
| note: new FormControl(null, []), | note: new FormControl(null, []), | ||||
| createdAt: new FormControl(null, []) | createdAt: new FormControl(null, []) | ||||
| @@ -28,7 +28,7 @@ | |||||
| [getDataFunction]="getLocations" | [getDataFunction]="getLocations" | ||||
| [displayedDataField]="'name'" | [displayedDataField]="'name'" | ||||
| [listColDefinitions]="locationColDefinitions" | [listColDefinitions]="locationColDefinitions" | ||||
| [dataSet]="tripLocation.locationIri" | |||||
| [dataSet]="tripLocation.location" | |||||
| > | > | ||||
| </app-search-select> | </app-search-select> | ||||
| </div> | </div> | ||||
| @@ -15,7 +15,7 @@ | |||||
| [getDataFunction]="getVessels" | [getDataFunction]="getVessels" | ||||
| [displayedDataField]="'name'" | [displayedDataField]="'name'" | ||||
| [listColDefinitions]="vesselColDefinitions" | [listColDefinitions]="vesselColDefinitions" | ||||
| [dataSet]="data?.vesselIri" | |||||
| [dataSet]="data?.vessel" | |||||
| > | > | ||||
| </app-search-select> | </app-search-select> | ||||
| <input id="vesselIri" type="hidden" formControlName="vesselIri" required/> | <input id="vesselIri" type="hidden" formControlName="vesselIri" required/> | ||||
| @@ -29,7 +29,7 @@ | |||||
| [getDataFunction]="getLocations" | [getDataFunction]="getLocations" | ||||
| [displayedDataField]="'name'" | [displayedDataField]="'name'" | ||||
| [listColDefinitions]="locationColDefinitions" | [listColDefinitions]="locationColDefinitions" | ||||
| [dataSet]="data?.startLocationIri" | |||||
| [dataSet]="data?.startLocation" | |||||
| > | > | ||||
| </app-search-select> | </app-search-select> | ||||
| <input id="startLocationIri" type="hidden" formControlName="startLocationIri" required/> | <input id="startLocationIri" type="hidden" formControlName="startLocationIri" required/> | ||||
| @@ -43,7 +43,7 @@ | |||||
| [getDataFunction]="getLocations" | [getDataFunction]="getLocations" | ||||
| [displayedDataField]="'name'" | [displayedDataField]="'name'" | ||||
| [listColDefinitions]="locationColDefinitions" | [listColDefinitions]="locationColDefinitions" | ||||
| [dataSet]="data?.endLocationIri" | |||||
| [dataSet]="data?.endLocation" | |||||
| > | > | ||||
| </app-search-select> | </app-search-select> | ||||
| <input id="endLocationIri" type="hidden" formControlName="endLocationIri" required/> | <input id="endLocationIri" type="hidden" formControlName="endLocationIri" required/> | ||||
| @@ -34,9 +34,7 @@ | |||||
| @if (data.signatureUrl && showSignatureImage) { | @if (data.signatureUrl && showSignatureImage) { | ||||
| <div class="mt-1 d-flex align-items-start gap-2"> | <div class="mt-1 d-flex align-items-start gap-2"> | ||||
| <img [src]="data.signatureUrl" alt="Signatur" class="img-fluid" /> | <img [src]="data.signatureUrl" alt="Signatur" class="img-fluid" /> | ||||
| <button type="button" class="btn btn-sm btn-danger" (click)="markSignatureForRemoval()"> | |||||
| {{ 'basic.remove' | translate }} | |||||
| </button> | |||||
| <button type="button" class="btn btn-sm btn-danger" (click)="markSignatureForRemoval()">X</button> | |||||
| </div> | </div> | ||||
| } | } | ||||
| </div> | </div> | ||||
| @@ -21,6 +21,8 @@ export interface UserTripEvent { | |||||
| userTripIri: string | null; | userTripIri: string | null; | ||||
| readonly event?: string; | readonly event?: string; | ||||
| eventIri: string | null; | eventIri: string | null; | ||||
| readonly location?: string; | |||||
| locationIri: string | null; | |||||
| date: string; | date: string; | ||||
| note?: string | null; | note?: string | null; | ||||
| readonly createdAt?: string | null; | readonly createdAt?: string | null; | ||||
| @@ -12,6 +12,7 @@ | |||||
| import { UserTripJsonld } from './userTripJsonld'; | import { UserTripJsonld } from './userTripJsonld'; | ||||
| import { EventJsonld } from './eventJsonld'; | import { EventJsonld } from './eventJsonld'; | ||||
| import { EventJsonldContext } from './eventJsonldContext'; | import { EventJsonldContext } from './eventJsonldContext'; | ||||
| import { LocationJsonld } from './locationJsonld'; | |||||
| /** | /** | ||||
| @@ -26,6 +27,8 @@ export interface UserTripEventJsonld { | |||||
| userTripIri: string | null; | userTripIri: string | null; | ||||
| readonly event?: EventJsonld; | readonly event?: EventJsonld; | ||||
| eventIri: string | null; | eventIri: string | null; | ||||
| readonly location?: LocationJsonld; | |||||
| locationIri: string | null; | |||||
| date: string; | date: string; | ||||
| note?: string | null; | note?: string | null; | ||||
| readonly createdAt?: string | null; | readonly createdAt?: string | null; | ||||
| @@ -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 Version20250317140441 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('ALTER TABLE user_trip_event ADD location_id INT NOT NULL'); | |||||
| $this->addSql('ALTER TABLE user_trip_event ADD CONSTRAINT FK_46824C0864D218E FOREIGN KEY (location_id) REFERENCES location (id)'); | |||||
| $this->addSql('CREATE INDEX IDX_46824C0864D218E ON user_trip_event (location_id)'); | |||||
| } | |||||
| public function down(Schema $schema): void | |||||
| { | |||||
| // this down() migration is auto-generated, please modify it to your needs | |||||
| $this->addSql('ALTER TABLE user_trip_event DROP FOREIGN KEY FK_46824C0864D218E'); | |||||
| $this->addSql('DROP INDEX IDX_46824C0864D218E ON user_trip_event'); | |||||
| $this->addSql('ALTER TABLE user_trip_event DROP location_id'); | |||||
| } | |||||
| } | |||||
| @@ -86,6 +86,26 @@ class UserTripEventApi | |||||
| #[ApiProperty(writable: true)] | #[ApiProperty(writable: true)] | ||||
| public ?EventApi $eventIri = null; | public ?EventApi $eventIri = null; | ||||
| /** | |||||
| * @var LocationApi | |||||
| */ | |||||
| #[ApiProperty( | |||||
| writable: false, | |||||
| readableLink: true, | |||||
| writableLink: false, | |||||
| builtinTypes: [ | |||||
| new Type( | |||||
| 'object', | |||||
| class: LocationApi::class, | |||||
| ) | |||||
| ] | |||||
| )] | |||||
| public ?LocationApi $location = null; | |||||
| #[NotBlank] | |||||
| #[ApiProperty(writable: true)] | |||||
| public ?LocationApi $locationIri = null; | |||||
| #[Assert\NotBlank] | #[Assert\NotBlank] | ||||
| public \DateTimeImmutable $date; | public \DateTimeImmutable $date; | ||||
| @@ -24,6 +24,10 @@ class UserTripEvent | |||||
| #[ORM\JoinColumn(nullable: false)] | #[ORM\JoinColumn(nullable: false)] | ||||
| private Event $event; | private Event $event; | ||||
| #[ORM\ManyToOne(targetEntity: Location::class)] | |||||
| #[ORM\JoinColumn(name: 'location_id', nullable: false)] | |||||
| private Location $location; | |||||
| #[ORM\Column(nullable: false)] | #[ORM\Column(nullable: false)] | ||||
| private DateTimeImmutable $date; | private DateTimeImmutable $date; | ||||
| @@ -69,6 +73,16 @@ class UserTripEvent | |||||
| $this->event = $event; | $this->event = $event; | ||||
| } | } | ||||
| public function getLocation(): Location | |||||
| { | |||||
| return $this->location; | |||||
| } | |||||
| public function setLocation(Location $location): void | |||||
| { | |||||
| $this->location = $location; | |||||
| } | |||||
| public function getDate(): DateTimeImmutable | public function getDate(): DateTimeImmutable | ||||
| { | { | ||||
| return $this->date; | return $this->date; | ||||
| @@ -46,15 +46,15 @@ class TripEntityToApiMapper implements MapperInterface | |||||
| $dto->createdAt = $entity->getCreatedAt(); | $dto->createdAt = $entity->getCreatedAt(); | ||||
| // Map related entities | // Map related entities | ||||
| $dto->vessel = $this->microMapper->map($entity->getVessel(), VesselApi::class, [ | |||||
| $dto->vesselIri = $dto->vessel = $this->microMapper->map($entity->getVessel(), VesselApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| $dto->startLocation = $this->microMapper->map($entity->getStartLocation(), LocationApi::class, [ | |||||
| $dto->startLocationIri = $dto->startLocation = $this->microMapper->map($entity->getStartLocation(), LocationApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| $dto->endLocation = $this->microMapper->map($entity->getEndLocation(), LocationApi::class, [ | |||||
| $dto->endLocationIri = $dto->endLocation = $this->microMapper->map($entity->getEndLocation(), LocationApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| @@ -3,6 +3,7 @@ | |||||
| namespace App\Mapper; | namespace App\Mapper; | ||||
| use App\ApiResource\EventApi; | use App\ApiResource\EventApi; | ||||
| use App\ApiResource\LocationApi; | |||||
| use App\ApiResource\UserTripApi; | use App\ApiResource\UserTripApi; | ||||
| use App\ApiResource\UserTripEventApi; | use App\ApiResource\UserTripEventApi; | ||||
| use App\Entity\UserTripEvent; | use App\Entity\UserTripEvent; | ||||
| @@ -41,11 +42,15 @@ class UserTripEventEntityToApiMapper implements MapperInterface | |||||
| $dto->note = $entity->getNote(); | $dto->note = $entity->getNote(); | ||||
| $dto->createdAt = $entity->getCreatedAt(); | $dto->createdAt = $entity->getCreatedAt(); | ||||
| $dto->userTrip = $this->microMapper->map($entity->getUserTrip(), UserTripApi::class, [ | |||||
| $dto->userTripIri = $dto->userTrip = $this->microMapper->map($entity->getUserTrip(), UserTripApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| $dto->event = $this->microMapper->map($entity->getEvent(), EventApi::class, [ | |||||
| $dto->eventIri = $dto->event = $this->microMapper->map($entity->getEvent(), EventApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | |||||
| ]); | |||||
| $dto->locationIri = $dto->location = $this->microMapper->map($entity->getEvent(), LocationApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| @@ -18,9 +18,7 @@ class EntityClassDtoStateProcessor implements ProcessorInterface | |||||
| #[Autowire(service: RemoveProcessor::class)] private ProcessorInterface $removeProcessor, | #[Autowire(service: RemoveProcessor::class)] private ProcessorInterface $removeProcessor, | ||||
| private MicroMapperInterface $microMapper | private MicroMapperInterface $microMapper | ||||
| ) | ) | ||||
| { | |||||
| } | |||||
| {} | |||||
| /** | /** | ||||
| * @param mixed $data | * @param mixed $data | ||||