Skip to content

Commit 8001bb9

Browse files
fdelavegaSHENGXING LU
andauthored
Support for dataspace integration (#187)
* did party char * product spec creation with 2 more chars * characteristics post and patch * Add proper support for policy and auth characteristics * Update the product details to show the credential and policy chars * Show proper browser header and fav icon depending on the theme * Show feedbak modal only in DOME theme * Fix failing test --------- Co-authored-by: SHENGXING LU <slu@SHENGXINGs-MacBook-Air.local>
1 parent 2a61b47 commit 8001bb9

30 files changed

Lines changed: 703 additions & 33 deletions

src/app/app.component.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ describe('AppComponent', () => {
1818
expect(app).toBeTruthy();
1919
});
2020

21-
it(`should have as title 'DOME Marketplace'`, () => {
21+
it(`should have as title 'BAE Marketplace'`, () => {
2222
const fixture = TestBed.createComponent(AppComponent);
2323
const app = fixture.componentInstance;
24-
expect(app.title).toEqual('DOME Marketplace');
24+
expect(app.title).toEqual('BAE Marketplace');
2525
});
2626

2727
it('should render shell layout', () => {

src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { filter } from 'rxjs';
2121
styleUrls: ['./app.component.css'],
2222
})
2323
export class AppComponent implements OnInit {
24-
title = 'DOME Marketplace';
24+
title = 'BAE Marketplace';
2525
showPanel = false;
2626
providerThemeName=environment.providerThemeName;
2727
isProduction:boolean = environment.isProduction;

src/app/pages/product-details/product-details.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,18 +466,18 @@ <h2 class="text-4xl font-extrabold text-primary-100 text-center pb-8 pt-12 dark:
466466
<div class="flex items-center pl-4">
467467
<input disabled checked id="disabled-checked-checkbox" type="checkbox" value="" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-600 dark:border-gray-800 rounded-full focus:ring-blue-500 focus:ring-2">
468468
@if(val.value !== undefined && val.value !== null){
469-
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 dark:bg-secondary-200 dark:border-gray-800 text-wrap break-words">{{val.value}}{{val.unitOfMeasure ? ' (' + val.unitOfMeasure + ')' : ''}}</label>
469+
<label [title]="getCharacteristicValueLabel(val)" for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 dark:bg-secondary-200 dark:border-gray-800 text-wrap break-all">{{ getCharacteristicValuePreview(val) }}</label>
470470
} @else {
471-
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 dark:bg-secondary-200 dark:border-gray-800 text-wrap break-words">{{val.valueFrom}} - {{val.valueTo}}{{val.unitOfMeasure ? ' (' + val.unitOfMeasure + ')' : ''}}</label>
471+
<label [title]="getCharacteristicRangeLabel(val)" for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 dark:bg-secondary-200 dark:border-gray-800 text-wrap break-all">{{ getCharacteristicRangePreview(val) }}</label>
472472
}
473473
</div>
474474
} @else {
475475
<div class="flex items-center pl-4">
476476
<input disabled id="disabled-checkbox" type="checkbox" value="" class="w-4 h-4 text-blue-600 bg-gray-100 dark:bg-gray-600 dark:border-gray-800 border-gray-300 rounded-full focus:ring-blue-500 focus:ring-2">
477477
@if(val.value !== undefined && val.value !== null){
478-
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 text-wrap break-words">{{val.value}}{{val.unitOfMeasure ? ' (' + val.unitOfMeasure + ')' : ''}}</label>
478+
<label [title]="getCharacteristicValueLabel(val)" for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 text-wrap break-all">{{ getCharacteristicValuePreview(val) }}</label>
479479
} @else {
480-
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 text-wrap break-words">{{val.valueFrom}} - {{val.valueTo}}{{val.unitOfMeasure ? ' (' + val.unitOfMeasure + ')' : ''}}</label>
480+
<label [title]="getCharacteristicRangeLabel(val)" for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-gray-200 text-wrap break-all">{{ getCharacteristicRangePreview(val) }}</label>
481481
}
482482
</div>
483483
}

src/app/pages/product-details/product-details.component.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,57 @@ describe('ProductDetailsComponent', () => {
461461
expect(component.normalizeName('Compliance:ISO/IEC 27001')).toBe('ISO/IEC 27001');
462462
expect(component.normalizeName(undefined)).toBe('');
463463
});
464+
465+
it('getCharacteristicValueLabel should stringify object values and append unit', () => {
466+
const label = component.getCharacteristicValueLabel({
467+
value: { issuer: 'vault', endpoint: 'https://example.test' },
468+
unitOfMeasure: 'json',
469+
});
470+
471+
expect(label).toBe('{"issuer":"vault","endpoint":"https://example.test"} (json)');
472+
});
473+
474+
it('getCharacteristicValueLabel should keep boolean false and omit empty unit', () => {
475+
const label = component.getCharacteristicValueLabel({
476+
value: false,
477+
});
478+
479+
expect(label).toBe('false');
480+
});
481+
482+
it('getCharacteristicRangeLabel should support object unit and avoid empty parenthesis', () => {
483+
const withUnit = component.getCharacteristicRangeLabel({
484+
valueFrom: 1,
485+
valueTo: 10,
486+
unitOfMeasure: { units: 'GB' },
487+
});
488+
const withoutUnit = component.getCharacteristicRangeLabel({
489+
valueFrom: 5,
490+
valueTo: 15,
491+
unitOfMeasure: {},
492+
});
493+
494+
expect(withUnit).toBe('1 - 10 (GB)');
495+
expect(withoutUnit).toBe('5 - 15');
496+
});
497+
498+
it('getCharacteristicValuePreview should truncate long values with ellipsis', () => {
499+
const longValue = 'x'.repeat(140);
500+
const preview = component.getCharacteristicValuePreview({
501+
value: longValue,
502+
});
503+
504+
expect(preview.endsWith('...')).toBeTrue();
505+
expect(preview.length).toBe(123);
506+
});
507+
508+
it('getCharacteristicRangePreview should keep short values unchanged', () => {
509+
const preview = component.getCharacteristicRangePreview({
510+
valueFrom: 1,
511+
valueTo: 3,
512+
unitOfMeasure: 'GB',
513+
});
514+
515+
expect(preview).toBe('1 - 3 (GB)');
516+
});
464517
});

src/app/pages/product-details/product-details.component.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,70 @@ async deleteProduct(product: Product | undefined){
10211021
}
10221022
}
10231023

