@startinblox/core 2.0.6-beta.6 → 2.0.6-beta.7

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { g as getDefaultExportFromCjs, S as StoreService, b as base_context, f as formatAttributesToServerPaginationOptions, m as mergeServerSearchOptions, a as formatAttributesToServerSearchOptions, c as StoreType, d as StoreFactory, h as hasSetLocalData, e as hasQueryIndex, __tla as __tla_0 } from "./store-B7CtE5CD.js";
4
+ import { g as getDefaultExportFromCjs, S as StoreService, b as base_context, f as formatAttributesToServerPaginationOptions, m as mergeServerSearchOptions, a as formatAttributesToServerSearchOptions, c as StoreType, d as StoreFactory, h as hasSetLocalData, e as hasQueryIndex, __tla as __tla_0 } from "./store-pxHgUL4R.js";
5
5
  import { d as defineComponent, n as normalizeContext, u as uniqID, f as fuzzyCompare, a as asyncQuerySelector, i as importInlineCSS, b as importCSS, c as doesResourceContainList, e as findClosingBracketMatchIndex, p as parseFieldsString, g as evalTemplateString, h as compare, j as generalComparator, t as transformArrayToContainer, s as setDeepProperty } from "./helpers-vZrb1UDN.js";
6
6
  import { k } from "./helpers-vZrb1UDN.js";
7
7
  let index$4, BaseWidgetMixin, index$3, CounterMixin, EdcAssetsDisplay, EdcCatalogDisplay, EdcFederatedCatalogDisplay, FederationMixin, FilterMixin, GrouperMixin, HighlighterMixin, ListMixin, NextMixin, PaginateMixin, RequiredMixin, Sib, SolidAcChecker, SolidDelete, SolidDisplay, SolidForm, SolidFormSearch, SolidLang, SolidMemberAdd, SolidMemberDelete, SolidMembership, SolidTable, SolidTemplateElement, SolidWidget, SorterMixin, StoreMixin, index$2, index$1, index, TranslationMixin, ValidationMixin, WidgetMixin, x, o$2, newWidgetFactory, B, o$1, m, widgetFactory;
@@ -2703,6 +2703,46 @@ Component: ${componentName}
2703
2703
  }, "SolidDelete:render")
2704
2704
  };
2705
2705
  Sib.register(SolidDelete);
2706
+ class ProviderRegistry {
2707
+ constructor(initialProviders) {
2708
+ __publicField(this, "providers", /* @__PURE__ */ new Map());
2709
+ if (initialProviders) {
2710
+ for (const provider of initialProviders) {
2711
+ this.addProvider(provider);
2712
+ }
2713
+ }
2714
+ }
2715
+ addProvider(provider) {
2716
+ this.providers.set(provider.protocolAddress, provider);
2717
+ }
2718
+ getProviderByAddress(protocolAddress) {
2719
+ return this.providers.get(protocolAddress);
2720
+ }
2721
+ getProviderByParticipantId(participantId) {
2722
+ return Array.from(this.providers.values()).find((provider) => provider.participantId === participantId);
2723
+ }
2724
+ getAllProviders() {
2725
+ return Array.from(this.providers.values());
2726
+ }
2727
+ removeProvider(protocolAddress) {
2728
+ return this.providers.delete(protocolAddress);
2729
+ }
2730
+ updateProviderStatus(protocolAddress, status) {
2731
+ const provider = this.providers.get(protocolAddress);
2732
+ if (provider) {
2733
+ provider.status = status;
2734
+ provider.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
2735
+ }
2736
+ }
2737
+ static fromConfig(config2) {
2738
+ return new ProviderRegistry(config2.providers);
2739
+ }
2740
+ toConfig() {
2741
+ return {
2742
+ providers: this.getAllProviders()
2743
+ };
2744
+ }
2745
+ }
2706
2746
  const ActionMixin = {
2707
2747
  name: "action-mixin",
2708
2748
  attributes: {
@@ -99792,429 +99832,8 @@ ${escapeText(this.code(index2, length))}
99792
99832
  return field.startsWith("@") ? field.slice(1, field.length) : field;
99793
99833
  }
99794
99834
  };
