Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contract Termination UI #767

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9c29be7
chore: added terminated contracts to fake-backend
kamilczaja Jul 16, 2024
ae52eeb
feat: added termination status to contract cards
kamilczaja Jul 16, 2024
24e75cd
feat: added termination information to contract agreement details
kamilczaja Jul 16, 2024
e2b14c8
feat: adjusted icons in both cards and details
kamilczaja Jul 16, 2024
22f5ffd
feat: spaced buttons in contract details differently, added terminati…
kamilczaja Jul 16, 2024
352d0a9
chore: prettier
kamilczaja Jul 16, 2024
3841ae8
--wip-- [skip ci]
kamilczaja Jul 17, 2024
f9a06a4
feat: termination dialog
kamilczaja Jul 17, 2024
1e01dd7
feat: contract termination request
kamilczaja Jul 17, 2024
f5998d9
feat: contract termination via ui possible - wip: autorefresh contrac…
kamilczaja Jul 17, 2024
d5cfc84
feat: termination status filter
kamilczaja Jul 17, 2024
c9a6dd1
fix: termination status filter now actually works
kamilczaja Jul 17, 2024
f9132eb
--wip-- [skip ci]
kamilczaja Jul 17, 2024
3f62734
fix: termination dialog styling
kamilczaja Jul 17, 2024
fd3f5fe
feat: auto-refresh after termination
kamilczaja Jul 17, 2024
b78db3c
fix: contract limit counting termination depending on filter
kamilczaja Jul 17, 2024
3da7b0f
chore: removed redundant route
kamilczaja Jul 17, 2024
c9beb0b
chore: prettier
kamilczaja Jul 18, 2024
7018d18
chore: updated CHANGELOG
kamilczaja Jul 18, 2024
b292705
chore: self-review
kamilczaja Jul 18, 2024
a71ee71
fix: icon in contract dialog inconsistent with card
kamilczaja Jul 18, 2024
b58bd9e
chore: review comments
kamilczaja Jul 18, 2024
4391595
chore: review 2
kamilczaja Jul 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ the detailed section referring to by linking pull requests or issues.

#### Minor

- Both providers and consumers can now terminate contracts.
- Contracts can be filtered by their termination status.

#### Patch

