@startinblox/components-ds4go 3.3.8 → 4.0.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.
@@ -0,0 +1,110 @@
1
+ import { localized, msg } from "@lit/localize";
2
+ import { html, nothing, type TemplateResult } from "lit";
3
+ import { customElement, property } from "lit/decorators.js";
4
+ import { LitElement } from "lit";
5
+ import type { DSPOffer, AgreementInfo } from "@src/ds4go";
6
+
7
+ /**
8
+ * Agreement info component for displaying contract agreement details
9
+ */
10
+ @customElement("catalog-modal-agreement-info")
11
+ @localized()
12
+ export class CatalogModalAgreementInfo extends LitElement {
13
+ @property({ attribute: false })
14
+ offer?: DSPOffer;
15
+
16
+ @property({ attribute: false })
17
+ agreementInfo?: AgreementInfo;
18
+
19
+ @property({ attribute: false })
20
+ contractId?: string;
21
+
22
+ private _handleRenewContract(): void {
23
+ this.dispatchEvent(
24
+ new CustomEvent("renew-contract", {
25
+ bubbles: true,
26
+ composed: true,
27
+ }),
28
+ );
29
+ }
30
+
31
+ render(): TemplateResult | typeof nothing {
32
+ // Only show if we have agreement info
33
+ if (!this.contractId || !this.agreementInfo) {
34
+ return nothing;
35
+ }
36
+
37
+ const agreementDate = this.agreementInfo.timestamp
38
+ ? new Date(this.agreementInfo.timestamp).toLocaleString()
39
+ : null;
40
+
41
+ // Get endpoint URL from asset
42
+ const endpointUrl = this.offer?.["dcat:endpointUrl"];
43
+
44
+ return html`<div
45
+ style="margin-top: 24px; padding: 16px; background: #e8f5e9; border-radius: 8px;"
46
+ >
47
+ <tems-division type="h4"
48
+ ><div>${msg("Contract Agreement")}</div></tems-division
49
+ >
50
+ <div style="font-size: 0.9em; margin-top: 12px;">
51
+ <div style="margin-bottom: 8px;">
52
+ <strong>✅ ${msg("Agreement ID:")}</strong>
53
+ <div
54
+ style="font-family: monospace; background: white; padding: 8px; border-radius: 4px; margin-top: 4px; word-break: break-all;"
55
+ >
56
+ ${this.contractId}
57
+ </div>
58
+ </div>
59
+
60
+ ${endpointUrl
61
+ ? html`
62
+ <div style="margin-bottom: 8px;">
63
+ <strong>🔗 ${msg("Endpoint URL:")}</strong>
64
+ <div
65
+ style="font-family: monospace; background: white; padding: 8px; border-radius: 4px; margin-top: 4px; word-break: break-all;"
66
+ >
67
+ ${endpointUrl}
68
+ </div>
69
+ </div>
70
+ `
71
+ : nothing}
72
+ ${agreementDate
73
+ ? html`
74
+ <div style="opacity: 0.8; font-size: 0.85em;">
75
+ <strong>${msg("Agreed on:")}</strong> ${agreementDate}
76
+ </div>
77
+ `
78
+ : nothing}
79
+ </div>
80
+
81
+ <div
82
+ style="margin-top: 12px; padding: 12px; background: rgba(0,0,0,0.05); border-radius: 4px; font-size: 0.85em;"
83
+ >
84
+ <div style="margin-bottom: 4px;">
85
+ <strong>â„šī¸ ${msg("Note:")}</strong>
86
+ </div>
87
+ <div>
88
+ ${msg(
89
+ "You can now use this agreement ID to access the service through the provider's API or data gateway.",
90
+ )}
91
+ </div>
92
+ </div>
93
+
94
+ ${this.agreementInfo
95
+ ? html`
96
+ <div
97
+ style="margin-top: 12px; padding-top: 12px; border-top: 1px solid rgba(0,0,0,0.1);"
98
+ >
99
+ <button
100
+ @click=${this._handleRenewContract}
101
+ style="font-size: 0.85em; color: #666; background: none; border: none; cursor: pointer; text-decoration: underline; padding: 0;"
102
+ >
103
+ 🔄 ${msg("Renegotiate contract")}
104
+ </button>
105
+ </div>
106
+ `
107
+ : nothing}
108
+ </div>`;
109
+ }
110
+ }
@@ -0,0 +1,4 @@
1
+ export { CatalogModalPolicySelection } from "./policy-selection";
2
+ export { CatalogModalPolicyDisplay } from "./policy-display";
3
+ export { CatalogModalAgreementInfo } from "./agreement-info";
4
+ export { CatalogModalNegotiationButton } from "./negotiation-button";
@@ -0,0 +1,111 @@
1
+ import { localized, msg } from "@lit/localize";
2
+ import { html, type TemplateResult } from "lit";
3
+ import { customElement, property } from "lit/decorators.js";
4
+ import { LitElement } from "lit";
5
+
6
+ /**
7
+ * Negotiation button component for handling DSP contract negotiation UI
8
+ */
9
+ @customElement("catalog-modal-negotiation-button")
10
+ @localized()
11
+ export class CatalogModalNegotiationButton extends LitElement {
12
+ @property({ attribute: false })
13
+ dspStore?: any;
14
+
15
+ @property({ attribute: false })
16
+ showPolicySelection = false;
17
+
18
+ @property()
19
+ negotiationStatus:
20
+ | "idle"
21
+ | "negotiating"
22
+ | "pending"
23
+ | "granted"
24
+ | "failed"
25
+ | "transferring" = "idle";
26
+
27
+ @property()
28
+ currentState?: string;
29
+
30
+ @property()
31
+ attempt?: number;
32
+
33
+ @property()
34
+ maxAttempts?: number;
35
+
36
+ @property()
37
+ negotiationError?: string;
38
+
39
+ private _handleNegotiate(): void {
40
+ this.dispatchEvent(
41
+ new CustomEvent("negotiate", {
42
+ bubbles: true,
43
+ composed: true,
44
+ }),
45
+ );
46
+ }
47
+
48
+ private _handleRetry(): void {
49
+ this.dispatchEvent(
50
+ new CustomEvent("retry", {
51
+ bubbles: true,
52
+ composed: true,
53
+ }),
54
+ );
55
+ }
56
+
57
+ render(): TemplateResult {
58
+ const hasDspConnector =
59
+ this.dspStore !== undefined && this.dspStore !== null;
60
+
61
+ if (!hasDspConnector) {
62
+ return html`<tems-button disabled=""
63
+ >${msg("Activate this service")}</tems-button
64
+ >`;
65
+ }
66
+
67
+ switch (this.negotiationStatus) {
68
+ case "idle":
69
+ return html`<tems-button @click=${this._handleNegotiate}
70
+ >${msg("Negotiate access")}</tems-button
71
+ >`;
72
+
73
+ case "negotiating":
74
+ return html`<tems-button disabled="">
75
+ ${msg("Negotiating...")}
76
+ </tems-button>`;
77
+
78
+ case "pending":
79
+ return html`<tems-button disabled="">
80
+ ${this.currentState || msg("Pending")}
81
+ ${this.attempt ? `(${this.attempt}/${this.maxAttempts})` : ""}
82
+ </tems-button>`;
83
+
84
+ case "granted": {
85
+ return html`
86
+ <tems-button disabled="" type="success">
87
+ ✅ ${msg("Access Granted")}
88
+ </tems-button>
89
+ `;
90
+ }
91
+
92
+ case "failed":
93
+ return html`<div
94
+ style="display: flex; flex-direction: column; gap: 8px;"
95
+ >
96
+ <tems-button disabled="" type="error">
97
+ ❌ ${msg("Failed")}:
98
+ ${this.negotiationError || msg("Unknown error")}
99
+ </tems-button>
100
+ <tems-button @click=${this._handleRetry} type="outline-gray">
101
+ ${msg("Retry")}
102
+ </tems-button>
103
+ </div>`;
104
+
105
+ default:
106
+ return html`<tems-button disabled=""
107
+ >${msg("Activate this service")}</tems-button
108
+ >`;
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,66 @@
1
+ import { localized, msg } from "@lit/localize";
2
+ import { html, nothing, type TemplateResult } from "lit";
3
+ import { customElement, property } from "lit/decorators.js";
4
+ import { LitElement } from "lit";
5
+ import { hasMultiplePolicies } from "@helpers/dsp/policyHelpers";
6
+ import type { ODRLPolicy } from "@src/ds4go";
7
+
8
+ /**
9
+ * Policy display component for showing access policy information
10
+ */
11
+ @customElement("catalog-modal-policy-display")
12
+ @localized()
13
+ export class CatalogModalPolicyDisplay extends LitElement {
14
+ @property({ attribute: false })
15
+ policy?: ODRLPolicy;
16
+
17
+ @property({ attribute: false })
18
+ policies?: ODRLPolicy[];
19
+
20
+ render(): TemplateResult | typeof nothing {
21
+ const hasMultiple = hasMultiplePolicies(this.policies || []);
22
+ const policies = this.policies || [];
23
+
24
+ // Only show if there's a policy
25
+ if (!this.policy && (!this.policies || this.policies.length === 0)) {
26
+ return nothing;
27
+ }
28
+
29
+ return html`<div
30
+ style="margin-top: 24px; padding: 16px; background: #f0f7ff; border-radius: 8px; border: 1px solid #d0e7ff;"
31
+ >
32
+ ${hasMultiple
33
+ ? html`<tems-division type="h4"
34
+ ><div>${msg("Access Policies")}</div></tems-division
35
+ >
36
+ <div style="margin-bottom: 12px; color: #0066cc; font-size: 0.9em;">
37
+ ${msg("Multiple contract policies available for this asset")}
38
+ (${policies.length})
39
+ </div>
40
+ ${policies.map(
41
+ (p: ODRLPolicy, index: number) =>
42
+ html`<div
43
+ style="margin-bottom: 16px; padding: 12px; background: white; border-radius: 6px; border-left: 4px solid #0066cc;"
44
+ >
45
+ <div
46
+ style="font-weight: 600; margin-bottom: 8px; color: #333;"
47
+ >
48
+ ${msg("Policy")} ${index + 1}
49
+ ${p["@id"]
50
+ ? html`<span
51
+ style="font-weight: normal; font-size: 0.85em; color: #666; display: block; margin-top: 4px; word-break: break-all; font-family: monospace;"
52
+ >
53
+ ${p["@id"]}
54
+ </span>`
55
+ : nothing}
56
+ </div>
57
+ <odrl-policy-viewer .policy=${p}></odrl-policy-viewer>
58
+ </div>`,
59
+ )}`
60
+ : html`<tems-division type="h4"
61
+ ><div>${msg("Access Policy")}</div></tems-division
62
+ >
63
+ <odrl-policy-viewer .policy=${this.policy}></odrl-policy-viewer>`}
64
+ </div>`;
65
+ }
66
+ }
@@ -0,0 +1,71 @@
1
+ import { localized, msg } from "@lit/localize";
2
+ import { html, nothing, type TemplateResult } from "lit";
3
+ import { customElement, property } from "lit/decorators.js";
4
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
5
+ import { LitElement } from "lit";
6
+ import { formatPolicyDetails } from "@helpers/dsp/policyHelpers";
7
+ import type { ODRLPolicy } from "@src/ds4go";
8
+
9
+ /**
10
+ * Policy selection component for choosing from multiple available policies
11
+ */
12
+ @customElement("catalog-modal-policy-selection")
13
+ @localized()
14
+ export class CatalogModalPolicySelection extends LitElement {
15
+ @property({ attribute: false })
16
+ policies: ODRLPolicy[] = [];
17
+
18
+ private _handlePolicySelect(index: number): void {
19
+ this.dispatchEvent(
20
+ new CustomEvent("policy-selected", {
21
+ detail: { index },
22
+ bubbles: true,
23
+ composed: true,
24
+ }),
25
+ );
26
+ }
27
+
28
+ private _handleCancel(): void {
29
+ this.dispatchEvent(
30
+ new CustomEvent("policy-cancel", {
31
+ bubbles: true,
32
+ composed: true,
33
+ }),
34
+ );
35
+ }
36
+
37
+ render(): TemplateResult {
38
+ return html`<div class="policy-selection-modal">
39
+ <div class="policy-selection-header">
40
+ <h3>${msg("Select a Policy")}</h3>
41
+ <p>
42
+ ${msg(
43
+ "Multiple policies are available for this dataset. Please select one to proceed with the negotiation.",
44
+ )}
45
+ </p>
46
+ </div>
47
+ <div class="policy-selection-list">
48
+ ${this.policies.map(
49
+ (policy: ODRLPolicy, index: number) =>
50
+ html`<div
51
+ class="policy-option"
52
+ @click=${() => this._handlePolicySelect(index)}
53
+ >
54
+ <div class="policy-option-header">
55
+ <strong>${msg("Policy")} ${index + 1}</strong>
56
+ ${policy["@id"] ? html`<code>${policy["@id"]}</code>` : nothing}
57
+ </div>
58
+ <div class="policy-option-details">
59
+ ${formatPolicyDetails(policy)}
60
+ </div>
61
+ </div>`,
62
+ )}
63
+ </div>
64
+ <div class="policy-selection-actions">
65
+ <tems-button type="outline-gray" @click=${this._handleCancel}>
66
+ ${msg("Cancel")}
67
+ </tems-button>
68
+ </div>
69
+ </div>`;
70
+ }
71
+ }