Skip to content

Commit 814df85

Browse files
committed
Improve UI usability: required fields in form, removed HttpData option in transfer, removed action column in transfer history table and improved poll for negotiation and transfer requests
1 parent 2fc9738 commit 814df85

File tree

10 files changed

+123
-202
lines changed

10 files changed

+123
-202
lines changed

src/app/app.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export function jwtOptionsFactory(authService: AuthService) {
105105
},
106106
{
107107
provide: 'TRANSFER_TYPES',
108-
useFactory: () => [{id: DATA_ADDRESS_TYPES.httpData, name: DATA_ADDRESS_TYPES.httpData}, {id: DATA_ADDRESS_TYPES.amazonS3, name: 'ExternalStoreS3'}, {id: DATA_ADDRESS_TYPES.inesDataStore, name: DATA_ADDRESS_TYPES.inesDataStore}],
108+
useFactory: () => [{id: DATA_ADDRESS_TYPES.amazonS3, name: 'ExternalStoreS3'}, {id: DATA_ADDRESS_TYPES.inesDataStore, name: DATA_ADDRESS_TYPES.inesDataStore}],
109109
},
110110
{ provide: HTTP_INTERCEPTORS, useClass: Oauth2Interceptor, multi: true },
111111
{

src/app/pages/assets/asset-create/asset-create.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@
197197

198198
<mat-form-field class="form-field" color="accent">
199199
<mat-label>Bucket Name</mat-label>
200-
<input [(ngModel)]="amazonS3DataAddress.bucketName" matInput>
200+
<input required [(ngModel)]="amazonS3DataAddress.bucketName" matInput>
201201
</mat-form-field>
202202

203203
<mat-form-field class="form-field" color="accent">
@@ -212,17 +212,17 @@
212212

213213
<mat-form-field class="form-field" color="accent">
214214
<mat-label>Access Key Id</mat-label>
215-
<input [(ngModel)]="amazonS3DataAddress.accessKeyId" matInput>
215+
<input required [(ngModel)]="amazonS3DataAddress.accessKeyId" matInput>
216216
</mat-form-field>
217217

218218
<mat-form-field class="form-field" color="accent">
219219
<mat-label>Secret Access Key</mat-label>
220-
<input [(ngModel)]="amazonS3DataAddress.secretAccessKey" matInput>
220+
<input required [(ngModel)]="amazonS3DataAddress.secretAccessKey" matInput>
221221
</mat-form-field>
222222

223223
<mat-form-field class="form-field" color="accent">
224224
<mat-label>Endpoint Override</mat-label>
225-
<input [(ngModel)]="amazonS3DataAddress.endpointOverride" matInput>
225+
<input required [(ngModel)]="amazonS3DataAddress.endpointOverride" matInput>
226226
</mat-form-field>
227227
</div>
228228

src/app/pages/catalog/contract-offers-viewer/contract-offers-viewer.component.ts

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { JsonDialogData } from '../../json-dialog/json-dialog/json-dialog.data';
1313
import { JsonDialogComponent } from '../../json-dialog/json-dialog/json-dialog.component'
1414
import { PolicyBuilder } from '@think-it-labs/edc-connector-client';
1515
import { Router } from '@angular/router';
16+
import { catchError, filter, from, interval, of, switchMap, takeUntil, tap, timer } from 'rxjs';
1617

1718
export interface ContractOffersDialogData {
1819
assetId: string;
@@ -192,48 +193,66 @@ export class ContractOffersViewerComponent {
192193
offerId: initiateRequest.policy["@id"]
193194
});
194195

195-
196-
if (!this.pollingHandleNegotiation) {
197-
this.checkActiveNegotiations();
198-
}
196+
this.checkActiveNegotiations(negotiationId, initiateRequest.policy["@id"]);
199197
}, error => {
200198
console.error(error);
201199
this.notificationService.showError("Error starting negotiation");
202200
});
203201
}
204202

