@startinblox/components-ds4go 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.storybook/preview.ts +1 -0
  2. package/biome.json +1 -1
  3. package/dist/custom-getter-ZPFnoSjt-BCNOlbJZ-B4tuxA42.js +338 -0
  4. package/dist/en-BySYJZMr-CWZl5AwU-CWZl5AwU.js +14 -0
  5. package/dist/fr-BZZDTsmw-CNDWt66j-CNDWt66j.js +14 -0
  6. package/dist/index-BSwVRtNS.js +104980 -0
  7. package/dist/index.js +1 -3032
  8. package/dist/quill.snow-C_A_QkE8-D-uedtvC-D-uedtvC.js +13 -0
  9. package/dist/slimselect-NFLzJMfV-DZ7j6Vsj-DZ7j6Vsj.js +5 -0
  10. package/package.json +9 -8
  11. package/src/components/cards/ds4go-card-catalog.ts +132 -0
  12. package/src/components/catalog/ds4go-catalog-filter-holder.ts +459 -0
  13. package/src/components/catalog/ds4go-customer-holder.ts +162 -0
  14. package/src/components/catalog/ds4go-fact-bundle-holder.ts +7 -7
  15. package/src/components/modal/ds4go-customer-modal.ts +134 -0
  16. package/src/components/modal/ds4go-fact-bundle-modal.ts +2 -2
  17. package/src/components/solid-customer-list.ts +195 -0
  18. package/src/components/solid-dsif-explorer-poc.ts +8 -8
  19. package/src/components/solid-dsp-connector.ts +12 -4
  20. package/src/components/solid-fact-bundle-creation.ts +266 -169
  21. package/src/components/solid-fact-bundle.ts +9 -4
  22. package/src/helpers/components/orbitComponent.ts +12 -13
  23. package/src/helpers/i18n/configureLocalization.ts +12 -5
  24. package/src/helpers/index.ts +0 -2
  25. package/src/styles/cards/ds4go-card-catalog.scss +149 -0
  26. package/src/styles/fact-bundle-creation.scss +6 -2
  27. package/src/styles/modal/ds4go-customer-modal.scss +91 -0
  28. package/src/styles/modal/ds4go-fact-bundle-modal.scss +1 -1
  29. package/vite.config.ts +7 -7
  30. package/src/components/solid-boilerplate.ts +0 -76
  31. package/src/helpers/components/ResourceMapper.ts +0 -469
  32. package/src/helpers/components/orbitDspComponent.ts +0 -250
  33. package/src/helpers/mappings/dsp-mapping-config.ts +0 -545
