@startinblox/components-ds4go 2.1.1 → 2.2.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.
- package/README.md +44 -0
- package/biome.json +1 -1
- package/dist/index.js +1823 -932
- package/package.json +2 -4
- package/src/component.d.ts +116 -0
- package/src/components/solid-dsif-explorer-poc.ts +345 -0
- package/src/components/solid-dsp-connector.ts +185 -0
- package/src/helpers/components/ResourceMapper.ts +56 -37
- package/src/helpers/components/{dspComponent.ts → orbitDspComponent.ts} +22 -25
- package/src/helpers/index.ts +2 -2
- package/vite.config.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@startinblox/components-ds4go",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Startin'blox DS4GO",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -83,11 +83,9 @@
|
|
|
83
83
|
"@storybook/addon-docs": "^10.2.3",
|
|
84
84
|
"@storybook/web-components-vite": "^10.2.3",
|
|
85
85
|
"baseline-browser-mapping": "^2.9.19",
|
|
86
|
-
"buffer": "^6.0.3",
|
|
87
86
|
"cypress": "^15.9.0",
|
|
88
87
|
"cypress-ct-lit": "^1.0.0",
|
|
89
88
|
"lorem-ipsum": "^2.0.8",
|
|
90
|
-
"storybook": "^10.2.3"
|
|
91
|
-
"stream-browserify": "^3.0.0"
|
|
89
|
+
"storybook": "^10.2.3"
|
|
92
90
|
}
|
|
93
91
|
}
|
package/src/component.d.ts
CHANGED
|
@@ -149,6 +149,122 @@ export interface SearchObject {
|
|
|
149
149
|
type?: string;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
export interface DSPComponentParameters extends ComponentParameters {
|
|
153
|
+
"api-gateway-config"?: string;
|
|
154
|
+
"participant-connector-uri"?: string;
|
|
155
|
+
"participant-id"?: string;
|
|
156
|
+
"participant-api-key"?: string;
|
|
157
|
+
providers?: {
|
|
158
|
+
name: string;
|
|
159
|
+
address: string;
|
|
160
|
+
participantId: string;
|
|
161
|
+
}[];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface Asset {
|
|
165
|
+
"@id": string;
|
|
166
|
+
"@type"?: string;
|
|
167
|
+
properties?: Record<string, any>;
|
|
168
|
+
dataAddress?: {
|
|
169
|
+
"@type"?: string;
|
|
170
|
+
type?: string;
|
|
171
|
+
baseUrl?: string;
|
|
172
|
+
endpoint?: string;
|
|
173
|
+
};
|
|
174
|
+
createdAt?: number;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface AssetInput {
|
|
178
|
+
"@id": string;
|
|
179
|
+
properties?: Record<string, any>;
|
|
180
|
+
dataAddress?: {
|
|
181
|
+
"@type": string;
|
|
182
|
+
type: string;
|
|
183
|
+
baseUrl?: string;
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
interface OdrlPermission {
|
|
188
|
+
"@type"?: string;
|
|
189
|
+
action: string | string[];
|
|
190
|
+
target?: string;
|
|
191
|
+
constraint?: Constraint[];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface Prohibition {
|
|
195
|
+
"@type"?: string;
|
|
196
|
+
action: string | string[];
|
|
197
|
+
target?: string;
|
|
198
|
+
constraint?: Constraint[];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
interface Duty {
|
|
202
|
+
"@type"?: string;
|
|
203
|
+
action: string | string[];
|
|
204
|
+
constraint?: Constraint[];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface Constraint {
|
|
208
|
+
"@type"?: string;
|
|
209
|
+
leftOperand: string;
|
|
210
|
+
operator: string;
|
|
211
|
+
rightOperand: string | number | boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
interface OdrlPolicy {
|
|
215
|
+
"@type": "Set" | "Offer" | "Agreement";
|
|
216
|
+
"@id"?: string;
|
|
217
|
+
target?: string;
|
|
218
|
+
permission?: OdrlPermission[];
|
|
219
|
+
prohibition?: Prohibition[];
|
|
220
|
+
obligation?: Duty[];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface PolicyDefinition {
|
|
224
|
+
"@type"?: string;
|
|
225
|
+
"@id": string;
|
|
226
|
+
policy: OdrlPolicy;
|
|
227
|
+
createdAt?: number;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface PolicyDefinitionInput {
|
|
231
|
+
"@type"?: string;
|
|
232
|
+
"@id": string;
|
|
233
|
+
policy: OdrlPolicy;
|
|
234
|
+
}interface AssetSelector {
|
|
235
|
+
"@type": "CriterionDto";
|
|
236
|
+
operandLeft: string;
|
|
237
|
+
operator: string;
|
|
238
|
+
operandRight: any;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface ContractDefinition {
|
|
242
|
+
"@type": "ContractDefinition";
|
|
243
|
+
"@id": string;
|
|
244
|
+
"@context"?: any;
|
|
245
|
+
accessPolicyId: string;
|
|
246
|
+
contractPolicyId: string;
|
|
247
|
+
assetsSelector?: AssetSelector[] | AssetSelector;
|
|
248
|
+
createdAt?: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface ContractDefinitionInput {
|
|
252
|
+
"@id": string;
|
|
253
|
+
accessPolicyId: string;
|
|
254
|
+
contractPolicyId: string;
|
|
255
|
+
assetsSelector?: AssetSelector[];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface PolicyDefinition {
|
|
259
|
+
"@id": string;
|
|
260
|
+
policy?: OdrlPolicy;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface Asset {
|
|
264
|
+
"@id": string;
|
|
265
|
+
properties?: Record<string, any>;
|
|
266
|
+
}
|
|
267
|
+
|
|
152
268
|
export declare global {
|
|
153
269
|
interface Window {
|
|
154
270
|
orbit: LiveOrbit;
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { formatDate, OrbitComponent, sort } from "@helpers";
|
|
2
|
+
import { msg, str } from "@lit/localize";
|
|
3
|
+
import { Task } from "@lit/task";
|
|
4
|
+
import type { PropertiesPicker, Resource, SearchObject } from "@src/component";
|
|
5
|
+
import { css, html, nothing } from "lit";
|
|
6
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
7
|
+
|
|
8
|
+
// TODO: move to @src/component
|
|
9
|
+
//------------------------------------------------------------------------------
|
|
10
|
+
interface Sector {
|
|
11
|
+
sectorName: string;
|
|
12
|
+
description: string;
|
|
13
|
+
federatedCatalogEndpoint: string;
|
|
14
|
+
lastUpdated: string;
|
|
15
|
+
id: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Catalog {
|
|
19
|
+
catalogId: string;
|
|
20
|
+
type: string;
|
|
21
|
+
description: string;
|
|
22
|
+
endpoints: {
|
|
23
|
+
catalog: string;
|
|
24
|
+
};
|
|
25
|
+
lastUpdated: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Dataset extends Resource {
|
|
29
|
+
"dct:title": string;
|
|
30
|
+
"dct:description": string;
|
|
31
|
+
"dct:creator": string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface CatalogEntry extends Resource {
|
|
35
|
+
"dct:title": string;
|
|
36
|
+
"dct:description": string;
|
|
37
|
+
"dcat:dataset": Dataset[];
|
|
38
|
+
}
|
|
39
|
+
//------------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
@customElement("solid-dsif-explorer-poc")
|
|
42
|
+
export class SolidDsifExplorerPoc extends OrbitComponent {
|
|
43
|
+
static styles = css`
|
|
44
|
+
.card-grid {
|
|
45
|
+
margin: var(--scale-900) 0;
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: row;
|
|
48
|
+
flex-wrap: wrap;
|
|
49
|
+
gap: 20px;
|
|
50
|
+
}
|
|
51
|
+
.card-grid-vertical {
|
|
52
|
+
justify-content: stretch;
|
|
53
|
+
}
|
|
54
|
+
.card-grid-vertical tems-card-catalog {
|
|
55
|
+
width: 354px;
|
|
56
|
+
height: auto;
|
|
57
|
+
}
|
|
58
|
+
tems-card-catalog.cursor-pointer {
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
}
|
|
61
|
+
tems-division {
|
|
62
|
+
margin-top: var(--scale-900);
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
@property({ attribute: "sector-id", type: String })
|
|
67
|
+
sectorId?: string;
|
|
68
|
+
|
|
69
|
+
@property({ attribute: "catalog-id", type: String })
|
|
70
|
+
catalogId?: string;
|
|
71
|
+
|
|
72
|
+
@state()
|
|
73
|
+
search: SearchObject[] = [];
|
|
74
|
+
|
|
75
|
+
@state()
|
|
76
|
+
resultCount = this.objects?.length || 0;
|
|
77
|
+
|
|
78
|
+
cherryPickedProperties: PropertiesPicker[] = [
|
|
79
|
+
{ key: "dct:title", value: "title" },
|
|
80
|
+
{ key: "dct:description", value: "description" },
|
|
81
|
+
{ key: "dcat:dataset", value: "dataset", expand: true },
|
|
82
|
+
{ key: "dct:creator", value: "creator" },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
async _afterAttach() {
|
|
86
|
+
this.menuComponent = document.querySelector(
|
|
87
|
+
`[uniq="${this.orbit?.getComponent("menu")?.uniq}"]`,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@state()
|
|
94
|
+
sectors: Sector[] = [];
|
|
95
|
+
|
|
96
|
+
@state()
|
|
97
|
+
catalogs?: Catalog[];
|
|
98
|
+
|
|
99
|
+
@state()
|
|
100
|
+
object?: CatalogEntry;
|
|
101
|
+
|
|
102
|
+
_getResource = new Task(this, {
|
|
103
|
+
task: async ([dataSrc, sectorId, catalogId]) => {
|
|
104
|
+
if (
|
|
105
|
+
!dataSrc ||
|
|
106
|
+
!this.orbit ||
|
|
107
|
+
(!this.noRouter &&
|
|
108
|
+
this.route &&
|
|
109
|
+
this.currentRoute &&
|
|
110
|
+
!this.route.startsWith(this.currentRoute))
|
|
111
|
+
)
|
|
112
|
+
return;
|
|
113
|
+
|
|
114
|
+
this.displayFiltering = !this.component.parameters.disableFiltering;
|
|
115
|
+
|
|
116
|
+
if (!this.hasCachedDatas) {
|
|
117
|
+
if (!dataSrc) return;
|
|
118
|
+
|
|
119
|
+
this.sectors = [];
|
|
120
|
+
try {
|
|
121
|
+
const rootAuthority = await fetch(dataSrc);
|
|
122
|
+
this.sectors = await rootAuthority.json();
|
|
123
|
+
|
|
124
|
+
this.hasCachedDatas = true;
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.warn(`Failed to fetch sector authority ${dataSrc}`, error);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (sectorId) {
|
|
132
|
+
this.catalogs = [];
|
|
133
|
+
|
|
134
|
+
const selectedSectors = this.sectors.filter(
|
|
135
|
+
(sector) => sector.id === sectorId,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
if (selectedSectors.length > 0) {
|
|
139
|
+
this.catalogs = (
|
|
140
|
+
await Promise.all(
|
|
141
|
+
selectedSectors.map(async (sector) => {
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch(
|
|
144
|
+
`${sector.federatedCatalogEndpoint}/discovery`,
|
|
145
|
+
);
|
|
146
|
+
return (await response.json()).catalogs as Catalog[];
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.warn(
|
|
149
|
+
`Failed to fetch sector authority ${sector.federatedCatalogEndpoint}/discovery`,
|
|
150
|
+
error,
|
|
151
|
+
);
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
)
|
|
156
|
+
).flat();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (catalogId) {
|
|
160
|
+
// FIXME: What if both sbx and sa use the same catalogId?
|
|
161
|
+
const selectedCatalog = this.catalogs.find(
|
|
162
|
+
(catalog) => catalog.catalogId === catalogId,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
if (selectedCatalog) {
|
|
166
|
+
try {
|
|
167
|
+
this.object = (await (
|
|
168
|
+
await fetch(selectedCatalog.endpoints.catalog)
|
|
169
|
+
).json()) as CatalogEntry;
|
|
170
|
+
|
|
171
|
+
this.object["dcat:dataset"] = sort(
|
|
172
|
+
this.object["dcat:dataset"],
|
|
173
|
+
"dct:title",
|
|
174
|
+
"asc",
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return this.object;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.warn(
|
|
180
|
+
`Failed to fetch catalog from ${selectedCatalog.endpoints.catalog}`,
|
|
181
|
+
error,
|
|
182
|
+
);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return sort(this.catalogs, "catalogId", "asc");
|
|
188
|
+
}
|
|
189
|
+
return sort(this.sectors, "id", "asc");
|
|
190
|
+
},
|
|
191
|
+
args: () => [
|
|
192
|
+
this.dataSrc,
|
|
193
|
+
this.sectorId,
|
|
194
|
+
this.catalogId,
|
|
195
|
+
this.caching,
|
|
196
|
+
this.currentRoute,
|
|
197
|
+
],
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
_search(e: Event) {
|
|
201
|
+
e.preventDefault();
|
|
202
|
+
this.search = e.detail;
|
|
203
|
+
this.filterCount = this.search.filter((s) => s.name !== "search").length;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
_resultCountUpdate(e: Event) {
|
|
207
|
+
this.resultCount = e.detail ?? 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
_back() {
|
|
211
|
+
if (this.catalogId) {
|
|
212
|
+
this.catalogId = "";
|
|
213
|
+
} else if (this.sectorId) {
|
|
214
|
+
this.sectorId = "";
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
_selectSector(sectorId: string) {
|
|
219
|
+
if (this.sectors.find((sector) => sector.id === sectorId)) {
|
|
220
|
+
this.sectorId = sectorId;
|
|
221
|
+
} else {
|
|
222
|
+
this.sectorId = "";
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
_selectCatalog(catalogId: string) {
|
|
227
|
+
if (this.catalogs?.find((catalog) => catalog.catalogId === catalogId)) {
|
|
228
|
+
this.catalogId = catalogId;
|
|
229
|
+
} else {
|
|
230
|
+
this.catalogId = "";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
render() {
|
|
235
|
+
return (
|
|
236
|
+
this.gatekeeper() ||
|
|
237
|
+
this._getResource.render({
|
|
238
|
+
pending: () => html`<solid-loader></solid-loader>`,
|
|
239
|
+
error: (e) => {
|
|
240
|
+
console.warn("[solid-dsif-explorer-poc] Task error:", e);
|
|
241
|
+
return nothing;
|
|
242
|
+
},
|
|
243
|
+
complete: (datas) => {
|
|
244
|
+
return html`<tems-viewport>
|
|
245
|
+
<tems-header
|
|
246
|
+
slot="header"
|
|
247
|
+
heading=${this.catalogId
|
|
248
|
+
? `${msg("Datasets from")}
|
|
249
|
+
${(datas as CatalogEntry)["dct:title"]} (From ${this.sectorId})`
|
|
250
|
+
: this.sectorId
|
|
251
|
+
? `${msg("Catalogs available in")} ${this.sectorId}`
|
|
252
|
+
: `${msg("Root Authority")}`}
|
|
253
|
+
>${this.sectorId || this.catalogId
|
|
254
|
+
? html` <div slot="cta">
|
|
255
|
+
<tems-button
|
|
256
|
+
type="primary"
|
|
257
|
+
label=${msg(
|
|
258
|
+
str`Back to ${this.catalogId ? this.sectorId : "Root Authority"}`,
|
|
259
|
+
)}
|
|
260
|
+
@click=${this._back}
|
|
261
|
+
></tems-button>
|
|
262
|
+
</div>`
|
|
263
|
+
: nothing}</tems-header
|
|
264
|
+
>
|
|
265
|
+
<div slot="content">
|
|
266
|
+
${datas
|
|
267
|
+
? html`<div>
|
|
268
|
+
${this.catalogId
|
|
269
|
+
? html`<tems-division type="body-m"
|
|
270
|
+
>${(datas as CatalogEntry)[
|
|
271
|
+
"dct:description"
|
|
272
|
+
]}</tems-division
|
|
273
|
+
>`
|
|
274
|
+
: nothing}
|
|
275
|
+
<div class="card-grid card-grid-vertical">
|
|
276
|
+
${this.catalogId
|
|
277
|
+
? html`${(datas as CatalogEntry)["dcat:dataset"].map(
|
|
278
|
+
(dataset: Dataset) =>
|
|
279
|
+
html`<tems-card-catalog
|
|
280
|
+
.object=${import.meta.env.DEV
|
|
281
|
+
? dataset
|
|
282
|
+
: nothing}
|
|
283
|
+
type=${"bill-image"}
|
|
284
|
+
.header=${dataset["dct:title"] || nothing}
|
|
285
|
+
.content=${dataset["dct:description"] ||
|
|
286
|
+
nothing}
|
|
287
|
+
></tems-card-catalog>`,
|
|
288
|
+
)}`
|
|
289
|
+
: this.sectorId
|
|
290
|
+
? html`${datas.map(
|
|
291
|
+
(catalog: Catalog) =>
|
|
292
|
+
html`<tems-card-catalog
|
|
293
|
+
class="cursor-pointer"
|
|
294
|
+
.object=${import.meta.env.DEV
|
|
295
|
+
? catalog
|
|
296
|
+
: nothing}
|
|
297
|
+
type=${"bill-image"}
|
|
298
|
+
.header=${catalog.catalogId || nothing}
|
|
299
|
+
.content=${catalog.description || nothing}
|
|
300
|
+
date=${formatDate(catalog.lastUpdated) ||
|
|
301
|
+
nothing}
|
|
302
|
+
@click=${() =>
|
|
303
|
+
this._selectCatalog(catalog.catalogId)}
|
|
304
|
+
></tems-card-catalog>`,
|
|
305
|
+
)}`
|
|
306
|
+
: html`${datas.map(
|
|
307
|
+
(sector: Sector) =>
|
|
308
|
+
html`<tems-card-catalog
|
|
309
|
+
class="cursor-pointer"
|
|
310
|
+
.object=${import.meta.env.DEV
|
|
311
|
+
? sector
|
|
312
|
+
: nothing}
|
|
313
|
+
type=${"bill-image"}
|
|
314
|
+
.header=${sector.id || nothing}
|
|
315
|
+
.content=${sector.description || nothing}
|
|
316
|
+
date=${formatDate(sector.lastUpdated) ||
|
|
317
|
+
nothing}
|
|
318
|
+
@click=${() => this._selectSector(sector.id)}
|
|
319
|
+
></tems-card-catalog>`,
|
|
320
|
+
)}`}
|
|
321
|
+
</div>
|
|
322
|
+
</div>`
|
|
323
|
+
: html`<p>
|
|
324
|
+
${msg(
|
|
325
|
+
"No data available, data source may be temporarily unavailable.",
|
|
326
|
+
)}
|
|
327
|
+
</p>
|
|
328
|
+
${this.sectorId || this.catalogId
|
|
329
|
+
? html`<tems-button
|
|
330
|
+
type="primary"
|
|
331
|
+
label=${msg("Back")}
|
|
332
|
+
@click=${this._back}
|
|
333
|
+
></tems-button>`
|
|
334
|
+
: html`<tems-button
|
|
335
|
+
type="primary"
|
|
336
|
+
label=${msg("Retry")}
|
|
337
|
+
@click=${this.requestUpdate}
|
|
338
|
+
></tems-button>`}`}
|
|
339
|
+
</div>
|
|
340
|
+
</tems-viewport>`;
|
|
341
|
+
},
|
|
342
|
+
})
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { dspComponent } from "@helpers";
|
|
2
|
+
import { Task } from "@lit/task";
|
|
3
|
+
import type { Asset, AssetInput, ContractDefinition, ContractDefinitionInput, PolicyDefinition, PolicyDefinitionInput, Resource } from "@src/component";
|
|
4
|
+
import { nothing } from "lit";
|
|
5
|
+
import { customElement, state } from "lit/decorators.js";
|
|
6
|
+
|
|
7
|
+
export interface DSPProviderConfig {
|
|
8
|
+
name: string;
|
|
9
|
+
address: string;
|
|
10
|
+
color?: string;
|
|
11
|
+
participantId?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@customElement("solid-dsp-connector")
|
|
15
|
+
export class SolidDspConnector extends dspComponent {
|
|
16
|
+
async _responseAdaptator(response: Resource): Promise<Resource> {
|
|
17
|
+
if (response.providers) {
|
|
18
|
+
if (!Array.isArray(response.providers)) {
|
|
19
|
+
response.providers = [response.providers].filter((i: any) => i);
|
|
20
|
+
}
|
|
21
|
+
} else if (response.provider) {
|
|
22
|
+
response.providers = [response.provider].filter((i: any) => i);
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@state()
|
|
28
|
+
assets: Asset[] = [];
|
|
29
|
+
|
|
30
|
+
private async loadAssets() {
|
|
31
|
+
if (!this.storeService) {
|
|
32
|
+
console.error("Store not initialized. Check connector configuration.");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const assets = await this.storeService.getAllAssets();
|
|
38
|
+
this.assets = Array.isArray(assets) ? assets : [];
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error("Failed to load assets:", e);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async createAsset(assetData: AssetInput) {
|
|
45
|
+
if (!this.storeService) return false;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// TODO: Check asset integrity & reject
|
|
49
|
+
await this.storeService.createAsset(assetData);
|
|
50
|
+
await this.loadAssets();
|
|
51
|
+
|
|
52
|
+
this.dispatchEvent(
|
|
53
|
+
new CustomEvent("asset-created", {
|
|
54
|
+
detail: { asset: assetData },
|
|
55
|
+
bubbles: true,
|
|
56
|
+
composed: true,
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error("Failed to create asset", e);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@state()
|
|
68
|
+
policies: PolicyDefinition[] = [];
|
|
69
|
+
|
|
70
|
+
private async loadPolicies() {
|
|
71
|
+
if (!this.storeService) {
|
|
72
|
+
console.error("Store not initialized. Check connector configuration.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const policies = await this.storeService.getAllPolicies();
|
|
78
|
+
this.policies = Array.isArray(policies) ? policies : [];
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.error("Failed to load policies", e);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async createPolicy(policyData: PolicyDefinitionInput) {
|
|
85
|
+
if (!this.storeService) return false;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
// TODO: Check policy integrity & reject
|
|
89
|
+
await this.storeService.createPolicy(policyData);
|
|
90
|
+
await this.loadPolicies();
|
|
91
|
+
|
|
92
|
+
this.dispatchEvent(
|
|
93
|
+
new CustomEvent("policy-created", {
|
|
94
|
+
detail: { policy: policyData },
|
|
95
|
+
bubbles: true,
|
|
96
|
+
composed: true,
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return true;
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.error("Failed to create policy", e);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@state()
|
|
108
|
+
contracts: ContractDefinition[] = [];
|
|
109
|
+
|
|
110
|
+
private async loadContracts() {
|
|
111
|
+
if (!this.storeService) {
|
|
112
|
+
console.error("Store not initialized. Check connector configuration.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
// TODO: Check contract integrity & reject
|
|
118
|
+
const contracts = await this.storeService.getAllContractDefinitions();
|
|
119
|
+
this.contracts = Array.isArray(contracts) ? contracts : [];
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.error("Failed to load contract definitions", e);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public async createContract(contractData: ContractDefinitionInput) {
|
|
126
|
+
if (!this.storeService) return false;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
await this.storeService.createContractDefinition(contractData);
|
|
130
|
+
await this.loadContracts();
|
|
131
|
+
|
|
132
|
+
this.dispatchEvent(
|
|
133
|
+
new CustomEvent("contract-created", {
|
|
134
|
+
detail: { contract: contractData },
|
|
135
|
+
bubbles: true,
|
|
136
|
+
composed: true,
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
return true;
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.error("Failed to create contract definition", e);
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
_getResource = new Task(this, {
|
|
148
|
+
task: async () => {
|
|
149
|
+
if (!this.orbit) return;
|
|
150
|
+
|
|
151
|
+
if (!this.hasCachedDatas) {
|
|
152
|
+
const datasets = await this.fetchFederatedCatalog();
|
|
153
|
+
|
|
154
|
+
if (datasets !== undefined && Array.isArray(datasets)) {
|
|
155
|
+
this.datas = await Promise.all(
|
|
156
|
+
datasets.map(
|
|
157
|
+
async (dataset) => await this._responseAdaptator(dataset),
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
this.hasCachedDatas = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!Array.isArray(this.datas)) {
|
|
165
|
+
this.datas = [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return this.datas;
|
|
169
|
+
},
|
|
170
|
+
args: () => [this.caching, this.currentRoute],
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
render() {
|
|
174
|
+
return this._getResource.render({
|
|
175
|
+
pending: () => nothing,
|
|
176
|
+
complete: () => nothing,
|
|
177
|
+
error: (e) => {
|
|
178
|
+
if (import.meta.env.DEV) {
|
|
179
|
+
console.error(e, this);
|
|
180
|
+
}
|
|
181
|
+
return nothing;
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|