### Deployment Migration Notes
Expand Down
2 changes: 1 addition & 1 deletion src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {NgModule} from '@angular/core';
import {RouterModule, ROUTES, Routes} from '@angular/router';
import {ROUTES, RouterModule, Routes} from '@angular/router';
import {PageNotFoundComponent} from './component-library/error-404-component/page-not-found.component';
import {APP_CONFIG, AppConfig} from './core/config/app-config';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class AssetDetailDialogDataService {

contractAgreementDetails(
contractAgreement: ContractAgreementCardMapped,
refreshCallback: () => void,
): AssetDetailDialogData {
const asset = contractAgreement.asset;

Expand All @@ -85,6 +86,7 @@ export class AssetDetailDialogDataService {
asset: contractAgreement.asset,
contractAgreement,
propertyGridGroups,
refreshCallback,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ import {ContractAgreementCardMapped} from '../../../routes/connector-ui/contract
import {PropertyGridGroup} from '../../property-grid/property-grid-group/property-grid-group';

export interface AssetDetailDialogData {
type:
| 'asset-details'
| 'data-offer'
| 'contract-agreement'
type: 'asset-details' | 'data-offer' | 'contract-agreement';
propertyGridGroups: PropertyGridGroup[];
asset: UiAssetMapped;
dataOffer?: DataOffer;
contractAgreement?: ContractAgreementCardMapped;
showDeleteButton?: boolean;
showEditButton?: boolean;
onAssetEditClick?: OnAssetEditClickFn;
refreshCallback?: () => void;
}

export type OnAssetEditClickFn = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
</mat-icon>
<mat-icon
*ngIf="data.type === 'contract-agreement'"
class="mat-card-avatar-icon">
class="mat-card-avatar-icon"
[class.text-warn]="data.contractAgreement?.terminationStatus === 'TERMINATED'">
{{
data.contractAgreement!!.direction === 'PROVIDING'
? 'upload'
: 'download'
? data.contractAgreement!!.isTerminated
? 'file_upload_off'
: 'file_upload'
: data.contractAgreement!!.isTerminated
? 'file_download_off'
: 'file_download'
}}
</mat-icon>
<contract-offer-icon
Expand Down Expand Up @@ -55,6 +60,47 @@
color="primary"
mode="indeterminate"></mat-progress-bar>

<!-- Termination notice -->
<div
*ngIf="data.contractAgreement?.isTerminated"
class="rounded-md bg-red-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg
class="h-5 w-5 text-red-400"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true">
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z"
clip-rule="evenodd" />
</svg>
</div>
<div class="flex flex-col ml-3 grow">
<div class="text-base text-red-800">
{{ data.contractAgreement!!.terminationInformation!!.reason }}
</div>
<div class="text-[0.9rem] text-red-700 mt-2">
{{ data.contractAgreement!!.terminationInformation!!.detail }}
</div>
<div class="text-xs text-red-700 mt-2">
<ago
[date]="
data.contractAgreement!!.terminationInformation!!.terminatedAt
"></ago>
· terminated by
{{
data.contractAgreement!!.terminationInformation?.terminatedBy ===
'SELF'
? 'you'
: 'the counter-party'
}}
</div>
</div>
</div>
</div>

<!-- Description -->
<markdown-description
class="pt-3"
Expand Down Expand Up @@ -95,9 +141,23 @@
</div>

<mat-dialog-actions>
<div class="w-full flex flex-row justify-end">
<div class="w-full flex flex-row justify-between">
<div class="flex gap-1 items-center">
<button
*ngIf="
data.type === 'contract-agreement' &&
!data.contractAgreement?.isTerminated
"
mat-raised-button
color="warn"
[disabled]="data.contractAgreement?.isTerminated ?? false"
(click)="onTerminateClick()">
Terminate
</button>
</div>

<div class="flex gap-1 items-center">
<button mat-button [mat-dialog-close]="null" [disabled]="loading">
<button mat-stroked-button [mat-dialog-close]="null" [disabled]="loading">
Close
</button>

Expand Down Expand Up @@ -139,10 +199,12 @@
</button>
</ng-container>

<!-- Contact Agreement Buttons -->
<button
*ngIf="
data.type === 'contract-agreement' &&
data.contractAgreement?.direction === 'CONSUMING'
data.contractAgreement?.direction === 'CONSUMING' &&
!data.contractAgreement?.isTerminated
"
mat-raised-button
color="primary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {EdcApiService} from '../../../core/services/api/edc-api.service';
import {ContractNegotiationService} from '../../../core/services/contract-negotiation.service';
import {UiAssetMapped} from '../../../core/services/models/ui-asset-mapped';
import {NotificationService} from '../../../core/services/notification.service';
import {ContractAgreementTerminationDialogData} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-termination-dialog/contract-agreement-termination-dialog-data';
import {ContractAgreementTerminationDialogResult} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-termination-dialog/contract-agreement-termination-dialog-result';
import {ContractAgreementTerminationDialogComponent} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-termination-dialog/contract-agreement-termination-dialog.component';
import {ContractAgreementTransferDialogData} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-transfer-dialog/contract-agreement-transfer-dialog-data';
import {ContractAgreementTransferDialogResult} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-transfer-dialog/contract-agreement-transfer-dialog-result';
import {ContractAgreementTransferDialogComponent} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-transfer-dialog/contract-agreement-transfer-dialog.component';
import {
ConfirmDialogModel,
Expand Down Expand Up @@ -108,9 +112,40 @@ export class AssetDetailDialogComponent implements OnDestroy {
contractId: this.data.contractAgreement?.contractAgreementId!!,
asset: this.data.asset,
};
this.matDialog.open(ContractAgreementTransferDialogComponent, {
const ref = this.matDialog.open(ContractAgreementTransferDialogComponent, {
data,
});

ref
.afterClosed()
.subscribe(
(result: ContractAgreementTransferDialogResult | undefined) => {
if (result) {
this.data.refreshCallback?.();
}
},
);
}

onTerminateClick() {
const data: ContractAgreementTerminationDialogData = {
contractId: this.data.contractAgreement?.contractAgreementId!!,
asset: this.data.asset,
};
const ref = this.matDialog.open(
ContractAgreementTerminationDialogComponent,
{data},
);

ref
.afterClosed()
.subscribe(
(result: ContractAgreementTerminationDialogResult | undefined) => {
if (result) {
this.data.refreshCallback?.();
}
},
);
}

private confirmDelete(): Observable<boolean> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import {UiPolicy} from '@sovity.de/edc-client';
import {ActiveFeatureSet} from '../../../core/config/active-feature-set';
import {UiAssetMapped} from '../../../core/services/models/ui-asset-mapped';
import {ParticipantIdLocalization} from '../../../core/services/participant-id-localization';
import {
ContractAgreementCardMapped
} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-cards/contract-agreement-card-mapped';
import {ContractAgreementCardMapped} from '../../../routes/connector-ui/contract-agreement-page/contract-agreement-cards/contract-agreement-card-mapped';
import {PropertyGridGroup} from '../../property-grid/property-grid-group/property-grid-group';
import {PropertyGridField} from '../../property-grid/property-grid/property-grid-field';
import {PropertyGridFieldService} from '../../property-grid/property-grid/property-grid-field.service';
Expand Down
4 changes: 1 addition & 3 deletions src/app/component-library/catalog/catalog.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {MatIconModule} from '@angular/material/icon';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatTooltipModule} from '@angular/material/tooltip';
import {
InitiateNegotiationConfirmTosDialogModule
} from '../initiate-negotiation-confirm-tos-dialog/initiate-negotiation-confirm-tos-dialog.module';
import {InitiateNegotiationConfirmTosDialogModule} from '../initiate-negotiation-confirm-tos-dialog/initiate-negotiation-confirm-tos-dialog.module';
import {JsonDialogModule} from '../json-dialog/json-dialog.module';
import {PipesAndDirectivesModule} from '../pipes-and-directives/pipes-and-directives.module';
import {PropertyGridModule} from '../property-grid/property-grid.module';
Expand Down
7 changes: 4 additions & 3 deletions src/app/component-library/ui-elements/ago/ago.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {Component, Input} from '@angular/core';
*/
@Component({
selector: 'ago',
template: `<span [title]="date | date : 'EEEE yyyy-MM-dd hh:mm'">{{
date | ago | async
}}</span>`,
template: `<span
[matTooltip]="(date | date : 'EEEE yyyy-MM-dd hh:mm') ?? ''"
>{{ date | ago | async }}</span
>`,
})
export class AgoComponent {
@Input()
Expand Down
2 changes: 2 additions & 0 deletions src/app/component-library/ui-elements/ui-elements.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
import {MatIconModule} from '@angular/material/icon';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatTooltipModule} from '@angular/material/tooltip';
import {AgoComponent} from './ago/ago.component';
import {AgoPipe} from './ago/ago.pipe';
import {DateComponent} from './date/date.component';
Expand All @@ -18,6 +19,7 @@ import {LoadingStateComponent} from './loading-state/loading-state.component';
// Angular Material
MatIconModule,
MatProgressSpinnerModule,
MatTooltipModule,
],
declarations: [
AgoComponent,
Expand Down
42 changes: 40 additions & 2 deletions src/app/core/services/api/edc-api.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import {Inject, Injectable} from '@angular/core';
import {Observable, from} from 'rxjs';
import {map} from 'rxjs/operators';
import {
AssetPage,
ConnectorLimits,
ContractAgreementCard,
ContractAgreementPage,
ContractDefinitionPage,
ContractDefinitionRequest,
ContractNegotiationRequest,
DashboardPage,
EdcClient,
GetContractAgreementPageRequest,
IdResponseDto,
InitiateCustomTransferRequest,
InitiateTransferRequest,
PolicyDefinitionCreateRequest,
PolicyDefinitionPage,
TerminateContractAgreementRequest,
TransferHistoryPage,
UiAsset,
UiAssetCreateRequest,
Expand All @@ -23,6 +27,7 @@ import {
buildEdcClient,
} from '@sovity.de/edc-client';
import {APP_CONFIG, AppConfig} from '../../config/app-config';
import {throwIfNull} from '../../utils/rxjs-utils';
import {EDC_FAKE_BACKEND} from './fake-backend/edc-fake-backend';

@Injectable({providedIn: 'root'})
Expand Down Expand Up @@ -127,6 +132,16 @@ export class EdcApiService {
);
}

terminateContractAgreement(
terminateContractAgreementRequest: TerminateContractAgreementRequest,
): Observable<IdResponseDto> {
return from(
this.edcClient.uiApi.terminateContractAgreement(
terminateContractAgreementRequest,
),
);
}

getContractNegotiation(
contractNegotiationId: string,
): Observable<UiContractNegotiation> {
Expand All @@ -135,8 +150,31 @@ export class EdcApiService {
);
}

getContractAgreementPage(): Observable<ContractAgreementPage> {
return from(this.edcClient.uiApi.getContractAgreementPage());
getContractAgreementPage(
getContractAgreementPageRequest: GetContractAgreementPageRequest,
): Observable<ContractAgreementPage> {
return from(
this.edcClient.uiApi.getContractAgreementPage(
getContractAgreementPageRequest,
),
);
}

getContractAgreementById(
contractAgreementId: string,
): Observable<ContractAgreementCard> {
return this.getContractAgreementPage({
contractAgreementPageQuery: {terminationStatus: undefined},
}).pipe(
map((page) =>
page.contractAgreements.find(
(it) => it.contractAgreementId === contractAgreementId,
),
),
throwIfNull(
`Contract Agreement with ID ${contractAgreementId} not found`,
),
);
}

initiateTransfer(
Expand Down
Loading
Loading