99795
- EdcAssetsDisplay = {
99796
- name: "edc-assets-display",
99797
- use: [
99798
- WidgetMixin,
99799
- AttributeBinderMixin
99800
- ],
99801
- attributes: {
99802
- connectorUri: {
99803
- type: String,
99804
- default: null,
99805
- callback: function(value) {
99806
- if (value && this.apiKey) {
99807
- this.fetchAssets();
99808
- }
99809
- }
99810
- },
99811
- apiKey: {
99812
- type: String,
99813
- default: null,
99814
- callback: function(value) {
99815
- if (value && this.connectorUri) {
99816
- this.fetchAssets();
99817
- }
99818
- }
99819
- },
99820
- defaultWidget: {
99821
- type: String,
99822
- default: "edc-asset-item"
99823
- }
99824
- },
99825
- initialState: {
99826
- assets: [],
99827
- loading: false,
99828
- error: null
99829
- },
99830
- created() {
99831
- if (this.connectorUri && this.apiKey) {
99832
- this.fetchAssets();
99833
- }
99834
- },
99835
- async fetchAssets() {
99836
- if (!this.connectorUri || !this.apiKey) return;
99837
- this.loading = true;
99838
- this.error = null;
99839
- this.render();
99840
- try {
99841
- const config2 = {
99842
- type: StoreType.DataspaceConnector,
99843
- endpoint: this.connectorUri,
99844
- catalogEndpoint: `${this.connectorUri}/v3/catalog/request`,
99845
- contractNegotiationEndpoint: `${this.connectorUri}/v3/contractnegotiations`,
99846
- transferProcessEndpoint: `${this.connectorUri}/v3/transferprocesses`,
99847
- assetsEndpoint: `${this.connectorUri}/v3/assets/request`,
99848
- authMethod: "edc-api-key",
99849
- edcApiKey: this.apiKey,
99850
- retryAttempts: 3,
99851
- timeout: 3e4
99852
- };
99853
- const store2 = StoreFactory.create(config2);
99854
- const assetsRaw = await store2.getAssets();
99855
- this.assets = Array.isArray(assetsRaw) ? assetsRaw : assetsRaw ? [
99856
- assetsRaw
99857
- ] : [];
99858
- } catch (error2) {
99859
- console.error("Failed to fetch EDC assets:", error2);
99860
- this.error = error2.message;
99861
- this.assets = [];
99862
- } finally {
99863
- this.loading = false;
99864
- this.render();
99865
- }
99866
- },
99867
- render() {
99868
- if (this.loading) {
99869
- B(x`<div class="loading">Loading assets...</div>`, this.element);
99870
- return;
99871
- }
99872
- if (this.error) {
99873
- B(x`<div class="error">Error: ${this.error}</div>`, this.element);
99874
- return;
99875
- }
99876
- if (!this.assets || this.assets.length === 0) {
99877
- B(x`<div class="empty">No assets found</div>`, this.element);
99878
- return;
99879
- }
99880
- const template = x`
99881
- <div class="edc-assets-list">
99882
- ${this.assets.map((asset) => {
99883
- var _a3, _b, _c, _d;
99884
- return x`
99885
- <div class="edc-asset-item" data-asset-id="${asset["@id"]}">
99886
- <h3 class="asset-title">
99887
- ${asset["dcterms:title"] || ((_a3 = asset.properties) == null ? void 0 : _a3.name) || asset["@id"]}
99888
- </h3>
99889
- ${asset["dcterms:description"] || ((_b = asset.properties) == null ? void 0 : _b.description) ? x`<p class="asset-description">
99890
- ${asset["dcterms:description"] || ((_c = asset.properties) == null ? void 0 : _c.description)}
99891
- </p>` : ""}
99892
- <div class="asset-metadata">
99893
- <span class="asset-id">ID: ${asset["@id"]}</span>
99894
- ${((_d = asset.properties) == null ? void 0 : _d["https://w3id.org/edc/v0.0.1/ns/type"]) ? x`<span class="asset-type">
99895
- Type: ${asset.properties["https://w3id.org/edc/v0.0.1/ns/type"]}
99896
- </span>` : ""}
99897
- </div>
99898
- </div>
99899
- `;
99900
- })}
99901
- </div>
99902
- `;
99903
- B(template, this.element);
99904
- }
99905
- };
99906
- Sib.register(EdcAssetsDisplay);
99907
- EdcCatalogDisplay = {
99908
- name: "edc-catalog-display",
99909
- use: [
99910
- WidgetMixin,
99911
- AttributeBinderMixin
99912
- ],
99913
- attributes: {
99914
- connectorUri: {
99915
- type: String,
99916
- default: null,
99917
- callback: function(value) {
99918
- if (value && this.apiKey && this.counterPartyAddress) {
99919
- this.fetchCatalog();
99920
- }
99921
- }
99922
- },
99923
- apiKey: {
99924
- type: String,
99925
- default: null,
99926
- callback: function(value) {
99927
- if (value && this.connectorUri && this.counterPartyAddress) {
99928
- this.fetchCatalog();
99929
- }
99930
- }
99931
- },
99932
- counterPartyAddress: {
99933
- type: String,
99934
- default: null,
99935
- callback: function(value) {
99936
- if (value && this.connectorUri && this.apiKey) {
99937
- this.fetchCatalog();
99938
- }
99939
- }
99940
- },
99941
- defaultWidget: {
99942
- type: String,
99943
- default: "edc-dataset-item"
99944
- }
99945
- },
99946
- initialState: {
99947
- catalog: null,
99948
- datasets: [],
99949
- loading: false,
99950
- error: null,
99951
- negotiations: /* @__PURE__ */ new Map(),
99952
- store: null
99953
- },
99954
- created() {
99955
- if (this.connectorUri && this.apiKey && this.counterPartyAddress) {
99956
- this.fetchCatalog();
99957
- }
99958
- },
99959
- async fetchCatalog() {
99960
- if (!this.connectorUri || !this.apiKey || !this.counterPartyAddress) return;
99961
- this.loading = true;
99962
- this.error = null;
99963
- this.render();
99964
- try {
99965
- const config2 = {
99966
- type: StoreType.DataspaceConnector,
99967
- endpoint: this.connectorUri,
99968
- catalogEndpoint: `${this.connectorUri}/v3/catalog/request`,
99969
- contractNegotiationEndpoint: `${this.connectorUri}/v3/contractnegotiations`,
99970
- transferProcessEndpoint: `${this.connectorUri}/v3/transferprocesses`,
99971
- authMethod: "edc-api-key",
99972
- edcApiKey: this.apiKey,
99973
- retryAttempts: 8,
99974
- timeout: 1e4
99975
- };
99976
- const store2 = StoreFactory.create(config2);
99977
- const catalog = await store2.getCatalog(this.counterPartyAddress);
99978
- this.catalog = catalog;
99979
- this.datasets = (catalog == null ? void 0 : catalog["dcat:dataset"]) || [];
99980
- this.store = store2;
99981
- } catch (error2) {
99982
- console.error("Failed to fetch EDC catalog:", error2);
99983
- this.error = error2.message;
99984
- this.catalog = null;
99985
- this.datasets = [];
99986
- } finally {
99987
- this.loading = false;
99988
- this.render();
99989
- }
99990
- },
99991
- async negotiateAccess(dataset) {
99992
- if (!dataset["odrl:hasPolicy"] || dataset["odrl:hasPolicy"].length === 0) {
99993
- console.error("No policies available for dataset:", dataset["@id"]);
99994
- return;
99995
- }
99996
- try {
99997
- const offer = dataset["odrl:hasPolicy"][0];
99998
- const offerId = offer["@id"];
99999
- const assetId = dataset["@id"];
100000
- this.negotiations.set(assetId, {
100001
- status: "negotiating",
100002
- offerId
100003
- });
100004
- this.render();
100005
- if (!this.store) {
100006
- console.error("Store not available for negotiation");
100007
- return;
100008
- }
100009
- const store2 = this.store;
100010
- const modifiedOffer = {
100011
- ...offer,
100012
- target: assetId
100013
- };
100014
- const negotiationId = await store2.initiateNegotiation(this.counterPartyAddress, assetId, modifiedOffer);
100015
- this.negotiations.set(assetId, {
100016
- status: "pending",
100017
- negotiationId,
100018
- offerId
100019
- });
100020
- this.render();
100021
- this.pollNegotiationStatus(assetId, negotiationId);
100022
- } catch (error2) {
100023
- console.error("Contract negotiation failed:", error2);
100024
- this.negotiations.set(dataset["@id"], {
100025
- status: "failed",
100026
- error: error2.message
100027
- });
100028
- this.render();
100029
- }
100030
- },
100031
- async pollNegotiationStatus(assetId, negotiationId) {
100032
- const maxAttempts = 60;
100033
- const pollInterval = 5e3;
100034
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
100035
- try {
100036
- if (!this.store) {
100037
- console.error("Store not available for polling");
100038
- return;
100039
- }
100040
- const store2 = this.store;
100041
- const status = await store2.getNegotiationStatus(negotiationId);
100042
- this.negotiations.set(assetId, {
100043
- status: "pending",
100044
- negotiationId,
100045
- currentState: status.state,
100046
- attempt: attempt + 1,
100047
- maxAttempts
100048
- });
100049
- this.render();
100050
- if (status.state === "FINALIZED" || status.state === "AGREED") {
100051
- this.negotiations.set(assetId, {
100052
- status: "granted",
100053
- negotiationId,
100054
- contractId: status.contractAgreementId || negotiationId
100055
- });
100056
- this.render();
100057
- return;
100058
- }
100059
- if (status.state === "TERMINATED") {
100060
- this.negotiations.set(assetId, {
100061
- status: "failed",
100062
- error: status.errorDetail || "Negotiation terminated"
100063
- });
100064
- this.render();
100065
- return;
100066
- }
100067
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
100068
- } catch (error2) {
100069
- console.error(`Error polling negotiation status (attempt ${attempt + 1}):`, error2);
100070
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
100071
- }
100072
- }
100073
- this.negotiations.set(assetId, {
100074
- status: "failed",
100075
- error: "Negotiation timeout after 5 minutes - may still be processing on provider side"
100076
- });
100077
- this.render();
100078
- },
100079
- render() {
100080
- if (this.loading) {
100081
- B(x`<div class="loading">Loading catalog...</div>`, this.element);
100082
- return;
100083
- }
100084
- if (this.error) {
100085
- B(x`<div class="error">Error: ${this.error}</div>`, this.element);
100086
- return;
100087
- }
100088
- if (!this.datasets || this.datasets.length === 0) {
100089
- B(x`<div class="empty">No datasets found in catalog</div>`, this.element);
100090
- return;
100091
- }
100092
- const template = x`
100093
- <div class="edc-catalog-info">
100094
- ${this.catalog ? x`
100095
- <div class="catalog-header">
100096
- <h2>Catalog: ${this.catalog["@id"]}</h2>
100097
- <p>Provider: ${this.catalog.participantId}</p>
100098
- <p>Datasets: ${this.datasets.length}</p>
100099
- </div>
100100
- ` : ""}
100101
- </div>
100102
- <div class="edc-datasets-list">
100103
- ${this.datasets.map((dataset) => {
100104
- var _a3, _b, _c, _d, _e;
100105
- return x`
100106
- <div class="edc-dataset-item" data-dataset-id="${dataset["@id"]}">
100107
- <h3 class="dataset-title">
100108
- ${dataset["dcterms:title"] || ((_a3 = dataset.properties) == null ? void 0 : _a3.name) || dataset["@id"]}
100109
- </h3>
100110
- ${dataset["dcterms:description"] || ((_b = dataset.properties) == null ? void 0 : _b.description) ? x`<p class="dataset-description">
100111
- ${dataset["dcterms:description"] || ((_c = dataset.properties) == null ? void 0 : _c.description)}
100112
- </p>` : ""}
100113
- <div class="dataset-metadata">
100114
- <span class="dataset-id">ID: ${dataset["@id"]}</span>
100115
- ${dataset["dcterms:creator"] ? x`<span class="dataset-creator">Creator: ${dataset["dcterms:creator"]}</span>` : ""}
100116
- ${((_d = dataset["dcat:keyword"]) == null ? void 0 : _d.length) > 0 ? x`<span class="dataset-keywords">Keywords: ${dataset["dcat:keyword"].join(", ")}</span>` : ""}
100117
- ${((_e = dataset["odrl:hasPolicy"]) == null ? void 0 : _e.length) > 0 ? x`<span class="dataset-policies">Policies: ${dataset["odrl:hasPolicy"].length}</span>` : ""}
100118
- </div>
100119
- <div class="dataset-actions">
100120
- ${this.renderNegotiationButton(dataset)}
100121
- </div>
100122
- </div>
100123
- `;
100124
- })}
100125
- </div>
100126
- `;
100127
- B(template, this.element);
100128
- },
100129
- renderNegotiationButton(dataset) {
100130
- const assetId = dataset["@id"];
100131
- const negotiation = this.negotiations.get(assetId);
100132
- if (!dataset["odrl:hasPolicy"] || dataset["odrl:hasPolicy"].length === 0) {
100133
- return x`<span class="no-policy">No policies available</span>`;
100134
- }
100135
- if (negotiation) {
100136
- switch (negotiation.status) {
100137
- case "negotiating":
100138
- return x`<button class="negotiate-btn negotiating" disabled>
100139
- Negotiating...
100140
- </button>`;
100141
- case "pending":
100142
- return x`<div class="negotiation-info">
100143
- <span class="negotiation-id">Negotiation: ${negotiation.negotiationId}</span>
100144
- <span class="negotiation-status pending">
100145
- ${negotiation.currentState || "Pending"}
100146
- ${negotiation.attempt ? `(${negotiation.attempt}/${negotiation.maxAttempts})` : ""}
100147
- </span>
100148
- </div>`;
100149
- case "granted":
100150
- return x`<div class="negotiation-success">
100151
- <span class="access-granted">✅ Access Granted</span>
100152
- <span class="contract-id">Contract: ${negotiation.contractId}</span>
100153
- <button class="api-ready-btn" disabled>
100154
- API Ready
100155
- </button>
100156
- </div>`;
100157
- case "failed":
100158
- return x`<div class="negotiation-error">
100159
- <span>Failed: ${negotiation.error}</span>
100160
- <button class="negotiate-btn retry" @click=${() => this.negotiateAccess(dataset)}>
100161
- Retry
100162
- </button>
100163
- </div>`;
100164
- default:
100165
- return x`<button class="negotiate-btn" @click=${() => this.negotiateAccess(dataset)}>
100166
- Negotiate Access
100167
- </button>`;
100168
- }
100169
- }
100170
- return x`<button class="negotiate-btn" @click=${() => this.negotiateAccess(dataset)}>
100171
- Negotiate Access (${dataset["odrl:hasPolicy"].length} ${dataset["odrl:hasPolicy"].length === 1 ? "offer" : "offers"})
100172
- </button>`;
100173
- }
100174
- };
100175
- Sib.register(EdcCatalogDisplay);
100176
- class ProviderRegistry {
100177
- constructor(initialProviders) {
100178
- __publicField(this, "providers", /* @__PURE__ */ new Map());
100179
- if (initialProviders) {
100180
- for (const provider of initialProviders) {
100181
- this.addProvider(provider);
100182
- }
100183
- }
100184
- }
100185
- addProvider(provider) {
100186
- this.providers.set(provider.protocolAddress, provider);
100187
- }
100188
- getProviderByAddress(protocolAddress) {
100189
- return this.providers.get(protocolAddress);
100190
- }
100191
- getProviderByParticipantId(participantId) {
100192
- return Array.from(this.providers.values()).find((provider) => provider.participantId === participantId);
100193
- }
100194
- getAllProviders() {
100195
- return Array.from(this.providers.values());
100196
- }
100197
- removeProvider(protocolAddress) {
100198
- return this.providers.delete(protocolAddress);
100199
- }
100200
- updateProviderStatus(protocolAddress, status) {
100201
- const provider = this.providers.get(protocolAddress);
100202
- if (provider) {
100203
- provider.status = status;
100204
- provider.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
100205
- }
100206
- }
100207
- static fromConfig(config2) {
100208
- return new ProviderRegistry(config2.providers);
100209
- }
100210
- toConfig() {
100211
- return {
100212
- providers: this.getAllProviders()
100213
- };
100214
- }
100215
- }
100216
99835
  EdcFederatedCatalogDisplay = {
100217
- name: "edc-federated-catalog-display",
99836
+ name: "dsp-catalog-display",
100218
99837
  use: [
100219
99838
  WidgetMixin,
100220
99839
  AttributeBinderMixin
@@ -100257,6 +99876,18 @@ ${escapeText(this.code(index2, length))}
100257
99876
  }
100258
99877
  }
