@redacto.io/consent-sdk-react 10.1.0 → 10.2.0-beta.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/dist/index.js +790 -314
- package/dist/index.mjs +797 -315
- package/dist/privacy-center.d.mts +3 -1
- package/dist/privacy-center.d.ts +3 -1
- package/dist/privacy-center.js +106 -30
- package/dist/privacy-center.mjs +106 -30
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -17,7 +17,13 @@ import {
|
|
|
17
17
|
} from "./chunk-FT5G2PXK.mjs";
|
|
18
18
|
|
|
19
19
|
// src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
useCallback,
|
|
22
|
+
useEffect as useEffect2,
|
|
23
|
+
useMemo as useMemo2,
|
|
24
|
+
useRef,
|
|
25
|
+
useState
|
|
26
|
+
} from "react";
|
|
21
27
|
|
|
22
28
|
// src/RedactoNoticeConsent/api/index.ts
|
|
23
29
|
import { jwtDecode as jwtDecode2 } from "jwt-decode";
|
|
@@ -347,6 +353,9 @@ var submitConsentEvent = async ({
|
|
|
347
353
|
}));
|
|
348
354
|
return {
|
|
349
355
|
purpose_uuid: purpose.uuid,
|
|
356
|
+
// Omitted on a single-product notice, where the ledger applies the
|
|
357
|
+
// selection to every product the purpose covers.
|
|
358
|
+
product_uuid: purpose.product_uuid || void 0,
|
|
350
359
|
selected: Boolean(purpose.selected),
|
|
351
360
|
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
352
361
|
};
|
|
@@ -606,6 +615,9 @@ var DPO_AUDIO_ELEMENT_MAP = [
|
|
|
606
615
|
{ audioKey: "dpo_text_audio_url", elementId: "dpo-dpo-text" },
|
|
607
616
|
{ audioKey: "dpo_anchor_text_audio_url", elementId: "dpo-dpo-link" }
|
|
608
617
|
];
|
|
618
|
+
var PRODUCT_SECTION_COPY = {
|
|
619
|
+
toggleSelection: (productName, purposeCount) => `Toggle all ${purposeCount} purposes for ${productName}`
|
|
620
|
+
};
|
|
609
621
|
|
|
610
622
|
// src/RedactoNoticeConsent/styles.ts
|
|
611
623
|
var styles = {
|
|
@@ -822,6 +834,28 @@ var styles = {
|
|
|
822
834
|
padding: 0,
|
|
823
835
|
boxSizing: "border-box"
|
|
824
836
|
},
|
|
837
|
+
// A product section's heading. Its own tokens rather than the row's: sharing
|
|
838
|
+
// optionTitle rendered the group name at the same size, weight and indent as
|
|
839
|
+
// the purposes inside it, leaving nothing to mark it as a heading.
|
|
840
|
+
sectionHeader: {
|
|
841
|
+
display: "flex",
|
|
842
|
+
justifyContent: "space-between",
|
|
843
|
+
alignItems: "center",
|
|
844
|
+
margin: "0 0 8px",
|
|
845
|
+
padding: 0,
|
|
846
|
+
boxSizing: "border-box"
|
|
847
|
+
},
|
|
848
|
+
// No colour token: the header always overrides it with the notice's
|
|
849
|
+
// headingColor, so one here would imply a default that never applies.
|
|
850
|
+
sectionTitle: {
|
|
851
|
+
fontWeight: 600,
|
|
852
|
+
fontSize: "17px",
|
|
853
|
+
lineHeight: "150%",
|
|
854
|
+
letterSpacing: "0.2px",
|
|
855
|
+
margin: 0,
|
|
856
|
+
padding: 0,
|
|
857
|
+
textAlign: "left"
|
|
858
|
+
},
|
|
825
859
|
optionTextContainer: {
|
|
826
860
|
display: "flex",
|
|
827
861
|
flexDirection: "column",
|
|
@@ -1163,18 +1197,76 @@ var NoticeFooter = ({
|
|
|
1163
1197
|
] });
|
|
1164
1198
|
};
|
|
1165
1199
|
|
|
1200
|
+
// src/shared/productMatrix.ts
|
|
1201
|
+
var productPurposeKey = (productUuid, purposeUuid) => productUuid ? `${productUuid}:${purposeUuid}` : purposeUuid;
|
|
1202
|
+
var purposeCoversProduct = (purpose, productUuid) => {
|
|
1203
|
+
const scope = purpose.product_uuids;
|
|
1204
|
+
if (!scope || scope.length === 0) return true;
|
|
1205
|
+
return scope.includes(productUuid);
|
|
1206
|
+
};
|
|
1207
|
+
var isMultiProduct = (products) => Boolean(products && products.length > 1);
|
|
1208
|
+
var groupPurposesByProduct = (products, purposes, order) => {
|
|
1209
|
+
if (!products || products.length === 0) return [];
|
|
1210
|
+
return products.map((product) => {
|
|
1211
|
+
const covered = purposes.filter(
|
|
1212
|
+
(purpose) => purposeCoversProduct(purpose, product.uuid)
|
|
1213
|
+
);
|
|
1214
|
+
const saved = order == null ? void 0 : order[product.uuid];
|
|
1215
|
+
if (!saved || saved.length === 0) return { product, purposes: covered };
|
|
1216
|
+
const byUuid = new Map(covered.map((p) => [p.uuid, p]));
|
|
1217
|
+
const ordered = [];
|
|
1218
|
+
for (const uuid of saved) {
|
|
1219
|
+
const found = byUuid.get(uuid);
|
|
1220
|
+
if (found) ordered.push(found);
|
|
1221
|
+
}
|
|
1222
|
+
const rest = covered.filter((p) => !saved.includes(p.uuid));
|
|
1223
|
+
return { product, purposes: [...ordered, ...rest] };
|
|
1224
|
+
}).filter((group) => group.purposes.length > 0);
|
|
1225
|
+
};
|
|
1226
|
+
var expandPurposesByProduct = (products, purposes, order) => {
|
|
1227
|
+
if (!isMultiProduct(products)) return [];
|
|
1228
|
+
const rows = [];
|
|
1229
|
+
for (const group of groupPurposesByProduct(products, purposes, order)) {
|
|
1230
|
+
for (const purpose of group.purposes) {
|
|
1231
|
+
rows.push({ product: group.product, purpose });
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
return rows;
|
|
1235
|
+
};
|
|
1236
|
+
var noticePurposeRows = (products, purposes, order) => {
|
|
1237
|
+
if (!isMultiProduct(products)) {
|
|
1238
|
+
return purposes.map((purpose) => ({ purpose, productUuid: void 0 }));
|
|
1239
|
+
}
|
|
1240
|
+
const rows = expandPurposesByProduct(products, purposes, order).map(
|
|
1241
|
+
(row) => ({
|
|
1242
|
+
purpose: row.purpose,
|
|
1243
|
+
productUuid: row.product.uuid
|
|
1244
|
+
})
|
|
1245
|
+
);
|
|
1246
|
+
const rendered = new Set(rows.map((row) => row.purpose.uuid));
|
|
1247
|
+
const orphaned = purposes.filter((purpose) => !rendered.has(purpose.uuid));
|
|
1248
|
+
if (orphaned.length > 0) {
|
|
1249
|
+
console.warn(
|
|
1250
|
+
"[redacto] purposes cover no product on this notice and will not be shown or submitted:",
|
|
1251
|
+
orphaned.map((purpose) => purpose.uuid)
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
return rows;
|
|
1255
|
+
};
|
|
1256
|
+
|
|
1166
1257
|
// src/RedactoNoticeConsent/utils/consentSelection.ts
|
|
1167
|
-
var dataElementKey = (purposeUuid, elementUuid) => `${purposeUuid}-${elementUuid}`;
|
|
1168
|
-
var buildSelectionForMode = (
|
|
1258
|
+
var dataElementKey = (purposeUuid, elementUuid, productUuid) => `${productPurposeKey(productUuid, purposeUuid)}-${elementUuid}`;
|
|
1259
|
+
var buildSelectionForMode = (rows, mode, current) => {
|
|
1169
1260
|
if (mode === "selected") {
|
|
1170
1261
|
return current;
|
|
1171
1262
|
}
|
|
1172
1263
|
const selectedPurposes = {};
|
|
1173
1264
|
const selectedDataElements = {};
|
|
1174
|
-
|
|
1175
|
-
|
|
1265
|
+
rows.forEach(({ purpose, productUuid }) => {
|
|
1266
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
1267
|
+
selectedPurposes[key] = true;
|
|
1176
1268
|
purpose.data_elements.forEach((element) => {
|
|
1177
|
-
selectedDataElements[dataElementKey(purpose.uuid, element.uuid)] = element.enabled;
|
|
1269
|
+
selectedDataElements[dataElementKey(purpose.uuid, element.uuid, productUuid)] = element.enabled;
|
|
1178
1270
|
});
|
|
1179
1271
|
});
|
|
1180
1272
|
return { selectedPurposes, selectedDataElements };
|
|
@@ -1194,10 +1286,11 @@ var buildPreselection = (purposes, mode) => {
|
|
|
1194
1286
|
const selectedPurposes = {};
|
|
1195
1287
|
const selectedDataElements = {};
|
|
1196
1288
|
if (mode === "ALL") {
|
|
1197
|
-
return buildSelectionForMode(
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1289
|
+
return buildSelectionForMode(
|
|
1290
|
+
purposes.map((purpose) => ({ purpose, productUuid: void 0 })),
|
|
1291
|
+
"all",
|
|
1292
|
+
{ selectedPurposes, selectedDataElements }
|
|
1293
|
+
);
|
|
1201
1294
|
}
|
|
1202
1295
|
purposes.forEach((purpose) => {
|
|
1203
1296
|
let hasPreselectedElement = false;
|
|
@@ -1625,8 +1718,113 @@ var updateConsentState = (updates) => {
|
|
|
1625
1718
|
|
|
1626
1719
|
// src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
|
|
1627
1720
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1721
|
+
var DEFAULT_HEADING_COLOR = "#323B4B";
|
|
1722
|
+
var CHEVRON_BUTTON_STYLE = {
|
|
1723
|
+
background: "none",
|
|
1724
|
+
border: "none",
|
|
1725
|
+
padding: 0,
|
|
1726
|
+
margin: 0,
|
|
1727
|
+
cursor: "pointer",
|
|
1728
|
+
display: "flex",
|
|
1729
|
+
alignItems: "center"
|
|
1730
|
+
};
|
|
1731
|
+
var CHEVRON_WRAPPER_STYLE = {
|
|
1732
|
+
display: "flex",
|
|
1733
|
+
alignItems: "center",
|
|
1734
|
+
justifyContent: "center",
|
|
1735
|
+
marginLeft: "5px"
|
|
1736
|
+
};
|
|
1737
|
+
var CollapseChevron = ({ open, color }) => /* @__PURE__ */ jsx3("div", { style: CHEVRON_WRAPPER_STYLE, children: /* @__PURE__ */ jsx3(
|
|
1738
|
+
"svg",
|
|
1739
|
+
{
|
|
1740
|
+
width: "7",
|
|
1741
|
+
height: "12",
|
|
1742
|
+
viewBox: "0 0 7 12",
|
|
1743
|
+
fill: "none",
|
|
1744
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1745
|
+
stroke: color,
|
|
1746
|
+
strokeWidth: "2",
|
|
1747
|
+
strokeLinecap: "round",
|
|
1748
|
+
strokeLinejoin: "round",
|
|
1749
|
+
style: {
|
|
1750
|
+
transform: open ? "rotate(90deg)" : "rotate(0deg)",
|
|
1751
|
+
transition: "transform 0.3s ease"
|
|
1752
|
+
},
|
|
1753
|
+
"aria-hidden": "true",
|
|
1754
|
+
children: /* @__PURE__ */ jsx3("path", { d: "M1 1L6 6L1 11" })
|
|
1755
|
+
}
|
|
1756
|
+
) });
|
|
1757
|
+
var ProductSectionHeader = ({
|
|
1758
|
+
product,
|
|
1759
|
+
purposeCount,
|
|
1760
|
+
allSelected,
|
|
1761
|
+
someSelected,
|
|
1762
|
+
collapsed,
|
|
1763
|
+
locked,
|
|
1764
|
+
settings,
|
|
1765
|
+
styles: styles4,
|
|
1766
|
+
responsiveStyles,
|
|
1767
|
+
onToggleCollapse,
|
|
1768
|
+
onToggleSelect,
|
|
1769
|
+
getTranslatedText
|
|
1770
|
+
}) => {
|
|
1771
|
+
const checkboxRef = useRef(null);
|
|
1772
|
+
const name = getTranslatedText("products.name", product.name, product.uuid);
|
|
1773
|
+
const headingColor = (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR;
|
|
1774
|
+
useEffect2(() => {
|
|
1775
|
+
if (checkboxRef.current) {
|
|
1776
|
+
checkboxRef.current.indeterminate = someSelected && !allSelected;
|
|
1777
|
+
}
|
|
1778
|
+
}, [someSelected, allSelected]);
|
|
1779
|
+
const handleToggleCollapse = () => {
|
|
1780
|
+
onToggleCollapse(product.uuid);
|
|
1781
|
+
};
|
|
1782
|
+
const handleToggleSelect = () => {
|
|
1783
|
+
onToggleSelect(product.uuid);
|
|
1784
|
+
};
|
|
1785
|
+
return /* @__PURE__ */ jsxs2("div", { style: styles4.sectionHeader, children: [
|
|
1786
|
+
/* @__PURE__ */ jsxs2("div", { style: styles4.optionLeft, children: [
|
|
1787
|
+
/* @__PURE__ */ jsx3(
|
|
1788
|
+
"button",
|
|
1789
|
+
{
|
|
1790
|
+
type: "button",
|
|
1791
|
+
onClick: handleToggleCollapse,
|
|
1792
|
+
"aria-expanded": !collapsed,
|
|
1793
|
+
"aria-controls": `product-${product.uuid}`,
|
|
1794
|
+
"aria-labelledby": `product-name-${product.uuid}`,
|
|
1795
|
+
style: CHEVRON_BUTTON_STYLE,
|
|
1796
|
+
children: /* @__PURE__ */ jsx3(CollapseChevron, { open: !collapsed, color: headingColor })
|
|
1797
|
+
}
|
|
1798
|
+
),
|
|
1799
|
+
/* @__PURE__ */ jsx3("div", { style: styles4.optionTextContainer, children: /* @__PURE__ */ jsx3(
|
|
1800
|
+
"h2",
|
|
1801
|
+
{
|
|
1802
|
+
id: `product-name-${product.uuid}`,
|
|
1803
|
+
style: {
|
|
1804
|
+
...styles4.sectionTitle,
|
|
1805
|
+
...responsiveStyles.optionTitle,
|
|
1806
|
+
color: headingColor
|
|
1807
|
+
},
|
|
1808
|
+
children: name
|
|
1809
|
+
}
|
|
1810
|
+
) })
|
|
1811
|
+
] }),
|
|
1812
|
+
!locked && /* @__PURE__ */ jsx3(
|
|
1813
|
+
"input",
|
|
1814
|
+
{
|
|
1815
|
+
ref: checkboxRef,
|
|
1816
|
+
className: "redacto-checkbox-large",
|
|
1817
|
+
type: "checkbox",
|
|
1818
|
+
checked: allSelected,
|
|
1819
|
+
onChange: handleToggleSelect,
|
|
1820
|
+
"aria-label": PRODUCT_SECTION_COPY.toggleSelection(name, purposeCount)
|
|
1821
|
+
}
|
|
1822
|
+
)
|
|
1823
|
+
] });
|
|
1824
|
+
};
|
|
1628
1825
|
var PurposeItem = ({
|
|
1629
1826
|
purpose,
|
|
1827
|
+
productUuid,
|
|
1630
1828
|
selectedPurposes,
|
|
1631
1829
|
collapsedPurposes,
|
|
1632
1830
|
selectedDataElements,
|
|
@@ -1641,9 +1839,10 @@ var PurposeItem = ({
|
|
|
1641
1839
|
selectedLanguage,
|
|
1642
1840
|
initialDataElementSelections = {}
|
|
1643
1841
|
}) => {
|
|
1842
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
1644
1843
|
const headingStyle = useMemo2(
|
|
1645
1844
|
() => ({
|
|
1646
|
-
color: (settings == null ? void 0 : settings.headingColor) ||
|
|
1845
|
+
color: (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR
|
|
1647
1846
|
}),
|
|
1648
1847
|
[settings == null ? void 0 : settings.headingColor]
|
|
1649
1848
|
);
|
|
@@ -1659,12 +1858,12 @@ var PurposeItem = ({
|
|
|
1659
1858
|
"div",
|
|
1660
1859
|
{
|
|
1661
1860
|
style: styles4.optionLeft,
|
|
1662
|
-
onClick: () => onPurposeCollapse(purpose.uuid),
|
|
1861
|
+
onClick: () => onPurposeCollapse(purpose.uuid, productUuid),
|
|
1663
1862
|
role: "button",
|
|
1664
1863
|
tabIndex: 0,
|
|
1665
|
-
"aria-expanded": !collapsedPurposes[
|
|
1864
|
+
"aria-expanded": !collapsedPurposes[stateKey],
|
|
1666
1865
|
"aria-controls": `purpose-${purpose.uuid}`,
|
|
1667
|
-
"aria-label": `${collapsedPurposes[
|
|
1866
|
+
"aria-label": `${collapsedPurposes[stateKey] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
1668
1867
|
`purposes.name`,
|
|
1669
1868
|
purpose.name,
|
|
1670
1869
|
purpose.uuid
|
|
@@ -1672,46 +1871,22 @@ var PurposeItem = ({
|
|
|
1672
1871
|
onKeyDown: (e) => {
|
|
1673
1872
|
if (e.key === "Enter" || e.key === " ") {
|
|
1674
1873
|
e.preventDefault();
|
|
1675
|
-
onPurposeCollapse(purpose.uuid);
|
|
1874
|
+
onPurposeCollapse(purpose.uuid, productUuid);
|
|
1676
1875
|
}
|
|
1677
1876
|
},
|
|
1678
1877
|
children: [
|
|
1679
1878
|
/* @__PURE__ */ jsx3(
|
|
1680
|
-
|
|
1879
|
+
CollapseChevron,
|
|
1681
1880
|
{
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
alignItems: "center",
|
|
1685
|
-
justifyContent: "center",
|
|
1686
|
-
marginLeft: "5px"
|
|
1687
|
-
},
|
|
1688
|
-
children: /* @__PURE__ */ jsx3(
|
|
1689
|
-
"svg",
|
|
1690
|
-
{
|
|
1691
|
-
width: "7",
|
|
1692
|
-
height: "12",
|
|
1693
|
-
viewBox: "0 0 7 12",
|
|
1694
|
-
fill: "none",
|
|
1695
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
1696
|
-
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
1697
|
-
strokeWidth: "2",
|
|
1698
|
-
strokeLinecap: "round",
|
|
1699
|
-
strokeLinejoin: "round",
|
|
1700
|
-
style: {
|
|
1701
|
-
transform: !collapsedPurposes[purpose.uuid] ? "rotate(90deg)" : "rotate(0deg)",
|
|
1702
|
-
transition: "transform 0.3s ease"
|
|
1703
|
-
},
|
|
1704
|
-
"aria-hidden": "true",
|
|
1705
|
-
children: /* @__PURE__ */ jsx3("path", { d: "M1 1L6 6L1 11" })
|
|
1706
|
-
}
|
|
1707
|
-
)
|
|
1881
|
+
open: !collapsedPurposes[stateKey],
|
|
1882
|
+
color: (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR
|
|
1708
1883
|
}
|
|
1709
1884
|
),
|
|
1710
1885
|
/* @__PURE__ */ jsxs2("div", { style: styles4.optionTextContainer, children: [
|
|
1711
1886
|
/* @__PURE__ */ jsxs2(
|
|
1712
1887
|
"h2",
|
|
1713
1888
|
{
|
|
1714
|
-
id: `purpose-name-${
|
|
1889
|
+
id: `purpose-name-${stateKey}`,
|
|
1715
1890
|
style: {
|
|
1716
1891
|
...styles4.optionTitle,
|
|
1717
1892
|
...responsiveStyles.optionTitle,
|
|
@@ -1727,7 +1902,7 @@ var PurposeItem = ({
|
|
|
1727
1902
|
/* @__PURE__ */ jsx3(
|
|
1728
1903
|
"h3",
|
|
1729
1904
|
{
|
|
1730
|
-
id: `purpose-description-${
|
|
1905
|
+
id: `purpose-description-${stateKey}`,
|
|
1731
1906
|
style: {
|
|
1732
1907
|
...styles4.optionDescription,
|
|
1733
1908
|
...responsiveStyles.optionDescription,
|
|
@@ -1750,8 +1925,8 @@ var PurposeItem = ({
|
|
|
1750
1925
|
{
|
|
1751
1926
|
className: "redacto-checkbox-large",
|
|
1752
1927
|
type: "checkbox",
|
|
1753
|
-
checked: selectedPurposes[
|
|
1754
|
-
onChange: () => onPurposeToggle(purpose.uuid),
|
|
1928
|
+
checked: selectedPurposes[stateKey] || false,
|
|
1929
|
+
onChange: () => onPurposeToggle(purpose.uuid, productUuid),
|
|
1755
1930
|
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
1756
1931
|
`purposes.name`,
|
|
1757
1932
|
purpose.name,
|
|
@@ -1801,7 +1976,7 @@ var PurposeItem = ({
|
|
|
1801
1976
|
}
|
|
1802
1977
|
)
|
|
1803
1978
|
] }),
|
|
1804
|
-
!collapsedPurposes[
|
|
1979
|
+
!collapsedPurposes[stateKey] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ jsx3(
|
|
1805
1980
|
"div",
|
|
1806
1981
|
{
|
|
1807
1982
|
id: `purpose-${purpose.uuid}`,
|
|
@@ -1814,7 +1989,7 @@ var PurposeItem = ({
|
|
|
1814
1989
|
/* @__PURE__ */ jsxs2(
|
|
1815
1990
|
"span",
|
|
1816
1991
|
{
|
|
1817
|
-
id: `data-element-${
|
|
1992
|
+
id: `data-element-${stateKey}-${dataElement.uuid}`,
|
|
1818
1993
|
style: {
|
|
1819
1994
|
...styles4.dataElementText,
|
|
1820
1995
|
...responsiveStyles.dataElementText,
|
|
@@ -1836,8 +2011,12 @@ var PurposeItem = ({
|
|
|
1836
2011
|
{
|
|
1837
2012
|
className: "redacto-checkbox-small",
|
|
1838
2013
|
type: "checkbox",
|
|
1839
|
-
checked: selectedDataElements[`${
|
|
1840
|
-
onChange: () => onDataElementToggle(
|
|
2014
|
+
checked: selectedDataElements[`${stateKey}-${dataElement.uuid}`] || false,
|
|
2015
|
+
onChange: () => onDataElementToggle(
|
|
2016
|
+
dataElement.uuid,
|
|
2017
|
+
purpose.uuid,
|
|
2018
|
+
productUuid
|
|
2019
|
+
),
|
|
1841
2020
|
"aria-label": `Select ${getTranslatedText(
|
|
1842
2021
|
`data_elements.name`,
|
|
1843
2022
|
dataElement.name,
|
|
@@ -1846,7 +2025,7 @@ var PurposeItem = ({
|
|
|
1846
2025
|
}
|
|
1847
2026
|
),
|
|
1848
2027
|
isAlreadyConsented && /* @__PURE__ */ jsx3(Fragment2, { children: (() => {
|
|
1849
|
-
const combinedId = `${
|
|
2028
|
+
const combinedId = `${stateKey}-${dataElement.uuid}`;
|
|
1850
2029
|
const wasOriginallySelected = initialDataElementSelections[combinedId] || false;
|
|
1851
2030
|
if (wasOriginallySelected) {
|
|
1852
2031
|
return /* @__PURE__ */ jsx3(
|
|
@@ -1984,7 +2163,9 @@ var GuardianForm = ({
|
|
|
1984
2163
|
switch (e.key) {
|
|
1985
2164
|
case "ArrowDown":
|
|
1986
2165
|
e.preventDefault();
|
|
1987
|
-
setFocusedIndex(
|
|
2166
|
+
setFocusedIndex(
|
|
2167
|
+
(prev) => Math.min(prev + 1, RELATIONSHIP_OPTIONS.length - 1)
|
|
2168
|
+
);
|
|
1988
2169
|
break;
|
|
1989
2170
|
case "ArrowUp":
|
|
1990
2171
|
e.preventDefault();
|
|
@@ -1993,7 +2174,8 @@ var GuardianForm = ({
|
|
|
1993
2174
|
case "Enter":
|
|
1994
2175
|
case " ":
|
|
1995
2176
|
e.preventDefault();
|
|
1996
|
-
if (focusedIndex >= 0)
|
|
2177
|
+
if (focusedIndex >= 0)
|
|
2178
|
+
handleSelect(RELATIONSHIP_OPTIONS[focusedIndex].value);
|
|
1997
2179
|
break;
|
|
1998
2180
|
case "Escape":
|
|
1999
2181
|
case "Tab":
|
|
@@ -2058,7 +2240,9 @@ var GuardianForm = ({
|
|
|
2058
2240
|
lineHeight: "1.5",
|
|
2059
2241
|
color: "#1E40AF"
|
|
2060
2242
|
};
|
|
2061
|
-
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find(
|
|
2243
|
+
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find(
|
|
2244
|
+
(o) => o.value === formData.guardianRelationship
|
|
2245
|
+
)) == null ? void 0 : _a.label;
|
|
2062
2246
|
const hasError = Boolean(errors.guardianRelationship);
|
|
2063
2247
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2064
2248
|
/* @__PURE__ */ jsx3("div", { style: { ...styles4.topSection, ...componentTextStyle }, children: /* @__PURE__ */ jsxs2("div", { style: styles4.topLeft, children: [
|
|
@@ -2158,7 +2342,8 @@ var GuardianForm = ({
|
|
|
2158
2342
|
] }),
|
|
2159
2343
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
2160
2344
|
/* @__PURE__ */ jsxs2("label", { htmlFor: "guardianContact", style: labelStyle, children: [
|
|
2161
|
-
"Guardian's Phone Number
|
|
2345
|
+
"Guardian's Phone Number",
|
|
2346
|
+
" ",
|
|
2162
2347
|
/* @__PURE__ */ jsx3("span", { style: { color: "#DC2626" }, children: "*" })
|
|
2163
2348
|
] }),
|
|
2164
2349
|
/* @__PURE__ */ jsx3(
|
|
@@ -2214,7 +2399,17 @@ var GuardianForm = ({
|
|
|
2214
2399
|
transition: "border-color 0.15s, box-shadow 0.15s"
|
|
2215
2400
|
},
|
|
2216
2401
|
children: [
|
|
2217
|
-
/* @__PURE__ */ jsx3(
|
|
2402
|
+
/* @__PURE__ */ jsx3(
|
|
2403
|
+
"span",
|
|
2404
|
+
{
|
|
2405
|
+
style: {
|
|
2406
|
+
overflow: "hidden",
|
|
2407
|
+
textOverflow: "ellipsis",
|
|
2408
|
+
whiteSpace: "nowrap"
|
|
2409
|
+
},
|
|
2410
|
+
children: selectedLabel || "Select relationship"
|
|
2411
|
+
}
|
|
2412
|
+
),
|
|
2218
2413
|
/* @__PURE__ */ jsx3(
|
|
2219
2414
|
"svg",
|
|
2220
2415
|
{
|
|
@@ -2882,6 +3077,7 @@ var RedactoNoticeConsent = ({
|
|
|
2882
3077
|
const [selectedPurposes, setSelectedPurposes] = useState({});
|
|
2883
3078
|
const [selectedDataElements, setSelectedDataElements] = useState({});
|
|
2884
3079
|
const [initialDataElementSelections, setInitialDataElementSelections] = useState({});
|
|
3080
|
+
const [collapsedProducts, setCollapsedProducts] = useState({});
|
|
2885
3081
|
const [collapsedPurposes, setCollapsedPurposes] = useState({});
|
|
2886
3082
|
const [hasAlreadyConsented, setHasAlreadyConsented] = useState(false);
|
|
2887
3083
|
const [isFullyConsentedReviewMode, setIsFullyConsentedReviewMode] = useState(false);
|
|
@@ -2927,7 +3123,9 @@ var RedactoNoticeConsent = ({
|
|
|
2927
3123
|
const statusPollIntervalRef = useRef(null);
|
|
2928
3124
|
const verificationPopupRef = useRef(null);
|
|
2929
3125
|
const pollingCleanupRef = useRef(null);
|
|
2930
|
-
const autoTransitionTimerRef = useRef(
|
|
3126
|
+
const autoTransitionTimerRef = useRef(
|
|
3127
|
+
null
|
|
3128
|
+
);
|
|
2931
3129
|
const digilockerRedirectTimeoutRef = useRef(null);
|
|
2932
3130
|
const isInitialMountRef = useRef(true);
|
|
2933
3131
|
const isPollingStatusRef = useRef(false);
|
|
@@ -3037,21 +3235,70 @@ var RedactoNoticeConsent = ({
|
|
|
3037
3235
|
const logoRowStyle = useMemo2(
|
|
3038
3236
|
() => ({
|
|
3039
3237
|
...styles.logoRow,
|
|
3040
|
-
justifyContent: logoRowJustify(
|
|
3238
|
+
justifyContent: logoRowJustify(
|
|
3239
|
+
resolveLogoPosition(content == null ? void 0 : content.logo_position)
|
|
3240
|
+
)
|
|
3041
3241
|
}),
|
|
3042
3242
|
[content == null ? void 0 : content.logo_position]
|
|
3043
3243
|
);
|
|
3244
|
+
const purposeRows = useMemo2(
|
|
3245
|
+
() => {
|
|
3246
|
+
var _a2;
|
|
3247
|
+
return noticePurposeRows(
|
|
3248
|
+
content == null ? void 0 : content.products,
|
|
3249
|
+
(_a2 = content == null ? void 0 : content.purposes) != null ? _a2 : [],
|
|
3250
|
+
content == null ? void 0 : content.product_purpose_order
|
|
3251
|
+
);
|
|
3252
|
+
},
|
|
3253
|
+
[content]
|
|
3254
|
+
);
|
|
3255
|
+
const productGroups = useMemo2(
|
|
3256
|
+
() => {
|
|
3257
|
+
var _a2;
|
|
3258
|
+
return groupPurposesByProduct(
|
|
3259
|
+
content == null ? void 0 : content.products,
|
|
3260
|
+
(_a2 = content == null ? void 0 : content.purposes) != null ? _a2 : [],
|
|
3261
|
+
content == null ? void 0 : content.product_purpose_order
|
|
3262
|
+
);
|
|
3263
|
+
},
|
|
3264
|
+
[content]
|
|
3265
|
+
);
|
|
3044
3266
|
const areAllRequiredElementsChecked = useMemo2(() => {
|
|
3267
|
+
var _a2;
|
|
3045
3268
|
if (!content) return false;
|
|
3046
|
-
|
|
3269
|
+
if (purposeRows.length === 0) return true;
|
|
3270
|
+
const isSatisfied = ({
|
|
3271
|
+
purpose,
|
|
3272
|
+
productUuid
|
|
3273
|
+
}) => {
|
|
3274
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3047
3275
|
const requiredElements = purpose.data_elements.filter(
|
|
3048
3276
|
(element) => element.required && element.enabled
|
|
3049
3277
|
);
|
|
3050
3278
|
return requiredElements.every(
|
|
3051
|
-
(element) => selectedDataElements[`${
|
|
3279
|
+
(element) => selectedDataElements[`${key}-${element.uuid}`]
|
|
3052
3280
|
);
|
|
3053
|
-
}
|
|
3054
|
-
|
|
3281
|
+
};
|
|
3282
|
+
const rowsByProduct = /* @__PURE__ */ new Map();
|
|
3283
|
+
for (const row of purposeRows) {
|
|
3284
|
+
const groupKey = (_a2 = row.productUuid) != null ? _a2 : "";
|
|
3285
|
+
const group = rowsByProduct.get(groupKey);
|
|
3286
|
+
if (group) {
|
|
3287
|
+
group.push(row);
|
|
3288
|
+
} else {
|
|
3289
|
+
rowsByProduct.set(groupKey, [row]);
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
const groups = [...rowsByProduct.values()];
|
|
3293
|
+
const everyProductHasMandatory = groups.every(
|
|
3294
|
+
(rows) => rows.some(
|
|
3295
|
+
({ purpose }) => purpose.data_elements.some(
|
|
3296
|
+
(element) => element.required && element.enabled
|
|
3297
|
+
)
|
|
3298
|
+
)
|
|
3299
|
+
);
|
|
3300
|
+
return everyProductHasMandatory ? groups.some((rows) => rows.every(isSatisfied)) : purposeRows.every(isSatisfied);
|
|
3301
|
+
}, [content, purposeRows, selectedDataElements]);
|
|
3055
3302
|
const acceptDisabled = isSubmitting || !areAllRequiredElementsChecked;
|
|
3056
3303
|
useEffect2(() => {
|
|
3057
3304
|
var _a2, _b2;
|
|
@@ -3063,6 +3310,7 @@ var RedactoNoticeConsent = ({
|
|
|
3063
3310
|
setSelectedDataElements({});
|
|
3064
3311
|
setInitialDataElementSelections({});
|
|
3065
3312
|
setCollapsedPurposes({});
|
|
3313
|
+
setCollapsedProducts({});
|
|
3066
3314
|
setHasAlreadyConsented(false);
|
|
3067
3315
|
setErrorMessage(null);
|
|
3068
3316
|
setFetchError(null);
|
|
@@ -3127,7 +3375,7 @@ var RedactoNoticeConsent = ({
|
|
|
3127
3375
|
return false;
|
|
3128
3376
|
};
|
|
3129
3377
|
const getTranslatedText = (key, defaultText, itemId) => {
|
|
3130
|
-
var _a2, _b2;
|
|
3378
|
+
var _a2, _b2, _c2;
|
|
3131
3379
|
if (!content) return defaultText;
|
|
3132
3380
|
if (isDefaultLanguage(selectedLanguage)) {
|
|
3133
3381
|
if (key === "privacy_policy_anchor_text" && content.privacy_policy_anchor_text) {
|
|
@@ -3165,8 +3413,18 @@ var RedactoNoticeConsent = ({
|
|
|
3165
3413
|
}
|
|
3166
3414
|
return defaultText;
|
|
3167
3415
|
}
|
|
3416
|
+
if (key === "products.name" || key === "products.description") {
|
|
3417
|
+
const productData = (_b2 = translationMap.products) == null ? void 0 : _b2[itemId];
|
|
3418
|
+
if (productData) {
|
|
3419
|
+
if (typeof productData === "string") {
|
|
3420
|
+
return key === "products.name" ? productData : defaultText;
|
|
3421
|
+
}
|
|
3422
|
+
return key === "products.name" ? productData.name || defaultText : productData.description || defaultText;
|
|
3423
|
+
}
|
|
3424
|
+
return defaultText;
|
|
3425
|
+
}
|
|
3168
3426
|
if (key.startsWith("data_elements.")) {
|
|
3169
|
-
return ((
|
|
3427
|
+
return ((_c2 = translationMap.data_elements) == null ? void 0 : _c2[itemId]) || defaultText;
|
|
3170
3428
|
}
|
|
3171
3429
|
}
|
|
3172
3430
|
const value = translationMap[key];
|
|
@@ -3224,63 +3482,76 @@ var RedactoNoticeConsent = ({
|
|
|
3224
3482
|
defaultLang === "en" || defaultLang === "EN" ? "English" : defaultLang
|
|
3225
3483
|
);
|
|
3226
3484
|
}
|
|
3227
|
-
const initialCollapsedState =
|
|
3228
|
-
|
|
3485
|
+
const initialCollapsedState = noticePurposeRows(
|
|
3486
|
+
activeConfig.products,
|
|
3487
|
+
activeConfig.purposes,
|
|
3488
|
+
activeConfig.product_purpose_order
|
|
3489
|
+
).reduce(
|
|
3490
|
+
(acc, { purpose, productUuid }) => ({
|
|
3229
3491
|
...acc,
|
|
3230
|
-
[purpose.uuid]: true
|
|
3492
|
+
[productPurposeKey(productUuid, purpose.uuid)]: true
|
|
3231
3493
|
}),
|
|
3232
3494
|
{}
|
|
3233
3495
|
);
|
|
3234
3496
|
setCollapsedPurposes(initialCollapsedState);
|
|
3497
|
+
setCollapsedProducts({});
|
|
3235
3498
|
const isReconsentRequired = consentContentData.detail.reconsent_required;
|
|
3236
3499
|
const purposeSelections = consentContentData.detail.purpose_selections;
|
|
3237
3500
|
const newCategorizedPurposes = isReconsentRequired ? {
|
|
3238
|
-
alreadyConsented: activeConfig.purposes.filter(
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3247
|
-
return !selection || selection.status !== "ACTIVE" || selection.needs_reconsent;
|
|
3248
|
-
}
|
|
3249
|
-
)
|
|
3501
|
+
alreadyConsented: activeConfig.purposes.filter((purpose) => {
|
|
3502
|
+
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3503
|
+
return selection && (selection.status === "ACTIVE" || selection.status === "EXPIRED") && !selection.needs_reconsent;
|
|
3504
|
+
}),
|
|
3505
|
+
needsConsent: activeConfig.purposes.filter((purpose) => {
|
|
3506
|
+
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3507
|
+
return !selection || selection.status !== "ACTIVE" || selection.needs_reconsent;
|
|
3508
|
+
})
|
|
3250
3509
|
} : null;
|
|
3251
3510
|
setCategorizedPurposes(newCategorizedPurposes);
|
|
3252
3511
|
const preselection = buildPreselection(
|
|
3253
3512
|
activeConfig.purposes,
|
|
3254
3513
|
resolvePurposePreselection(activeConfig.purpose_preselection)
|
|
3255
3514
|
);
|
|
3256
|
-
const
|
|
3257
|
-
|
|
3515
|
+
const seedRows = noticePurposeRows(
|
|
3516
|
+
activeConfig.products,
|
|
3517
|
+
activeConfig.purposes,
|
|
3518
|
+
activeConfig.product_purpose_order
|
|
3519
|
+
);
|
|
3520
|
+
const recordedFor = (purposeUuid, productUuid) => {
|
|
3521
|
+
var _a3, _b2;
|
|
3522
|
+
const perProduct = productUuid ? (_b2 = (_a3 = activeConfig.product_purpose_selections) == null ? void 0 : _a3[productUuid]) == null ? void 0 : _b2[purposeUuid] : void 0;
|
|
3523
|
+
return perProduct != null ? perProduct : purposeSelections == null ? void 0 : purposeSelections[purposeUuid];
|
|
3524
|
+
};
|
|
3525
|
+
const initialPurposeState = seedRows.reduce(
|
|
3526
|
+
(acc, { purpose, productUuid }) => {
|
|
3258
3527
|
var _a3;
|
|
3259
|
-
const
|
|
3528
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3529
|
+
const recorded = recordedFor(purpose.uuid, productUuid);
|
|
3260
3530
|
if (hasRecordedPurposeState(recorded)) {
|
|
3261
|
-
acc[
|
|
3531
|
+
acc[key] = recorded.selected;
|
|
3262
3532
|
} else {
|
|
3263
|
-
acc[
|
|
3533
|
+
acc[key] = (_a3 = preselection.selectedPurposes[purpose.uuid]) != null ? _a3 : false;
|
|
3264
3534
|
}
|
|
3265
3535
|
return acc;
|
|
3266
3536
|
},
|
|
3267
3537
|
{}
|
|
3268
3538
|
);
|
|
3269
3539
|
setSelectedPurposes(initialPurposeState);
|
|
3270
|
-
const initialDataElementState =
|
|
3271
|
-
(acc, purpose) => {
|
|
3272
|
-
const
|
|
3273
|
-
|
|
3274
|
-
);
|
|
3540
|
+
const initialDataElementState = seedRows.reduce(
|
|
3541
|
+
(acc, { purpose, productUuid }) => {
|
|
3542
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3543
|
+
const recorded = recordedFor(purpose.uuid, productUuid);
|
|
3544
|
+
const hasRecordedSelection = hasRecordedPurposeState(recorded);
|
|
3275
3545
|
purpose.data_elements.forEach((element) => {
|
|
3276
|
-
var _a3, _b2
|
|
3277
|
-
const combinedId = `${
|
|
3278
|
-
|
|
3279
|
-
|
|
3546
|
+
var _a3, _b2;
|
|
3547
|
+
const combinedId = `${key}-${element.uuid}`;
|
|
3548
|
+
const recordedElement = (_a3 = recorded == null ? void 0 : recorded.data_elements) == null ? void 0 : _a3[element.uuid];
|
|
3549
|
+
if (recordedElement) {
|
|
3550
|
+
acc[combinedId] = recordedElement.selected;
|
|
3280
3551
|
} else if (hasRecordedSelection) {
|
|
3281
3552
|
acc[combinedId] = false;
|
|
3282
3553
|
} else {
|
|
3283
|
-
acc[combinedId] = (
|
|
3554
|
+
acc[combinedId] = (_b2 = preselection.selectedDataElements[`${purpose.uuid}-${element.uuid}`]) != null ? _b2 : false;
|
|
3284
3555
|
}
|
|
3285
3556
|
});
|
|
3286
3557
|
return acc;
|
|
@@ -3291,10 +3562,14 @@ var RedactoNoticeConsent = ({
|
|
|
3291
3562
|
if (isReconsentRequired && newCategorizedPurposes) {
|
|
3292
3563
|
setIsFullyConsentedReviewMode(false);
|
|
3293
3564
|
const initialSelections = {};
|
|
3294
|
-
|
|
3565
|
+
const alreadyConsentedUuids = new Set(
|
|
3566
|
+
newCategorizedPurposes.alreadyConsented.map((p) => p.uuid)
|
|
3567
|
+
);
|
|
3568
|
+
seedRows.filter(({ purpose }) => alreadyConsentedUuids.has(purpose.uuid)).forEach(({ purpose, productUuid }) => {
|
|
3569
|
+
const rowKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3295
3570
|
purpose.data_elements.forEach((element) => {
|
|
3296
3571
|
var _a3, _b2;
|
|
3297
|
-
const combinedId = `${
|
|
3572
|
+
const combinedId = `${rowKey}-${element.uuid}`;
|
|
3298
3573
|
if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
|
|
3299
3574
|
initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
|
|
3300
3575
|
} else {
|
|
@@ -3304,28 +3579,27 @@ var RedactoNoticeConsent = ({
|
|
|
3304
3579
|
});
|
|
3305
3580
|
setInitialDataElementSelections(initialSelections);
|
|
3306
3581
|
} else if (includeFullyConsentedData && purposeSelections) {
|
|
3307
|
-
const allPurposesSelected =
|
|
3308
|
-
(
|
|
3582
|
+
const allPurposesSelected = seedRows.length > 0 && seedRows.every(
|
|
3583
|
+
({ purpose, productUuid }) => {
|
|
3309
3584
|
var _a3;
|
|
3310
|
-
return ((_a3 =
|
|
3585
|
+
return ((_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.selected) === true;
|
|
3311
3586
|
}
|
|
3312
3587
|
);
|
|
3313
3588
|
setIsFullyConsentedReviewMode(allPurposesSelected);
|
|
3314
3589
|
if (allPurposesSelected) {
|
|
3315
3590
|
const initialSelections = {};
|
|
3316
|
-
|
|
3317
|
-
(purpose)
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
);
|
|
3591
|
+
seedRows.forEach(({ purpose, productUuid }) => {
|
|
3592
|
+
const rowKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3593
|
+
purpose.data_elements.forEach((element) => {
|
|
3594
|
+
var _a3, _b2;
|
|
3595
|
+
const combinedId = `${rowKey}-${element.uuid}`;
|
|
3596
|
+
if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
|
|
3597
|
+
initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
|
|
3598
|
+
} else {
|
|
3599
|
+
initialSelections[combinedId] = false;
|
|
3600
|
+
}
|
|
3601
|
+
});
|
|
3602
|
+
});
|
|
3329
3603
|
setInitialDataElementSelections(initialSelections);
|
|
3330
3604
|
} else {
|
|
3331
3605
|
setIsFullyConsentedReviewMode(false);
|
|
@@ -3375,10 +3649,11 @@ var RedactoNoticeConsent = ({
|
|
|
3375
3649
|
// Removed onError and isRefreshingToken from dependencies to prevent duplicate API calls
|
|
3376
3650
|
// onError is only called on errors, not needed for initial data fetching
|
|
3377
3651
|
]);
|
|
3378
|
-
const togglePurposeCollapse = (purposeUuid) => {
|
|
3652
|
+
const togglePurposeCollapse = (purposeUuid, productUuid) => {
|
|
3653
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
3379
3654
|
setCollapsedPurposes((prev) => ({
|
|
3380
3655
|
...prev,
|
|
3381
|
-
[
|
|
3656
|
+
[key]: !prev[key]
|
|
3382
3657
|
}));
|
|
3383
3658
|
};
|
|
3384
3659
|
const toggleLanguageDropdown = () => {
|
|
@@ -3388,28 +3663,70 @@ var RedactoNoticeConsent = ({
|
|
|
3388
3663
|
setSelectedLanguage(lang);
|
|
3389
3664
|
setIsLanguageDropdownOpen(false);
|
|
3390
3665
|
};
|
|
3391
|
-
const handlePurposeCheckboxChange = (purposeUuid) => {
|
|
3666
|
+
const handlePurposeCheckboxChange = (purposeUuid, productUuid) => {
|
|
3392
3667
|
if (content) {
|
|
3393
3668
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
3394
3669
|
if (purpose) {
|
|
3395
|
-
const
|
|
3670
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
3671
|
+
const newPurposeState = !selectedPurposes[key];
|
|
3396
3672
|
setSelectedPurposes((prev) => ({
|
|
3397
3673
|
...prev,
|
|
3398
|
-
[
|
|
3674
|
+
[key]: newPurposeState
|
|
3399
3675
|
}));
|
|
3400
3676
|
setSelectedDataElements((prev) => {
|
|
3401
3677
|
const updated = { ...prev };
|
|
3402
3678
|
purpose.data_elements.forEach((el) => {
|
|
3403
|
-
updated[`${
|
|
3679
|
+
updated[`${key}-${el.uuid}`] = newPurposeState;
|
|
3404
3680
|
});
|
|
3405
3681
|
return updated;
|
|
3406
3682
|
});
|
|
3407
3683
|
}
|
|
3408
3684
|
}
|
|
3409
3685
|
};
|
|
3410
|
-
const
|
|
3686
|
+
const toggleProductCollapse = (productUuid) => {
|
|
3687
|
+
setCollapsedProducts((prev) => ({
|
|
3688
|
+
...prev,
|
|
3689
|
+
[productUuid]: !prev[productUuid]
|
|
3690
|
+
}));
|
|
3691
|
+
};
|
|
3692
|
+
const handleProductCheckboxChange = (productUuid) => {
|
|
3693
|
+
if (!content) {
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
const group = productGroups.find(
|
|
3697
|
+
(candidate) => candidate.product.uuid === productUuid
|
|
3698
|
+
);
|
|
3699
|
+
if (!group) {
|
|
3700
|
+
return;
|
|
3701
|
+
}
|
|
3702
|
+
const nextState = !group.purposes.every(
|
|
3703
|
+
(purpose) => selectedPurposes[productPurposeKey(productUuid, purpose.uuid)]
|
|
3704
|
+
);
|
|
3705
|
+
setSelectedPurposes((prev) => {
|
|
3706
|
+
const updated = { ...prev };
|
|
3707
|
+
group.purposes.forEach((purpose) => {
|
|
3708
|
+
updated[productPurposeKey(productUuid, purpose.uuid)] = nextState;
|
|
3709
|
+
});
|
|
3710
|
+
return updated;
|
|
3711
|
+
});
|
|
3712
|
+
setSelectedDataElements((prev) => {
|
|
3713
|
+
const updated = { ...prev };
|
|
3714
|
+
group.purposes.forEach((purpose) => {
|
|
3715
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3716
|
+
purpose.data_elements.forEach((element) => {
|
|
3717
|
+
updated[`${key}-${element.uuid}`] = nextState;
|
|
3718
|
+
});
|
|
3719
|
+
});
|
|
3720
|
+
return updated;
|
|
3721
|
+
});
|
|
3722
|
+
if (!nextState) {
|
|
3723
|
+
setCollapsedProducts((prev) => ({ ...prev, [productUuid]: false }));
|
|
3724
|
+
}
|
|
3725
|
+
};
|
|
3726
|
+
const handleDataElementCheckboxChange = (elementUuid, purposeUuid, productUuid) => {
|
|
3411
3727
|
if (!content) return;
|
|
3412
|
-
const
|
|
3728
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
3729
|
+
const combinedId = `${key}-${elementUuid}`;
|
|
3413
3730
|
setSelectedDataElements((prev) => {
|
|
3414
3731
|
const newState = {
|
|
3415
3732
|
...prev,
|
|
@@ -3423,16 +3740,16 @@ var RedactoNoticeConsent = ({
|
|
|
3423
3740
|
let shouldCheckPurpose;
|
|
3424
3741
|
if (requiredElements.length > 0) {
|
|
3425
3742
|
shouldCheckPurpose = requiredElements.every(
|
|
3426
|
-
(el) => newState[`${
|
|
3743
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
3427
3744
|
);
|
|
3428
3745
|
} else {
|
|
3429
3746
|
shouldCheckPurpose = purpose.data_elements.some(
|
|
3430
|
-
(el) => newState[`${
|
|
3747
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
3431
3748
|
);
|
|
3432
3749
|
}
|
|
3433
3750
|
setSelectedPurposes((prevPurposes) => ({
|
|
3434
3751
|
...prevPurposes,
|
|
3435
|
-
[
|
|
3752
|
+
[key]: shouldCheckPurpose
|
|
3436
3753
|
}));
|
|
3437
3754
|
}
|
|
3438
3755
|
return newState;
|
|
@@ -3442,14 +3759,16 @@ var RedactoNoticeConsent = ({
|
|
|
3442
3759
|
const submitController = new AbortController();
|
|
3443
3760
|
try {
|
|
3444
3761
|
if (isMinorFlow && !verificationReference) {
|
|
3445
|
-
setErrorMessage(
|
|
3762
|
+
setErrorMessage(
|
|
3763
|
+
"Guardian verification is required before consent can be submitted."
|
|
3764
|
+
);
|
|
3446
3765
|
return;
|
|
3447
3766
|
}
|
|
3448
3767
|
setIsSubmittingAccept(true);
|
|
3449
3768
|
setIsSubmitting(true);
|
|
3450
3769
|
setErrorMessage(null);
|
|
3451
3770
|
if (content) {
|
|
3452
|
-
const selection = buildSelectionForMode(
|
|
3771
|
+
const selection = buildSelectionForMode(purposeRows, mode, {
|
|
3453
3772
|
selectedPurposes,
|
|
3454
3773
|
selectedDataElements
|
|
3455
3774
|
});
|
|
@@ -3462,14 +3781,20 @@ var RedactoNoticeConsent = ({
|
|
|
3462
3781
|
baseUrl,
|
|
3463
3782
|
ledgerBaseUrl,
|
|
3464
3783
|
noticeUuid: content.notice_uuid,
|
|
3465
|
-
|
|
3784
|
+
// One entry per (product, purpose) once a notice covers several. The
|
|
3785
|
+
// ledger keys consent on the pair, and repeating a purpose under two
|
|
3786
|
+
// products is how one submission accepts it for one and declines it
|
|
3787
|
+
// for the other. Collapses to content.purposes on a single-product
|
|
3788
|
+
// notice, so that payload is byte-identical to before.
|
|
3789
|
+
purposes: purposeRows.map(({ purpose, productUuid }) => {
|
|
3790
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3466
3791
|
const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
|
|
3467
3792
|
(p) => p.uuid === purpose.uuid
|
|
3468
3793
|
)) || false;
|
|
3469
|
-
let purposeSelected = selection.selectedPurposes[
|
|
3794
|
+
let purposeSelected = selection.selectedPurposes[stateKey] || false;
|
|
3470
3795
|
if (mode === "selected" && isAlreadyConsented) {
|
|
3471
3796
|
const wasModified = purpose.data_elements.some((element) => {
|
|
3472
|
-
const combinedId = `${
|
|
3797
|
+
const combinedId = `${stateKey}-${element.uuid}`;
|
|
3473
3798
|
const currentSelection = selection.selectedDataElements[combinedId] || false;
|
|
3474
3799
|
const initialSelection = initialDataElementSelections[combinedId] || false;
|
|
3475
3800
|
return currentSelection !== initialSelection;
|
|
@@ -3480,10 +3805,11 @@ var RedactoNoticeConsent = ({
|
|
|
3480
3805
|
}
|
|
3481
3806
|
return {
|
|
3482
3807
|
...purpose,
|
|
3808
|
+
...productUuid ? { product_uuid: productUuid } : {},
|
|
3483
3809
|
selected: purposeSelected,
|
|
3484
3810
|
data_elements: purpose.data_elements.map((element) => ({
|
|
3485
3811
|
...element,
|
|
3486
|
-
selected: element.required ? true : selection.selectedDataElements[`${
|
|
3812
|
+
selected: element.required ? true : selection.selectedDataElements[`${stateKey}-${element.uuid}`] || false
|
|
3487
3813
|
}))
|
|
3488
3814
|
};
|
|
3489
3815
|
}),
|
|
@@ -3586,7 +3912,9 @@ var RedactoNoticeConsent = ({
|
|
|
3586
3912
|
return;
|
|
3587
3913
|
}
|
|
3588
3914
|
if (!response.session_token || !response.digilocker_redirect_url) {
|
|
3589
|
-
throw new Error(
|
|
3915
|
+
throw new Error(
|
|
3916
|
+
"Invalid response from server: missing required fields"
|
|
3917
|
+
);
|
|
3590
3918
|
}
|
|
3591
3919
|
setShowGuardianForm(false);
|
|
3592
3920
|
setShowVerificationScreen(true);
|
|
@@ -3676,7 +4004,18 @@ var RedactoNoticeConsent = ({
|
|
|
3676
4004
|
} finally {
|
|
3677
4005
|
setIsSubmittingGuardian(false);
|
|
3678
4006
|
}
|
|
3679
|
-
}, [
|
|
4007
|
+
}, [
|
|
4008
|
+
accessToken,
|
|
4009
|
+
sandboxParams,
|
|
4010
|
+
baseUrl,
|
|
4011
|
+
guardianFormData,
|
|
4012
|
+
digilockerMode,
|
|
4013
|
+
digilockerCallbackUrl,
|
|
4014
|
+
selectedPurposes,
|
|
4015
|
+
selectedDataElements,
|
|
4016
|
+
noticeId,
|
|
4017
|
+
onError
|
|
4018
|
+
]);
|
|
3680
4019
|
const handleAgeVerificationYes = useCallback(() => {
|
|
3681
4020
|
setShowAgeVerification(false);
|
|
3682
4021
|
setIsMinorFlow(false);
|
|
@@ -3727,20 +4066,21 @@ var RedactoNoticeConsent = ({
|
|
|
3727
4066
|
} catch {
|
|
3728
4067
|
}
|
|
3729
4068
|
}
|
|
3730
|
-
setVerificationError(
|
|
3731
|
-
"Verification window was closed. Please try again."
|
|
3732
|
-
);
|
|
4069
|
+
setVerificationError("Verification window was closed. Please try again.");
|
|
3733
4070
|
setIsPollingStatus(false);
|
|
3734
4071
|
isPollingStatusRef.current = false;
|
|
3735
4072
|
setIsInitiatingVerification(false);
|
|
3736
4073
|
}, [accessToken, sandboxParams, baseUrl]);
|
|
3737
|
-
const startPopupMonitoring = useCallback(
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
4074
|
+
const startPopupMonitoring = useCallback(
|
|
4075
|
+
(popup) => {
|
|
4076
|
+
popupCheckIntervalRef.current = window.setInterval(() => {
|
|
4077
|
+
if (popup.closed) {
|
|
4078
|
+
handlePopupClosed();
|
|
4079
|
+
}
|
|
4080
|
+
}, 500);
|
|
4081
|
+
},
|
|
4082
|
+
[handlePopupClosed]
|
|
4083
|
+
);
|
|
3744
4084
|
const getVerificationErrorMessage = useCallback(
|
|
3745
4085
|
(errorCode, fallbackError) => {
|
|
3746
4086
|
switch (errorCode) {
|
|
@@ -3842,7 +4182,10 @@ var RedactoNoticeConsent = ({
|
|
|
3842
4182
|
return;
|
|
3843
4183
|
}
|
|
3844
4184
|
if (!paused) {
|
|
3845
|
-
statusPollIntervalRef.current = window.setTimeout(
|
|
4185
|
+
statusPollIntervalRef.current = window.setTimeout(
|
|
4186
|
+
poll,
|
|
4187
|
+
POLL_INTERVAL
|
|
4188
|
+
);
|
|
3846
4189
|
}
|
|
3847
4190
|
} catch (error) {
|
|
3848
4191
|
const err = error;
|
|
@@ -3863,7 +4206,10 @@ var RedactoNoticeConsent = ({
|
|
|
3863
4206
|
);
|
|
3864
4207
|
return;
|
|
3865
4208
|
}
|
|
3866
|
-
statusPollIntervalRef.current = window.setTimeout(
|
|
4209
|
+
statusPollIntervalRef.current = window.setTimeout(
|
|
4210
|
+
poll,
|
|
4211
|
+
POLL_INTERVAL
|
|
4212
|
+
);
|
|
3867
4213
|
}
|
|
3868
4214
|
};
|
|
3869
4215
|
const onVisibilityChange = () => {
|
|
@@ -4164,12 +4510,19 @@ var RedactoNoticeConsent = ({
|
|
|
4164
4510
|
const dataElementsAudioCount = ((_a2 = purpose.data_elements) == null ? void 0 : _a2.length) || 0;
|
|
4165
4511
|
const totalPurposeAudioCount = purposeAudioCount + dataElementsAudioCount;
|
|
4166
4512
|
if (currentIndex >= audioOffset && currentIndex < audioOffset + totalPurposeAudioCount) {
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4513
|
+
setCollapsedPurposes((prev) => {
|
|
4514
|
+
const next = { ...prev };
|
|
4515
|
+
let changed = false;
|
|
4516
|
+
for (const row of purposeRows) {
|
|
4517
|
+
if (row.purpose.uuid !== purpose.uuid) continue;
|
|
4518
|
+
const rowKey = productPurposeKey(row.productUuid, purpose.uuid);
|
|
4519
|
+
if (next[rowKey]) {
|
|
4520
|
+
next[rowKey] = false;
|
|
4521
|
+
changed = true;
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
return changed ? next : prev;
|
|
4525
|
+
});
|
|
4173
4526
|
break;
|
|
4174
4527
|
}
|
|
4175
4528
|
audioOffset += totalPurposeAudioCount;
|
|
@@ -4247,7 +4600,15 @@ var RedactoNoticeConsent = ({
|
|
|
4247
4600
|
return () => {
|
|
4248
4601
|
ttsAbortController.abort();
|
|
4249
4602
|
};
|
|
4250
|
-
}, [
|
|
4603
|
+
}, [
|
|
4604
|
+
content,
|
|
4605
|
+
selectedLanguage,
|
|
4606
|
+
accessToken,
|
|
4607
|
+
sandboxParams,
|
|
4608
|
+
baseUrl,
|
|
4609
|
+
ledgerBaseUrl,
|
|
4610
|
+
getLanguageCode
|
|
4611
|
+
]);
|
|
4251
4612
|
const modalStyle = {
|
|
4252
4613
|
borderRadius: (settings == null ? void 0 : settings.borderRadius) || "8px",
|
|
4253
4614
|
backgroundColor: (settings == null ? void 0 : settings.backgroundColor) || "#ffffff",
|
|
@@ -4946,7 +5307,7 @@ var RedactoNoticeConsent = ({
|
|
|
4946
5307
|
},
|
|
4947
5308
|
`purpose-section-heading-${selectedLanguage}`
|
|
4948
5309
|
),
|
|
4949
|
-
categorizedPurposes ? /* @__PURE__ */ jsxs2("div", { style: styles.optionsContainer, children: [
|
|
5310
|
+
categorizedPurposes && !isMultiProduct(content == null ? void 0 : content.products) ? /* @__PURE__ */ jsxs2("div", { style: styles.optionsContainer, children: [
|
|
4950
5311
|
categorizedPurposes.alreadyConsented.map((purpose) => /* @__PURE__ */ jsx3(
|
|
4951
5312
|
PurposeItem,
|
|
4952
5313
|
{
|
|
@@ -4988,7 +5349,61 @@ var RedactoNoticeConsent = ({
|
|
|
4988
5349
|
))
|
|
4989
5350
|
] }) : (
|
|
4990
5351
|
/* Regular consent UI */
|
|
4991
|
-
/* @__PURE__ */ jsx3("div", { style: styles.optionsContainer, children: (
|
|
5352
|
+
/* @__PURE__ */ jsx3("div", { style: styles.optionsContainer, children: isMultiProduct(content == null ? void 0 : content.products) ? productGroups.map((group) => {
|
|
5353
|
+
const selectedInGroup = group.purposes.filter(
|
|
5354
|
+
(purpose) => selectedPurposes[productPurposeKey(
|
|
5355
|
+
group.product.uuid,
|
|
5356
|
+
purpose.uuid
|
|
5357
|
+
)]
|
|
5358
|
+
).length;
|
|
5359
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
5360
|
+
/* @__PURE__ */ jsx3(
|
|
5361
|
+
ProductSectionHeader,
|
|
5362
|
+
{
|
|
5363
|
+
product: group.product,
|
|
5364
|
+
purposeCount: group.purposes.length,
|
|
5365
|
+
allSelected: selectedInGroup === group.purposes.length,
|
|
5366
|
+
someSelected: selectedInGroup > 0,
|
|
5367
|
+
collapsed: collapsedProducts[group.product.uuid] || false,
|
|
5368
|
+
locked: isFullyConsentedReviewMode,
|
|
5369
|
+
settings,
|
|
5370
|
+
styles,
|
|
5371
|
+
responsiveStyles,
|
|
5372
|
+
onToggleCollapse: toggleProductCollapse,
|
|
5373
|
+
onToggleSelect: handleProductCheckboxChange,
|
|
5374
|
+
getTranslatedText
|
|
5375
|
+
}
|
|
5376
|
+
),
|
|
5377
|
+
/* @__PURE__ */ jsx3(
|
|
5378
|
+
"div",
|
|
5379
|
+
{
|
|
5380
|
+
id: `product-${group.product.uuid}`,
|
|
5381
|
+
hidden: collapsedProducts[group.product.uuid] || false,
|
|
5382
|
+
children: group.purposes.map((purpose) => /* @__PURE__ */ jsx3(
|
|
5383
|
+
PurposeItem,
|
|
5384
|
+
{
|
|
5385
|
+
purpose,
|
|
5386
|
+
productUuid: group.product.uuid,
|
|
5387
|
+
selectedPurposes,
|
|
5388
|
+
collapsedPurposes,
|
|
5389
|
+
selectedDataElements,
|
|
5390
|
+
settings,
|
|
5391
|
+
styles,
|
|
5392
|
+
responsiveStyles,
|
|
5393
|
+
onPurposeToggle: handlePurposeCheckboxChange,
|
|
5394
|
+
onPurposeCollapse: togglePurposeCollapse,
|
|
5395
|
+
onDataElementToggle: handleDataElementCheckboxChange,
|
|
5396
|
+
getTranslatedText,
|
|
5397
|
+
isAlreadyConsented: isFullyConsentedReviewMode,
|
|
5398
|
+
selectedLanguage,
|
|
5399
|
+
initialDataElementSelections
|
|
5400
|
+
},
|
|
5401
|
+
`${group.product.uuid}-${purpose.uuid}-${selectedLanguage}`
|
|
5402
|
+
))
|
|
5403
|
+
}
|
|
5404
|
+
)
|
|
5405
|
+
] }, group.product.uuid);
|
|
5406
|
+
}) : (_y = content == null ? void 0 : content.purposes) == null ? void 0 : _y.map((purpose) => /* @__PURE__ */ jsx3(
|
|
4992
5407
|
PurposeItem,
|
|
4993
5408
|
{
|
|
4994
5409
|
purpose,
|
|
@@ -5699,7 +6114,6 @@ var RedactoConsentInlineComponent = ({
|
|
|
5699
6114
|
settings,
|
|
5700
6115
|
applicationId
|
|
5701
6116
|
}) => {
|
|
5702
|
-
var _a;
|
|
5703
6117
|
const [content, setContent] = useState3(null);
|
|
5704
6118
|
const [isLoading, setIsLoading] = useState3(true);
|
|
5705
6119
|
const [isSubmitting, setIsSubmitting] = useState3(false);
|
|
@@ -5756,7 +6170,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
5756
6170
|
}
|
|
5757
6171
|
}, [hasAlreadyConsented, onAccept]);
|
|
5758
6172
|
const getTranslatedText = (key, defaultText, itemId) => {
|
|
5759
|
-
var
|
|
6173
|
+
var _a, _b, _c;
|
|
5760
6174
|
if (!content) return defaultText;
|
|
5761
6175
|
if (selectedLanguage === "English" || selectedLanguage === "en" || selectedLanguage === "EN") {
|
|
5762
6176
|
if (key === "privacy_policy_anchor_text" && content.privacy_policy_anchor_text) {
|
|
@@ -5773,7 +6187,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
5773
6187
|
}
|
|
5774
6188
|
if (itemId) {
|
|
5775
6189
|
if (key === "purposes.name" || key === "purposes.description") {
|
|
5776
|
-
const purposeData = (
|
|
6190
|
+
const purposeData = (_a = translationMap.purposes) == null ? void 0 : _a[itemId];
|
|
5777
6191
|
if (purposeData) {
|
|
5778
6192
|
if (typeof purposeData === "string") {
|
|
5779
6193
|
return key === "purposes.name" ? purposeData : defaultText;
|
|
@@ -5782,8 +6196,18 @@ var RedactoConsentInlineComponent = ({
|
|
|
5782
6196
|
}
|
|
5783
6197
|
return defaultText;
|
|
5784
6198
|
}
|
|
6199
|
+
if (key === "products.name" || key === "products.description") {
|
|
6200
|
+
const productData = (_b = translationMap.products) == null ? void 0 : _b[itemId];
|
|
6201
|
+
if (productData) {
|
|
6202
|
+
if (typeof productData === "string") {
|
|
6203
|
+
return key === "products.name" ? productData : defaultText;
|
|
6204
|
+
}
|
|
6205
|
+
return key === "products.name" ? productData.name || defaultText : productData.description || defaultText;
|
|
6206
|
+
}
|
|
6207
|
+
return defaultText;
|
|
6208
|
+
}
|
|
5785
6209
|
if (key.startsWith("data_elements.")) {
|
|
5786
|
-
return ((
|
|
6210
|
+
return ((_c = translationMap.data_elements) == null ? void 0 : _c[itemId]) || defaultText;
|
|
5787
6211
|
}
|
|
5788
6212
|
}
|
|
5789
6213
|
const value = translationMap[key];
|
|
@@ -5892,25 +6316,27 @@ var RedactoConsentInlineComponent = ({
|
|
|
5892
6316
|
controller.abort();
|
|
5893
6317
|
};
|
|
5894
6318
|
}, [ledgerBaseUrl, applicationId, accessToken, content, notice_uuid]);
|
|
5895
|
-
const togglePurposeCollapse = (purposeUuid) => {
|
|
6319
|
+
const togglePurposeCollapse = (purposeUuid, productUuid) => {
|
|
6320
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
5896
6321
|
setCollapsedPurposes((prev) => ({
|
|
5897
6322
|
...prev,
|
|
5898
|
-
[
|
|
6323
|
+
[key]: !prev[key]
|
|
5899
6324
|
}));
|
|
5900
6325
|
};
|
|
5901
|
-
const handlePurposeCheckboxChange = (purposeUuid) => {
|
|
6326
|
+
const handlePurposeCheckboxChange = (purposeUuid, productUuid) => {
|
|
5902
6327
|
if (content) {
|
|
5903
6328
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
5904
6329
|
if (purpose) {
|
|
5905
|
-
const
|
|
6330
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
6331
|
+
const newPurposeState = !selectedPurposes[key];
|
|
5906
6332
|
setSelectedPurposes((prev) => ({
|
|
5907
6333
|
...prev,
|
|
5908
|
-
[
|
|
6334
|
+
[key]: newPurposeState
|
|
5909
6335
|
}));
|
|
5910
6336
|
setSelectedDataElements((prev) => {
|
|
5911
6337
|
const updated = { ...prev };
|
|
5912
6338
|
purpose.data_elements.forEach((el) => {
|
|
5913
|
-
const combinedId = `${
|
|
6339
|
+
const combinedId = `${key}-${el.uuid}`;
|
|
5914
6340
|
updated[combinedId] = newPurposeState;
|
|
5915
6341
|
});
|
|
5916
6342
|
return updated;
|
|
@@ -5918,7 +6344,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
5918
6344
|
}
|
|
5919
6345
|
}
|
|
5920
6346
|
};
|
|
5921
|
-
const handleDataElementCheckboxChange = (elementUuid, purposeUuid) => {
|
|
6347
|
+
const handleDataElementCheckboxChange = (elementUuid, purposeUuid, productUuid) => {
|
|
5922
6348
|
if (!content) return;
|
|
5923
6349
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
5924
6350
|
if (!purpose) return;
|
|
@@ -5926,7 +6352,8 @@ var RedactoConsentInlineComponent = ({
|
|
|
5926
6352
|
(el) => el.uuid === elementUuid
|
|
5927
6353
|
);
|
|
5928
6354
|
if (!dataElement) return;
|
|
5929
|
-
const
|
|
6355
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
6356
|
+
const combinedId = `${key}-${elementUuid}`;
|
|
5930
6357
|
const currentState = selectedDataElements[combinedId] || false;
|
|
5931
6358
|
const newElementState = !currentState;
|
|
5932
6359
|
setSelectedDataElements((prev) => {
|
|
@@ -5940,16 +6367,16 @@ var RedactoConsentInlineComponent = ({
|
|
|
5940
6367
|
let shouldCheckPurpose;
|
|
5941
6368
|
if (requiredElements.length > 0) {
|
|
5942
6369
|
shouldCheckPurpose = requiredElements.every(
|
|
5943
|
-
(el) => newState[`${
|
|
6370
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
5944
6371
|
);
|
|
5945
6372
|
} else {
|
|
5946
6373
|
shouldCheckPurpose = purpose.data_elements.some(
|
|
5947
|
-
(el) => newState[`${
|
|
6374
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
5948
6375
|
);
|
|
5949
6376
|
}
|
|
5950
6377
|
setSelectedPurposes((prevPurposes) => ({
|
|
5951
6378
|
...prevPurposes,
|
|
5952
|
-
[
|
|
6379
|
+
[key]: shouldCheckPurpose
|
|
5953
6380
|
}));
|
|
5954
6381
|
return newState;
|
|
5955
6382
|
});
|
|
@@ -5970,20 +6397,36 @@ var RedactoConsentInlineComponent = ({
|
|
|
5970
6397
|
baseUrl,
|
|
5971
6398
|
ledgerBaseUrl,
|
|
5972
6399
|
noticeUuid: content.notice_uuid,
|
|
5973
|
-
|
|
6400
|
+
// One entry per (product, purpose) once a notice covers several, so a
|
|
6401
|
+
// purpose can be accepted for one product and declined for another.
|
|
6402
|
+
// Collapses to content.purposes below two products, leaving that
|
|
6403
|
+
// payload byte-identical to before.
|
|
6404
|
+
purposes: (isMultiProduct(content.products) ? expandPurposesByProduct(
|
|
6405
|
+
content.products,
|
|
6406
|
+
content.purposes,
|
|
6407
|
+
content.product_purpose_order
|
|
6408
|
+
).map((row) => ({
|
|
6409
|
+
purpose: row.purpose,
|
|
6410
|
+
productUuid: row.product.uuid
|
|
6411
|
+
})) : content.purposes.map((purpose) => ({
|
|
6412
|
+
purpose,
|
|
6413
|
+
productUuid: void 0
|
|
6414
|
+
}))).map(({ purpose, productUuid }) => {
|
|
6415
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
5974
6416
|
const hasSelectedRequiredElement = purpose.data_elements.some(
|
|
5975
|
-
(element) => element.required && (selectedDataElements[`${
|
|
6417
|
+
(element) => element.required && (selectedDataElements[`${key}-${element.uuid}`] || false)
|
|
5976
6418
|
);
|
|
5977
6419
|
const hasSelectedDataElement = purpose.data_elements.some(
|
|
5978
|
-
(element) => selectedDataElements[`${
|
|
6420
|
+
(element) => selectedDataElements[`${key}-${element.uuid}`] || false
|
|
5979
6421
|
);
|
|
5980
|
-
const purposeSelected = selectedPurposes[
|
|
6422
|
+
const purposeSelected = selectedPurposes[key] || hasSelectedRequiredElement || hasSelectedDataElement;
|
|
5981
6423
|
return {
|
|
5982
6424
|
...purpose,
|
|
6425
|
+
...productUuid ? { product_uuid: productUuid } : {},
|
|
5983
6426
|
selected: purposeSelected,
|
|
5984
6427
|
data_elements: purpose.data_elements.map((element) => ({
|
|
5985
6428
|
...element,
|
|
5986
|
-
selected: selectedDataElements[`${
|
|
6429
|
+
selected: selectedDataElements[`${key}-${element.uuid}`] || false
|
|
5987
6430
|
}))
|
|
5988
6431
|
};
|
|
5989
6432
|
}),
|
|
@@ -6084,133 +6527,99 @@ var RedactoConsentInlineComponent = ({
|
|
|
6084
6527
|
children: errorMessage
|
|
6085
6528
|
}
|
|
6086
6529
|
),
|
|
6087
|
-
(
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
onClick: () => togglePurposeCollapse(purpose.uuid),
|
|
6094
|
-
role: "button",
|
|
6095
|
-
tabIndex: 0,
|
|
6096
|
-
"aria-expanded": !collapsedPurposes[purpose.uuid],
|
|
6097
|
-
"aria-controls": `purpose-${purpose.uuid}`,
|
|
6098
|
-
"aria-label": `${collapsedPurposes[purpose.uuid] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
6099
|
-
`purposes.name`,
|
|
6100
|
-
purpose.name,
|
|
6101
|
-
purpose.uuid
|
|
6102
|
-
)} details`,
|
|
6103
|
-
onKeyDown: (e) => {
|
|
6104
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
6105
|
-
e.preventDefault();
|
|
6106
|
-
togglePurposeCollapse(purpose.uuid);
|
|
6107
|
-
}
|
|
6108
|
-
},
|
|
6109
|
-
children: [
|
|
6110
|
-
/* @__PURE__ */ jsx4(
|
|
6111
|
-
"div",
|
|
6112
|
-
{
|
|
6113
|
-
style: {
|
|
6114
|
-
display: "flex",
|
|
6115
|
-
alignItems: "center",
|
|
6116
|
-
justifyContent: "center",
|
|
6117
|
-
marginLeft: "5px"
|
|
6118
|
-
},
|
|
6119
|
-
children: /* @__PURE__ */ jsx4(
|
|
6120
|
-
"svg",
|
|
6121
|
-
{
|
|
6122
|
-
width: "7",
|
|
6123
|
-
height: "12",
|
|
6124
|
-
viewBox: "0 0 7 12",
|
|
6125
|
-
fill: "none",
|
|
6126
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
6127
|
-
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
6128
|
-
strokeWidth: "2",
|
|
6129
|
-
strokeLinecap: "round",
|
|
6130
|
-
strokeLinejoin: "round",
|
|
6131
|
-
style: {
|
|
6132
|
-
transform: !collapsedPurposes[purpose.uuid] ? "rotate(90deg)" : "rotate(0deg)",
|
|
6133
|
-
transition: "transform 0.3s ease"
|
|
6134
|
-
},
|
|
6135
|
-
"aria-hidden": "true",
|
|
6136
|
-
children: /* @__PURE__ */ jsx4("path", { d: "M1 1L6 6L1 11" })
|
|
6137
|
-
}
|
|
6138
|
-
)
|
|
6139
|
-
}
|
|
6140
|
-
),
|
|
6141
|
-
/* @__PURE__ */ jsxs3("div", { style: styles2.optionTextContainer, children: [
|
|
6142
|
-
/* @__PURE__ */ jsxs3(
|
|
6143
|
-
"h2",
|
|
6144
|
-
{
|
|
6145
|
-
style: {
|
|
6146
|
-
...styles2.optionTitle,
|
|
6147
|
-
...responsiveStyles.optionTitle,
|
|
6148
|
-
...headingStyle
|
|
6149
|
-
},
|
|
6150
|
-
children: [
|
|
6151
|
-
getTranslatedText(
|
|
6152
|
-
`purposes.name`,
|
|
6153
|
-
purpose.name,
|
|
6154
|
-
purpose.uuid
|
|
6155
|
-
),
|
|
6156
|
-
hasRequiredDataElement(purpose) && /* @__PURE__ */ jsx4(RequiredMarker, {})
|
|
6157
|
-
]
|
|
6158
|
-
}
|
|
6159
|
-
),
|
|
6160
|
-
/* @__PURE__ */ jsx4(
|
|
6161
|
-
"h3",
|
|
6162
|
-
{
|
|
6163
|
-
style: {
|
|
6164
|
-
...styles2.optionDescription,
|
|
6165
|
-
...responsiveStyles.optionDescription,
|
|
6166
|
-
...textStyle
|
|
6167
|
-
},
|
|
6168
|
-
children: getTranslatedText(
|
|
6169
|
-
`purposes.description`,
|
|
6170
|
-
purpose.description,
|
|
6171
|
-
purpose.uuid
|
|
6172
|
-
)
|
|
6173
|
-
}
|
|
6174
|
-
)
|
|
6175
|
-
] })
|
|
6176
|
-
]
|
|
6177
|
-
}
|
|
6178
|
-
),
|
|
6179
|
-
/* @__PURE__ */ jsx4(
|
|
6180
|
-
"input",
|
|
6181
|
-
{
|
|
6182
|
-
type: "checkbox",
|
|
6183
|
-
checked: selectedPurposes[purpose.uuid] || false,
|
|
6184
|
-
onChange: () => handlePurposeCheckboxChange(purpose.uuid),
|
|
6185
|
-
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
6186
|
-
`purposes.name`,
|
|
6187
|
-
purpose.name,
|
|
6188
|
-
purpose.uuid
|
|
6189
|
-
)}`
|
|
6190
|
-
}
|
|
6191
|
-
)
|
|
6192
|
-
] }),
|
|
6193
|
-
!collapsedPurposes[purpose.uuid] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ jsx4(
|
|
6194
|
-
"div",
|
|
6195
|
-
{
|
|
6196
|
-
id: `purpose-${purpose.uuid}`,
|
|
6197
|
-
style: styles2.dataElementsContainer,
|
|
6198
|
-
children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ jsxs3("div", { style: styles2.dataElementItem, children: [
|
|
6530
|
+
(() => {
|
|
6531
|
+
var _a, _b;
|
|
6532
|
+
const renderPurpose = (purpose, productUuid) => {
|
|
6533
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
6534
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
6535
|
+
/* @__PURE__ */ jsxs3("div", { style: styles2.optionItem, children: [
|
|
6199
6536
|
/* @__PURE__ */ jsxs3(
|
|
6200
|
-
"
|
|
6537
|
+
"div",
|
|
6201
6538
|
{
|
|
6202
|
-
style:
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6539
|
+
style: styles2.optionLeft,
|
|
6540
|
+
onClick: () => togglePurposeCollapse(purpose.uuid, productUuid),
|
|
6541
|
+
role: "button",
|
|
6542
|
+
tabIndex: 0,
|
|
6543
|
+
"aria-expanded": !collapsedPurposes[stateKey],
|
|
6544
|
+
"aria-controls": `purpose-${stateKey}`,
|
|
6545
|
+
"aria-label": `${collapsedPurposes[stateKey] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
6546
|
+
`purposes.name`,
|
|
6547
|
+
purpose.name,
|
|
6548
|
+
purpose.uuid
|
|
6549
|
+
)} details`,
|
|
6550
|
+
onKeyDown: (e) => {
|
|
6551
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6552
|
+
e.preventDefault();
|
|
6553
|
+
togglePurposeCollapse(purpose.uuid, productUuid);
|
|
6554
|
+
}
|
|
6206
6555
|
},
|
|
6207
6556
|
children: [
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6557
|
+
/* @__PURE__ */ jsx4(
|
|
6558
|
+
"div",
|
|
6559
|
+
{
|
|
6560
|
+
style: {
|
|
6561
|
+
display: "flex",
|
|
6562
|
+
alignItems: "center",
|
|
6563
|
+
justifyContent: "center",
|
|
6564
|
+
marginLeft: "5px"
|
|
6565
|
+
},
|
|
6566
|
+
children: /* @__PURE__ */ jsx4(
|
|
6567
|
+
"svg",
|
|
6568
|
+
{
|
|
6569
|
+
width: "7",
|
|
6570
|
+
height: "12",
|
|
6571
|
+
viewBox: "0 0 7 12",
|
|
6572
|
+
fill: "none",
|
|
6573
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6574
|
+
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
6575
|
+
strokeWidth: "2",
|
|
6576
|
+
strokeLinecap: "round",
|
|
6577
|
+
strokeLinejoin: "round",
|
|
6578
|
+
style: {
|
|
6579
|
+
transform: !collapsedPurposes[stateKey] ? "rotate(90deg)" : "rotate(0deg)",
|
|
6580
|
+
transition: "transform 0.3s ease"
|
|
6581
|
+
},
|
|
6582
|
+
"aria-hidden": "true",
|
|
6583
|
+
children: /* @__PURE__ */ jsx4("path", { d: "M1 1L6 6L1 11" })
|
|
6584
|
+
}
|
|
6585
|
+
)
|
|
6586
|
+
}
|
|
6212
6587
|
),
|
|
6213
|
-
|
|
6588
|
+
/* @__PURE__ */ jsxs3("div", { style: styles2.optionTextContainer, children: [
|
|
6589
|
+
/* @__PURE__ */ jsxs3(
|
|
6590
|
+
"h2",
|
|
6591
|
+
{
|
|
6592
|
+
style: {
|
|
6593
|
+
...styles2.optionTitle,
|
|
6594
|
+
...responsiveStyles.optionTitle,
|
|
6595
|
+
...headingStyle
|
|
6596
|
+
},
|
|
6597
|
+
children: [
|
|
6598
|
+
getTranslatedText(
|
|
6599
|
+
`purposes.name`,
|
|
6600
|
+
purpose.name,
|
|
6601
|
+
purpose.uuid
|
|
6602
|
+
),
|
|
6603
|
+
hasRequiredDataElement(purpose) && /* @__PURE__ */ jsx4(RequiredMarker, {})
|
|
6604
|
+
]
|
|
6605
|
+
}
|
|
6606
|
+
),
|
|
6607
|
+
/* @__PURE__ */ jsx4(
|
|
6608
|
+
"h3",
|
|
6609
|
+
{
|
|
6610
|
+
style: {
|
|
6611
|
+
...styles2.optionDescription,
|
|
6612
|
+
...responsiveStyles.optionDescription,
|
|
6613
|
+
...textStyle
|
|
6614
|
+
},
|
|
6615
|
+
children: getTranslatedText(
|
|
6616
|
+
`purposes.description`,
|
|
6617
|
+
purpose.description,
|
|
6618
|
+
purpose.uuid
|
|
6619
|
+
)
|
|
6620
|
+
}
|
|
6621
|
+
)
|
|
6622
|
+
] })
|
|
6214
6623
|
]
|
|
6215
6624
|
}
|
|
6216
6625
|
),
|
|
@@ -6218,22 +6627,87 @@ var RedactoConsentInlineComponent = ({
|
|
|
6218
6627
|
"input",
|
|
6219
6628
|
{
|
|
6220
6629
|
type: "checkbox",
|
|
6221
|
-
checked:
|
|
6222
|
-
onChange: () =>
|
|
6223
|
-
|
|
6630
|
+
checked: selectedPurposes[stateKey] || false,
|
|
6631
|
+
onChange: () => handlePurposeCheckboxChange(purpose.uuid, productUuid),
|
|
6632
|
+
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
6633
|
+
`purposes.name`,
|
|
6634
|
+
purpose.name,
|
|
6224
6635
|
purpose.uuid
|
|
6225
|
-
)
|
|
6226
|
-
"aria-label": `Select ${getTranslatedText(
|
|
6227
|
-
`data_elements.name`,
|
|
6228
|
-
dataElement.name,
|
|
6229
|
-
dataElement.uuid
|
|
6230
|
-
)}${dataElement.required ? " (required)" : ""}`
|
|
6636
|
+
)}`
|
|
6231
6637
|
}
|
|
6232
6638
|
)
|
|
6233
|
-
] },
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6639
|
+
] }),
|
|
6640
|
+
!collapsedPurposes[stateKey] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ jsx4(
|
|
6641
|
+
"div",
|
|
6642
|
+
{
|
|
6643
|
+
id: `purpose-${stateKey}`,
|
|
6644
|
+
style: styles2.dataElementsContainer,
|
|
6645
|
+
children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ jsxs3(
|
|
6646
|
+
"div",
|
|
6647
|
+
{
|
|
6648
|
+
style: styles2.dataElementItem,
|
|
6649
|
+
children: [
|
|
6650
|
+
/* @__PURE__ */ jsxs3(
|
|
6651
|
+
"span",
|
|
6652
|
+
{
|
|
6653
|
+
style: {
|
|
6654
|
+
...styles2.dataElementText,
|
|
6655
|
+
...responsiveStyles.dataElementText,
|
|
6656
|
+
...textStyle
|
|
6657
|
+
},
|
|
6658
|
+
children: [
|
|
6659
|
+
getTranslatedText(
|
|
6660
|
+
`data_elements.name`,
|
|
6661
|
+
dataElement.name,
|
|
6662
|
+
dataElement.uuid
|
|
6663
|
+
),
|
|
6664
|
+
dataElement.required && /* @__PURE__ */ jsx4(RequiredMarker, {})
|
|
6665
|
+
]
|
|
6666
|
+
}
|
|
6667
|
+
),
|
|
6668
|
+
/* @__PURE__ */ jsx4(
|
|
6669
|
+
"input",
|
|
6670
|
+
{
|
|
6671
|
+
type: "checkbox",
|
|
6672
|
+
checked: selectedDataElements[`${stateKey}-${dataElement.uuid}`] || false,
|
|
6673
|
+
onChange: () => handleDataElementCheckboxChange(
|
|
6674
|
+
dataElement.uuid,
|
|
6675
|
+
purpose.uuid,
|
|
6676
|
+
productUuid
|
|
6677
|
+
),
|
|
6678
|
+
"aria-label": `Select ${getTranslatedText(
|
|
6679
|
+
`data_elements.name`,
|
|
6680
|
+
dataElement.name,
|
|
6681
|
+
dataElement.uuid
|
|
6682
|
+
)}${dataElement.required ? " (required)" : ""}`
|
|
6683
|
+
}
|
|
6684
|
+
)
|
|
6685
|
+
]
|
|
6686
|
+
},
|
|
6687
|
+
dataElement.uuid
|
|
6688
|
+
))
|
|
6689
|
+
}
|
|
6690
|
+
)
|
|
6691
|
+
] }, stateKey);
|
|
6692
|
+
};
|
|
6693
|
+
if (!isMultiProduct(content == null ? void 0 : content.products)) {
|
|
6694
|
+
return (_a = content == null ? void 0 : content.purposes) == null ? void 0 : _a.map((purpose) => renderPurpose(purpose));
|
|
6695
|
+
}
|
|
6696
|
+
return groupPurposesByProduct(
|
|
6697
|
+
content == null ? void 0 : content.products,
|
|
6698
|
+
(_b = content == null ? void 0 : content.purposes) != null ? _b : [],
|
|
6699
|
+
content == null ? void 0 : content.product_purpose_order
|
|
6700
|
+
).map((group) => /* @__PURE__ */ jsxs3("div", { children: [
|
|
6701
|
+
/* @__PURE__ */ jsx4("div", { style: { ...styles2.optionTitle, margin: "0 0 8px" }, children: getTranslatedText(
|
|
6702
|
+
"products.name",
|
|
6703
|
+
group.product.name,
|
|
6704
|
+
group.product.uuid
|
|
6705
|
+
) }),
|
|
6706
|
+
group.purposes.map(
|
|
6707
|
+
(purpose) => renderPurpose(purpose, group.product.uuid)
|
|
6708
|
+
)
|
|
6709
|
+
] }, group.product.uuid));
|
|
6710
|
+
})()
|
|
6237
6711
|
] });
|
|
6238
6712
|
};
|
|
6239
6713
|
RedactoConsentInlineComponent.displayName = "RedactoConsentInline";
|
|
@@ -9375,10 +9849,14 @@ var RedactoNoticeAssisted = ({
|
|
|
9375
9849
|
const handleConfirmStep = useCallback3(
|
|
9376
9850
|
(mode = "selected") => {
|
|
9377
9851
|
if (mode !== "selected" && content) {
|
|
9378
|
-
const selection = buildSelectionForMode(
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9852
|
+
const selection = buildSelectionForMode(
|
|
9853
|
+
noticePurposeRows(void 0, content.purposes),
|
|
9854
|
+
mode,
|
|
9855
|
+
{
|
|
9856
|
+
selectedPurposes,
|
|
9857
|
+
selectedDataElements
|
|
9858
|
+
}
|
|
9859
|
+
);
|
|
9382
9860
|
setSelectedPurposes(selection.selectedPurposes);
|
|
9383
9861
|
setSelectedDataElements(selection.selectedDataElements);
|
|
9384
9862
|
}
|
|
@@ -9579,10 +10057,14 @@ var RedactoNoticeAssisted = ({
|
|
|
9579
10057
|
return;
|
|
9580
10058
|
}
|
|
9581
10059
|
}
|
|
9582
|
-
const selection = buildSelectionForMode(
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
10060
|
+
const selection = buildSelectionForMode(
|
|
10061
|
+
noticePurposeRows(void 0, content.purposes),
|
|
10062
|
+
acceptMode,
|
|
10063
|
+
{
|
|
10064
|
+
selectedPurposes,
|
|
10065
|
+
selectedDataElements
|
|
10066
|
+
}
|
|
10067
|
+
);
|
|
9586
10068
|
const submitPurposes = content.purposes.map((purpose) => ({
|
|
9587
10069
|
...purpose,
|
|
9588
10070
|
selected: selection.selectedPurposes[purpose.uuid] || false,
|