diff --git a/package-lock.json b/package-lock.json index 0734d7b39..09b65765f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@ng-apimock/core": "^3.11.0", "@ngxs/store": "^3.8.1", "@sovity.de/broker-server-client": "0.20230712.71619-main-a4860cff", - "@sovity.de/edc-client": "0.20230810.82616-main-89593380", + "@sovity.de/edc-client": "0.20230829.91501-main-0b8664eb", "clean-deep": "^3.4.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", @@ -3598,9 +3598,9 @@ "integrity": "sha512-305vHJj38Ma9x9YADM3SJh3sdqePeLcrUB1hHlYsuPdx7wYe9vwgb503KYStJ+5iN/ojP2xu8k6Unt+y+Bu5iQ==" }, "node_modules/@sovity.de/edc-client": { - "version": "0.20230810.82616-main-89593380", - "resolved": "https://registry.npmjs.org/@sovity.de/edc-client/-/edc-client-0.20230810.82616-main-89593380.tgz", - "integrity": "sha512-yRrEPYCv38H0ug/6Vc+bF0gVyCivQrV3cRMYvyVMh89VBJ+zof3QRE6R+yuu3GdJX/kQEuAoaxniA2BzSgSZTw==" + "version": "0.20230829.91501-main-0b8664eb", + "resolved": "https://registry.npmjs.org/@sovity.de/edc-client/-/edc-client-0.20230829.91501-main-0b8664eb.tgz", + "integrity": "sha512-lm2bPrf75KGBXPdjbkmySy+DO4A91leJR6Rl8ZgRH+Dq14mJfTaoDkBac8ZDBtogJJBkVrGTmBOmXoXJK0GhcA==" }, "node_modules/@tootallnate/once": { "version": "2.0.0", diff --git a/package.json b/package.json index 3813e994b..50c01a6f5 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@ng-apimock/core": "^3.11.0", "@ngxs/store": "^3.8.1", "@sovity.de/broker-server-client": "0.20230712.71619-main-a4860cff", - "@sovity.de/edc-client": "0.20230810.82616-main-89593380", + "@sovity.de/edc-client": "0.20230829.91501-main-0b8664eb", "clean-deep": "^3.4.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", diff --git a/src/app/core/services/api/edc-api.service.ts b/src/app/core/services/api/edc-api.service.ts index ef042bafe..07cf64f23 100644 --- a/src/app/core/services/api/edc-api.service.ts +++ b/src/app/core/services/api/edc-api.service.ts @@ -6,6 +6,7 @@ import { ConnectorLimits, ContractAgreementPage, ContractAgreementTransferRequest, + ContractDefinitionPage, EdcClient, IdResponse, IdResponseDto, @@ -13,8 +14,9 @@ import { buildEdcClient, } from '@sovity.de/edc-client'; import {AssetCreateRequest} from '@sovity.de/edc-client/dist/generated/models/AssetCreateRequest'; +import {ContractDefinitionRequest} from '@sovity.de/edc-client/dist/generated/models/ContractDefinitionRequest'; import {APP_CONFIG, AppConfig} from '../../config/app-config'; -import {EDC_FAKE_BACKEND} from './fake-backend/edc-api.fake-backend'; +import {EDC_FAKE_BACKEND} from './fake-backend/edc-fake-backend'; @Injectable({providedIn: 'root'}) export class EdcApiService { @@ -44,6 +46,28 @@ export class EdcApiService { return from(this.edcClient.uiApi.deleteAsset({assetId})); } + createContractDefinition( + contractDefinitionRequest: ContractDefinitionRequest, + ): Observable { + return from( + this.edcClient.uiApi.createContractDefinition({ + contractDefinitionRequest, + }), + ); + } + + getContractDefinitionPage(): Observable { + return from(this.edcClient.uiApi.contractDefinitionPage()); + } + + deleteContractDefinition( + contractDefinitionId: string, + ): Observable { + return from( + this.edcClient.uiApi.deleteContractDefinition({contractDefinitionId}), + ); + } + getContractAgreementPage(): Observable { return from(this.edcClient.uiApi.contractAgreementEndpoint()); } diff --git a/src/app/core/services/api/fake-backend/contract-definition-fake-service.ts b/src/app/core/services/api/fake-backend/contract-definition-fake-service.ts new file mode 100644 index 000000000..1aee2f701 --- /dev/null +++ b/src/app/core/services/api/fake-backend/contract-definition-fake-service.ts @@ -0,0 +1,53 @@ +import { + ContractDefinitionEntry, + ContractDefinitionPage, + IdResponseDto, +} from '@sovity.de/edc-client'; +import {ContractDefinitionRequest} from '@sovity.de/edc-client/dist/generated/models/ContractDefinitionRequest'; +import {AssetProperties} from '../../asset-properties'; + +export let contractDefinitions: ContractDefinitionEntry[] = [ + { + contractDefinitionId: 'test-contract-definition-1', + contractPolicyId: 'test-policy-definition-1', + accessPolicyId: 'test-policy-definition-1', + assetSelector: [ + { + operandLeft: AssetProperties.id, + operator: 'EQ', + operandRight: {type: 'VALUE', value: 'test-asset-1'}, + }, + ], + }, +]; + +export const contractDefinitionPage = (): ContractDefinitionPage => { + return { + contractDefinitions, + }; +}; + +export const createContractDefinition = ( + request: ContractDefinitionRequest, +): IdResponseDto => { + let newEntry: ContractDefinitionEntry = { + contractDefinitionId: request.contractDefinitionId!, + contractPolicyId: request.contractPolicyId!, + accessPolicyId: request.accessPolicyId!, + assetSelector: request.assetSelector!, + }; + + contractDefinitions = [newEntry, ...contractDefinitions]; + + return { + id: newEntry.contractDefinitionId, + lastUpdatedDate: new Date(), + }; +}; + +export const deleteContractDefinition = (id: string): IdResponseDto => { + contractDefinitions = contractDefinitions.filter( + (it) => it.contractDefinitionId !== id, + ); + return {id, lastUpdatedDate: new Date()}; +}; diff --git a/src/app/core/services/api/fake-backend/edc-api.fake-backend.ts b/src/app/core/services/api/fake-backend/edc-fake-backend.ts similarity index 60% rename from src/app/core/services/api/fake-backend/edc-api.fake-backend.ts rename to src/app/core/services/api/fake-backend/edc-fake-backend.ts index a9df4bcd7..563e66693 100644 --- a/src/app/core/services/api/fake-backend/edc-api.fake-backend.ts +++ b/src/app/core/services/api/fake-backend/edc-fake-backend.ts @@ -1,6 +1,12 @@ import {FetchAPI} from '@sovity.de/edc-client'; import {AssetCreateRequest} from '@sovity.de/edc-client/dist/generated/models/AssetCreateRequest'; +import {ContractDefinitionRequest} from '@sovity.de/edc-client/dist/generated/models/ContractDefinitionRequest'; import {assetPage, createAsset, deleteAsset} from './asset-fake-service'; +import { + contractDefinitionPage, + createContractDefinition, + deleteContractDefinition, +} from './contract-definition-fake-service'; import {getBody, getMethod, getUrl} from './utils/request-utils'; import {ok} from './utils/response-utils'; import {UrlInterceptor} from './utils/url-interceptor'; @@ -26,5 +32,18 @@ export const EDC_FAKE_BACKEND: FetchAPI = async ( .url('pages/asset-page/assets/*') .on('DELETE', (assetId) => ok(deleteAsset(assetId))) + .url('pages/contract-definition-page') + .on('GET', () => ok(contractDefinitionPage())) + + .url('pages/contract-definition-page/contract-definitions') + .on('POST', () => + ok(createContractDefinition(body as ContractDefinitionRequest)), + ) + + .url('pages/contract-definition-page/contract-definitions/*') + .on('DELETE', (contractDefinitionId) => + ok(deleteContractDefinition(contractDefinitionId)), + ) + .tryMatch(); }; diff --git a/src/app/core/services/contract-definition-builder.ts b/src/app/core/services/contract-definition-builder.ts index e2fff2bf5..9f2f9d2ec 100644 --- a/src/app/core/services/contract-definition-builder.ts +++ b/src/app/core/services/contract-definition-builder.ts @@ -1,4 +1,6 @@ import {Injectable} from '@angular/core'; +import {UiCriterionLiteralDtoTypeEnum} from '@sovity.de/edc-client'; +import {ContractDefinitionRequest} from '@sovity.de/edc-client/dist/generated/models/ContractDefinitionRequest'; import {ContractDefinitionEditorDialogFormValue} from '../../routes/connector-ui/contract-definition-page/contract-definition-editor-dialog/contract-definition-editor-dialog-form-model'; import { ContractDefinitionDto, @@ -18,16 +20,19 @@ export class ContractDefinitionBuilder { */ buildContractDefinition( formValue: ContractDefinitionEditorDialogFormValue, - ): ContractDefinitionDto { + ): ContractDefinitionRequest { return { - id: formValue.id!.trim(), + contractDefinitionId: formValue.id ?? '', accessPolicyId: policyDefinitionId(formValue.accessPolicy!), contractPolicyId: policyDefinitionId(formValue.contractPolicy!), - criteria: [ + assetSelector: [ { operandLeft: AssetProperties.id, - operator: 'in', - operandRight: formValue.assets!.map((it) => it.id), + operator: 'IN', + operandRight: { + type: UiCriterionLiteralDtoTypeEnum.ValueList, + valueList: formValue.assets!.map((it) => it.id), + }, }, ], }; diff --git a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card-builder.ts b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card-builder.ts index 2ddb7101f..9f11b7763 100644 --- a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card-builder.ts +++ b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card-builder.ts @@ -1,7 +1,10 @@ import {Injectable} from '@angular/core'; import { - ContractDefinitionDto, - Criterion, + ContractDefinitionEntry, + ContractDefinitionPage, + UiCriterionDto, +} from '@sovity.de/edc-client'; +import { PolicyDefinition, policyDefinitionId, } from '../../../../core/services/api/legacy-managent-api-client'; @@ -22,7 +25,7 @@ import { @Injectable({providedIn: 'root'}) export class ContractDefinitionCardBuilder { buildContractDefinitionCards( - contractDefinitions: ContractDefinitionDto[], + contractDefinitionPage: ContractDefinitionPage, assets: Asset[], policyDefinitions: PolicyDefinition[], ): ContractDefinitionCard[] { @@ -32,22 +35,23 @@ export class ContractDefinitionCardBuilder { policyDefinitionId, ); - return contractDefinitions.map((contractDefinition) => - this.buildContractDefinitionCard( - contractDefinition, - assetById, - policyDefinitionById, - ), + return contractDefinitionPage.contractDefinitions.map( + (contractDefinition) => + this.buildContractDefinitionCard( + contractDefinition, + assetById, + policyDefinitionById, + ), ); } buildContractDefinitionCard( - contractDefinition: ContractDefinitionDto, + contractDefinition: ContractDefinitionEntry, assetById: Map, policyDefinitionById: Map, ): ContractDefinitionCard { return { - id: contractDefinition.id, + id: contractDefinition.contractDefinitionId, contractPolicy: this.extractPolicy( contractDefinition.contractPolicyId, policyDefinitionById, @@ -57,7 +61,7 @@ export class ContractDefinitionCardBuilder { policyDefinitionById, ), - criteria: contractDefinition.criteria.map((criterion) => ({ + criteria: contractDefinition.assetSelector.map((criterion) => ({ label: this.extractCriterionOperation(criterion), values: this.extractCriterionValues(criterion, assetById), })), @@ -75,59 +79,54 @@ export class ContractDefinitionCardBuilder { }; } - private extractCriterionOperation(criterion: Criterion): string { - const {operandLeft} = criterion; + private extractCriterionOperation(criterion: UiCriterionDto): string { + const {operandLeft, operator} = criterion; if ( - operandLeft.toLowerCase() === AssetProperties.id && - (criterion.operator.toUpperCase() === 'EQ' || - criterion.operator.toUpperCase() === 'IN') + operandLeft.toLowerCase() === AssetProperties.id.toLowerCase() && + (operator === 'EQ' || operator === 'IN') ) { return 'Assets'; } - let operator = - OperatorSymbols[criterion.operator as Operator] ?? criterion.operator; - return `${operandLeft} ${operator}`; + let operatorStr = OperatorSymbols[operator as Operator] ?? operator; + return `${operandLeft} ${operatorStr}`; } private extractCriterionValues( - criterion: Criterion, + criterion: UiCriterionDto, assetsById: Map, ): ContractDefinitionCardCriterionValue[] { let {operandLeft, operandRight} = criterion; - let values: (object | string)[] = []; - if (Array.isArray(operandRight)) { - values = operandRight as string[]; + let values: string[] = []; + if (operandRight.type === 'VALUE_LIST') { + values = operandRight.valueList ?? []; } else { - values = [operandRight]; + values = [operandRight.value!!]; } return values.map((it) => { - if (typeof it === 'string') { - const stringType: ContractDefinitionCardCriterionValue = { - type: 'string', - value: it, - searchTargets: [it], - }; + const stringType: ContractDefinitionCardCriterionValue = { + type: 'string', + value: it, + searchTargets: [it], + }; - // Try to find asset - if (operandLeft === AssetProperties.id) { - let asset = assetsById.get(it); - if (asset) { - return { - type: 'asset', - asset, - searchTargets: assetSearchTargets(asset), - }; - } + // Try to find asset + if (operandLeft === AssetProperties.id) { + let asset = assetsById.get(it); + if (asset) { + return { + type: 'asset', + asset, + searchTargets: assetSearchTargets(asset), + }; } return stringType; } - // fall back to JSON for generic objects - return {type: 'json', json: it, searchTargets: [JSON.stringify(it)]}; + return stringType; }); } } diff --git a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card.ts b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card.ts index 56fffe318..80a73f8ad 100644 --- a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card.ts +++ b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-card.ts @@ -1,7 +1,5 @@ -import { - ContractDefinitionDto, - PolicyDefinition, -} from '../../../../core/services/api/legacy-managent-api-client'; +import {ContractDefinitionEntry} from '@sovity.de/edc-client'; +import {PolicyDefinition} from '../../../../core/services/api/legacy-managent-api-client'; import {Asset} from '../../../../core/services/models/asset'; export interface ContractDefinitionCard { @@ -10,7 +8,7 @@ export interface ContractDefinitionCard { contractPolicy: ContractDefinitionCardPolicy; accessPolicy: ContractDefinitionCardPolicy; - detailJsonObj: ContractDefinitionDto; + detailJsonObj: ContractDefinitionEntry; } export interface ContractDefinitionCardPolicy { diff --git a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-cards.component.ts b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-cards.component.ts index 11d31fff6..b0cb0d088 100644 --- a/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-cards.component.ts +++ b/src/app/routes/connector-ui/contract-definition-page/contract-definition-cards/contract-definition-cards.component.ts @@ -14,8 +14,8 @@ import {AssetDetailDialogService} from '../../../../component-library/catalog/as import {ConfirmDialogModel} from '../../../../component-library/confirmation-dialog/confirmation-dialog/confirmation-dialog.component'; import {JsonDialogComponent} from '../../../../component-library/json-dialog/json-dialog/json-dialog.component'; import {JsonDialogData} from '../../../../component-library/json-dialog/json-dialog/json-dialog.data'; +import {EdcApiService} from '../../../../core/services/api/edc-api.service'; import { - ContractDefinitionService, PolicyDefinition, policyDefinitionId, } from '../../../../core/services/api/legacy-managent-api-client'; @@ -43,10 +43,10 @@ export class ContractDefinitionCardsComponent implements OnDestroy { deleteDone = new EventEmitter(); constructor( + private edcApiService: EdcApiService, private assetDetailDialogDataService: AssetDetailDialogDataService, private assetDetailDialogService: AssetDetailDialogService, private matDialog: MatDialog, - private contractDefinitionService: ContractDefinitionService, private notificationService: NotificationService, ) {} @@ -83,7 +83,7 @@ export class ContractDefinitionCardsComponent implements OnDestroy { card.id, ), action: () => - this.contractDefinitionService.deleteContractDefinition(card.id).pipe( + this.edcApiService.deleteContractDefinition(card.id).pipe( tap(() => { this.notificationService.showInfo('Contract Definition deleted!'); this.deleteDone.emit(); diff --git a/src/app/routes/connector-ui/contract-definition-page/contract-definition-editor-dialog/contract-definition-editor-dialog.component.ts b/src/app/routes/connector-ui/contract-definition-page/contract-definition-editor-dialog/contract-definition-editor-dialog.component.ts index b16356ea9..25f98cd3b 100644 --- a/src/app/routes/connector-ui/contract-definition-page/contract-definition-editor-dialog/contract-definition-editor-dialog.component.ts +++ b/src/app/routes/connector-ui/contract-definition-page/contract-definition-editor-dialog/contract-definition-editor-dialog.component.ts @@ -2,8 +2,8 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; import {Subject} from 'rxjs'; import {finalize, takeUntil} from 'rxjs/operators'; +import {EdcApiService} from '../../../../core/services/api/edc-api.service'; import { - ContractDefinitionService, PolicyDefinition, PolicyService, } from '../../../../core/services/api/legacy-managent-api-client'; @@ -31,7 +31,7 @@ export class ContractDefinitionEditorDialog implements OnInit, OnDestroy { public form: ContractDefinitionEditorDialogForm, private notificationService: NotificationService, private policyService: PolicyService, - private contractDefinitionService: ContractDefinitionService, + private edcApiService: EdcApiService, private contractDefinitionBuilder: ContractDefinitionBuilder, private dialogRef: MatDialogRef, public validationMessages: ValidationMessages, @@ -56,9 +56,8 @@ export class ContractDefinitionEditorDialog implements OnInit, OnDestroy { const formValue = this.form.value; const contractDefinition = this.contractDefinitionBuilder.buildContractDefinition(formValue); - this.form.group.disable(); this.loading = true; - this.contractDefinitionService + this.edcApiService .createContractDefinition(contractDefinition) .pipe( takeUntil(this.ngOnDestroy$), diff --git a/src/app/routes/connector-ui/contract-definition-page/contract-definition-page/contract-definition-page.service.ts b/src/app/routes/connector-ui/contract-definition-page/contract-definition-page/contract-definition-page.service.ts index d8c295725..f6a70e496 100644 --- a/src/app/routes/connector-ui/contract-definition-page/contract-definition-page/contract-definition-page.service.ts +++ b/src/app/routes/connector-ui/contract-definition-page/contract-definition-page/contract-definition-page.service.ts @@ -1,10 +1,8 @@ import {Injectable} from '@angular/core'; import {Observable, combineLatest, of} from 'rxjs'; import {catchError, map, switchMap} from 'rxjs/operators'; -import { - ContractDefinitionService, - PolicyService, -} from '../../../../core/services/api/legacy-managent-api-client'; +import {EdcApiService} from '../../../../core/services/api/edc-api.service'; +import {PolicyService} from '../../../../core/services/api/legacy-managent-api-client'; import {AssetServiceMapped} from '../../../../core/services/asset-service-mapped'; import {Fetched} from '../../../../core/services/models/fetched'; import {search} from '../../../../core/utils/search-utils'; @@ -19,7 +17,7 @@ export interface ContractDefinitionList { @Injectable({providedIn: 'root'}) export class ContractDefinitionPageService { constructor( - private contractDefinitionService: ContractDefinitionService, + private edcApiService: EdcApiService, private assetServiceMapped: AssetServiceMapped, private policyService: PolicyService, private contractDefinitionCardBuilder: ContractDefinitionCardBuilder, @@ -56,10 +54,10 @@ export class ContractDefinitionPageService { .flatMap((it) => it.searchTargets), ]); } - + //ed fetchCards(): Observable> { return combineLatest([ - this.contractDefinitionService.getAllContractDefinitions(0, 10_000_000), + this.edcApiService.getContractDefinitionPage(), this.assetServiceMapped.fetchAssets().pipe( catchError((err) => { console.warn('Failed fetching assets.', err);