100259
99878
  },
99879
+ apiGateway: {
99880
+ type: String,
99881
+ default: null,
99882
+ callback: function(value) {
99883
+ try {
99884
+ this._apiGatewayConfig = value ? JSON.parse(value) : null;
99885
+ } catch (error2) {
99886
+ console.error("Failed to parse api-gateway JSON:", error2);
99887
+ this._apiGatewayConfig = null;
99888
+ }
99889
+ }
99890
+ },
100260
99891
  defaultWidget: {
100261
99892
  type: String,
100262
99893
  default: "edc-federated-dataset-item"
@@ -100278,6 +99909,7 @@ ${escapeText(this.code(index2, length))}
100278
99909
  negotiations: /* @__PURE__ */ new Map(),
100279
99910
  stores: /* @__PURE__ */ new Map(),
100280
99911
  _providersArray: [],
99912
+ _apiGatewayConfig: null,
100281
99913
  providerStats: /* @__PURE__ */ new Map(),
100282
99914
  selectedProviders: /* @__PURE__ */ new Set(),
100283
99915
  searchQuery: "",
@@ -100615,6 +100247,151 @@ ${escapeText(this.code(index2, length))}
100615
100247
  });
100616
100248
  this.render();
100617
100249
  },
100250
+ async getKeycloakAccessToken() {
100251
+ if (!this._apiGatewayConfig) {
100252
+ throw new Error("API Gateway configuration not provided");
100253
+ }
100254
+ const { keycloakUrl, realm, clientId, clientSecret, username, password } = this._apiGatewayConfig;
100255
+ if (!keycloakUrl || !realm || !clientId || !clientSecret || !username || !password) {
100256
+ throw new Error("Incomplete API Gateway configuration");
100257
+ }
100258
+ const tokenUrl = `${keycloakUrl}/realms/${realm}/protocol/openid-connect/token`;
100259
+ const params = new URLSearchParams({
100260
+ grant_type: "password",
100261
+ client_id: clientId,
100262
+ client_secret: clientSecret,
100263
+ scope: "openid",
100264
+ username,
100265
+ password
100266
+ });
100267
+ const response = await fetch(tokenUrl, {
100268
+ method: "POST",
100269
+ headers: {
100270
+ "Content-Type": "application/x-www-form-urlencoded"
100271
+ },
100272
+ body: params.toString()
100273
+ });
100274
+ if (!response.ok) {
100275
+ const errorText = await response.text();
100276
+ throw new Error(`Failed to get Keycloak access token: ${response.status} - ${errorText}`);
100277
+ }
100278
+ const data = await response.json();
100279
+ return data.access_token;
100280
+ },
100281
+ async getApiGatewayToken(accessToken, contractAgreementId) {
100282
+ if (!this._apiGatewayConfig) {
100283
+ throw new Error("API Gateway configuration not provided");
100284
+ }
100285
+ const { apiGatewayBaseUrl } = this._apiGatewayConfig;
100286
+ if (!apiGatewayBaseUrl) {
100287
+ throw new Error("API Gateway base URL not configured");
100288
+ }
100289
+ const tokenUrl = `${apiGatewayBaseUrl}/token`;
100290
+ const response = await fetch(tokenUrl, {
100291
+ method: "POST",
100292
+ headers: {
100293
+ "Content-Type": "application/json",
100294
+ Authorization: `Bearer ${accessToken}`
100295
+ },
100296
+ body: JSON.stringify({
100297
+ agreementId: contractAgreementId
100298
+ })
100299
+ });
100300
+ if (!response.ok) {
100301
+ const errorText = await response.text();
100302
+ throw new Error(`Failed to get API Gateway token: ${response.status} - ${errorText}`);
100303
+ }
100304
+ const data = await response.json();
100305
+ return data.apiGatewayToken || data.token;
100306
+ },
100307
+ async accessDataViaApiGateway(federatedDataset, negotiation) {
100308
+ const { dataset, provider } = federatedDataset;
100309
+ const assetId = dataset["@id"];
100310
+ const negotiationKey = `${assetId}@${provider.address}`;
100311
+ try {
100312
+ this.negotiations.set(negotiationKey, {
100313
+ ...negotiation,
100314
+ status: "getting-api-gateway-token"
100315
+ });
100316
+ this.render();
100317
+ const keycloakAccessToken = await this.getKeycloakAccessToken();
100318
+ const apiGatewayToken = await this.getApiGatewayToken(keycloakAccessToken, negotiation.contractId);
100319
+ this.negotiations.set(negotiationKey, {
100320
+ ...negotiation,
100321
+ status: "granted",
100322
+ apiGatewayToken
100323
+ });
100324
+ this.render();
100325
+ } catch (error2) {
100326
+ console.error("API Gateway token retrieval failed:", error2);
100327
+ this.negotiations.set(negotiationKey, {
100328
+ ...negotiation,
100329
+ status: "granted",
100330
+ apiGatewayError: error2.message
100331
+ });
100332
+ this.render();
100333
+ }
100334
+ },
100335
+ async fetchDataViaApiGateway(federatedDataset, negotiation) {
100336
+ var _a3;
100337
+ const { dataset, provider } = federatedDataset;
100338
+ const assetId = dataset["@id"];
100339
+ const negotiationKey = `${assetId}@${provider.address}`;
100340
+ try {
100341
+ this.negotiations.set(negotiationKey, {
100342
+ ...negotiation,
100343
+ status: "accessing-data-via-gateway"
100344
+ });
100345
+ this.render();
100346
+ if (!negotiation.apiGatewayToken) {
100347
+ throw new Error("API Gateway token not available");
100348
+ }
100349
+ if (!((_a3 = this._apiGatewayConfig) == null ? void 0 : _a3.apiGatewayBaseUrl)) {
100350
+ throw new Error("API Gateway base URL not configured");
100351
+ }
100352
+ const distributionsRaw = dataset["dcat:distribution"] || [];
100353
+ const distributions = Array.isArray(distributionsRaw) ? distributionsRaw : [
100354
+ distributionsRaw
100355
+ ];
100356
+ let endpointUrl = "";
100357
+ if (distributions.length > 0 && distributions[0]["dcat:accessService"]) {
100358
+ endpointUrl = distributions[0]["dcat:accessService"]["dcat:endpointUrl"] || distributions[0]["dcat:accessService"];
100359
+ }
100360
+ if (!endpointUrl) {
100361
+ throw new Error("No endpoint URL found in dataset distribution");
100362
+ }
100363
+ const response = await fetch(endpointUrl, {
100364
+ method: "GET",
100365
+ headers: {
100366
+ "X-API-Gateway-Token": negotiation.apiGatewayToken
100367
+ }
100368
+ });
100369
+ if (!response.ok) {
100370
+ const errorText = await response.text();
100371
+ throw new Error(`Failed to fetch data via API Gateway: ${response.status} - ${errorText}`);
100372
+ }
100373
+ const data = await response.json();
100374
+ const preview = JSON.stringify(data, null, 2).substring(0, 500);
100375
+ alert(`Data retrieved successfully via API Gateway!
100376
+
100377
+ Preview (first 500 chars):
100378
+ ${preview}${JSON.stringify(data).length > 500 ? "..." : ""}`);
100379
+ this.negotiations.set(negotiationKey, {
100380
+ ...negotiation,
100381
+ status: "granted"
100382
+ });
100383
+ this.render();
100384
+ } catch (error2) {
100385
+ console.error("Data access via API Gateway failed:", error2);
100386
+ this.negotiations.set(negotiationKey, {
100387
+ ...negotiation,
100388
+ status: "granted",
100389
+ dataAccessError: error2.message
100390
+ });
100391
+ this.render();
100392
+ alert(`Data access failed: ${error2.message}`);
100393
+ }
100394
+ },
100618
100395
  async initiateEDRTransfer(federatedDataset, negotiation) {
100619
100396
  const { dataset, provider } = federatedDataset;
100620
100397
  const assetId = dataset["@id"];
@@ -100889,15 +100666,15 @@ ${preview}${JSON.stringify(data).length > 500 ? "..." : ""}`);
100889
100666
  <div class="federated-dataset-item" data-dataset-id="${dataset["@id"]}" data-provider="${provider.address}">
100890
100667
  <div class="dataset-header">
100891
100668
  <h3 class="dataset-title">
100892
- ${dataset["dcterms:title"] || dataset["dct:title"] || ((_a3 = dataset.properties) == null ? void 0 : _a3.name) || dataset["@id"]}
100669
+ ${dataset["dcterms:title"] || dataset["dct:title"] || dataset["dcat:service"]["dct:title"] || ((_a3 = dataset.properties) == null ? void 0 : _a3.name) || dataset["@id"]}
100893
100670
  </h3>
100894
100671
  <div class="provider-badge" style="background-color: ${provider.color || "#1976d2"}">
100895
100672
  ${provider.name}
100896
100673
  </div>
100897
100674
  </div>
100898
100675
 
100899
- ${dataset["rdfs:comment"] || ((_b = dataset.properties) == null ? void 0 : _b.description) ? x`<p class="dataset-description">
100900
- ${dataset["rdfs:comment"] || ((_c = dataset.properties) == null ? void 0 : _c.description)}
100676
+ ${dataset["rdfs:comment"] || dataset["dcat:service"]["rdfs:comment"] || ((_b = dataset.properties) == null ? void 0 : _b.description) ? x`<p class="dataset-description">
100677
+ ${dataset["rdfs:comment"] || dataset["dcat:service"]["rdfs:comment"] || ((_c = dataset.properties) == null ? void 0 : _c.description)}
100901
100678
  </p>` : ""}
100902
100679
 
100903
100680
  <div class="dataset-metadata">
@@ -100972,7 +100749,24 @@ ${preview}${JSON.stringify(data).length > 500 ? "..." : ""}`);
100972
100749
  </div>` : ""}
