feat: Hinzufügen einer erweiterten Ansicht für die Tabelle im Envelope Generator

- In der Tabelle für Umschläge wurde ein versteckter Abschnitt unter den Zeilen hinzugefügt.
- Beim Klicken auf eine Zeile wird nun ein Detailbereich angezeigt, der Informationen zu Empfänger und Historie des Umschlags zeigt.
This commit is contained in:
Developer 02 2024-09-09 17:30:36 +02:00
parent d084a4cd81
commit b66c2f67da
11 changed files with 83 additions and 21 deletions

View File

@ -10,6 +10,7 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
int EnvelopeId, int EnvelopeId,
string UserReference, string UserReference,
int Status, int Status,
string? StatusName,
DateTime AddedWhen, DateTime AddedWhen,
DateTime? ActionDate, DateTime? ActionDate,
UserCreateDto? Sender, UserCreateDto? Sender,

View File

@ -43,11 +43,17 @@ namespace EnvelopeGenerator.Domain.Entities
public virtual Receiver? Receiver { get; set; } public virtual Receiver? Receiver { get; set; }
[NotMapped] [NotMapped]
public ReferenceType ReferenceType => (Status / 3) switch public ReferenceType ReferenceType => (Status / 1000) switch
{ {
1 => ReferenceType.Sender, 1 => ReferenceType.Sender,
2 or 3 => ReferenceType.Receiver, 2 or 3 => ReferenceType.Receiver,
_ => ReferenceType.Unknown, _ => ReferenceType.Unknown,
}; };
[NotMapped]
public string? StatusName
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
? Enum.GetName(typeof(EnvelopeStatus), Status)
: null;
} }
} }

View File

