diff --git a/.env.local-dev b/.env.local-dev index 131d53dd2..6488ca524 100644 --- a/.env.local-dev +++ b/.env.local-dev @@ -3,20 +3,8 @@ EDC_UI_ACTIVE_PROFILE=sovity-open-source EDC_UI_USE_FAKE_BACKEND=true -EDC_UI_DATA_MANAGEMENT_API_URL=http://edc.fake-backend +EDC_UI_MANAGEMENT_API_URL=http://edc.fake-backend EDC_UI_DATA_MANAGEMENT_API_KEY=no-api-key-required-in-local-dev EDC_UI_CATALOG_URLS=http://existing-other-connector/api/dsp,http://does-not-exist-but-is-super-long-so-we-can-test/api/dsp, http://how-wrapping-works-in-subtext-of-catalog-url-select/api/dsp EDC_UI_LOGOUT_URL=https://example.com/logout EDC_UI_CONNECTOR_ENDPOINT=http://localhost:3000/api/dsp - -EDC_UI_CONNECTOR_ID=https://localhost:3000 -EDC_UI_CONNECTOR_NAME=example-connector-name -EDC_UI_IDS_ID=urn:connector:example -EDC_UI_IDS_TITLE=Example Connector Title -EDC_UI_IDS_DESCRIPTION=This is an example sovity EDC UI in local dev. -EDC_UI_CURATOR_URL=https://example.com -EDC_UI_CURATOR_ORGANIZATION_NAME=Example GmbH -EDC_UI_DAPS_OAUTH_TOKEN_URL=https://example-daps.com/token -EDC_UI_DAPS_OAUTH_JWKS_URL=https://example-daps.com/jwks.json -EDC_UI_MAINTAINER_URL=https://example.com -EDC_UI_MAINTAINER_ORGANIZATION_NAME=Example GmbH diff --git a/CHANGELOG.md b/CHANGELOG.md index 88fbc09ae..3a17f81c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,25 +14,30 @@ the detailed section referring to by linking pull requests or issues. ### Detailed Changes -#### Added +#### Major + +- Switched to semantic versioning +- Migrated transfer history page to the api wrapper +- Migrated contract definition page to the api wrapper +- Migrated policy definition page to the api wrapper +- Migrated asset page to the api wrapper +- Migrated dashboard page to the api wrapper + +#### Minor - Added custom 404 pages to connector and broker ui +- New Asset Property "Participant ID" -#### Fixed +#### Patch - Removed 404-causing login polling from broker UI -- Migrated transfer history page to api wrapper -- Migrated contract definition page to api wrapper -- Migrated policy definition page to api wrapper -- Migrated asset page to api wrapper -- Broker: Fixed popularity not logged when clicking on a data offer. +- Renamed button from cancel to close in json-dialogs +- Broker: Fixed popularity not logged when clicking on a data offer - Broker: Fixed missing name in legal notice -#### Removed - -#### Fixed +#### Deployment Migration Notes -- Renamed button from cancel to close in json-dialogs +Removed Env Vars: ## [v0.0.1-milestone-8-sovity12] 12.07.2023 @@ -191,7 +196,7 @@ information is now displayed. #### Changed -- Marked `EDC_UI_DATA_MANAGEMENT_API_URL` as deprecated in favor of +- Marked `EDC_UI_MANAGEMENT_API_URL` as deprecated in favor of `EDC_UI_MANAGEMENT_API_URL`. - Marked `EDC_UI_DATA_MANAGEMENT_API_KEY` as deprecated in favor of `EDC_UI_MANAGEMENT_API_KEY`. diff --git a/package-lock.json b/package-lock.json index 41af9af3c..5c61d9ad7 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.20230926.151824-main-fdf8eb66", + "@sovity.de/edc-client": "0.20231006.85703-main-5ece112d", "clean-deep": "^3.4.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", @@ -3736,9 +3736,9 @@ "integrity": "sha512-305vHJj38Ma9x9YADM3SJh3sdqePeLcrUB1hHlYsuPdx7wYe9vwgb503KYStJ+5iN/ojP2xu8k6Unt+y+Bu5iQ==" }, "node_modules/@sovity.de/edc-client": { - "version": "0.20230926.151824-main-fdf8eb66", - "resolved": "https://registry.npmjs.org/@sovity.de/edc-client/-/edc-client-0.20230926.151824-main-fdf8eb66.tgz", - "integrity": "sha512-R6MOZaOda/alASVOKu8SySr0jGGB7hbWpQc1nbti7frJAEpyEJBgcZfibgiFnN6pqNJ1rITxblfbArY1kVNOMg==" + "version": "0.20231006.85703-main-5ece112d", + "resolved": "https://registry.npmjs.org/@sovity.de/edc-client/-/edc-client-0.20231006.85703-main-5ece112d.tgz", + "integrity": "sha512-lNokVrsn4t0HABxw761s/5SBvHXTTvuTHGNyP/wtxiTrNcrV9epfVFymIglWbqug9p8pp6nbaKzj1TU+G09vnw==" }, "node_modules/@tootallnate/once": { "version": "2.0.0", @@ -10404,9 +10404,9 @@ } }, "node_modules/postcss": { - "version": "8.4.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", - "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 67b41953b..77dcef82f 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.20230926.151824-main-fdf8eb66", + "@sovity.de/edc-client": "0.20231006.85703-main-5ece112d", "clean-deep": "^3.4.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", diff --git a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog-data.service.ts b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog-data.service.ts index d41b55cf2..888cccc28 100644 --- a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog-data.service.ts +++ b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog-data.service.ts @@ -52,7 +52,7 @@ export class AssetDetailDialogDataService { ), this.assetPropertyGridGroupBuilder.buildContractPolicyGroup( contractAgreement.contractPolicy, - asset.name, + asset.title, ), this.assetPropertyGridGroupBuilder.buildAssetPropertiesGroup( asset, diff --git a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.html b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.html index 202462b23..59191dce7 100644 --- a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.html +++ b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.html @@ -19,7 +19,7 @@ [dataOffer]="data.dataOffer!">
- {{ asset.name }} + {{ asset.title }}
{{ asset.creatorOrganizationName }} diff --git a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.ts b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.ts index 0d6e96b51..207015f74 100644 --- a/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.ts +++ b/src/app/component-library/catalog/asset-detail-dialog/asset-detail-dialog.component.ts @@ -110,7 +110,7 @@ export class AssetDetailDialogComponent implements OnDestroy { private confirmDelete(): Observable { const dialogData = ConfirmDialogModel.forDelete( 'asset', - `"${this.asset.name}"`, + `"${this.asset.title}"`, ); const ref = this.matDialog.open(ConfirmationDialogComponent, { maxWidth: '20%', diff --git a/src/app/component-library/catalog/asset-detail-dialog/asset-property-grid-group-builder.ts b/src/app/component-library/catalog/asset-detail-dialog/asset-property-grid-group-builder.ts index 46103016b..bb2b707f3 100644 --- a/src/app/component-library/catalog/asset-detail-dialog/asset-property-grid-group-builder.ts +++ b/src/app/component-library/catalog/asset-detail-dialog/asset-property-grid-group-builder.ts @@ -66,6 +66,11 @@ export class AssetPropertyGridGroupBuilder { label: 'Organization', ...this.propertyGridUtils.guessValue(asset.creatorOrganizationName), }, + { + icon: 'category', + label: 'Participant ID', + ...this.propertyGridUtils.guessValue(asset.participantId), + }, { icon: 'category', label: 'Content Type', @@ -162,7 +167,7 @@ export class AssetPropertyGridGroupBuilder { onclick: () => this.jsonDialogService.showJsonDetailDialog({ title: `${groupLabel} Contract Policy)`, - subtitle: asset.name, + subtitle: asset.title, icon: 'policy', objectForJson: JSON.parse( contractOffer.contractPolicy.legacyPolicy ?? 'null', diff --git a/src/app/component-library/catalog/contract-offer-mini-list/contract-offer-mini-list.component.html b/src/app/component-library/catalog/contract-offer-mini-list/contract-offer-mini-list.component.html index 8f0a64066..ae6dc6557 100644 --- a/src/app/component-library/catalog/contract-offer-mini-list/contract-offer-mini-list.component.html +++ b/src/app/component-library/catalog/contract-offer-mini-list/contract-offer-mini-list.component.html @@ -23,7 +23,9 @@ [columns]="3" [props]="contractOffer.properties"> -
+
diff --git a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.service.ts b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.service.ts index 77e7366c3..2ade48133 100644 --- a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.service.ts +++ b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.service.ts @@ -1,7 +1,7 @@ import {Injectable} from '@angular/core'; import {Observable, combineLatest, merge, of, sampleTime, scan} from 'rxjs'; import {catchError, map} from 'rxjs/operators'; -import {TransferHistoryEntry, UiDataOffer} from '@sovity.de/edc-client'; +import {DashboardTransferAmounts, UiDataOffer} from '@sovity.de/edc-client'; import {EdcApiService} from '../../../../core/services/api/edc-api.service'; import {LastCommitInfoService} from '../../../../core/services/api/last-commit-info.service'; import {ConnectorInfoPropertyGridGroupBuilder} from '../../../../core/services/connector-info-property-grid-group-builder'; @@ -27,14 +27,9 @@ export class DashboardPageDataService { // Dashboard is built from different API calls const sources: Observable>[] = [ - this.assetKpis(), this.catalogBrowserKpis(), - this.contractAgreementKpis(), - this.contractDefinitionKpis(), this.numCatalogs(), - this.policyKpis(), - this.transferProcessKpis(), - this.connectorProperties(), + this.dashboardData(), ]; // We merge all results as they come in, constructing our DashboardData @@ -44,34 +39,6 @@ export class DashboardPageDataService { ); } - private policyKpis(): Observable> { - return this.edcApiService.getPolicyDefinitionPage().pipe( - map((policyDefinitionPage) => policyDefinitionPage.policies.length), - Fetched.wrap({failureMessage: 'Failed fetching number of policies.'}), - map((numPolicies) => ({numPolicies})), - ); - } - - private contractDefinitionKpis(): Observable> { - return this.edcApiService.getContractDefinitionPage().pipe( - map((page) => page.contractDefinitions.length), - Fetched.wrap({ - failureMessage: 'Failed fetching number of contract definitions.', - }), - map((numContractDefinitions) => ({numContractDefinitions})), - ); - } - - private contractAgreementKpis(): Observable> { - return this.edcApiService.getContractAgreementPage().pipe( - map((page) => page.contractAgreements.length), - Fetched.wrap({ - failureMessage: 'Failed fetching contract agreements.', - }), - map((numContractAgreements) => ({numContractAgreements})), - ); - } - private catalogBrowserKpis(): Observable> { return this.getAllDataOffers().pipe( map((dataOffers) => dataOffers.length), @@ -97,16 +64,6 @@ export class DashboardPageDataService { ); } - private assetKpis(): Observable> { - return this.edcApiService.getAssetPage().pipe( - map((assetPage) => assetPage.assets.length), - Fetched.wrap({ - failureMessage: 'Failed fetching assets.', - }), - map((numAssets) => ({numAssets})), - ); - } - private numCatalogs(): Observable> { return of({ numCatalogs: Fetched.ready( @@ -115,71 +72,36 @@ export class DashboardPageDataService { }); } - private transferProcessKpis(): Observable> { - return this.edcApiService.getTransferHistoryPage().pipe( - Fetched.wrap({ - failureMessage: 'Failed fetching transfer processes.', - }), - map((transferData) => ({ - incomingTransfersChart: transferData.map((it) => - this.buildTransferChart(it.transferEntries, 'CONSUMING'), - ), - outgoingTransfersChart: transferData.map((it) => - this.buildTransferChart(it.transferEntries, 'PROVIDING'), - ), - })), - ); - } - private buildTransferChart( - transfers: TransferHistoryEntry[], + transfers: DashboardTransferAmounts, direction: 'CONSUMING' | 'PROVIDING', ): DonutChartData { - const filteredTransfers = - direction === 'CONSUMING' - ? transfers.filter((it) => it.direction === 'CONSUMING') - : transfers.filter((it) => it.direction === 'PROVIDING'); + const amounts: {label: string; amount: number; color: string}[] = [ + {label: 'Completed', amount: transfers.numOk, color: '#b2e061'}, + {label: 'In Progress', amount: transfers.numRunning, color: '#7eb0d5'}, + {label: 'Error', amount: transfers.numError, color: '#fd7f6f'}, + ].filter((it) => it.amount); - const states = [ - ...new Set( - filteredTransfers - .sort((a, b) => a.state.code - b.state.code) - .map((it) => it.state.name), - ), - ]; - - const colorsByState = new Map(); - colorsByState.set('IN_PROGRESS', '#7eb0d5'); - colorsByState.set('ERROR', '#fd7f6f'); - colorsByState.set('COMPLETED', '#b2e061'); - const defaultColor = '#bd7ebe'; - - const amountsByState = states.map( - (state) => - filteredTransfers.filter((it) => it.state.name === state).length, - ); + const total = transfers.numTotal; return { totalLabel: 'Total', - totalValue: filteredTransfers.length, - isEmpty: !filteredTransfers.length, + totalValue: total, + isEmpty: !total, emptyMessage: `No ${direction} transfer processes.`, - - labels: states, + labels: amounts.map((it) => it.label), datasets: [ { label: 'Number of Transfer Processes', - data: amountsByState, - backgroundColor: states.map( - (it) => colorsByState.get(it) ?? defaultColor, - ), + data: amounts.map((it) => it.amount), + backgroundColor: amounts.map((it) => it.color), }, ], options: {responsive: false}, }; } - private connectorProperties(): Observable> { + private dashboardData(): Observable> { return combineLatest([ this.lastCommitInfoService.getLastCommitInfoData().pipe( Fetched.wrap({ @@ -196,15 +118,55 @@ export class DashboardPageDataService { failureMessage: 'Failed fetching UI Last Commit Data', }), ), + this.edcApiService.getDashboardPage().pipe( + Fetched.wrap({ + failureMessage: 'Failed fetching Dashboard Page Data', + }), + ), ]).pipe( - map(([lastCommitInfo, uiBuildDate, uiCommitDetails]) => ({ + map(([lastCommitInfo, uiBuildDate, uiCommitDetails, fetched]) => ({ + title: this.extractString(fetched, (it) => it.connectorTitle), + description: this.extractString( + fetched, + (it) => it.connectorDescription, + ), + numAssets: fetched.map((it) => it.numAssets), + numPolicies: fetched.map((it) => it.numPolicies), + numContractDefinitions: fetched.map((it) => it.numContractDefinitions), + numContractAgreements: fetched.map( + (it) => + it.numContractAgreementsConsuming + + it.numContractAgreementsProviding, + ), + connectorEndpoint: this.extractString( + fetched, + (it) => it.connectorEndpoint, + ), + incomingTransfersChart: fetched.map((it) => + this.buildTransferChart(it.transferProcessesConsuming, 'CONSUMING'), + ), + outgoingTransfersChart: fetched.map((it) => + this.buildTransferChart(it.transferProcessesProviding, 'PROVIDING'), + ), connectorProperties: this.connectorInfoPropertyGridGroupBuilder.buildPropertyGridGroups( lastCommitInfo, uiBuildDate, uiCommitDetails, + fetched, ), })), ); } + + private extractString( + fetched: Fetched, + extractor: (item: T) => string, + ): string { + return fetched.match({ + ifLoading: () => 'Loading...', + ifError: () => 'Failed loading.', + ifOk: extractor, + }); + } } diff --git a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.ts b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.ts index 20cbbb2bc..6c9b849ad 100644 --- a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.ts +++ b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page-data.ts @@ -12,6 +12,9 @@ export interface DashboardPageData { numPolicies: Fetched; numCatalogs: Fetched; connectorProperties: PropertyGridGroup[]; + connectorEndpoint: string; + title: string; + description: string; } export function defaultDashboardData(): DashboardPageData { @@ -25,5 +28,8 @@ export function defaultDashboardData(): DashboardPageData { numContractDefinitions: Fetched.empty(), numCatalogs: Fetched.empty(), connectorProperties: [], + connectorEndpoint: 'Loading...', + title: 'Loading...', + description: 'Loading...', }; } diff --git a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.html b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.html index 98872e40a..18197718c 100644 --- a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.html +++ b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.html @@ -61,10 +61,10 @@ EDC Connector - {{ config.connectorIdsTitle }} + {{ data.title }} -

- {{ config.connectorIdsDescription }} +

+ {{ data.description }}

Share the following Connector Endpoint to let others access your EDC @@ -78,14 +78,14 @@ matInput ngDefaultControl readonly - [ngModel]="config.connectorEndpoint" + [ngModel]="data.connectorEndpoint" (focus)="input.select()" /> link diff --git a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.ts b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.ts index 33ab6d79d..4d68dd671 100644 --- a/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.ts +++ b/src/app/routes/connector-ui/dashboard-page/dashboard-page/dashboard-page.component.ts @@ -1,7 +1,6 @@ -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {Component, OnDestroy, OnInit} from '@angular/core'; import {BehaviorSubject, Subject} from 'rxjs'; import {switchMap, takeUntil} from 'rxjs/operators'; -import {APP_CONFIG, AppConfig} from '../../../../core/config/app-config'; import {ConnectorInfoPropertyGridGroupBuilder} from '../../../../core/services/connector-info-property-grid-group-builder'; import {DashboardPageData, defaultDashboardData} from './dashboard-page-data'; import {DashboardPageDataService} from './dashboard-page-data.service'; @@ -15,10 +14,7 @@ export class DashboardPageComponent implements OnInit, OnDestroy { data: DashboardPageData = defaultDashboardData(); private refresh$ = new BehaviorSubject(true); - constructor( - @Inject(APP_CONFIG) public config: AppConfig, - private dashboardDataService: DashboardPageDataService, - ) {} + constructor(private dashboardDataService: DashboardPageDataService) {} ngOnInit() { this.refresh$ diff --git a/src/app/routes/connector-ui/transfer-history-page/transfer-history-page/transfer-history-page.component.ts b/src/app/routes/connector-ui/transfer-history-page/transfer-history-page/transfer-history-page.component.ts index 3492d9b30..01966185b 100644 --- a/src/app/routes/connector-ui/transfer-history-page/transfer-history-page/transfer-history-page.component.ts +++ b/src/app/routes/connector-ui/transfer-history-page/transfer-history-page/transfer-history-page.component.ts @@ -65,14 +65,7 @@ export class TransferHistoryPageComponent implements OnInit, OnDestroy { loadAssetDetails(item: TransferHistoryEntry): Observable { return this.edcApiService .getTransferProcessAsset(item.transferProcessId) - .pipe( - map((asset: UiAsset) => { - return this.assetBuilder.buildAsset( - asset, - item.counterPartyConnectorEndpoint, - ); - }), - ); + .pipe(map((asset: UiAsset) => this.assetBuilder.buildAsset(asset))); } onAssetDetailsClick(item: TransferHistoryEntry) {