100973
100750
  </div>`;
100974
100751
  }
100975
- case "granted":
100752
+ case "getting-api-gateway-token":
100753
+ return x`<div class="negotiation-info">
100754
+ <span class="negotiation-provider">Provider: ${provider.name}</span>
100755
+ <span class="contract-id">Contract: ${negotiation.contractId}</span>
100756
+ <span class="negotiation-status pending">
100757
+ <span class="spinner">🔑</span> Getting API Gateway Token...
100758
+ </span>
100759
+ </div>`;
100760
+ case "accessing-data-via-gateway":
100761
+ return x`<div class="negotiation-info">
100762
+ <span class="negotiation-provider">Provider: ${provider.name}</span>
100763
+ <span class="contract-id">Contract: ${negotiation.contractId}</span>
100764
+ <span class="negotiation-status pending">
100765
+ <span class="spinner">📡</span> Accessing Data via API Gateway...
100766
+ </span>
100767
+ </div>`;
100768
+ case "granted": {
100769
+ const useApiGateway = !!this._apiGatewayConfig;
100976
100770
  return x`<div class="negotiation-success">
100977
100771
  <span class="access-granted">✅ Access Granted via ${provider.name}</span>
100978
100772
  <span class="contract-id">Contract: ${negotiation.contractId}</span>