1024+
getCharacteristicValueLabel(valueSpec: any): string {
1025+
const valueLabel = this.formatCharacteristicScalar(valueSpec?.value);
1026+
const unitLabel = this.getUnitLabel(valueSpec?.unitOfMeasure);
1027+
1028+
return unitLabel ? `${valueLabel} (${unitLabel})` : valueLabel;
1029+
}
1030+
1031+
getCharacteristicValuePreview(valueSpec: any): string {
1032+
return this.truncateCharacteristicLabel(this.getCharacteristicValueLabel(valueSpec));
1033+
}
1034+
1035+
getCharacteristicRangeLabel(valueSpec: any): string {
1036+
const fromLabel = this.formatCharacteristicScalar(valueSpec?.valueFrom);
1037+
const toLabel = this.formatCharacteristicScalar(valueSpec?.valueTo);
1038+
const unitLabel = this.getUnitLabel(valueSpec?.unitOfMeasure);
1039+
const rangeLabel = `${fromLabel} - ${toLabel}`;
1040+
1041+
return unitLabel ? `${rangeLabel} (${unitLabel})` : rangeLabel;
1042+
}
1043+
1044+
getCharacteristicRangePreview(valueSpec: any): string {
1045+
return this.truncateCharacteristicLabel(this.getCharacteristicRangeLabel(valueSpec));
1046+
}
1047+
1048+
private formatCharacteristicScalar(value: any): string {
1049+
if (value === undefined || value === null) {
1050+
return '';
1051+
}
1052+
1053+
if (typeof value === 'object') {
1054+
try {
1055+
return JSON.stringify(value);
1056+
} catch {
1057+
return String(value);
1058+
}
1059+
}
1060+
1061+
return String(value);
1062+
}
1063+
1064+
private getUnitLabel(unitOfMeasure: any): string {
1065+
if (!unitOfMeasure) {
1066+
return '';
1067+
}
1068+
1069+
if (typeof unitOfMeasure === 'string') {
1070+
return unitOfMeasure;
1071+
}
1072+
1073+
if (typeof unitOfMeasure?.units === 'string') {
1074+
return unitOfMeasure.units;
1075+
}
1076+
1077+
return '';
1078+
}
1079+
1080+
private truncateCharacteristicLabel(label: string, maxLength = 120): string {
1081+
if (!label) {
1082+
return '';
1083+
}
1084+
1085+
return label.length > maxLength ? `${label.slice(0, maxLength)}...` : label;
1086+
}
1087+
10241088
normalizeName(name?: string): string {
10251089
return name?.replace(/compliance:/i, '').trim() ?? '';
10261090
}