205-
checkActiveNegotiations() {
206-
// there are no active negotiations
207-
this.pollingHandleNegotiation = setInterval(() => {
208-
209-
const finishedNegotiationStates = [
210-
"VERIFIED",
211-
"TERMINATED",
212-
"FINALIZED",
213-
"ERROR"];
214-
215-
for (const negotiation of this.runningNegotiations.values()) {
216-
this.apiService.getNegotiationState(negotiation.id).subscribe(updatedNegotiation => {
217-
if (finishedNegotiationStates.includes(updatedNegotiation.state)) {
218-
let offerId = negotiation.offerId;
203+
checkActiveNegotiations(negotiationId: string, offerId: string) {
204+
const timeout$ = timer(30000).pipe(
205+
tap(() => {
206+
if (this.runningNegotiations.has(offerId)) {
207+
this.notificationService.showWarning(
208+
`Negotiation [${negotiationId}] timed out after 30 seconds.`
209+
);
210+
this.runningNegotiations.delete(offerId);
211+
}
212+
})
213+
);
214+
215+
this.pollingHandleNegotiation = interval(2000).pipe(
216+
takeUntil(timeout$),
217+
switchMap(() => from([...this.runningNegotiations.values()])),
218+
switchMap(negotiation =>
219+
this.apiService.getNegotiationState(negotiation.id).pipe(
220+
catchError(error => {
221+
console.error("Polling error:", error);
222+
this.notificationService.showError("Error polling negotiation");
223+
this.runningNegotiations.delete(negotiation.offerId);
224+
return of(null);
225+
})
226+
)
227+
),
228+
filter(updatedNegotiation => updatedNegotiation !== null),
229+
tap(updatedNegotiation => {
230+
const finishedStates = ["VERIFIED", "TERMINATED", "FINALIZED", "ERROR"];
231+
if (finishedStates.includes(updatedNegotiation.state)) {
219232
this.runningNegotiations.delete(offerId);
233+
234+
if (updatedNegotiation.state === "VERIFIED" || updatedNegotiation.state === "FINALIZED") {
235+
this.finishedNegotiations.set(offerId, updatedNegotiation);
236+
this.notificationService.showInfo("Contract Negotiation complete!");
237+
} else if (updatedNegotiation.state === "TERMINATED") {
220238
const errorDetail = updatedNegotiation.optionalValue("edc", "errorDetail");
221-
if (updatedNegotiation["state"] === "VERIFIED" || updatedNegotiation["state"] === "FINALIZED") {
222-
this.finishedNegotiations.set(offerId, updatedNegotiation);
223-
this.notificationService.showInfo("Contract Negotiation complete!");
224-
} else if (updatedNegotiation["state"] === "TERMINATED" && typeof errorDetail === 'string' && errorDetail.includes("Contract offer is not valid")) {
239+
if (typeof errorDetail === 'string' && errorDetail.includes("Contract offer is not valid")) {
225240
this.finishedNegotiations.set(offerId, updatedNegotiation);
226241
this.notificationService.showError("Contract offer is not valid.");
227242
}
228243
}
229244

230245
if (this.runningNegotiations.size === 0) {
231-
clearInterval(this.pollingHandleNegotiation);
232-
this.pollingHandleNegotiation = undefined;
246+
this.cleanupPolling();
233247
}
234-
});
235-
}
236-
}, 1000);
248+
}
249+
})
250+
).subscribe();
251+
}
252+
253+
private cleanupPolling() {
254+
this.pollingHandleNegotiation?.unsubscribe();
255+
this.pollingHandleNegotiation = undefined;
237256
}
238257

239258
getJsonPolicy(policy: Policy): any {

src/app/pages/contracts/contract-transfer-dialog/contract-transfer-dialog.component.html

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,63 +22,6 @@
2222
</mat-select>
2323
</mat-form-field>
2424

25-
<div *ngIf="storageTypeId === 'HttpData'">
26-
<mat-form-field class="form-field" color="accent">
27-
<mat-label>Name</mat-label>
28-
<input required [(ngModel)]="httpDataAddress.name" matInput>
29-
</mat-form-field>
30-
31-
<mat-form-field class="form-field" color="accent">
32-
<mat-label>Path</mat-label>
33-
<input [(ngModel)]="httpDataAddress.path" matInput>
34-
</mat-form-field>
35-
36-
<mat-form-field class="form-field" color="accent">
37-
<mat-label>Base URL</mat-label>
38-
<input required [(ngModel)]="httpDataAddress.baseUrl" matInput>
39-
</mat-form-field>
40-
41-
<mat-form-field class="form-field" color="accent">
42-
<mat-label>Auth Key</mat-label>
43-
<input [(ngModel)]="httpDataAddress.authKey" matInput>
44-
</mat-form-field>
45-
46-
<mat-form-field class="form-field" color="accent">
47-
<mat-label>Auth Code</mat-label>
48-
<input [(ngModel)]="httpDataAddress.authCode" matInput>
49-
</mat-form-field>
50-
51-
<mat-form-field class="form-field" color="accent">
52-
<mat-label>Secret Name</mat-label>
53-
<input [(ngModel)]="httpDataAddress.secretName" matInput>
54-
</mat-form-field>
55-
56-
<mat-form-field class="form-field" color="accent">
57-
<mat-label>Proxy Body</mat-label>
58-
<input [(ngModel)]="httpDataAddress.proxyBody" matInput>
59-
</mat-form-field>
60-
61-
<mat-form-field class="form-field" color="accent">
62-
<mat-label>Proxy Path</mat-label>
63-
<input [(ngModel)]="httpDataAddress.proxyPath" matInput>
64-
</mat-form-field>
65-
66-
<mat-form-field class="form-field" color="accent">
67-
<mat-label>Proxy Query Params</mat-label>
68-
<input [(ngModel)]="httpDataAddress.proxyQueryParams" matInput>
69-
</mat-form-field>
70-
71-
<mat-form-field class="form-field" color="accent">
72-
<mat-label>Proxy Method</mat-label>
73-
<input [(ngModel)]="httpDataAddress.proxyMethod" matInput>
74-
</mat-form-field>
75-
76-
<mat-form-field class="form-field" color="accent">
77-
<mat-label>Content Type</mat-label>
78-
<input [(ngModel)]="httpDataAddress.contentType" matInput>
79-
</mat-form-field>
80-
</div>
81-
8225
<div *ngIf="storageTypeId === 'AmazonS3'">
8326
<mat-form-field class="form-field" color="accent">
8427
<mat-label>Region</mat-label>

src/app/pages/contracts/contract-transfer-dialog/contract-transfer-dialog.component.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, Inject, QueryList, ViewChildren } from '@angular/core';
22
import { NgModel } from '@angular/forms';
33
import { MatDialogRef } from '@angular/material/dialog';
4-
import { DataAddress, HttpDataAddress } from '@think-it-labs/edc-connector-client';
4+
import { DataAddress } from '@think-it-labs/edc-connector-client';
55
import { AmazonS3DataAddress } from 'src/app/shared/models/amazon-s3-data-address';
66
import { NotificationService } from 'src/app/shared/services/notification.service';
77
import { DATA_ADDRESS_TYPES } from 'src/app/shared/utils/app.constants';
@@ -29,10 +29,6 @@ export class ContractTransferDialog {
2929
region: ''
3030
};
3131

32-
httpDataAddress: HttpDataAddress = {
33-
type: 'HttpData'
34-
};
35-
3632
@ViewChildren(NgModel) formControls: QueryList<NgModel>;
3733

3834
constructor(@Inject('TRANSFER_TYPES') public transferTypes: StorageType[],
@@ -56,8 +52,6 @@ export class ContractTransferDialog {
5652
this.notificationService.showError("Review the form fields");
5753
return;
5854
}
59-
} else if (this.storageTypeId === DATA_ADDRESS_TYPES.httpData) {
60-
dataAddress = this.httpDataAddress;
6155
} else if (this.storageTypeId === DATA_ADDRESS_TYPES.inesDataStore) {
6256
dataAddress = this.inesDataDataAddress;
6357
} else {
@@ -80,10 +74,7 @@ export class ContractTransferDialog {
8074
if (this.storageTypeId === DATA_ADDRESS_TYPES.amazonS3 && (!this.amazonS3DataAddress.region || !this.amazonS3DataAddress.bucketName
8175
|| !this.amazonS3DataAddress.endpointOverride || !this.amazonS3DataAddress.secretAccessKey || !this.amazonS3DataAddress.accessKeyId)) {
8276
return false;
83-
}
84-
else if (this.storageTypeId === DATA_ADDRESS_TYPES.httpData && (!this.httpDataAddress.name || !this.httpDataAddress.baseUrl)) {
85-
return false;
86-
}else{
77+
} else {
8778
return true;
8879
}
8980
}

src/app/pages/contracts/contract-viewer/contract-viewer.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
</mat-card-content>
4141
<div *ngIf="isNotProvisionedByItself(contract)">
4242
<mat-card-actions class="card-actions text-align-end">
43-
<button color="accent" mat-stroked-button (click)="onTransferClicked(contract)">
43+
<button color="accent" mat-stroked-button (click)="onTransferClicked(contract)" [disabled]="isTransferInProgress(contract.id!)">
4444
<mat-icon>downloading</mat-icon> Transfer
4545
</button>
4646
</mat-card-actions>

0 commit comments

Comments
 (0)