Browse Source

list edit, delete etc

master
Daniel 10 months ago
parent
commit
f941b3086b
13 changed files with 271 additions and 131 deletions
  1. +1
    -1
      angular/src/app/_components/image-upload/image-upload.component.html
  2. +1
    -1
      angular/src/app/_components/list/list.component.html
  3. +2
    -0
      angular/src/app/_components/list/list.component.ts
  4. +72
    -0
      angular/src/app/_components/search-select/search-select.component.ts
  5. +11
    -39
      angular/src/app/_views/trip/trip-detail/trip-detail.component.html
  6. +2
    -69
      angular/src/app/_views/trip/trip-list/trip-list.component.ts
  7. +1
    -1
      angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html
  8. +6
    -4
      angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts
  9. +38
    -6
      angular/src/app/_views/user-trip/user-trip-form/user-trip-form.component.html
  10. +105
    -5
      angular/src/app/_views/user-trip/user-trip-form/user-trip-form.component.ts
  11. +5
    -0
      angular/src/app/_views/user-trip/user-trip-list/user-trip-list.component.html
  12. +25
    -4
      angular/src/app/_views/user-trip/user-trip-list/user-trip-list.component.ts
  13. +2
    -1
      angular/src/assets/i18n/en.json

+ 1
- 1
angular/src/app/_components/image-upload/image-upload.component.html View File

@@ -13,7 +13,7 @@
</div>

