Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export class AssetCardComponent implements OnChanges {
ngOnChanges() {
this.name = this.asset?.properties.optionalValue('edc', 'name');
this.contentType = this.asset?.properties.optionalValue('edc', 'contenttype');
this.type = this.asset?.dataAddress.mandatoryValue('edc', 'type');
this.type = 'DataplaneMetadata';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ <h1 class="text-xl text-center divider m-0 2xl:col-span-2">Asset</h1>
</fieldset>

<fieldset class="fieldset w-lg bg-base-200 border border-base-300 p-4 rounded-box">
<legend class="fieldset-legend text-sm">Data Address</legend>
<legend class="fieldset-legend text-sm">Dataplane Metadata</legend>
<lib-data-address-form
[parentForm]="assetForm"
[dataAddress]="dataAddress"
(dataAddressChange)="dataAddress = $event"
></lib-data-address-form>
</fieldset>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,7 @@
*/

import { Component, EventEmitter, Input, OnChanges, Output, inject } from '@angular/core';
import {
Asset,
AssetInput,
BaseDataAddress,
compact,
DataAddress,
EdcConnectorClientError,
IdResponse,
} from '@think-it-labs/edc-connector-client';
import { Asset, compact, EdcConnectorClientError, IdResponse } from '@think-it-labs/edc-connector-client';
import { NgClass } from '@angular/common';
import { AssetService } from '../asset.service';
import {
Expand All @@ -34,6 +26,15 @@ import {
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { JsonValue } from '@angular-devkit/core';

type DataplaneMetadataFormValue = {
type?: string;
method?: string;
baseUrl?: string;
ttl?: number | string;
username?: string;
password?: string;
};

@Component({
selector: 'lib-asset-create',
standalone: true,
Expand Down Expand Up @@ -62,7 +63,6 @@ export class AssetCreateComponent implements OnChanges {

properties: Record<string, JsonValue> = {};
privateProperties: Record<string, JsonValue> = {};
dataAddress?: DataAddress;

assetForm: FormGroup;

Expand All @@ -85,15 +85,31 @@ export class AssetCreateComponent implements OnChanges {
private async updateAssetAndSyncForm() {
this.properties = await compact(this.asset!.properties);
this.privateProperties = await compact(this.asset!.privateProperties);
this.dataAddress = (await compact(this.asset!.dataAddress)) as unknown as BaseDataAddress;
this.assetForm.get('id')?.setValue(this.asset!.id);
this.assetForm.get('name')?.setValue(this.properties['name']);
this.assetForm.get('contenttype')?.setValue(this.properties['contenttype']);
this.assetForm.get('name')?.setValue(this.propertyValue('name'));
this.assetForm.get('contenttype')?.setValue(this.propertyValue('contenttype'));

setTimeout(async () => {
const dpm = await this.compactDataplaneMetadata();

if (dpm) {
this.assetForm.patchValue({
dataplaneMetadata: {
type: dpm['type'] || 'HttpData',
method: dpm['method'] || 'GET',
baseUrl: dpm['baseUrl'] || dpm['url'] || '',
ttl: dpm['ttl'] || 600,
username: dpm['auth.username'] || dpm['auth']?.['username'] || '',
password: dpm['auth.password'] || dpm['auth']?.['password'] || '',
},
});
}
});
}

createAsset(): void {
if (this.assetForm.valid) {
const assetInput: AssetInput = this.createAssetInput();
const assetInput = this.createAssetInput();
if (this.mode === 'create') {
this.assetService
.createAsset(assetInput)
Expand All @@ -114,21 +130,81 @@ export class AssetCreateComponent implements OnChanges {
}
}

private createAssetInput(): AssetInput {
const asset: AssetInput = {
dataAddress: this.dataAddress!,
properties: this.properties,
privateProperties: this.privateProperties,
private propertyValue(key: string): JsonValue | undefined {
const properties = this.properties as any;
const raw =
properties[key] ??
properties[`edc:${key}`] ??
properties[`asset:prop:${key}`] ??
properties[`https://w3id.org/edc/v0.0.1/ns/${key}`];

if (Array.isArray(raw) && raw.length === 1) {
return raw[0]?.['@value'] ?? raw[0]?.['@id'] ?? raw[0];
}

return raw?.['@value'] ?? raw?.['@id'] ?? raw;
}

private createAssetInput(): any {
const formValue = this.assetForm.getRawValue();
const dataplaneMetadata = this.createDataplaneMetadataProperties(
this.assetForm.get('dataplaneMetadata')?.value as DataplaneMetadataFormValue,
);

const asset: any = {
'@context': ['https://w3id.org/edc/connector/management/v2'],
'@type': 'Asset',
properties: {
...this.properties,
},
privateProperties: {
...this.privateProperties,
},
dataplaneMetadata: {
'@type': 'DataplaneMetadata',
properties: dataplaneMetadata,
},
};
if (this.assetForm.value.id) {
asset['@id'] = this.assetForm.value.id;

if (formValue.id) {
asset['@id'] = formValue.id;
}
if (this.assetForm.value.name) {
asset.properties['name'] = this.assetForm.value.name;
if (formValue.name) {
asset.properties['name'] = formValue.name;
}
if (this.assetForm.value.contenttype) {
asset.properties['contenttype'] = this.assetForm.value.contenttype;
if (formValue.contenttype) {
asset.properties['contenttype'] = formValue.contenttype;
}

return asset;
}
}

private createDataplaneMetadataProperties(dpm?: DataplaneMetadataFormValue): Record<string, JsonValue> {
const url = String(dpm?.baseUrl ?? '').trim();
const properties: Record<string, JsonValue> = {
type: dpm?.type || 'HttpData',
method: dpm?.method || 'GET',
url,
ttl: Number(dpm?.ttl ?? 600),
};

if (dpm?.username && dpm.password) {
properties['auth.type'] = 'basic';
properties['auth.username'] = dpm.username;
properties['auth.password'] = dpm.password;
}

return properties;
}

private async compactDataplaneMetadata(): Promise<any | undefined> {
const raw = (this.asset as any)?.dataplaneMetadata ?? (this.properties as any)?.dataplaneMetadata;
if (!raw) {
return undefined;
}

const compacted = await compact(raw);
return compacted?.properties?.['@value'] ?? compacted?.properties ?? raw?.properties?.['@value'] ?? raw?.properties;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class AssetViewComponent implements OnInit, OnDestroy {
asset.id.includes(searchText) ||
asset.properties.optionalValue<string>('edc', 'name')?.toLowerCase().includes(lower) ||
asset.properties.optionalValue<string>('edc', 'contenttype')?.toLowerCase().includes(lower) ||
asset.dataAddress.mandatoryValue<string>('edc', 'type').toLowerCase().includes(lower),
asset.properties.optionalValue<string>('edc', 'contenttype'),
),
),
);
Expand Down
143 changes: 122 additions & 21 deletions projects/dashboard-core/assets/src/asset.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
*/

import { Injectable, inject } from '@angular/core';
import { EdcClientService } from '@eclipse-edc/dashboard-core';
import { DashboardStateService, EdcClientService } from '@eclipse-edc/dashboard-core';
import { Asset, AssetInput, IdResponse } from '@think-it-labs/edc-connector-client';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';

/**
* Service to manage and retrieve assets.
Expand All @@ -23,40 +25,139 @@ import { Asset, AssetInput, IdResponse } from '@think-it-labs/edc-connector-clie
providedIn: 'root',
})
export class AssetService {
private readonly http = inject(HttpClient);
private readonly stateService = inject(DashboardStateService);
private readonly edc = inject(EdcClientService);

/**
* Retrieves all assets from the management API.
* @returns A promise that resolves to an array of assets.
*/
// public async getAllAssets(): Promise<Asset[]> {
// const assets = await firstValueFrom(
// this.http.post<any[]>(await this.assetEndpoint('/request'), { '@type': 'QuerySpec' }, await this.options()),
// );
// return assets.map(asset => this.toAssetEntity(asset));
// }

public async getAllAssets(): Promise<Asset[]> {
return (await this.edc.getClient()).management.assets.queryAll();
const client = await this.edc.getClient();
return client.management.assets.queryAll();
}

/**
* Creates a new asset using the provided asset input.
* @param assetInput - The input data required to create a new asset.
* @returns A promise that resolves to the ID response of the created asset.
*/
// /**
// * Creates a new asset using the provided asset input.
// * @param assetInput - The input data required to create a new asset.
// * @returns A promise that resolves to the ID response of the created asset.
// */
// public async createAsset(assetInput: AssetInput): Promise<IdResponse> {
// const response = await firstValueFrom(this.http.post<any>(await this.assetEndpoint(), assetInput, await this.options()));
// return this.toIdResponse(response);
// }

// /**
// * Updates an existing asset with the provided asset input.
// * @param assetInput - The input data required to update the asset.
// * @returns A promise that resolves when the asset is successfully updated.
// */
// public async updateAsset(assetInput: AssetInput): Promise<void> {
// await firstValueFrom(this.http.put<void>(await this.assetEndpoint(), assetInput, await this.options()));
// }

// /**
// * Deletes an asset based on the provided ID.
// * @param id - The unique identifier of the asset to be deleted.
// * @returns A promise that resolves when the asset is successfully deleted.
// */
// public async deleteAsset(id: string): Promise<void> {
// await firstValueFrom(this.http.delete<void>(await this.assetEndpoint(`/${encodeURIComponent(id)}`), await this.options()));
// }

// private toAssetEntity(rawAsset: any): Asset {
// const properties = rawAsset.properties ?? {};
// const privateProperties = rawAsset.privateProperties ?? {};

// return {
// ...rawAsset,
// id: rawAsset['@id'] ?? rawAsset.id,
// properties: this.withValueAccessors(properties),
// privateProperties: this.withValueAccessors(privateProperties),
// } as Asset;
// }

// private withValueAccessors(values: Record<string, any>) {
// return {
// ...values,
// optionalValue: <T = any>(_ns: string, key: string): T | undefined => this.value(values, key),
// mandatoryValue: <T = any>(_ns: string, key: string): T => this.value(values, key),
// };
// }

// private value(entity: Record<string, any>, key: string): any {
// const raw =
// entity[`edc:${key}`] ??
// entity[`asset:prop:${key}`] ??
// entity[`https://w3id.org/edc/v0.0.1/ns/${key}`] ??
// entity[key];

// if (Array.isArray(raw) && raw.length === 1) {
// return raw[0]?.['@value'] ?? raw[0]?.['@id'] ?? raw[0];
// }

// return raw?.['@value'] ?? raw?.['@id'] ?? raw;
// }

// private toIdResponse(response: any): IdResponse {
// return {
// ...response,
// id: response.id ?? response['@id'],
// } as IdResponse;
// }

// private async assetEndpoint(path = ''): Promise<string> {
// const config = await firstValueFrom(this.stateService.currentEdcConfig$);
// if (!config) {
// throw new Error('No EDC configuration available.');
// }
// return `${config.managementUrl}/v4/assets${path}`;
// }

// private async options() {
// const config = await firstValueFrom(this.stateService.currentEdcConfig$);
// return {
// headers: config?.apiToken ? { 'x-api-key': config.apiToken } : undefined,
// };
// }

public async createAsset(assetInput: AssetInput): Promise<IdResponse> {
return (await this.edc.getClient()).management.assets.create(assetInput);
// return (await this.edc.getClient()).management.assets.create(assetInput);
const { url, options } = await this.assetEndpoint();
return firstValueFrom(this.http.post<IdResponse>(url, assetInput, options));
}

/**
* Updates an existing asset with the provided asset input.
* @param assetInput - The input data required to update the asset.
* @returns A promise that resolves when the asset is successfully updated.
*/

public async updateAsset(assetInput: AssetInput): Promise<void> {
return (await this.edc.getClient()).management.assets.update(assetInput);
//return (await this.edc.getClient()).management.assets.update(assetInput);
const { url, options } = await this.assetEndpoint();
return (await firstValueFrom(this.http.put<void>(url, assetInput, options)));
}

/**
* Deletes an asset based on the provided ID.
* @param id - The unique identifier of the asset to be deleted.
* @returns A promise that resolves when the asset is successfully deleted.
*/

public async deleteAsset(id: string): Promise<void> {
return (await this.edc.getClient()).management.assets.delete(id);

}

private async assetEndpoint() {
const config = await firstValueFrom(this.stateService.currentEdcConfig$);
if (!config) {
throw new Error('No EDC configuration available.');
}

return {
url: `${config.managementUrl}/v4/assets`,
options: {
headers: config.apiToken ? { 'x-api-key': config.apiToken } : undefined,
},
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,14 @@ export class CatalogViewComponent implements OnInit, OnDestroy {
}

async getCatalog(catalogRequest: CatalogRequest) {
if (this.isFederatedCatalogEnabled) {
return await this.getFederatedCatalogs();
}
if (catalogRequest.counterPartyAddress) {
return await this.getCatalogByAddress(catalogRequest);
} else if (!catalogRequest.counterPartyAddress && this.isFederatedCatalogEnabled) {
return await this.getFederatedCatalogs();
// } else if (!catalogRequest.counterPartyAddress && this.isFederatedCatalogEnabled) {
// return await this.getFederatedCatalogs();
// }
}
}

Expand Down
Empty file.
Loading