src/app/pages/seller-offerings/offerings/seller-product-spec/create-product-spec/create-product-spec.component.html

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,13 @@ <h3 class="font-bold text-primary-100 dark:text-primary-50 text-left ml-4">
510510
<td class="px-6 py-4 text-wrap break-all">
511511
@for (char of prod.productSpecCharacteristicValue; track char; let last=$last) {
512512
@if(char.value || char.value == 0){
513-
@if(char.unitOfMeasure){
513+
@if(prod.valueType === 'credentialsConfiguration' || prod.valueType === 'authorizationPolicy'){
514+
@if(!last){
515+
{{getValuePreview(char.value)}},
516+
} @else {
517+
{{getValuePreview(char.value)}}
518+
}
519+
} @else if(char.unitOfMeasure){
514520
@if(!last){
515521
{{char.value}} (<i>{{char?.unitOfMeasure}}</i>),
516522
} @else {
@@ -570,14 +576,18 @@ <h3 class="font-bold text-primary-100 dark:text-primary-50 text-left ml-4">
570576
<option value="number">Number</option>
571577
<option value="range">Number range</option>
572578
<option value="boolean">Boolean</option>
579+
@if(DATA_SPACE_ENABLED){
580+
<option value="credentialsConfiguration">Credentials Configuration</option>
581+
<option value="authorizationPolicy">Authorization Policy</option>
582+
}
573583
</select>
574584
</div>
575585
<div class="col-span-2">
576586
<label for="description" class="font-bold text-lg dark:text-white">{{ 'CREATE_PROD_SPEC._product_description' | translate }}</label>
577587
<textarea data-cy="charDescription" id="description" formControlName="description" rows="4" maxLength="500"
578588
class="mb-2 min-h-fit bg-gray-50 dark:bg-secondary-300 border border-gray-300 dark:border-secondary-200 dark:text-white text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"></textarea>
579589
</div>
580-
@if(charTypeSelected !== 'boolean'){
590+
@if(charTypeSelected !== 'boolean' && charTypeSelected !== 'credentialsConfiguration' && charTypeSelected !== 'authorizationPolicy'){
581591
<div class="col-span-2 flex align-items-middle h-fit">
582592
<label for="is-optional" class="font-bold text-lg dark:text-white">{{ 'CREATE_PROD_SPEC._make_optional' | translate }}</label>
583593
<label class="inline-flex items-center me-5 cursor-pointer ml-4">
@@ -624,6 +634,8 @@ <h3 class="font-bold text-primary-100 dark:text-primary-50 text-left ml-4">
624634
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-full focus:ring-blue-500 focus:ring-2">
625635
@if(charTypeSelected === 'number'){
626636
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-white text-wrap break-all">{{char.value}} (<i>{{char?.unitOfMeasure}}</i>)</label>
637+
} @else if (charTypeSelected === 'credentialsConfiguration' || charTypeSelected === 'authorizationPolicy') {
638+
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-white text-wrap break-all">{{getValuePreview(char.value)}}</label>
627639
} @else {
628640
<label for="disabled-checked-checkbox" class="ms-2 text-sm font-medium text-gray-700 dark:text-white text-wrap break-all">{{char.value}}</label>
629641
}
@@ -709,6 +721,21 @@ <h3 class="font-bold text-primary-100 dark:text-primary-50 text-left ml-4">
709721
</svg>
710722
</button>
711723
</div>
724+
} @else if (charTypeSelected == "credentialsConfiguration" || charTypeSelected == "authorizationPolicy"){
725+
@if(creatingChars.length === 0){
726+
<div class="flex flex-col w-full">
727+
<label for="json-value" class="font-bold text-sm dark:text-white mb-2">{{ 'CREATE_PROD_SPEC._json_value' | translate }}</label>
728+
<textarea id="json-value" [(ngModel)]="jsonValue" rows="10"
729+
class="mb-2 min-h-fit bg-gray-50 dark:bg-secondary-300 border border-gray-300 dark:border-secondary-200 dark:text-white text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 font-mono"
730+
placeholder='{"example": "Enter your JSON here"}'></textarea>
731+
<button (click)="addCharValue()" [disabled]="!jsonValue" [ngClass]="!jsonValue ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'" type="button" class="text-white w-fit bg-primary-100 hover:bg-primary-50 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 text-center inline-flex items-center">
732+
<svg class="w-4 h-4 mr-2 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
733+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14m-7 7V5"/>
734+
</svg>
735+
{{ 'CREATE_PROD_SPEC._add_json' | translate }}
736+
</button>
737+
</div>
738+
}
712739
}
713740
<div class="flex w-full justify-items-center justify-center mt-4">
714741
<button data-cy="btnSaveCharacteristic" type="button" (click)="saveChar()" [disabled]="!charsForm.valid || creatingChars.length==0" [ngClass]="!charsForm.valid || creatingChars.length==0 ? 'opacity-50' : 'hover:bg-primary-50'" class="flex text-white justify-center bg-primary-100 hover:bg-primary-50 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center">
@@ -1479,7 +1506,13 @@ <h4 class="text-lg font-bold ml-4 dark:text-white">{{ 'CREATE_PROD_SPEC._add_att
14791506
<td class="px-6 py-4 text-wrap break-all">
14801507
@for (char of prod.productSpecCharacteristicValue; track char; let last = $last) {
14811508
@if(char.value || char.value == 0){
1482-
@if(char.unitOfMeasure){
1509+
@if(prod.valueType === 'credentialsConfiguration' || prod.valueType === 'authorizationPolicy'){
1510+
@if(!last){
1511+
{{getValuePreview(char.value)}},
1512+
} @else {
1513+
{{getValuePreview(char.value)}}
1514+
}
1515+
} @else if(char.unitOfMeasure){
14831516
@if(!last){
14841517
{{char.value}} (<i>{{char?.unitOfMeasure}}</i>),
14851518
} @else {

0 commit comments

Comments
 (0)