@if (imageUrl && showImage) {
<div class="col-12 col-lg-6 mb-3">
<div class="col-12 mb-3">
<span class="form-label">&nbsp;</span>
<div class="image-display">
<img [src]="imageUrl" [alt]="label" class="img-fluid" />


+ 1
- 1
angular/src/app/_components/list/list.component.html View File

@@ -5,7 +5,7 @@
[hidePageSize]="hidePageSize"
[displayOptions]="displayOptions"
[defaultDisplayOption]="defaultDisplayOption"
[showCreateDataButton]="dataFormComponent !== undefined"
[showCreateDataButton]="showCreateButton && dataFormComponent !== undefined"
(createNewData)="onCreateData()"
(displayOptionChange)="onDisplayOptionChange($event)"
>


+ 2
- 0
angular/src/app/_components/list/list.component.ts View File

@@ -35,6 +35,7 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy {
@Input() public showDetailButton: boolean;
@Input() public showEditButton: boolean;
@Input() public showRemoveButton: boolean;
@Input() public showCreateButton: boolean;
@Input() public showPosition: boolean;
@Input() public showFilterBar: boolean;
@Input() public listColDefinitions!: ListColDefinition[];
@@ -91,6 +92,7 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy {
this.showDetailButton = true;
this.showEditButton = true;
this.showRemoveButton = true;
this.showCreateButton = true;
this.showFilterBar = true;
this.filterExists = false;
this.filterObj = {};


+ 72
- 0
angular/src/app/_components/search-select/search-select.component.ts View File

@@ -365,6 +365,78 @@ export class SearchSelectComponent implements OnInit, AfterViewInit {
];
}

public static getDefaultColDefTrips(subResource?: string): ListColDefinition[] {
return [
{
name: 'pilotageReference',
text: 'trip.pilot_reference',
type: ListComponent.COLUMN_TYPE_TEXT_BOLD,
field: 'pilotageReference',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'vessel',
text: 'trip.vessel',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'vessel',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'startLocation',
text: 'trip.start_location',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'startLocation',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'endLocation',
text: 'trip.end_location',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'endLocation',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'startDate',
text: 'trip.start_date',
type: ListComponent.COLUMN_TYPE_DATE,
field: 'startDate',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_DATE,
} as ListColDefinition,
{
name: 'endDate',
text: 'trip.end_date',
type: ListComponent.COLUMN_TYPE_DATE,
field: 'endDate',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_DATE,
} as ListColDefinition,
{
name: 'completed',
text: 'trip.completed',
type: ListComponent.COLUMN_TYPE_BOOLEAN,
field: 'completed',
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,
];
}

public static getDefaultColDefEvents(subResource?: string): ListColDefinition[] {
return [
{


+ 11
- 39
angular/src/app/_views/trip/trip-detail/trip-detail.component.html View File

@@ -6,55 +6,27 @@
</div>
<mat-tab-group>
<mat-tab label="{{ 'trip.view_single' | translate }}">
<app-trip-form
[data]="trip"
(submit)="onFormUpdate($event)"
></app-trip-form>
<div>
<app-trip-form
[data]="trip"
(submit)="onFormUpdate($event)"
></app-trip-form>
</div>
</mat-tab>
<mat-tab label="{{ 'trip.itinerary' | translate }}">
<div>
<h4 class="mb-4">{{ 'trip.itinerary_locations' | translate }}</h4>
<app-trip-location-list
[trip]="trip"
>
</app-trip-location-list>
</div>
</mat-tab>
<mat-tab label="{{ 'trip.assigned_users' | translate }}">
<mat-tab label="{{ 'trip.pilotage' | translate }}">
<div>
<h4 class="mb-4">{{ 'trip.assigned_users' | translate }}</h4>
<div *ngFor="let userTrip of userTrips; let i = index" class="p-2 mb-2 changing-list">
<div class="row">
<div class="col-12 col-md-10 mb-1">
<label [for]="'user_' + i" class="form-label">{{ 'model.user' | translate }}*:</label>
<app-search-select
[formId]="'user'"
[formLabelLangKey]="'model.user'"
[documentForm]="userForms[i]"
[getDataFunction]="getUsers"
[displayedDataField]="'fullName'"
[listColDefinitions]="userColDefinitions"
[dataSet]="userTrip.user"
(change)="onUserSelectChange(i)"
>
</app-search-select>
</div>
</div>
</div>

<div class="row">
<div class="col-12 mb-3">
<button type="button" class="btn btn-primary" (click)="addNewUserTrip()">+</button>
</div>
</div>

<div class="row">
<div class="col-12 mb-3">
<button type="button" class="btn btn-primary" (click)="saveAllUserTrips()">
{{ 'basic.save' | translate }}
</button>
</div>
</div>
<app-user-trip-list
[trip]="trip"
[showCreateButton]="true"
></app-user-trip-list>
</div>
</mat-tab>
<mat-tab label="{{ 'trip.events' | translate }}">


+ 2
- 69
angular/src/app/_views/trip/trip-list/trip-list.component.ts View File

@@ -7,6 +7,7 @@ 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 {SearchSelectComponent} from "@app/_components/search-select/search-select.component";

@Component({
selector: 'app-trip-list',
@@ -24,75 +25,7 @@ export class TripListComponent {
private tripService: TripService,
protected appHelperService: AppHelperService,
) {
this.listColDefinitions = [
{
name: 'pilotageReference',
text: 'trip.pilot_reference',
type: ListComponent.COLUMN_TYPE_TEXT_BOLD,
field: 'pilotageReference',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'vessel',
text: 'trip.vessel',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'vessel',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'startLocation',
text: 'trip.start_location',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'startLocation',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'endLocation',
text: 'trip.end_location',
type: ListComponent.COLUMN_TYPE_TEXT,
subResource: 'endLocation',
field: 'name',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_TEXT,
} as ListColDefinition,
{
name: 'startDate',
text: 'trip.start_date',
type: ListComponent.COLUMN_TYPE_DATE,
field: 'startDate',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_DATE,
} as ListColDefinition,
{
name: 'endDate',
text: 'trip.end_date',
type: ListComponent.COLUMN_TYPE_DATE,
field: 'endDate',
sortable: true,
filterType: FilterBarComponent.FILTER_TYPE_DATE,
} as ListColDefinition,
{
name: 'completed',
text: 'trip.completed',
type: ListComponent.COLUMN_TYPE_BOOLEAN,
field: 'completed',
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.getDefaultColDefTrips();
}

ngOnInit() {


+ 1
- 1
angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html View File

@@ -51,7 +51,7 @@

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


+ 6
- 4
angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts View File

@@ -59,12 +59,14 @@ export class TripLocationFormComponent extends AbstractDataFormComponent<TripLoc
override ngOnInit() {
super.ngOnInit();
this.form.get('tripIri')?.setValue(this.trip.id);
console.log(this.newArrivalDateTime);
console.log(this.newDepartureDateTime);
if (!this.isEditMode()) {
this.form.get('newArrivalDateTime')?.setValue(this.newArrivalDateTime);
this.form.get('newDepartureDateTime')?.setValue(this.newDepartureDateTime);
this.form.get('arrivalDateTime')?.setValue(this.newArrivalDateTime);
this.form.get('departureDateTime')?.setValue(this.newDepartureDateTime);
} else {
this.form.get('newArrivalDateTime')?.setValue(this.data?.arrivalDateTime);
this.form.get('newDepartureDateTime')?.setValue(this.data?.departureDateTime);
this.form.get('arrivalDateTime')?.setValue(this.data?.arrivalDateTime);
this.form.get('departureDateTime')?.setValue(this.data?.departureDateTime);
}
}



+ 38
- 6
angular/src/app/_views/user-trip/user-trip-form/user-trip-form.component.html View File

@@ -2,10 +2,43 @@
<div class="spt-form">
@if (data !== undefined) {
<form [formGroup]="userTripForm" (ngSubmit)="onSubmit()">
<input type="hidden" formControlName="tripIri" />
<input type="hidden" formControlName="userIri" />
<input type="hidden" formControlName="signatureIri" />
<div class="row">
@if (trip) {
<div>{{ 'model.trip' | translate }}: {{ trip.pilotageReference }}</div>
} @else {
<div class="col-12 mb-3">
<label for="tripIri" class="form-label">{{ 'model.trip' | translate }}*:</label>
<app-search-select #tripSearchSelect
[formId]="'tripIri'"
[formLabelLangKey]="'model.location'"
[documentForm]="userTripForm"
[getDataFunction]="getTrips"
[displayedDataField]="'pilotageReference'"
[listColDefinitions]="tripColDefinitions"
[dataSet]="trip"
>
</app-search-select>
<input id="tripIri" type="hidden" formControlName="tripIri" required/>
</div>
}
@if (user) {
<div>{{ 'user_trip.pilot' | translate }}: {{ user.fullName }}</div>
} @else {
<div class="row">
<label for="userIri" class="form-label">{{ 'user_trip.pilot' | translate }}*:</label>
<app-search-select #userSearchSelect
[formId]="'userIri'"
[formLabelLangKey]="'model.user'"
[documentForm]="userTripForm"
[getDataFunction]="getUsers"
[displayedDataField]="'fullName'"
[listColDefinitions]="userColDefinitions"
[dataSet]="user"
>
</app-search-select>
<input id="userIri" type="hidden" formControlName="userIri" required/>
</div>
}
<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"/>
@@ -25,8 +58,7 @@
</label>
</div>
</div>


<input type="hidden" formControlName="signatureIri" />
<!-- Verwende die neue ImageUpload-Komponente -->
<app-image-upload
#imageUpload


+ 105
- 5
angular/src/app/_views/user-trip/user-trip-form/user-trip-form.component.ts View File

@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { UserTripJsonld, UserTripService } from "@app/core/api/v1";
import {TripJsonld, TripService, UserJsonld, UserService, UserTripJsonld, UserTripService} from "@app/core/api/v1";
import { userTripForm } from "@app/_forms/apiForms";
import { TranslateService } from "@ngx-translate/core";
import { Router } from "@angular/router";
@@ -7,6 +7,11 @@ import { ROUTE_USER_TRIPS } from "@app/app-routing.module";
import { AppHelperService } from "@app/_helpers/app-helper.service";
import { AbstractImageFormComponent } from "@app/_components/_abstract/abstract-image-form-component";
import { ImageUploadService } from "@app/_services/image-upload.service";
import {ListColDefinition} from "@app/_components/list/list-col-definition";
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";

@Component({
selector: 'app-user-trip-form',
@@ -16,9 +21,15 @@ import { ImageUploadService } from "@app/_services/image-upload.service";
export class UserTripFormComponent extends AbstractImageFormComponent<UserTripJsonld> {

protected readonly userTripForm = userTripForm;
protected userColDefinitions: ListColDefinition[];
protected tripColDefinitions: ListColDefinition[];
protected trip?: TripJsonld;
protected user?: UserJsonld;

constructor(
private userTripService: UserTripService,
protected userTripService: UserTripService,
protected userService: UserService,
protected tripService: TripService,
imageUploadService: ImageUploadService,
appHelperService: AppHelperService,
translateService: TranslateService,
@@ -28,18 +39,107 @@ export class UserTripFormComponent extends AbstractImageFormComponent<UserTripJs
imageUploadService,
userTripForm,
appHelperService,
undefined,
(data: UserTripJsonld) => this.userTripService.userTripsPost(data),
(id: string | number, data: UserTripJsonld) =>
this.userTripService.userTripsIdPatch(
id.toString(),
this.appHelperService.convertJsonldToJson(data)
),
),
(id: string | number) => userTripService.userTripsIdDelete(id.toString()),
'signatureIri',
'signature.dbId',
translateService,
router
);
this.redirectAfterDelete = '/' + ROUTE_USER_TRIPS;
this.redirectAfterDelete = '/' + ROUTE_USER_TRIPS
this.userColDefinitions = SearchSelectComponent.getDefaultColDefUsers();
this.tripColDefinitions = SearchSelectComponent.getDefaultColDefTrips();
}

override ngOnInit() {
super.ngOnInit();

if (this.data?.trip && !this.trip) {
this.trip = this.data?.trip;
}
if (this.data?.user && !this.user) {
this.user = this.data?.user;
}

if (this.trip && !this.data!.tripIri!) {
this.data!.tripIri = this.trip.id!;
this.form.get('tripIri')?.setValue(this.trip.id!);
}
if (this.user && !this.data!.userIri!) {
this.data!.userIri = this.user.id!;
this.form.get('userIri')?.setValue(this.user.id!);
}
if (!this.isEditMode()) {
this.form.get('completed')?.setValue(false);
this.form.get('approved')?.setValue(false);
}
}

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 kein Trip vorhanden ist, gib alle Benutzer zurück
if (!this.trip?.id) {
return of(usersResponse);
}

// Hole alle UserTrips für diesen Trip
return this.userTripService.userTripsGetCollection(
1,
100,
this.trip.id
).pipe(
map(userTripsResponse => {
// Extrahiere die User-IDs aus den UserTrips
const usedUserIds = new Set(
userTripsResponse.member?.map(
(userTrip: UserTripJsonld) => userTrip.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;
})
);
})
);
}

getTrips: ListGetDataFunctionType = (
index: number,
pageSize: number,
term?: string,
) => {
return this.tripService.tripsGetCollection(
index,
pageSize,
);
}
}

+ 5
- 0
angular/src/app/_views/user-trip/user-trip-list/user-trip-list.component.html View File

@@ -3,5 +3,10 @@
[listId]="'userTripList'"
[getDataFunction]="getData"
[listColDefinitions]="listColDefinitions"
[dataFormComponent]="userTripLocationFormComponent"
[dataFormComponentData]="dataFormComponentData"
[deleteItemFunction]="deleteItemFunction"
[showCreateButton]="showCreateButton"
[getCustomDetailLinkFunction]="getCustomDetailLink"
></app-list>
</div>

+ 25
- 4
angular/src/app/_views/user-trip/user-trip-list/user-trip-list.component.ts View File

@@ -1,10 +1,13 @@
import {Component, Input, ViewChild} from '@angular/core';
import {ListComponent} from "@app/_components/list/list.component";
import {ListColDefinition} from "@app/_components/list/list-col-definition";
import {UserJsonld, UserTripService} from "@app/core/api/v1";
import {LocationJsonld, TripJsonld, UserJsonld, UserTripService} from "@app/core/api/v1";
import {AppHelperService} from "@app/_helpers/app-helper.service";
import {FilterBarComponent} from "@app/_components/filter-bar/filter-bar.component";
import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type";
import {Observable} from "rxjs";
import {UserTripFormComponent} from "@app/_views/user-trip/user-trip-form/user-trip-form.component";
import {ROUTE_LOCATIONS, ROUTE_USER_TRIPS} from "@app/app-routing.module";

@Component({
selector: 'app-user-trip-list',
@@ -13,14 +16,19 @@ import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-funct
})
export class UserTripListComponent {
@Input() public user?: UserJsonld;
@Input() public trip?: TripJsonld;
@Input() public showCreateButton: boolean;
@ViewChild("listComponent", {static: false}) listComponent!: ListComponent;

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

constructor(
private userTripService: UserTripService,
protected appHelperService: AppHelperService,
) {
this.showCreateButton = false;
this.listColDefinitions = [
{
name: 'pilotageReference',
@@ -102,7 +110,13 @@ export class UserTripListComponent {
}

ngOnInit() {

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

ngAfterViewInit(): void {
@@ -117,13 +131,20 @@ export class UserTripListComponent {
return this.userTripService.userTripsGetCollection(
index,
pageSize,
undefined,
this.trip ? this.trip.id : undefined,
undefined,
this.user ? this.user.id : undefined,
undefined,
// term ? Number(term) : undefined,
this.listComponent.getFilterJsonString(),
this.listComponent.getSortingJsonString()
);
}

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

getCustomDetailLink(element: LocationJsonld) {
return ROUTE_USER_TRIPS + '/' + this.appHelperService.extractId(element?.id);
}
}

+ 2
- 1
angular/src/assets/i18n/en.json View File

@@ -83,7 +83,7 @@
},
"trip": {
"add_itinerary_location": "Add itinerary location",
"assigned_users": "Assigned Pilots",
"pilotage": "Pilotage",
"captain_name": "Captain name",
"completed": "Completed",
"customer_reference": "Customer reference",
@@ -116,6 +116,7 @@
"completed_at": "Completed at",
"event_date": "Event date",
"events": "Events",
"pilot": "Pilot",
"signature": "Signature Image",
"view": "Pilotage"
},


Loading…
Cancel
Save