@ -0,0 +1,23 @@
<table mat-table [dataSource]="receiverData" class="mat-elevation-z8">
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element; let i = index">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter"></receiver-input>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Anrede Email </th>
<td mat-cell *matCellDef="let element">
<clearable-input [label]="'Anrede Email'" [value]="element.name"></clearable-input>
</td>
</ng-container>
<ng-container matColumnDef="accessCode">
<th mat-header-cell *matHeaderCellDef> Zugriffscode </th>
<td mat-cell *matCellDef="let element"> {{element.accessCode}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@ -6,6 +6,7 @@
<receiver-status-table></receiver-status-table> <receiver-status-table></receiver-status-table>
</mat-tab> </mat-tab>
<mat-tab label="History"> <mat-tab label="History">
<history-table></history-table>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
</dd-table> </dd-table>

View File

@ -6,12 +6,14 @@ import { DDTable } from "../dd-table/dd-table.component";
import { ClearableInputComponent } from '../../clearable-input/clearable-input.component' import { ClearableInputComponent } from '../../clearable-input/clearable-input.component'
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
import { ReceiverStatusTableComponent } from "../receiver-status-table/receiver-status-table.component"; import { ReceiverStatusTableComponent } from "../receiver-status-table/receiver-status-table.component";
import { HistoryTableComponent } from "../history-table/history-table.component";
import { EnvelopeReceiverService } from '../../../services/envelope-receiver.service'; import { EnvelopeReceiverService } from '../../../services/envelope-receiver.service';
import { HistoryService } from '../../../services/history.service';
@Component({ @Component({
selector: 'envelope-table', selector: 'envelope-table',
standalone: true, standalone: true,
imports: [DDTable, ClearableInputComponent, MatTabsModule, ReceiverStatusTableComponent], imports: [DDTable, ClearableInputComponent, MatTabsModule, ReceiverStatusTableComponent, HistoryTableComponent],
templateUrl: './envelope-table.component.html', templateUrl: './envelope-table.component.html',
animations: [ animations: [
trigger('detailExpand', [ trigger('detailExpand', [
@ -51,12 +53,19 @@ export class EnvelopeTableComponent implements AfterViewInit {
@ViewChild(ReceiverStatusTableComponent) rsTable!: ReceiverStatusTableComponent @ViewChild(ReceiverStatusTableComponent) rsTable!: ReceiverStatusTableComponent
@ViewChild(HistoryTableComponent) histTable!: HistoryTableComponent
onToggleExpandedRow: (envelope: any, event: Event) => Promise<void> = async (envelope, event) => { onToggleExpandedRow: (envelope: any, event: Event) => Promise<void> = async (envelope, event) => {
if (envelope === null || envelope === undefined) if (envelope === null || envelope === undefined)
return; return;
var uuid: string = envelope.uuid; var uuid: string = envelope.uuid;
this.rsTable.data = await this.erService.getSecretAsync(uuid); this.rsTable.data = await this.erService.getSecretAsync(uuid);
var id: number = envelope.id;
var refType: number = this.config.referenceType.receiver;
const histories = await this.histService.getHistoryAsync({ envelopeId: id, referenceType: refType, withReceiver: true })
this.histTable.data = histories;
} }
private eService: EnvelopeService = inject(EnvelopeService); private eService: EnvelopeService = inject(EnvelopeService);
@ -65,6 +74,8 @@ export class EnvelopeTableComponent implements AfterViewInit {
private readonly erService: EnvelopeReceiverService = inject(EnvelopeReceiverService); private readonly erService: EnvelopeReceiverService = inject(EnvelopeReceiverService);
private readonly histService: HistoryService = inject(HistoryService);
async ngAfterViewInit() { async ngAfterViewInit() {
this.data = await this.eService.getEnvelopeAsync(this.options); this.data = await this.eService.getEnvelopeAsync(this.options);
} }

View File

@ -1 +1 @@
<p>history-table works!</p> <dd-table [data]="data" [columnsToDisplay]="columnsToDisplay" [schema]="schema" [isSortable]="true"></dd-table>

View File

@ -1,12 +1,30 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component'
@Component({ @Component({
selector: 'history-table', selector: 'history-table',
standalone: true, standalone: true,
imports: [], imports: [DDTable],
templateUrl: './history-table.component.html', templateUrl: './history-table.component.html',
styleUrl: './history-table.component.scss' styleUrl: './history-table.component.scss'
}) })
export class HistoryTableComponent { export class HistoryTableComponent {
data: any[] = [];
} schema: Record<string, { header: string; field: (element: any) => any; }> = {
"status": {
"header": "Status",
"field": hist => hist.statusName
},
"user": {
"header": "Benutzer",
"field": hist => hist.userReference
},
"date": {
"header": "Datum",
"field": hist => hist.actionDate
}
}
columnsToDisplay: string[] = ["status", "user", "date"];
}

View File

@ -1,4 +1,4 @@
import { Component, inject } from '@angular/core'; import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component' import { DDTable } from '../dd-table/dd-table.component'
@Component({ @Component({

View File

@ -14,7 +14,7 @@ export class ConfigurationService implements OnInit {
private _envelopeTypeTitles! : any[]; private _envelopeTypeTitles! : any[];
private referenceType!: any; private _referenceType!: any;
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
const api_url = inject(API_URL); const api_url = inject(API_URL);
@ -29,7 +29,7 @@ export class ConfigurationService implements OnInit {
}}); }});
this.http.get<any>(`${this.url}/History/reference-type`).subscribe({ this.http.get<any>(`${this.url}/History/reference-type`).subscribe({
next: res => this.referenceType = res next: res => this._referenceType = res
}) })
} }
@ -39,5 +39,9 @@ export class ConfigurationService implements OnInit {
public get envelopeTypeTitles() { public get envelopeTypeTitles() {
return this._envelopeTypeTitles; return this._envelopeTypeTitles;
} }
public get referenceType() {
return this._referenceType;
}
} }

View File

@ -19,15 +19,15 @@ export class HistoryService {
let params = new HttpParams(); let params = new HttpParams();
if (options) { if (options) {
if (options.envelopeId) if (options.envelopeId)
params = params.set('envelopeId', options.envelopeId.toString()); params = params.set('envelopeId', options.envelopeId);
if (options.referenceType) if (options.referenceType != null)
params = params.set('referenceType', options.referenceType.toString()); params = params.set('referenceType', options.referenceType);
if (options.userReference) if (options.userReference)
params = params.set('userReference', options.userReference.toString()); params = params.set('userReference', options.userReference);
if (options.withReceiver) if (options.withReceiver)
params = params.set('withReceiver', options.withReceiver.toString()); params = params.set('withReceiver', options.withReceiver);
if (options.withSender) if (options.withSender)
params = params.set('withSender', options.withSender.toString()); params = params.set('withSender', options.withSender);
} }
return this.http.get(this.url, { params }); return this.http.get(this.url, { params });
} }
@ -37,10 +37,10 @@ export class HistoryService {
} }
} }
interface Options { class Options {
envelopeId?: number; envelopeId?: number;
userReference?: string; userReference?: string;
referenceType?: number; referenceType: number | null = null;
withSender?: boolean; withSender?: boolean;
withReceiver?: boolean; withReceiver?: boolean;
} }

View File

@ -45,12 +45,10 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
ReferenceType? refTypEnum = null; ReferenceType? refTypEnum = null;
if (referenceType is int refTypInt) if (referenceType is int refTypInt)
{
if (Enum.IsDefined(typeof(ReferenceType), refTypInt)) if (Enum.IsDefined(typeof(ReferenceType), refTypInt))
refTypEnum = (ReferenceType)refTypInt; refTypEnum = (ReferenceType)refTypInt;
} else
else throw new ArgumentException($"The provided referenceType '{referenceType}' is not valid. It must correspond to a valid value in the {nameof(ReferenceType)} enum.");
throw new ArgumentException($"The provided referenceType '{referenceType}' is not valid. It must correspond to a valid value in the {nameof(ReferenceType)} enum.");
switch(referenceType) switch(referenceType)
{ {