@@ -1,545 +0,0 @@
1
- /**
2
- * DSP (Dataspace Protocol) Mapping Configuration
3
- *
4
- * Defines how DSP catalog datasets are mapped to TEMS-compatible resources.
5
- *
6
- * Source structure (simplified):
7
- * {
8
- * '@id': 'urn:uuid:dataset-id',
9
- * 'dcat:distribution': [{
10
- * 'dct:title': 'Dataset Name',
11
- * 'dct:description': 'Description',
12
- * 'dcat:keyword': ['keyword1', 'keyword2'],
13
- * 'dcat:endpointURL': 'https://service.com/endpoint',
14
- * 'foaf:thumbnail': { 'rdf:resource': 'https://image.com/logo.png' },
15
- * 'dcterms:creator': {
16
- * 'foaf:name': 'Creator Name',
17
- * 'foaf:thumbnail': { 'rdf:resource': 'https://creator.com/logo.png' }
18
- * }
19
- * }],
20
- * 'odrl:hasPolicy': { ... }
21
- * }
22
- *
23
- * Note: Properties can be at dataset level OR in dcat:distribution[0]
24
- */
25
-
26
- import {
27
- type MappingContext,
28
- processPolicyTransform,
29
- type ResourceMapperConfig,
30
- stripUrnPrefix,
31
- } from "@helpers/components/ResourceMapper";
32
-
33
- /**
34
- * Get properties from dataset, checking distribution first, then dataset level, then EDC properties
35
- */
36
- function getProperties(source: any): any {
37
- return source["dcat:distribution"]?.[0] || source["properties"] || source;
38
- }
39
-
40
- /**
41
- * Get EDC-style endpoint URL from properties
42
- * Priority: source-level dcat:endpointUrl (actual data endpoint) first
43
- */
44
- function getEndpointUrl(source: any): string {
45
- const props = getProperties(source);
46
- // Check source-level first (EDC catalog returns actual endpoint at top level)
47
- return (
48
- source["dcat:endpointUrl"] ||
49
- source["dcat:endpointURL"] ||
50
- source["http://www.w3.org/ns/dcat#endpointUrl"] ||
51
- source["endpointUrl"] ||
52
- source["endpointURL"] ||
53
- // Then check distribution/props level
54
- props["http://www.w3.org/ns/dcat#endpointUrl"] ||
55
- props["dcat:endpointUrl"] ||
56
- props["dcat:endpointURL"] ||
57
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
58
- props["endpointURL"] ||
59
- props["endpointUrl"] ||
60
- ""
61
- );
62
- }
63
-
64
- /**
65
- * Get content type from EDC properties
66
- * Priority: source-level fields first
67
- */
68
- function getContentType(source: any): string {
69
- const props = getProperties(source);
70
- // Check source-level first (EDC catalog returns these at top level)
71
- return (
72
- source["contenttype"] ||
73
- source["contentType"] ||
74
- source["http://www.w3.org/ns/dcat#mediaType"] ||
75
- source["dcat:mediaType"] ||
76
- // Then check distribution/props level
77
- props["contenttype"] ||
78
- props["contentType"] ||
79
- props["http://www.w3.org/ns/dcat#mediaType"] ||
80
- props["dcat:mediaType"] ||
81
- ""
82
- );
83
- }
84
-
85
- /**
86
- * Get field with multiple fallback paths
87
- */
88
- // function getFieldWithFallbacks(source: any, paths: string[][]): any {
89
- // for (const path of paths) {
90
- // const value = getNestedValue(source, path);
91
- // if (value !== undefined && value !== null && value !== "") {
92
- // return value;
93
- // }
94
- // }
95
- // return undefined;
96
- // }
97
-
98
- export const dspMappingConfig: ResourceMapperConfig = {
99
- baseFields: {
100
- "@id": {
101
- source: ["@id"],
102
- transform: (value, source, context: MappingContext) => {
103
- const stripped = stripUrnPrefix(value || source["id"] || "");
104
- const slug = stripped || value?.split("/").pop() || "unknown";
105
- // Include providerParticipantId in the @id to make it unique per provider
106
- // This prevents collision when different providers have assets with the same ID
107
- const providerPrefix = context.providerParticipantId
108
- ? `${encodeURIComponent(context.providerParticipantId)}/`
109
- : "";
110
- // FIXME: Avoid magic strings
111
- return `${context.temsServiceBase || "https://api.tems.example.com/services/"}${providerPrefix}${encodeURIComponent(slug)}/`;
112
- },
113
- },
114
- "@type": {
115
- source: [],
116
- defaultValue: "tems:Service",
117
- },
118
- name: {
119
- source: [],
120
- transform: (_, source) => {
121
- const props = getProperties(source);
122
- // Check multiple possible locations for the asset name
123
- // Priority: source-level fields > DCAT/DCTERMS fields > EDC namespace fields > id fields
124
- return (
125
- // Source-level fields (EDC catalog returns these at top level)
126
- source["name"] ||
127
- source["title"] ||
128
- source["dct:title"] ||
129
- source["dcterms:title"] ||
130
- // EDC namespace fields at source level
131
- source["https://w3id.org/edc/v0.0.1/ns/name"] ||
132
- source["edc:name"] ||
133
- // Distribution/props level
134
- props["dct:title"] ||
135
- props["dcterms:title"] ||
136
- props["title"] ||
137
- props["https://w3id.org/edc/v0.0.1/ns/name"] ||
138
- props["edc:name"] ||
139
- props["name"] ||
140
- // Fall back to ID but extract meaningful part
141
- (source["@id"]?.startsWith("urn:uuid:")
142
- ? source["@id"]
143
- : source["@id"]?.split("/").pop() || source["@id"]) ||
144
- source["id"] ||
145
- ""
146
- );
147
- },
148
- },
149
- description: {
150
- source: [],
151
- transform: (_, source) => {
152
- const props = getProperties(source);
153
- // Check multiple possible locations for description
154
- // Priority: source-level fields first
155
- return (
156
- // Source-level fields (EDC catalog returns these at top level)
157
- source["description"] ||
158
- source["dct:description"] ||
159
- source["dcterms:description"] ||
160
- source["https://w3id.org/edc/v0.0.1/ns/description"] ||
161
- source["edc:description"] ||
162
- // Distribution/props level
163
- props["dct:description"] ||
164
- props["dcterms:description"] ||
165
- props["description"] ||
166
- props["https://w3id.org/edc/v0.0.1/ns/description"] ||
167
- props["edc:description"] ||
168
- ""
169
- );
170
- },
171
- },
172
- long_description: {
173
- source: [],
174
- transform: (_, source) => {
175
- const props = getProperties(source);
176
- const keywords = Array.isArray(props["dcat:keyword"])
177
- ? props["dcat:keyword"]
178
- : props["dcat:keyword"]
179
- ? [props["dcat:keyword"]]
180
- : [];
181
- const description =
182
- props["dct:description"] ||
183
- props["dcterms:description"] ||
184
- props["description"] ||
185
- "";
186
- return keywords.length > 0
187
- ? `Keywords: ${keywords.join(", ")}`
188
- : description;
189
- },
190
- },
191
- url: {
192
- source: [],
193
- transform: (_, source) => getEndpointUrl(source),
194
- },
195
- endpointUrl: {
196
- source: [],
197
- transform: (_, source) => getEndpointUrl(source),
198
- },
199
- contentType: {
200
- source: [],
201
- transform: (_, source) => getContentType(source),
202
- },
203
- activation_status: {
204
- source: [],
205
- transform: (_, source) => {
206
- const props = getProperties(source);
207
- const endpointURL =
208
- props["dcat:endpointURL"] ||
209
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
210
- props["endpointURL"] ||
211
- "";
212
- return endpointURL.trim().length > 0;
213
- },
214
- },
215
- is_in_app: {
216
- source: [],
217
- transform: (_, source) => {
218
- const props = getProperties(source);
219
- const endpointURL =
220
- props["dcat:endpointURL"] ||
221
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
222
- props["endpointURL"] ||
223
- "";
224
- return endpointURL.trim().length > 0;
225
- },
226
- },
227
- is_external: {
228
- source: [],
229
- transform: (_, source) => {
230
- const props = getProperties(source);
231
- const endpointURL =
232
- props["dcat:endpointURL"] ||
233
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
234
- props["endpointURL"] ||
235
- "";
236
- return endpointURL.trim().length > 0;
237
- },
238
- },
239
- is_api: {
240
- source: [],
241
- transform: (_, source) => {
242
- const props = getProperties(source);
243
- const endpointURL =
244
- props["dcat:endpointURL"] ||
245
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
246
- props["endpointURL"] ||
247
- "";
248
- return endpointURL.trim().length > 0;
249
- },
250
- },
251
- contact_url: {
252
- source: [],
253
- transform: (_, source) => {
254
- const props = getProperties(source);
255
- return (
256
- props["dcat:endpointDescription"] || props["dct:conformsTo"] || ""
257
- );
258
- },
259
- },
260
- documentation_url: {
261
- source: [],
262
- transform: (_, source) => {
263
- const props = getProperties(source);
264
- return (
265
- props["dcat:endpointDescription"] || props["dct:conformsTo"] || ""
266
- );
267
- },
268
- },
269
- creation_date: {
270
- source: [],
271
- transform: (_, source) => {
272
- const props = getProperties(source);
273
- return (
274
- props["dct:issued"] ||
275
- props["dcterms:issued"] ||
276
- new Date().toISOString()
277
- );
278
- },
279
- },
280
- update_date: {
281
- source: [],
282
- transform: (_, source) => {
283
- const props = getProperties(source);
284
- const creationDate =
285
- props["dct:issued"] ||
286
- props["dcterms:issued"] ||
287
- new Date().toISOString();
288
- return (
289
- props["dct:modified"] || props["dcterms:modified"] || creationDate
290
- );
291
- },
292
- },
293
- release_date: {
294
- source: [],
295
- transform: (_, source) => {
296
- const props = getProperties(source);
297
- return (
298
- props["dct:issued"] ||
299
- props["dcterms:issued"] ||
300
- new Date().toISOString()
301
- );
302
- },
303
- },
304
- last_update: {
305
- source: [],
306
- transform: (_, source) => {
307
- const props = getProperties(source);
308
- const creationDate =
309
- props["dct:issued"] ||
310
- props["dcterms:issued"] ||
311
- new Date().toISOString();
312
- return (
313
- props["dct:modified"] || props["dcterms:modified"] || creationDate
314
- );
315
- },
316
- },
317
- activation_date: {
318
- source: [],
319
- defaultValue: null,
320
- },
321
- licence: {
322
- source: [],
323
- defaultValue: null,
324
- },
325
- developper: {
326
- source: [],
327
- defaultValue: null,
328
- },
329
- data_offers: {
330
- source: [],
331
- defaultValue: [],
332
- },
333
- },
334
-
335
- containerFields: {
336
- categories: {
337
- source: [],
338
- containerType: "ldp:Container",
339
- itemType: "tems:Category",
340
- transform: (_, source) => {
341
- const props = getProperties(source);
342
- const keywords = props["dcat:keyword"];
343
- if (!keywords) return [];
344
- return Array.isArray(keywords) ? keywords : [keywords];
345
- },
346
- itemFields: {
347
- "@id": (kw, _index, context) =>
348
- `${context.temsCategoryBase || "https://api.tems.example.com/categories/"}${encodeURIComponent(kw)}/`,
349
- name: (kw) => kw,
350
- },
351
- },
352
- images: {
353
- source: [],
354
- containerType: "ldp:Container",
355
- itemType: "tems:Image",
356
- transform: (_, source) => {
357
- const props = getProperties(source);
358
- const imageUrls: string[] = [];
359
-
360
- // Check for thumbnail in properties
361
- if (props["foaf:thumbnail"]?.["rdf:resource"]) {
362
- imageUrls.push(props["foaf:thumbnail"]["rdf:resource"]);
363
- }
364
-
365
- // Check for creator thumbnail
366
- if (props["dcterms:creator"]?.["foaf:thumbnail"]?.["rdf:resource"]) {
367
- imageUrls.push(
368
- props["dcterms:creator"]["foaf:thumbnail"]["rdf:resource"],
369
- );
370
- }
371
-
372
- return imageUrls;
373
- },
374
- itemFields: {
375
- "@id": (url, index, context) => {
376
- const filename = url.split("/").pop() || `image-${index}`;
377
- // FIXME: Avoid magic strings
378
- return `${context.temsImageBase || "https://api.tems.example.com/images/"}${encodeURIComponent(filename)}/`;
379
- },
380
- url: (url) => url,
381
- iframe: () => false,
382
- name: (url) => url.split("/").pop() || "image",
383
- },
384
- },
385
- },
386
-
387
- nestedObjects: {
388
- provider: {
389
- source: [],
390
- type: "tems:Provider",
391
- fields: {
392
- "@id": {
393
- source: [],
394
- transform: (_, _source, context: MappingContext) => {
395
- // Provider info comes from context (DSPProviderConfig)
396
- const providerSlug =
397
- context.providerParticipantId ||
398
- context.providerName ||
399
- "unknown";
400
- // FIXME: Avoid magic strings
401
- return `${context.temsProviderBase || "https://api.tems.example.com/providers/"}${encodeURIComponent(providerSlug)}/`;
402
- },
403
- },
404
- name: {
405
- source: [],
406
- transform: (_, source, context: MappingContext) => {
407
- const props = getProperties(source);
408
- return (
409
- props["dcterms:creator"]?.["foaf:name"] ||
410
- context.providerName ||
411
- ""
412
- );
413
- },
414
- },
415
- image: {
416
- source: [],
417
- transform: (_, source, context: MappingContext) => {
418
- const props = getProperties(source);
419
- const logoUrl =
420
- props["dcterms:creator"]?.["foaf:thumbnail"]?.["rdf:resource"];
421
-
422
- if (!logoUrl) return undefined;
423
-
424
- const filename = logoUrl.split("/").pop() || "provider-logo";
425
- return {
426
- // FIXME: Avoid magic strings
427
- "@id": `${context.temsImageBase || "https://api.tems.example.com/images/"}${encodeURIComponent(filename)}/`,
428
- "@type": "tems:Image",
429
- iframe: false,
430
- url: logoUrl,
431
- name: filename,
432
- };
433
- },
434
- },
435
- },
436
- },
437
- },
438
-
439
- contractFields: {
440
- counterPartyAddress: {
441
- source: [],
442
- transform: (_, _source, context: MappingContext) =>
443
- context.providerAddress,
444
- },
445
- counterPartyId: {
446
- source: [],
447
- transform: (_, _source, context: MappingContext) =>
448
- context.providerParticipantId || context.providerName,
449
- },
450
- assetId: {
451
- source: ["@id"],
452
- transform: (value, source) => stripUrnPrefix(value || source["id"] || ""),
453
- },
454
- datasetId: {
455
- source: ["@id"],
456
- transform: (value, source) => stripUrnPrefix(value || source["id"] || ""),
457
- },
458
- // Index endpoint URL for index assets - try multiple property variations
459
- // Priority: source-level dcat:endpointUrl (index endpoint) over props-level dcat:endpointURL (protocol URL)
460
- indexEndpointUrl: {
461
- source: [],
462
- transform: (_, source, context: MappingContext) => {
463
- const props = getProperties(source);
464
- // DEBUG: Log all possible sources for endpoint URL
465
- console.log("[DSP Mapping] indexEndpointUrl extraction for:", {
466
- assetId: source["@id"] || source["id"],
467
- assetName: source["name"] || props["name"] || props["dct:title"],
468
- provider: context.providerName,
469
- providerParticipantId: context.providerParticipantId,
470
- "source.dcat:endpointUrl": source["dcat:endpointUrl"],
471
- "props.dcat:endpointUrl": props["dcat:endpointUrl"],
472
- "source.dcat:endpointURL": source["dcat:endpointURL"],
473
- "props.dcat:accessService": props["dcat:accessService"],
474
- });
475
- // Prioritize source-level (lowercase Url) which contains the actual index endpoint
476
- // over props-level (uppercase URL) which may contain the protocol URL
477
- const result =
478
- source["dcat:endpointUrl"] ||
479
- props["dcat:endpointUrl"] ||
480
- source["dcat:endpointURL"] ||
481
- props["dcat:accessService"]?.["dcat:endpointUrl"] ||
482
- props["dcat:accessService"]?.["dcat:endpointURL"] ||
483
- props["endpointUrl"] ||
484
- props["endpointURL"] ||
485
- undefined;
486
- console.log("[DSP Mapping] indexEndpointUrl result:", result);
487
- return result;
488
- },
489
- },
490
- policy: {
491
- source: ["odrl:hasPolicy"],
492
- fallback: (source) => source["hasPolicy"],
493
- transform: (policy, source, context) => {
494
- if (!policy) return undefined;
495
-
496
- // Use the processPolicyTransform helper
497
- const processed = processPolicyTransform(policy, source, context);
498
-
499
- // Additional processing for permissions, prohibitions, obligations
500
- if (processed) {
501
- const processRules = (rules: any) => {
502
- if (Array.isArray(rules)) {
503
- return rules.map((rule) => {
504
- if (rule["@id"]) {
505
- rule["@id"] = stripUrnPrefix(rule["@id"]);
506
- }
507
- return rule;
508
- });
509
- }
510
- return rules;
511
- };
512
-
513
- if (processed["odrl:permission"]) {
514
- processed["odrl:permission"] = processRules(
515
- processed["odrl:permission"],
516
- );
517
- }
518
- if (processed["odrl:prohibition"]) {
519
- processed["odrl:prohibition"] = processRules(
520
- processed["odrl:prohibition"],
521
- );
522
- }
523
- if (processed["odrl:obligation"]) {
524
- processed["odrl:obligation"] = processRules(
525
- processed["odrl:obligation"],
526
- );
527
- }
528
- }
529
-
530
- return processed;
531
- },
532
- },
533
- },
534
-
535
- // Post-processing to add provider metadata fields
536
- postProcess: (resource, _source, context: MappingContext) => {
537
- return {
538
- ...resource,
539
- _provider: context.providerName,
540
- _providerAddress: context.providerAddress,
541
- _providerColor: context.providerColor || "#1976d2",
542
- _providerParticipantId: context.providerParticipantId,
543
- };
544
- },
545
- };