@@ -100982,19 +100776,39 @@ ${preview}${JSON.stringify(data).length > 500 ? "..." : ""}`);
100982
100776
  🔄 Retry EDR
100983
100777
  </button>
100984
100778
  ` : ""}
100779
+ ${negotiation.apiGatewayError ? x`
100780
+ <span class="transfer-error">⚠️ ${negotiation.apiGatewayError}</span>
100781
+ <button class="negotiate-btn retry" @click=${() => this.accessDataViaApiGateway(item, negotiation)}>
100782
+ 🔄 Retry API Gateway
100783
+ </button>
100784
+ ` : ""}
100985
100785
  <div class="api-access-actions">
100986
- ${!negotiation.edrToken ? x`
100987
- <button class="negotiate-btn" @click=${() => this.initiateEDRTransfer(item, negotiation)}>
100988
- 🚀 Get EDR Token
100989
- </button>
100990
- ` : x`
100991
- <span class="edr-ready">🔑 EDR Token Ready</span>
100992
- <button class="negotiate-btn" @click=${() => this.accessData(item, negotiation)}>
100993
- 📁 Access Data
100994
- </button>
100995
- `}
100786
+ ${useApiGateway ? x`
100787
+ ${!negotiation.apiGatewayToken ? x`
100788
+ <button class="negotiate-btn" @click=${() => this.accessDataViaApiGateway(item, negotiation)}>
100789
+ 🔑 Get API Gateway Token
100790
+ </button>
100791
+ ` : x`
100792
+ <span class="edr-ready">🔑 API Gateway Token Ready</span>
100793
+ <button class="negotiate-btn" @click=${() => this.fetchDataViaApiGateway(item, negotiation)}>
100794
+ 📁 Access Data via API Gateway
100795
+ </button>
100796
+ `}
100797
+ ` : x`
100798
+ ${!negotiation.edrToken ? x`
100799
+ <button class="negotiate-btn" @click=${() => this.initiateEDRTransfer(item, negotiation)}>
100800
+ 🚀 Get EDR Token
100801
+ </button>
100802
+ ` : x`
100803
+ <span class="edr-ready">🔑 EDR Token Ready</span>
100804
+ <button class="negotiate-btn" @click=${() => this.accessData(item, negotiation)}>
100805
+ 📁 Access Data
100806
+ </button>
100807
+ `}
100808
+ `}
100996
100809
  </div>
100997
100810
  </div>`;
100811
+ }
100998
100812
  case "failed":
100999
100813
  return x`<div class="negotiation-error">
101000
100814
  <span>Failed with ${provider.name}: ${negotiation.error}</span>
@@ -101014,6 +100828,387 @@ ${preview}${JSON.stringify(data).length > 500 ? "..." : ""}`);
101014
100828
  }
101015
100829
  };
101016
100830
  Sib.register(EdcFederatedCatalogDisplay);
100831
+ EdcAssetsDisplay = {
100832
+ name: "edc-assets-display",
100833
+ use: [
100834
+ WidgetMixin,
100835
+ AttributeBinderMixin
100836
+ ],
100837
+ attributes: {
100838
+ connectorUri: {
100839
+ type: String,
100840
+ default: null,
100841
+ callback: function(value) {
100842
+ if (value && this.apiKey) {
100843
+ this.fetchAssets();
100844
+ }
100845
+ }
100846
+ },
100847
+ apiKey: {
100848
+ type: String,
100849
+ default: null,
100850
+ callback: function(value) {
100851
+ if (value && this.connectorUri) {
100852
+ this.fetchAssets();
100853
+ }
100854
+ }
100855
+ },
100856
+ defaultWidget: {
100857
+ type: String,
100858
+ default: "edc-asset-item"
100859
+ }
100860
+ },
100861
+ initialState: {
100862
+ assets: [],
100863
+ loading: false,
100864
+ error: null
100865
+ },
100866
+ created() {
100867
+ if (this.connectorUri && this.apiKey) {
100868
+ this.fetchAssets();
100869
+ }
100870
+ },
100871
+ async fetchAssets() {
100872
+ if (!this.connectorUri || !this.apiKey) return;
100873
+ this.loading = true;
100874
+ this.error = null;
100875
+ this.render();
100876
+ try {
100877
+ const config2 = {
100878
+ type: StoreType.DataspaceConnector,
100879
+ endpoint: this.connectorUri,
100880
+ catalogEndpoint: `${this.connectorUri}/v3/catalog/request`,
100881
+ contractNegotiationEndpoint: `${this.connectorUri}/v3/contractnegotiations`,
100882
+ transferProcessEndpoint: `${this.connectorUri}/v3/transferprocesses`,
100883
+ assetsEndpoint: `${this.connectorUri}/v3/assets/request`,
100884
+ authMethod: "edc-api-key",
100885
+ edcApiKey: this.apiKey,
100886
+ retryAttempts: 3,
100887
+ timeout: 3e4
100888
+ };
100889
+ const store2 = StoreFactory.create(config2);
100890
+ const assetsRaw = await store2.getAssets();
100891
+ this.assets = Array.isArray(assetsRaw) ? assetsRaw : assetsRaw ? [
100892
+ assetsRaw
100893
+ ] : [];
100894
+ } catch (error2) {
100895
+ console.error("Failed to fetch EDC assets:", error2);
100896
+ this.error = error2.message;
100897
+ this.assets = [];
100898
+ } finally {
100899
+ this.loading = false;
100900
+ this.render();
100901
+ }
100902
+ },
100903
+ render() {
100904
+ if (this.loading) {
100905
+ B(x`<div class="loading">Loading assets...</div>`, this.element);
100906
+ return;
100907
+ }
100908
+ if (this.error) {
100909
+ B(x`<div class="error">Error: ${this.error}</div>`, this.element);
100910
+ return;
100911
+ }
100912
+ if (!this.assets || this.assets.length === 0) {
100913
+ B(x`<div class="empty">No assets found</div>`, this.element);
100914
+ return;
100915
+ }
100916
+ const template = x`
100917
+ <div class="edc-assets-list">
100918
+ ${this.assets.map((asset) => {
100919
+ var _a3, _b, _c, _d;
100920
+ return x`
100921
+ <div class="edc-asset-item" data-asset-id="${asset["@id"]}">
100922
+ <h3 class="asset-title">
100923
+ ${asset["dcterms:title"] || ((_a3 = asset.properties) == null ? void 0 : _a3.name) || asset["@id"]}
100924
+ </h3>
100925
+ ${asset["dcterms:description"] || ((_b = asset.properties) == null ? void 0 : _b.description) ? x`<p class="asset-description">
100926
+ ${asset["dcterms:description"] || ((_c = asset.properties) == null ? void 0 : _c.description)}
100927
+ </p>` : ""}
100928
+ <div class="asset-metadata">
100929
+ <span class="asset-id">ID: ${asset["@id"]}</span>
100930
+ ${((_d = asset.properties) == null ? void 0 : _d["https://w3id.org/edc/v0.0.1/ns/type"]) ? x`<span class="asset-type">
100931
+ Type: ${asset.properties["https://w3id.org/edc/v0.0.1/ns/type"]}
100932
+ </span>` : ""}
100933
+ </div>
100934
+ </div>
100935
+ `;
100936
+ })}
100937
+ </div>
100938
+ `;
100939
+ B(template, this.element);
100940
+ }
100941
+ };
100942
+ Sib.register(EdcAssetsDisplay);
100943
+ EdcCatalogDisplay = {
100944
+ name: "edc-catalog-display",
100945
+ use: [
100946
+ WidgetMixin,
100947
+ AttributeBinderMixin
100948
+ ],
100949
+ attributes: {
100950
+ connectorUri: {
100951
+ type: String,
100952
+ default: null,
100953
+ callback: function(value) {
100954
+ if (value && this.apiKey && this.counterPartyAddress) {
100955
+ this.fetchCatalog();
100956
+ }
100957
+ }
100958
+ },
100959
+ apiKey: {
100960
+ type: String,
100961
+ default: null,
100962
+ callback: function(value) {
100963
+ if (value && this.connectorUri && this.counterPartyAddress) {
100964
+ this.fetchCatalog();
100965
+ }
100966
+ }
100967
+ },
100968
+ counterPartyAddress: {
100969
+ type: String,
100970
+ default: null,
100971
+ callback: function(value) {
100972
+ if (value && this.connectorUri && this.apiKey) {
100973
+ this.fetchCatalog();
100974
+ }
100975
+ }
100976
+ },
100977
+ defaultWidget: {
100978
+ type: String,
100979
+ default: "edc-dataset-item"
100980
+ }
100981
+ },
100982
+ initialState: {
100983
+ catalog: null,
100984
+ datasets: [],
100985
+ loading: false,
100986
+ error: null,
100987
+ negotiations: /* @__PURE__ */ new Map(),
100988
+ store: null
100989
+ },
100990
+ created() {
100991
+ if (this.connectorUri && this.apiKey && this.counterPartyAddress) {
100992
+ this.fetchCatalog();
100993
+ }
100994
+ },
100995
+ async fetchCatalog() {
100996
+ if (!this.connectorUri || !this.apiKey || !this.counterPartyAddress) return;
100997
+ this.loading = true;
100998
+ this.error = null;
100999
+ this.render();
101000
+ try {
101001
+ const config2 = {
101002
+ type: StoreType.DataspaceConnector,
101003
+ endpoint: this.connectorUri,
101004
+ catalogEndpoint: `${this.connectorUri}/v3/catalog/request`,
101005
+ contractNegotiationEndpoint: `${this.connectorUri}/v3/contractnegotiations`,
101006
+ transferProcessEndpoint: `${this.connectorUri}/v3/transferprocesses`,
101007
+ authMethod: "edc-api-key",
101008
+ edcApiKey: this.apiKey,
101009
+ retryAttempts: 8,
101010
+ timeout: 1e4
101011
+ };
101012
+ const store2 = StoreFactory.create(config2);
101013
+ const catalog = await store2.getCatalog(this.counterPartyAddress);
101014
+ this.catalog = catalog;
101015
+ this.datasets = (catalog == null ? void 0 : catalog["dcat:dataset"]) || [];
101016
+ this.store = store2;
101017
+ } catch (error2) {
101018
+ console.error("Failed to fetch EDC catalog:", error2);
101019
+ this.error = error2.message;
101020
+ this.catalog = null;
101021
+ this.datasets = [];
101022
+ } finally {
101023
+ this.loading = false;
101024
+ this.render();
101025
+ }
101026
+ },
101027
+ async negotiateAccess(dataset) {
101028
+ if (!dataset["odrl:hasPolicy"] || dataset["odrl:hasPolicy"].length === 0) {
101029
+ console.error("No policies available for dataset:", dataset["@id"]);
101030
+ return;
101031
+ }
101032
+ try {
101033
+ const offer = dataset["odrl:hasPolicy"][0];
101034
+ const offerId = offer["@id"];
101035
+ const assetId = dataset["@id"];
101036
+ this.negotiations.set(assetId, {
101037
+ status: "negotiating",
101038
+ offerId
101039
+ });
101040
+ this.render();
101041
+ if (!this.store) {
101042
+ console.error("Store not available for negotiation");
101043
+ return;
101044
+ }
101045
+ const store2 = this.store;
101046
+ const modifiedOffer = {
101047
+ ...offer,
101048
+ target: assetId
101049
+ };
101050
+ const negotiationId = await store2.initiateNegotiation(this.counterPartyAddress, assetId, modifiedOffer);
101051
+ this.negotiations.set(assetId, {
101052
+ status: "pending",
101053
+ negotiationId,
101054
+ offerId
101055
+ });
101056
+ this.render();
101057
+ this.pollNegotiationStatus(assetId, negotiationId);
101058
+ } catch (error2) {
101059
+ console.error("Contract negotiation failed:", error2);
101060
+ this.negotiations.set(dataset["@id"], {
101061
+ status: "failed",
101062
+ error: error2.message
101063
+ });
101064
+ this.render();
101065
+ }
101066
+ },
101067
+ async pollNegotiationStatus(assetId, negotiationId) {
101068
+ const maxAttempts = 60;
101069
+ const pollInterval = 5e3;
101070
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
101071
+ try {
101072
+ if (!this.store) {
101073
+ console.error("Store not available for polling");
101074
+ return;
101075
+ }
101076
+ const store2 = this.store;
101077
+ const status = await store2.getNegotiationStatus(negotiationId);
101078
+ this.negotiations.set(assetId, {
101079
+ status: "pending",
101080
+ negotiationId,
101081
+ currentState: status.state,
101082
+ attempt: attempt + 1,
101083
+ maxAttempts
101084
+ });
101085
+ this.render();
101086
+ if (status.state === "FINALIZED" || status.state === "AGREED") {
101087
+ this.negotiations.set(assetId, {
101088
+ status: "granted",
101089
+ negotiationId,
101090
+ contractId: status.contractAgreementId || negotiationId
101091
+ });
101092
+ this.render();
101093
+ return;
101094
+ }
101095
+ if (status.state === "TERMINATED") {
101096
+ this.negotiations.set(assetId, {
101097
+ status: "failed",
101098
+ error: status.errorDetail || "Negotiation terminated"
101099
+ });
101100
+ this.render();
101101
+ return;
101102
+ }
101103
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
101104
+ } catch (error2) {
101105
+ console.error(`Error polling negotiation status (attempt ${attempt + 1}):`, error2);
101106
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
101107
+ }
101108
+ }
101109
+ this.negotiations.set(assetId, {
101110
+ status: "failed",
101111
+ error: "Negotiation timeout after 5 minutes - may still be processing on provider side"
101112
+ });
101113
+ this.render();
101114
+ },
101115
+ render() {
101116
+ if (this.loading) {
101117
+ B(x`<div class="loading">Loading catalog...</div>`, this.element);
101118
+ return;
101119
+ }
101120
+ if (this.error) {
101121
+ B(x`<div class="error">Error: ${this.error}</div>`, this.element);
101122
+ return;
101123
+ }
101124
+ if (!this.datasets || this.datasets.length === 0) {
101125
+ B(x`<div class="empty">No datasets found in catalog</div>`, this.element);
101126
+ return;
101127
+ }
101128
+ const template = x`
101129
+ <div class="edc-catalog-info">
101130
+ ${this.catalog ? x`
101131
+ <div class="catalog-header">
101132
+ <h2>Catalog: ${this.catalog["@id"]}</h2>
101133
+ <p>Provider: ${this.catalog.participantId}</p>
101134
+ <p>Datasets: ${this.datasets.length}</p>
101135
+ </div>
101136
+ ` : ""}
101137
+ </div>
101138
+ <div class="edc-datasets-list">
101139
+ ${this.datasets.map((dataset) => {
101140
+ var _a3, _b, _c, _d, _e;
101141
+ return x`
101142
+ <div class="edc-dataset-item" data-dataset-id="${dataset["@id"]}">
101143
+ <h3 class="dataset-title">
101144
+ ${dataset["dcterms:title"] || ((_a3 = dataset.properties) == null ? void 0 : _a3.name) || dataset["@id"]}
101145
+ </h3>
101146
+ ${dataset["dcterms:description"] || ((_b = dataset.properties) == null ? void 0 : _b.description) ? x`<p class="dataset-description">
101147
+ ${dataset["dcterms:description"] || ((_c = dataset.properties) == null ? void 0 : _c.description)}
101148
+ </p>` : ""}
101149
+ <div class="dataset-metadata">
101150
+ <span class="dataset-id">ID: ${dataset["@id"]}</span>
101151
+ ${dataset["dcterms:creator"] ? x`<span class="dataset-creator">Creator: ${dataset["dcterms:creator"]}</span>` : ""}
101152
+ ${((_d = dataset["dcat:keyword"]) == null ? void 0 : _d.length) > 0 ? x`<span class="dataset-keywords">Keywords: ${dataset["dcat:keyword"].join(", ")}</span>` : ""}
101153
+ ${((_e = dataset["odrl:hasPolicy"]) == null ? void 0 : _e.length) > 0 ? x`<span class="dataset-policies">Policies: ${dataset["odrl:hasPolicy"].length}</span>` : ""}
101154
+ </div>
101155
+ <div class="dataset-actions">
101156
+ ${this.renderNegotiationButton(dataset)}
101157
+ </div>
101158
+ </div>
101159
+ `;
101160
+ })}
101161
+ </div>
101162
+ `;
101163
+ B(template, this.element);
101164
+ },
101165
+ renderNegotiationButton(dataset) {
101166
+ const assetId = dataset["@id"];
101167
+ const negotiation = this.negotiations.get(assetId);
101168
+ if (!dataset["odrl:hasPolicy"] || dataset["odrl:hasPolicy"].length === 0) {
101169
+ return x`<span class="no-policy">No policies available</span>`;
101170
+ }
101171
+ if (negotiation) {
101172
+ switch (negotiation.status) {
101173
+ case "negotiating":
101174
+ return x`<button class="negotiate-btn negotiating" disabled>
101175
+ Negotiating...
101176
+ </button>`;
101177
+ case "pending":
101178
+ return x`<div class="negotiation-info">
101179
+ <span class="negotiation-id">Negotiation: ${negotiation.negotiationId}</span>
101180
+ <span class="negotiation-status pending">
101181
+ ${negotiation.currentState || "Pending"}
101182
+ ${negotiation.attempt ? `(${negotiation.attempt}/${negotiation.maxAttempts})` : ""}
101183
+ </span>
101184
+ </div>`;
101185
+ case "granted":
101186
+ return x`<div class="negotiation-success">
101187
+ <span class="access-granted">✅ Access Granted</span>
101188
+ <span class="contract-id">Contract: ${negotiation.contractId}</span>
101189
+ <button class="api-ready-btn" disabled>
101190
+ API Ready
101191
+ </button>
101192
+ </div>`;
101193
+ case "failed":
101194
+ return x`<div class="negotiation-error">
101195
+ <span>Failed: ${negotiation.error}</span>
101196
+ <button class="negotiate-btn retry" @click=${() => this.negotiateAccess(dataset)}>
101197
+ Retry
101198
+ </button>
101199
+ </div>`;
101200
+ default:
101201
+ return x`<button class="negotiate-btn" @click=${() => this.negotiateAccess(dataset)}>
101202
+ Negotiate Access
101203
+ </button>`;
101204
+ }
101205
+ }
101206
+ return x`<button class="negotiate-btn" @click=${() => this.negotiateAccess(dataset)}>
101207
+ Negotiate Access (${dataset["odrl:hasPolicy"].length} ${dataset["odrl:hasPolicy"].length === 1 ? "offer" : "offers"})
101208
+ </button>`;
101209
+ }
101210
+ };
101211
+ Sib.register(EdcCatalogDisplay);
101017
101212
  CounterMixin = {
101018
101213
  name: "counter-mixin",
101019
101214
  use: [],