@redacto.io/consent-sdk-react 10.1.0 → 10.2.0-beta.1
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/chunk-6EET4YOY.mjs +93 -0
- package/dist/index.js +915 -343
- package/dist/index.mjs +864 -343
- package/dist/privacy-center.d.mts +3 -1
- package/dist/privacy-center.d.ts +3 -1
- package/dist/privacy-center.js +177 -35
- package/dist/privacy-center.mjs +122 -37
- package/package.json +1 -1
- package/dist/chunk-OGL6OC3A.mjs +0 -34
package/dist/index.js
CHANGED
|
@@ -219,6 +219,64 @@ var sandboxBodyIdentity = (sandbox) => {
|
|
|
219
219
|
};
|
|
220
220
|
var sandboxQueryIdentity = (sandbox) => sandboxBodyIdentity(sandbox);
|
|
221
221
|
|
|
222
|
+
// src/shared/idempotency.ts
|
|
223
|
+
var HEADER = "Idempotency-Key";
|
|
224
|
+
var pending = /* @__PURE__ */ new Map();
|
|
225
|
+
var MAX_PENDING = 16;
|
|
226
|
+
var mintKey = () => {
|
|
227
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
228
|
+
return crypto.randomUUID();
|
|
229
|
+
}
|
|
230
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 14)}-${Math.random().toString(36).slice(2, 14)}`;
|
|
231
|
+
};
|
|
232
|
+
var statusOf = (outcome) => {
|
|
233
|
+
if (typeof Response !== "undefined" && outcome instanceof Response) {
|
|
234
|
+
return outcome.status;
|
|
235
|
+
}
|
|
236
|
+
if (outcome && typeof outcome === "object" && "status" in outcome) {
|
|
237
|
+
const status = outcome.status;
|
|
238
|
+
if (typeof status === "number") return status;
|
|
239
|
+
}
|
|
240
|
+
return void 0;
|
|
241
|
+
};
|
|
242
|
+
var settledOnResolve = (result) => {
|
|
243
|
+
const status = statusOf(result);
|
|
244
|
+
return status === void 0 || status < 500;
|
|
245
|
+
};
|
|
246
|
+
var settledOnReject = (error) => {
|
|
247
|
+
const status = statusOf(error);
|
|
248
|
+
return status !== void 0 && status < 500;
|
|
249
|
+
};
|
|
250
|
+
var withIdempotencyKey = async (url, body, send) => {
|
|
251
|
+
const signature = `${url}
|
|
252
|
+
${body}`;
|
|
253
|
+
let entry = pending.get(signature);
|
|
254
|
+
if (!entry) {
|
|
255
|
+
entry = { key: mintKey(), inFlight: 0, keep: false };
|
|
256
|
+
if (pending.size >= MAX_PENDING) {
|
|
257
|
+
const oldest = pending.keys().next().value;
|
|
258
|
+
if (oldest !== void 0) pending.delete(oldest);
|
|
259
|
+
}
|
|
260
|
+
pending.set(signature, entry);
|
|
261
|
+
} else if (entry.inFlight === 0) {
|
|
262
|
+
entry.keep = false;
|
|
263
|
+
}
|
|
264
|
+
entry.inFlight += 1;
|
|
265
|
+
const settle = (settled) => {
|
|
266
|
+
entry.inFlight -= 1;
|
|
267
|
+
if (!settled) entry.keep = true;
|
|
268
|
+
if (entry.inFlight === 0 && !entry.keep) pending.delete(signature);
|
|
269
|
+
};
|
|
270
|
+
try {
|
|
271
|
+
const result = await send({ [HEADER]: entry.key });
|
|
272
|
+
settle(settledOnResolve(result));
|
|
273
|
+
return result;
|
|
274
|
+
} catch (error) {
|
|
275
|
+
settle(settledOnReject(error));
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
222
280
|
// src/shared/notice-consent-status.ts
|
|
223
281
|
var import_jwt_decode = require("jwt-decode");
|
|
224
282
|
var decodeNoticeConsentToken = (token) => {
|
|
@@ -420,6 +478,9 @@ var submitConsentEvent = async ({
|
|
|
420
478
|
}));
|
|
421
479
|
return {
|
|
422
480
|
purpose_uuid: purpose.uuid,
|
|
481
|
+
// Omitted on a single-product notice, where the ledger applies the
|
|
482
|
+
// selection to every product the purpose covers.
|
|
483
|
+
product_uuid: purpose.product_uuid || void 0,
|
|
423
484
|
selected: Boolean(purpose.selected),
|
|
424
485
|
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
425
486
|
};
|
|
@@ -436,17 +497,21 @@ var submitConsentEvent = async ({
|
|
|
436
497
|
self_declared_adult: selfDeclaredAdult
|
|
437
498
|
};
|
|
438
499
|
const requestBody = sandbox ? { ...payload, ...sandboxBodyIdentity(sandbox) } : payload;
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
500
|
+
const url = `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`;
|
|
501
|
+
const serialisedBody = JSON.stringify(requestBody);
|
|
502
|
+
const response = await withIdempotencyKey(
|
|
503
|
+
url,
|
|
504
|
+
serialisedBody,
|
|
505
|
+
(idempotencyHeaders) => fetch(url, {
|
|
442
506
|
method: "POST",
|
|
443
507
|
headers: {
|
|
444
508
|
...buildAuthHeaders(accessToken, sandbox),
|
|
445
|
-
"Content-Type": "application/json"
|
|
509
|
+
"Content-Type": "application/json",
|
|
510
|
+
...idempotencyHeaders
|
|
446
511
|
},
|
|
447
|
-
body:
|
|
512
|
+
body: serialisedBody,
|
|
448
513
|
signal
|
|
449
|
-
}
|
|
514
|
+
})
|
|
450
515
|
);
|
|
451
516
|
if (!response.ok) {
|
|
452
517
|
throw await parseApiError(
|
|
@@ -679,6 +744,9 @@ var DPO_AUDIO_ELEMENT_MAP = [
|
|
|
679
744
|
{ audioKey: "dpo_text_audio_url", elementId: "dpo-dpo-text" },
|
|
680
745
|
{ audioKey: "dpo_anchor_text_audio_url", elementId: "dpo-dpo-link" }
|
|
681
746
|
];
|
|
747
|
+
var PRODUCT_SECTION_COPY = {
|
|
748
|
+
toggleSelection: (productName, purposeCount) => `Toggle all ${purposeCount} purposes for ${productName}`
|
|
749
|
+
};
|
|
682
750
|
|
|
683
751
|
// src/RedactoNoticeConsent/styles.ts
|
|
684
752
|
var styles = {
|
|
@@ -895,6 +963,37 @@ var styles = {
|
|
|
895
963
|
padding: 0,
|
|
896
964
|
boxSizing: "border-box"
|
|
897
965
|
},
|
|
966
|
+
// A product section's heading. Its own tokens rather than the row's: sharing
|
|
967
|
+
// optionTitle rendered the group name at the same size, weight and indent as
|
|
968
|
+
// the purposes inside it, leaving nothing to mark it as a heading.
|
|
969
|
+
sectionHeader: {
|
|
970
|
+
display: "flex",
|
|
971
|
+
justifyContent: "space-between",
|
|
972
|
+
alignItems: "center",
|
|
973
|
+
margin: "0 0 8px",
|
|
974
|
+
padding: 0,
|
|
975
|
+
boxSizing: "border-box"
|
|
976
|
+
},
|
|
977
|
+
// The purposes belonging to one product. Indented so the product chevron and
|
|
978
|
+
// the purpose chevrons below it do not sit on the same vertical line, which
|
|
979
|
+
// read as one flat list rather than a heading and its contents. The trailing
|
|
980
|
+
// margin separates a section from the next product heading.
|
|
981
|
+
sectionBody: {
|
|
982
|
+
paddingLeft: "18px",
|
|
983
|
+
margin: "0 0 14px",
|
|
984
|
+
boxSizing: "border-box"
|
|
985
|
+
},
|
|
986
|
+
// No colour token: the header always overrides it with the notice's
|
|
987
|
+
// headingColor, so one here would imply a default that never applies.
|
|
988
|
+
sectionTitle: {
|
|
989
|
+
fontWeight: 600,
|
|
990
|
+
fontSize: "17px",
|
|
991
|
+
lineHeight: "150%",
|
|
992
|
+
letterSpacing: "0.2px",
|
|
993
|
+
margin: 0,
|
|
994
|
+
padding: 0,
|
|
995
|
+
textAlign: "left"
|
|
996
|
+
},
|
|
898
997
|
optionTextContainer: {
|
|
899
998
|
display: "flex",
|
|
900
999
|
flexDirection: "column",
|
|
@@ -1039,10 +1138,10 @@ var styles = {
|
|
|
1039
1138
|
color: "#ffffff"
|
|
1040
1139
|
},
|
|
1041
1140
|
/**
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1141
|
+
* The accept-all shortcut. Tinted rather than filled so the primary
|
|
1142
|
+
* "accept selected" action stays visually dominant, and outlined-but-coloured
|
|
1143
|
+
* so it still reads as an accept next to the neutral decline button.
|
|
1144
|
+
*/
|
|
1046
1145
|
acceptSecondaryButton: {
|
|
1047
1146
|
backgroundColor: "#ffffff",
|
|
1048
1147
|
border: "1px solid #4f87ff",
|
|
@@ -1236,18 +1335,76 @@ var NoticeFooter = ({
|
|
|
1236
1335
|
] });
|
|
1237
1336
|
};
|
|
1238
1337
|
|
|
1338
|
+
// src/shared/productMatrix.ts
|
|
1339
|
+
var productPurposeKey = (productUuid, purposeUuid) => productUuid ? `${productUuid}:${purposeUuid}` : purposeUuid;
|
|
1340
|
+
var purposeCoversProduct = (purpose, productUuid) => {
|
|
1341
|
+
const scope = purpose.product_uuids;
|
|
1342
|
+
if (!scope || scope.length === 0) return true;
|
|
1343
|
+
return scope.includes(productUuid);
|
|
1344
|
+
};
|
|
1345
|
+
var isMultiProduct = (products) => Boolean(products && products.length > 1);
|
|
1346
|
+
var groupPurposesByProduct = (products, purposes, order) => {
|
|
1347
|
+
if (!products || products.length === 0) return [];
|
|
1348
|
+
return products.map((product) => {
|
|
1349
|
+
const covered = purposes.filter(
|
|
1350
|
+
(purpose) => purposeCoversProduct(purpose, product.uuid)
|
|
1351
|
+
);
|
|
1352
|
+
const saved = order == null ? void 0 : order[product.uuid];
|
|
1353
|
+
if (!saved || saved.length === 0) return { product, purposes: covered };
|
|
1354
|
+
const byUuid = new Map(covered.map((p) => [p.uuid, p]));
|
|
1355
|
+
const ordered = [];
|
|
1356
|
+
for (const uuid of saved) {
|
|
1357
|
+
const found = byUuid.get(uuid);
|
|
1358
|
+
if (found) ordered.push(found);
|
|
1359
|
+
}
|
|
1360
|
+
const rest = covered.filter((p) => !saved.includes(p.uuid));
|
|
1361
|
+
return { product, purposes: [...ordered, ...rest] };
|
|
1362
|
+
}).filter((group) => group.purposes.length > 0);
|
|
1363
|
+
};
|
|
1364
|
+
var expandPurposesByProduct = (products, purposes, order) => {
|
|
1365
|
+
if (!isMultiProduct(products)) return [];
|
|
1366
|
+
const rows = [];
|
|
1367
|
+
for (const group of groupPurposesByProduct(products, purposes, order)) {
|
|
1368
|
+
for (const purpose of group.purposes) {
|
|
1369
|
+
rows.push({ product: group.product, purpose });
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return rows;
|
|
1373
|
+
};
|
|
1374
|
+
var noticePurposeRows = (products, purposes, order) => {
|
|
1375
|
+
if (!isMultiProduct(products)) {
|
|
1376
|
+
return purposes.map((purpose) => ({ purpose, productUuid: void 0 }));
|
|
1377
|
+
}
|
|
1378
|
+
const rows = expandPurposesByProduct(products, purposes, order).map(
|
|
1379
|
+
(row) => ({
|
|
1380
|
+
purpose: row.purpose,
|
|
1381
|
+
productUuid: row.product.uuid
|
|
1382
|
+
})
|
|
1383
|
+
);
|
|
1384
|
+
const rendered = new Set(rows.map((row) => row.purpose.uuid));
|
|
1385
|
+
const orphaned = purposes.filter((purpose) => !rendered.has(purpose.uuid));
|
|
1386
|
+
if (orphaned.length > 0) {
|
|
1387
|
+
console.warn(
|
|
1388
|
+
"[redacto] purposes cover no product on this notice and will not be shown or submitted:",
|
|
1389
|
+
orphaned.map((purpose) => purpose.uuid)
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
return rows;
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1239
1395
|
// src/RedactoNoticeConsent/utils/consentSelection.ts
|
|
1240
|
-
var dataElementKey = (purposeUuid, elementUuid) => `${purposeUuid}-${elementUuid}`;
|
|
1241
|
-
var buildSelectionForMode = (
|
|
1396
|
+
var dataElementKey = (purposeUuid, elementUuid, productUuid) => `${productPurposeKey(productUuid, purposeUuid)}-${elementUuid}`;
|
|
1397
|
+
var buildSelectionForMode = (rows, mode, current) => {
|
|
1242
1398
|
if (mode === "selected") {
|
|
1243
1399
|
return current;
|
|
1244
1400
|
}
|
|
1245
1401
|
const selectedPurposes = {};
|
|
1246
1402
|
const selectedDataElements = {};
|
|
1247
|
-
|
|
1248
|
-
|
|
1403
|
+
rows.forEach(({ purpose, productUuid }) => {
|
|
1404
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
1405
|
+
selectedPurposes[key] = true;
|
|
1249
1406
|
purpose.data_elements.forEach((element) => {
|
|
1250
|
-
selectedDataElements[dataElementKey(purpose.uuid, element.uuid)] = element.enabled;
|
|
1407
|
+
selectedDataElements[dataElementKey(purpose.uuid, element.uuid, productUuid)] = element.enabled;
|
|
1251
1408
|
});
|
|
1252
1409
|
});
|
|
1253
1410
|
return { selectedPurposes, selectedDataElements };
|
|
@@ -1267,10 +1424,11 @@ var buildPreselection = (purposes, mode) => {
|
|
|
1267
1424
|
const selectedPurposes = {};
|
|
1268
1425
|
const selectedDataElements = {};
|
|
1269
1426
|
if (mode === "ALL") {
|
|
1270
|
-
return buildSelectionForMode(
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1427
|
+
return buildSelectionForMode(
|
|
1428
|
+
purposes.map((purpose) => ({ purpose, productUuid: void 0 })),
|
|
1429
|
+
"all",
|
|
1430
|
+
{ selectedPurposes, selectedDataElements }
|
|
1431
|
+
);
|
|
1274
1432
|
}
|
|
1275
1433
|
purposes.forEach((purpose) => {
|
|
1276
1434
|
let hasPreselectedElement = false;
|
|
@@ -1391,6 +1549,7 @@ var injectCheckboxStyles = () => {
|
|
|
1391
1549
|
cursor: pointer !important;
|
|
1392
1550
|
position: relative !important;
|
|
1393
1551
|
box-sizing: border-box !important;
|
|
1552
|
+
flex-shrink: 0 !important;
|
|
1394
1553
|
margin: 0 !important;
|
|
1395
1554
|
padding: 4px !important;
|
|
1396
1555
|
}
|
|
@@ -1407,6 +1566,7 @@ var injectCheckboxStyles = () => {
|
|
|
1407
1566
|
cursor: pointer !important;
|
|
1408
1567
|
position: relative !important;
|
|
1409
1568
|
box-sizing: border-box !important;
|
|
1569
|
+
flex-shrink: 0 !important;
|
|
1410
1570
|
margin: 0 !important;
|
|
1411
1571
|
padding: 4px !important;
|
|
1412
1572
|
}
|
|
@@ -1735,9 +1895,9 @@ var toFontFaceCss = (entry, sources) => sources.map(
|
|
|
1735
1895
|
).join("\n\n");
|
|
1736
1896
|
var fontSourceLoads = /* @__PURE__ */ new Map();
|
|
1737
1897
|
var loadFontSources = (entry, importSources) => {
|
|
1738
|
-
const
|
|
1739
|
-
if (
|
|
1740
|
-
return
|
|
1898
|
+
const pending2 = fontSourceLoads.get(entry.id);
|
|
1899
|
+
if (pending2) {
|
|
1900
|
+
return pending2;
|
|
1741
1901
|
}
|
|
1742
1902
|
const load = importSources().then((module2) => module2.NOTICE_FONT_SOURCES).catch((error) => {
|
|
1743
1903
|
fontSourceLoads.delete(entry.id);
|
|
@@ -1899,8 +2059,113 @@ var updateConsentState = (updates) => {
|
|
|
1899
2059
|
|
|
1900
2060
|
// src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
|
|
1901
2061
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2062
|
+
var DEFAULT_HEADING_COLOR = "#323B4B";
|
|
2063
|
+
var CHEVRON_BUTTON_STYLE = {
|
|
2064
|
+
background: "none",
|
|
2065
|
+
border: "none",
|
|
2066
|
+
padding: 0,
|
|
2067
|
+
margin: 0,
|
|
2068
|
+
cursor: "pointer",
|
|
2069
|
+
display: "flex",
|
|
2070
|
+
alignItems: "center"
|
|
2071
|
+
};
|
|
2072
|
+
var CHEVRON_WRAPPER_STYLE = {
|
|
2073
|
+
display: "flex",
|
|
2074
|
+
alignItems: "center",
|
|
2075
|
+
justifyContent: "center",
|
|
2076
|
+
marginLeft: "5px"
|
|
2077
|
+
};
|
|
2078
|
+
var CollapseChevron = ({ open, color }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: CHEVRON_WRAPPER_STYLE, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2079
|
+
"svg",
|
|
2080
|
+
{
|
|
2081
|
+
width: "7",
|
|
2082
|
+
height: "12",
|
|
2083
|
+
viewBox: "0 0 7 12",
|
|
2084
|
+
fill: "none",
|
|
2085
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2086
|
+
stroke: color,
|
|
2087
|
+
strokeWidth: "2",
|
|
2088
|
+
strokeLinecap: "round",
|
|
2089
|
+
strokeLinejoin: "round",
|
|
2090
|
+
style: {
|
|
2091
|
+
transform: open ? "rotate(90deg)" : "rotate(0deg)",
|
|
2092
|
+
transition: "transform 0.3s ease"
|
|
2093
|
+
},
|
|
2094
|
+
"aria-hidden": "true",
|
|
2095
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M1 1L6 6L1 11" })
|
|
2096
|
+
}
|
|
2097
|
+
) });
|
|
2098
|
+
var ProductSectionHeader = ({
|
|
2099
|
+
product,
|
|
2100
|
+
purposeCount,
|
|
2101
|
+
allSelected,
|
|
2102
|
+
someSelected,
|
|
2103
|
+
collapsed,
|
|
2104
|
+
locked,
|
|
2105
|
+
settings,
|
|
2106
|
+
styles: styles4,
|
|
2107
|
+
responsiveStyles,
|
|
2108
|
+
onToggleCollapse,
|
|
2109
|
+
onToggleSelect,
|
|
2110
|
+
getTranslatedText
|
|
2111
|
+
}) => {
|
|
2112
|
+
const checkboxRef = (0, import_react3.useRef)(null);
|
|
2113
|
+
const name = getTranslatedText("products.name", product.name, product.uuid);
|
|
2114
|
+
const headingColor = (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR;
|
|
2115
|
+
(0, import_react3.useEffect)(() => {
|
|
2116
|
+
if (checkboxRef.current) {
|
|
2117
|
+
checkboxRef.current.indeterminate = someSelected && !allSelected;
|
|
2118
|
+
}
|
|
2119
|
+
}, [someSelected, allSelected]);
|
|
2120
|
+
const handleToggleCollapse = () => {
|
|
2121
|
+
onToggleCollapse(product.uuid);
|
|
2122
|
+
};
|
|
2123
|
+
const handleToggleSelect = () => {
|
|
2124
|
+
onToggleSelect(product.uuid);
|
|
2125
|
+
};
|
|
2126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles4.sectionHeader, children: [
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles4.optionLeft, children: [
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2129
|
+
"button",
|
|
2130
|
+
{
|
|
2131
|
+
type: "button",
|
|
2132
|
+
onClick: handleToggleCollapse,
|
|
2133
|
+
"aria-expanded": !collapsed,
|
|
2134
|
+
"aria-controls": `product-${product.uuid}`,
|
|
2135
|
+
"aria-labelledby": `product-name-${product.uuid}`,
|
|
2136
|
+
style: CHEVRON_BUTTON_STYLE,
|
|
2137
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CollapseChevron, { open: !collapsed, color: headingColor })
|
|
2138
|
+
}
|
|
2139
|
+
),
|
|
2140
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles4.optionTextContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2141
|
+
"h2",
|
|
2142
|
+
{
|
|
2143
|
+
id: `product-name-${product.uuid}`,
|
|
2144
|
+
style: {
|
|
2145
|
+
...styles4.sectionTitle,
|
|
2146
|
+
...responsiveStyles.optionTitle,
|
|
2147
|
+
color: headingColor
|
|
2148
|
+
},
|
|
2149
|
+
children: name
|
|
2150
|
+
}
|
|
2151
|
+
) })
|
|
2152
|
+
] }),
|
|
2153
|
+
!locked && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2154
|
+
"input",
|
|
2155
|
+
{
|
|
2156
|
+
ref: checkboxRef,
|
|
2157
|
+
className: "redacto-checkbox-large",
|
|
2158
|
+
type: "checkbox",
|
|
2159
|
+
checked: allSelected,
|
|
2160
|
+
onChange: handleToggleSelect,
|
|
2161
|
+
"aria-label": PRODUCT_SECTION_COPY.toggleSelection(name, purposeCount)
|
|
2162
|
+
}
|
|
2163
|
+
)
|
|
2164
|
+
] });
|
|
2165
|
+
};
|
|
1902
2166
|
var PurposeItem = ({
|
|
1903
2167
|
purpose,
|
|
2168
|
+
productUuid,
|
|
1904
2169
|
selectedPurposes,
|
|
1905
2170
|
collapsedPurposes,
|
|
1906
2171
|
selectedDataElements,
|
|
@@ -1915,9 +2180,10 @@ var PurposeItem = ({
|
|
|
1915
2180
|
selectedLanguage,
|
|
1916
2181
|
initialDataElementSelections = {}
|
|
1917
2182
|
}) => {
|
|
2183
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
1918
2184
|
const headingStyle = (0, import_react3.useMemo)(
|
|
1919
2185
|
() => ({
|
|
1920
|
-
color: (settings == null ? void 0 : settings.headingColor) ||
|
|
2186
|
+
color: (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR
|
|
1921
2187
|
}),
|
|
1922
2188
|
[settings == null ? void 0 : settings.headingColor]
|
|
1923
2189
|
);
|
|
@@ -1933,12 +2199,12 @@ var PurposeItem = ({
|
|
|
1933
2199
|
"div",
|
|
1934
2200
|
{
|
|
1935
2201
|
style: styles4.optionLeft,
|
|
1936
|
-
onClick: () => onPurposeCollapse(purpose.uuid),
|
|
2202
|
+
onClick: () => onPurposeCollapse(purpose.uuid, productUuid),
|
|
1937
2203
|
role: "button",
|
|
1938
2204
|
tabIndex: 0,
|
|
1939
|
-
"aria-expanded": !collapsedPurposes[
|
|
2205
|
+
"aria-expanded": !collapsedPurposes[stateKey],
|
|
1940
2206
|
"aria-controls": `purpose-${purpose.uuid}`,
|
|
1941
|
-
"aria-label": `${collapsedPurposes[
|
|
2207
|
+
"aria-label": `${collapsedPurposes[stateKey] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
1942
2208
|
`purposes.name`,
|
|
1943
2209
|
purpose.name,
|
|
1944
2210
|
purpose.uuid
|
|
@@ -1946,46 +2212,22 @@ var PurposeItem = ({
|
|
|
1946
2212
|
onKeyDown: (e) => {
|
|
1947
2213
|
if (e.key === "Enter" || e.key === " ") {
|
|
1948
2214
|
e.preventDefault();
|
|
1949
|
-
onPurposeCollapse(purpose.uuid);
|
|
2215
|
+
onPurposeCollapse(purpose.uuid, productUuid);
|
|
1950
2216
|
}
|
|
1951
2217
|
},
|
|
1952
2218
|
children: [
|
|
1953
2219
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1954
|
-
|
|
2220
|
+
CollapseChevron,
|
|
1955
2221
|
{
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
alignItems: "center",
|
|
1959
|
-
justifyContent: "center",
|
|
1960
|
-
marginLeft: "5px"
|
|
1961
|
-
},
|
|
1962
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1963
|
-
"svg",
|
|
1964
|
-
{
|
|
1965
|
-
width: "7",
|
|
1966
|
-
height: "12",
|
|
1967
|
-
viewBox: "0 0 7 12",
|
|
1968
|
-
fill: "none",
|
|
1969
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
1970
|
-
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
1971
|
-
strokeWidth: "2",
|
|
1972
|
-
strokeLinecap: "round",
|
|
1973
|
-
strokeLinejoin: "round",
|
|
1974
|
-
style: {
|
|
1975
|
-
transform: !collapsedPurposes[purpose.uuid] ? "rotate(90deg)" : "rotate(0deg)",
|
|
1976
|
-
transition: "transform 0.3s ease"
|
|
1977
|
-
},
|
|
1978
|
-
"aria-hidden": "true",
|
|
1979
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M1 1L6 6L1 11" })
|
|
1980
|
-
}
|
|
1981
|
-
)
|
|
2222
|
+
open: !collapsedPurposes[stateKey],
|
|
2223
|
+
color: (settings == null ? void 0 : settings.headingColor) || DEFAULT_HEADING_COLOR
|
|
1982
2224
|
}
|
|
1983
2225
|
),
|
|
1984
2226
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles4.optionTextContainer, children: [
|
|
1985
2227
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1986
2228
|
"h2",
|
|
1987
2229
|
{
|
|
1988
|
-
id: `purpose-name-${
|
|
2230
|
+
id: `purpose-name-${stateKey}`,
|
|
1989
2231
|
style: {
|
|
1990
2232
|
...styles4.optionTitle,
|
|
1991
2233
|
...responsiveStyles.optionTitle,
|
|
@@ -2001,7 +2243,7 @@ var PurposeItem = ({
|
|
|
2001
2243
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2002
2244
|
"h3",
|
|
2003
2245
|
{
|
|
2004
|
-
id: `purpose-description-${
|
|
2246
|
+
id: `purpose-description-${stateKey}`,
|
|
2005
2247
|
style: {
|
|
2006
2248
|
...styles4.optionDescription,
|
|
2007
2249
|
...responsiveStyles.optionDescription,
|
|
@@ -2024,8 +2266,8 @@ var PurposeItem = ({
|
|
|
2024
2266
|
{
|
|
2025
2267
|
className: "redacto-checkbox-large",
|
|
2026
2268
|
type: "checkbox",
|
|
2027
|
-
checked: selectedPurposes[
|
|
2028
|
-
onChange: () => onPurposeToggle(purpose.uuid),
|
|
2269
|
+
checked: selectedPurposes[stateKey] || false,
|
|
2270
|
+
onChange: () => onPurposeToggle(purpose.uuid, productUuid),
|
|
2029
2271
|
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
2030
2272
|
`purposes.name`,
|
|
2031
2273
|
purpose.name,
|
|
@@ -2075,7 +2317,7 @@ var PurposeItem = ({
|
|
|
2075
2317
|
}
|
|
2076
2318
|
)
|
|
2077
2319
|
] }),
|
|
2078
|
-
!collapsedPurposes[
|
|
2320
|
+
!collapsedPurposes[stateKey] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2079
2321
|
"div",
|
|
2080
2322
|
{
|
|
2081
2323
|
id: `purpose-${purpose.uuid}`,
|
|
@@ -2088,7 +2330,7 @@ var PurposeItem = ({
|
|
|
2088
2330
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2089
2331
|
"span",
|
|
2090
2332
|
{
|
|
2091
|
-
id: `data-element-${
|
|
2333
|
+
id: `data-element-${stateKey}-${dataElement.uuid}`,
|
|
2092
2334
|
style: {
|
|
2093
2335
|
...styles4.dataElementText,
|
|
2094
2336
|
...responsiveStyles.dataElementText,
|
|
@@ -2110,8 +2352,12 @@ var PurposeItem = ({
|
|
|
2110
2352
|
{
|
|
2111
2353
|
className: "redacto-checkbox-small",
|
|
2112
2354
|
type: "checkbox",
|
|
2113
|
-
checked: selectedDataElements[`${
|
|
2114
|
-
onChange: () => onDataElementToggle(
|
|
2355
|
+
checked: selectedDataElements[`${stateKey}-${dataElement.uuid}`] || false,
|
|
2356
|
+
onChange: () => onDataElementToggle(
|
|
2357
|
+
dataElement.uuid,
|
|
2358
|
+
purpose.uuid,
|
|
2359
|
+
productUuid
|
|
2360
|
+
),
|
|
2115
2361
|
"aria-label": `Select ${getTranslatedText(
|
|
2116
2362
|
`data_elements.name`,
|
|
2117
2363
|
dataElement.name,
|
|
@@ -2120,7 +2366,7 @@ var PurposeItem = ({
|
|
|
2120
2366
|
}
|
|
2121
2367
|
),
|
|
2122
2368
|
isAlreadyConsented && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: (() => {
|
|
2123
|
-
const combinedId = `${
|
|
2369
|
+
const combinedId = `${stateKey}-${dataElement.uuid}`;
|
|
2124
2370
|
const wasOriginallySelected = initialDataElementSelections[combinedId] || false;
|
|
2125
2371
|
if (wasOriginallySelected) {
|
|
2126
2372
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -2258,7 +2504,9 @@ var GuardianForm = ({
|
|
|
2258
2504
|
switch (e.key) {
|
|
2259
2505
|
case "ArrowDown":
|
|
2260
2506
|
e.preventDefault();
|
|
2261
|
-
setFocusedIndex(
|
|
2507
|
+
setFocusedIndex(
|
|
2508
|
+
(prev) => Math.min(prev + 1, RELATIONSHIP_OPTIONS.length - 1)
|
|
2509
|
+
);
|
|
2262
2510
|
break;
|
|
2263
2511
|
case "ArrowUp":
|
|
2264
2512
|
e.preventDefault();
|
|
@@ -2267,7 +2515,8 @@ var GuardianForm = ({
|
|
|
2267
2515
|
case "Enter":
|
|
2268
2516
|
case " ":
|
|
2269
2517
|
e.preventDefault();
|
|
2270
|
-
if (focusedIndex >= 0)
|
|
2518
|
+
if (focusedIndex >= 0)
|
|
2519
|
+
handleSelect(RELATIONSHIP_OPTIONS[focusedIndex].value);
|
|
2271
2520
|
break;
|
|
2272
2521
|
case "Escape":
|
|
2273
2522
|
case "Tab":
|
|
@@ -2332,7 +2581,9 @@ var GuardianForm = ({
|
|
|
2332
2581
|
lineHeight: "1.5",
|
|
2333
2582
|
color: "#1E40AF"
|
|
2334
2583
|
};
|
|
2335
|
-
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find(
|
|
2584
|
+
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find(
|
|
2585
|
+
(o) => o.value === formData.guardianRelationship
|
|
2586
|
+
)) == null ? void 0 : _a.label;
|
|
2336
2587
|
const hasError = Boolean(errors.guardianRelationship);
|
|
2337
2588
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2338
2589
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...styles4.topSection, ...componentTextStyle }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles4.topLeft, children: [
|
|
@@ -2432,7 +2683,8 @@ var GuardianForm = ({
|
|
|
2432
2683
|
] }),
|
|
2433
2684
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
2434
2685
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { htmlFor: "guardianContact", style: labelStyle, children: [
|
|
2435
|
-
"Guardian's Phone Number
|
|
2686
|
+
"Guardian's Phone Number",
|
|
2687
|
+
" ",
|
|
2436
2688
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "#DC2626" }, children: "*" })
|
|
2437
2689
|
] }),
|
|
2438
2690
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -2488,7 +2740,17 @@ var GuardianForm = ({
|
|
|
2488
2740
|
transition: "border-color 0.15s, box-shadow 0.15s"
|
|
2489
2741
|
},
|
|
2490
2742
|
children: [
|
|
2491
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2743
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2744
|
+
"span",
|
|
2745
|
+
{
|
|
2746
|
+
style: {
|
|
2747
|
+
overflow: "hidden",
|
|
2748
|
+
textOverflow: "ellipsis",
|
|
2749
|
+
whiteSpace: "nowrap"
|
|
2750
|
+
},
|
|
2751
|
+
children: selectedLabel || "Select relationship"
|
|
2752
|
+
}
|
|
2753
|
+
),
|
|
2492
2754
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2493
2755
|
"svg",
|
|
2494
2756
|
{
|
|
@@ -3156,6 +3418,7 @@ var RedactoNoticeConsent = ({
|
|
|
3156
3418
|
const [selectedPurposes, setSelectedPurposes] = (0, import_react3.useState)({});
|
|
3157
3419
|
const [selectedDataElements, setSelectedDataElements] = (0, import_react3.useState)({});
|
|
3158
3420
|
const [initialDataElementSelections, setInitialDataElementSelections] = (0, import_react3.useState)({});
|
|
3421
|
+
const [collapsedProducts, setCollapsedProducts] = (0, import_react3.useState)({});
|
|
3159
3422
|
const [collapsedPurposes, setCollapsedPurposes] = (0, import_react3.useState)({});
|
|
3160
3423
|
const [hasAlreadyConsented, setHasAlreadyConsented] = (0, import_react3.useState)(false);
|
|
3161
3424
|
const [isFullyConsentedReviewMode, setIsFullyConsentedReviewMode] = (0, import_react3.useState)(false);
|
|
@@ -3201,7 +3464,9 @@ var RedactoNoticeConsent = ({
|
|
|
3201
3464
|
const statusPollIntervalRef = (0, import_react3.useRef)(null);
|
|
3202
3465
|
const verificationPopupRef = (0, import_react3.useRef)(null);
|
|
3203
3466
|
const pollingCleanupRef = (0, import_react3.useRef)(null);
|
|
3204
|
-
const autoTransitionTimerRef = (0, import_react3.useRef)(
|
|
3467
|
+
const autoTransitionTimerRef = (0, import_react3.useRef)(
|
|
3468
|
+
null
|
|
3469
|
+
);
|
|
3205
3470
|
const digilockerRedirectTimeoutRef = (0, import_react3.useRef)(null);
|
|
3206
3471
|
const isInitialMountRef = (0, import_react3.useRef)(true);
|
|
3207
3472
|
const isPollingStatusRef = (0, import_react3.useRef)(false);
|
|
@@ -3311,21 +3576,70 @@ var RedactoNoticeConsent = ({
|
|
|
3311
3576
|
const logoRowStyle = (0, import_react3.useMemo)(
|
|
3312
3577
|
() => ({
|
|
3313
3578
|
...styles.logoRow,
|
|
3314
|
-
justifyContent: logoRowJustify(
|
|
3579
|
+
justifyContent: logoRowJustify(
|
|
3580
|
+
resolveLogoPosition(content == null ? void 0 : content.logo_position)
|
|
3581
|
+
)
|
|
3315
3582
|
}),
|
|
3316
3583
|
[content == null ? void 0 : content.logo_position]
|
|
3317
3584
|
);
|
|
3585
|
+
const purposeRows = (0, import_react3.useMemo)(
|
|
3586
|
+
() => {
|
|
3587
|
+
var _a2;
|
|
3588
|
+
return noticePurposeRows(
|
|
3589
|
+
content == null ? void 0 : content.products,
|
|
3590
|
+
(_a2 = content == null ? void 0 : content.purposes) != null ? _a2 : [],
|
|
3591
|
+
content == null ? void 0 : content.product_purpose_order
|
|
3592
|
+
);
|
|
3593
|
+
},
|
|
3594
|
+
[content]
|
|
3595
|
+
);
|
|
3596
|
+
const productGroups = (0, import_react3.useMemo)(
|
|
3597
|
+
() => {
|
|
3598
|
+
var _a2;
|
|
3599
|
+
return groupPurposesByProduct(
|
|
3600
|
+
content == null ? void 0 : content.products,
|
|
3601
|
+
(_a2 = content == null ? void 0 : content.purposes) != null ? _a2 : [],
|
|
3602
|
+
content == null ? void 0 : content.product_purpose_order
|
|
3603
|
+
);
|
|
3604
|
+
},
|
|
3605
|
+
[content]
|
|
3606
|
+
);
|
|
3318
3607
|
const areAllRequiredElementsChecked = (0, import_react3.useMemo)(() => {
|
|
3608
|
+
var _a2;
|
|
3319
3609
|
if (!content) return false;
|
|
3320
|
-
|
|
3610
|
+
if (purposeRows.length === 0) return true;
|
|
3611
|
+
const isSatisfied = ({
|
|
3612
|
+
purpose,
|
|
3613
|
+
productUuid
|
|
3614
|
+
}) => {
|
|
3615
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3321
3616
|
const requiredElements = purpose.data_elements.filter(
|
|
3322
3617
|
(element) => element.required && element.enabled
|
|
3323
3618
|
);
|
|
3324
3619
|
return requiredElements.every(
|
|
3325
|
-
(element) => selectedDataElements[`${
|
|
3620
|
+
(element) => selectedDataElements[`${key}-${element.uuid}`]
|
|
3326
3621
|
);
|
|
3327
|
-
}
|
|
3328
|
-
|
|
3622
|
+
};
|
|
3623
|
+
const rowsByProduct = /* @__PURE__ */ new Map();
|
|
3624
|
+
for (const row of purposeRows) {
|
|
3625
|
+
const groupKey = (_a2 = row.productUuid) != null ? _a2 : "";
|
|
3626
|
+
const group = rowsByProduct.get(groupKey);
|
|
3627
|
+
if (group) {
|
|
3628
|
+
group.push(row);
|
|
3629
|
+
} else {
|
|
3630
|
+
rowsByProduct.set(groupKey, [row]);
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
const groups = [...rowsByProduct.values()];
|
|
3634
|
+
const everyProductHasMandatory = groups.every(
|
|
3635
|
+
(rows) => rows.some(
|
|
3636
|
+
({ purpose }) => purpose.data_elements.some(
|
|
3637
|
+
(element) => element.required && element.enabled
|
|
3638
|
+
)
|
|
3639
|
+
)
|
|
3640
|
+
);
|
|
3641
|
+
return everyProductHasMandatory ? groups.some((rows) => rows.every(isSatisfied)) : purposeRows.every(isSatisfied);
|
|
3642
|
+
}, [content, purposeRows, selectedDataElements]);
|
|
3329
3643
|
const acceptDisabled = isSubmitting || !areAllRequiredElementsChecked;
|
|
3330
3644
|
(0, import_react3.useEffect)(() => {
|
|
3331
3645
|
var _a2, _b2;
|
|
@@ -3337,6 +3651,7 @@ var RedactoNoticeConsent = ({
|
|
|
3337
3651
|
setSelectedDataElements({});
|
|
3338
3652
|
setInitialDataElementSelections({});
|
|
3339
3653
|
setCollapsedPurposes({});
|
|
3654
|
+
setCollapsedProducts({});
|
|
3340
3655
|
setHasAlreadyConsented(false);
|
|
3341
3656
|
setErrorMessage(null);
|
|
3342
3657
|
setFetchError(null);
|
|
@@ -3401,7 +3716,7 @@ var RedactoNoticeConsent = ({
|
|
|
3401
3716
|
return false;
|
|
3402
3717
|
};
|
|
3403
3718
|
const getTranslatedText = (key, defaultText, itemId) => {
|
|
3404
|
-
var _a2, _b2;
|
|
3719
|
+
var _a2, _b2, _c2;
|
|
3405
3720
|
if (!content) return defaultText;
|
|
3406
3721
|
if (isDefaultLanguage(selectedLanguage)) {
|
|
3407
3722
|
if (key === "privacy_policy_anchor_text" && content.privacy_policy_anchor_text) {
|
|
@@ -3439,8 +3754,18 @@ var RedactoNoticeConsent = ({
|
|
|
3439
3754
|
}
|
|
3440
3755
|
return defaultText;
|
|
3441
3756
|
}
|
|
3757
|
+
if (key === "products.name" || key === "products.description") {
|
|
3758
|
+
const productData = (_b2 = translationMap.products) == null ? void 0 : _b2[itemId];
|
|
3759
|
+
if (productData) {
|
|
3760
|
+
if (typeof productData === "string") {
|
|
3761
|
+
return key === "products.name" ? productData : defaultText;
|
|
3762
|
+
}
|
|
3763
|
+
return key === "products.name" ? productData.name || defaultText : productData.description || defaultText;
|
|
3764
|
+
}
|
|
3765
|
+
return defaultText;
|
|
3766
|
+
}
|
|
3442
3767
|
if (key.startsWith("data_elements.")) {
|
|
3443
|
-
return ((
|
|
3768
|
+
return ((_c2 = translationMap.data_elements) == null ? void 0 : _c2[itemId]) || defaultText;
|
|
3444
3769
|
}
|
|
3445
3770
|
}
|
|
3446
3771
|
const value = translationMap[key];
|
|
@@ -3498,63 +3823,88 @@ var RedactoNoticeConsent = ({
|
|
|
3498
3823
|
defaultLang === "en" || defaultLang === "EN" ? "English" : defaultLang
|
|
3499
3824
|
);
|
|
3500
3825
|
}
|
|
3501
|
-
const initialCollapsedState =
|
|
3502
|
-
|
|
3826
|
+
const initialCollapsedState = noticePurposeRows(
|
|
3827
|
+
activeConfig.products,
|
|
3828
|
+
activeConfig.purposes,
|
|
3829
|
+
activeConfig.product_purpose_order
|
|
3830
|
+
).reduce(
|
|
3831
|
+
(acc, { purpose, productUuid }) => ({
|
|
3503
3832
|
...acc,
|
|
3504
|
-
[purpose.uuid]: true
|
|
3833
|
+
[productPurposeKey(productUuid, purpose.uuid)]: true
|
|
3505
3834
|
}),
|
|
3506
3835
|
{}
|
|
3507
3836
|
);
|
|
3508
3837
|
setCollapsedPurposes(initialCollapsedState);
|
|
3838
|
+
setCollapsedProducts(
|
|
3839
|
+
groupPurposesByProduct(
|
|
3840
|
+
activeConfig.products,
|
|
3841
|
+
activeConfig.purposes,
|
|
3842
|
+
activeConfig.product_purpose_order
|
|
3843
|
+
).reduce(
|
|
3844
|
+
(acc, group, index) => ({
|
|
3845
|
+
...acc,
|
|
3846
|
+
[group.product.uuid]: index > 0
|
|
3847
|
+
}),
|
|
3848
|
+
{}
|
|
3849
|
+
)
|
|
3850
|
+
);
|
|
3509
3851
|
const isReconsentRequired = consentContentData.detail.reconsent_required;
|
|
3510
3852
|
const purposeSelections = consentContentData.detail.purpose_selections;
|
|
3511
3853
|
const newCategorizedPurposes = isReconsentRequired ? {
|
|
3512
|
-
alreadyConsented: activeConfig.purposes.filter(
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3521
|
-
return !selection || selection.status !== "ACTIVE" || selection.needs_reconsent;
|
|
3522
|
-
}
|
|
3523
|
-
)
|
|
3854
|
+
alreadyConsented: activeConfig.purposes.filter((purpose) => {
|
|
3855
|
+
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3856
|
+
return selection && (selection.status === "ACTIVE" || selection.status === "EXPIRED") && !selection.needs_reconsent;
|
|
3857
|
+
}),
|
|
3858
|
+
needsConsent: activeConfig.purposes.filter((purpose) => {
|
|
3859
|
+
const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
|
|
3860
|
+
return !selection || selection.status !== "ACTIVE" || selection.needs_reconsent;
|
|
3861
|
+
})
|
|
3524
3862
|
} : null;
|
|
3525
3863
|
setCategorizedPurposes(newCategorizedPurposes);
|
|
3526
3864
|
const preselection = buildPreselection(
|
|
3527
3865
|
activeConfig.purposes,
|
|
3528
3866
|
resolvePurposePreselection(activeConfig.purpose_preselection)
|
|
3529
3867
|
);
|
|
3530
|
-
const
|
|
3531
|
-
|
|
3868
|
+
const seedRows = noticePurposeRows(
|
|
3869
|
+
activeConfig.products,
|
|
3870
|
+
activeConfig.purposes,
|
|
3871
|
+
activeConfig.product_purpose_order
|
|
3872
|
+
);
|
|
3873
|
+
const recordedFor = (purposeUuid, productUuid) => {
|
|
3874
|
+
var _a3, _b2;
|
|
3875
|
+
const perProduct = productUuid ? (_b2 = (_a3 = activeConfig.product_purpose_selections) == null ? void 0 : _a3[productUuid]) == null ? void 0 : _b2[purposeUuid] : void 0;
|
|
3876
|
+
return perProduct != null ? perProduct : purposeSelections == null ? void 0 : purposeSelections[purposeUuid];
|
|
3877
|
+
};
|
|
3878
|
+
const initialPurposeState = seedRows.reduce(
|
|
3879
|
+
(acc, { purpose, productUuid }) => {
|
|
3532
3880
|
var _a3;
|
|
3533
|
-
const
|
|
3881
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3882
|
+
const recorded = recordedFor(purpose.uuid, productUuid);
|
|
3534
3883
|
if (hasRecordedPurposeState(recorded)) {
|
|
3535
|
-
acc[
|
|
3884
|
+
acc[key] = recorded.selected;
|
|
3536
3885
|
} else {
|
|
3537
|
-
acc[
|
|
3886
|
+
acc[key] = (_a3 = preselection.selectedPurposes[purpose.uuid]) != null ? _a3 : false;
|
|
3538
3887
|
}
|
|
3539
3888
|
return acc;
|
|
3540
3889
|
},
|
|
3541
3890
|
{}
|
|
3542
3891
|
);
|
|
3543
3892
|
setSelectedPurposes(initialPurposeState);
|
|
3544
|
-
const initialDataElementState =
|
|
3545
|
-
(acc, purpose) => {
|
|
3546
|
-
const
|
|
3547
|
-
|
|
3548
|
-
);
|
|
3893
|
+
const initialDataElementState = seedRows.reduce(
|
|
3894
|
+
(acc, { purpose, productUuid }) => {
|
|
3895
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
3896
|
+
const recorded = recordedFor(purpose.uuid, productUuid);
|
|
3897
|
+
const hasRecordedSelection = hasRecordedPurposeState(recorded);
|
|
3549
3898
|
purpose.data_elements.forEach((element) => {
|
|
3550
|
-
var _a3, _b2
|
|
3551
|
-
const combinedId = `${
|
|
3552
|
-
|
|
3553
|
-
|
|
3899
|
+
var _a3, _b2;
|
|
3900
|
+
const combinedId = `${key}-${element.uuid}`;
|
|
3901
|
+
const recordedElement = (_a3 = recorded == null ? void 0 : recorded.data_elements) == null ? void 0 : _a3[element.uuid];
|
|
3902
|
+
if (recordedElement) {
|
|
3903
|
+
acc[combinedId] = recordedElement.selected;
|
|
3554
3904
|
} else if (hasRecordedSelection) {
|
|
3555
3905
|
acc[combinedId] = false;
|
|
3556
3906
|
} else {
|
|
3557
|
-
acc[combinedId] = (
|
|
3907
|
+
acc[combinedId] = (_b2 = preselection.selectedDataElements[`${purpose.uuid}-${element.uuid}`]) != null ? _b2 : false;
|
|
3558
3908
|
}
|
|
3559
3909
|
});
|
|
3560
3910
|
return acc;
|
|
@@ -3565,10 +3915,14 @@ var RedactoNoticeConsent = ({
|
|
|
3565
3915
|
if (isReconsentRequired && newCategorizedPurposes) {
|
|
3566
3916
|
setIsFullyConsentedReviewMode(false);
|
|
3567
3917
|
const initialSelections = {};
|
|
3568
|
-
|
|
3918
|
+
const alreadyConsentedUuids = new Set(
|
|
3919
|
+
newCategorizedPurposes.alreadyConsented.map((p) => p.uuid)
|
|
3920
|
+
);
|
|
3921
|
+
seedRows.filter(({ purpose }) => alreadyConsentedUuids.has(purpose.uuid)).forEach(({ purpose, productUuid }) => {
|
|
3922
|
+
const rowKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3569
3923
|
purpose.data_elements.forEach((element) => {
|
|
3570
3924
|
var _a3, _b2;
|
|
3571
|
-
const combinedId = `${
|
|
3925
|
+
const combinedId = `${rowKey}-${element.uuid}`;
|
|
3572
3926
|
if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
|
|
3573
3927
|
initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
|
|
3574
3928
|
} else {
|
|
@@ -3578,28 +3932,27 @@ var RedactoNoticeConsent = ({
|
|
|
3578
3932
|
});
|
|
3579
3933
|
setInitialDataElementSelections(initialSelections);
|
|
3580
3934
|
} else if (includeFullyConsentedData && purposeSelections) {
|
|
3581
|
-
const allPurposesSelected =
|
|
3582
|
-
(
|
|
3935
|
+
const allPurposesSelected = seedRows.length > 0 && seedRows.every(
|
|
3936
|
+
({ purpose, productUuid }) => {
|
|
3583
3937
|
var _a3;
|
|
3584
|
-
return ((_a3 =
|
|
3938
|
+
return ((_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.selected) === true;
|
|
3585
3939
|
}
|
|
3586
3940
|
);
|
|
3587
3941
|
setIsFullyConsentedReviewMode(allPurposesSelected);
|
|
3588
3942
|
if (allPurposesSelected) {
|
|
3589
3943
|
const initialSelections = {};
|
|
3590
|
-
|
|
3591
|
-
(purpose)
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
);
|
|
3944
|
+
seedRows.forEach(({ purpose, productUuid }) => {
|
|
3945
|
+
const rowKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3946
|
+
purpose.data_elements.forEach((element) => {
|
|
3947
|
+
var _a3, _b2;
|
|
3948
|
+
const combinedId = `${rowKey}-${element.uuid}`;
|
|
3949
|
+
if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
|
|
3950
|
+
initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
|
|
3951
|
+
} else {
|
|
3952
|
+
initialSelections[combinedId] = false;
|
|
3953
|
+
}
|
|
3954
|
+
});
|
|
3955
|
+
});
|
|
3603
3956
|
setInitialDataElementSelections(initialSelections);
|
|
3604
3957
|
} else {
|
|
3605
3958
|
setIsFullyConsentedReviewMode(false);
|
|
@@ -3649,10 +4002,11 @@ var RedactoNoticeConsent = ({
|
|
|
3649
4002
|
// Removed onError and isRefreshingToken from dependencies to prevent duplicate API calls
|
|
3650
4003
|
// onError is only called on errors, not needed for initial data fetching
|
|
3651
4004
|
]);
|
|
3652
|
-
const togglePurposeCollapse = (purposeUuid) => {
|
|
4005
|
+
const togglePurposeCollapse = (purposeUuid, productUuid) => {
|
|
4006
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
3653
4007
|
setCollapsedPurposes((prev) => ({
|
|
3654
4008
|
...prev,
|
|
3655
|
-
[
|
|
4009
|
+
[key]: !prev[key]
|
|
3656
4010
|
}));
|
|
3657
4011
|
};
|
|
3658
4012
|
const toggleLanguageDropdown = () => {
|
|
@@ -3662,28 +4016,70 @@ var RedactoNoticeConsent = ({
|
|
|
3662
4016
|
setSelectedLanguage(lang);
|
|
3663
4017
|
setIsLanguageDropdownOpen(false);
|
|
3664
4018
|
};
|
|
3665
|
-
const handlePurposeCheckboxChange = (purposeUuid) => {
|
|
4019
|
+
const handlePurposeCheckboxChange = (purposeUuid, productUuid) => {
|
|
3666
4020
|
if (content) {
|
|
3667
4021
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
3668
4022
|
if (purpose) {
|
|
3669
|
-
const
|
|
4023
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
4024
|
+
const newPurposeState = !selectedPurposes[key];
|
|
3670
4025
|
setSelectedPurposes((prev) => ({
|
|
3671
4026
|
...prev,
|
|
3672
|
-
[
|
|
4027
|
+
[key]: newPurposeState
|
|
3673
4028
|
}));
|
|
3674
4029
|
setSelectedDataElements((prev) => {
|
|
3675
4030
|
const updated = { ...prev };
|
|
3676
4031
|
purpose.data_elements.forEach((el) => {
|
|
3677
|
-
updated[`${
|
|
4032
|
+
updated[`${key}-${el.uuid}`] = newPurposeState;
|
|
3678
4033
|
});
|
|
3679
4034
|
return updated;
|
|
3680
4035
|
});
|
|
3681
4036
|
}
|
|
3682
4037
|
}
|
|
3683
4038
|
};
|
|
3684
|
-
const
|
|
4039
|
+
const toggleProductCollapse = (productUuid) => {
|
|
4040
|
+
setCollapsedProducts((prev) => ({
|
|
4041
|
+
...prev,
|
|
4042
|
+
[productUuid]: !prev[productUuid]
|
|
4043
|
+
}));
|
|
4044
|
+
};
|
|
4045
|
+
const handleProductCheckboxChange = (productUuid) => {
|
|
4046
|
+
if (!content) {
|
|
4047
|
+
return;
|
|
4048
|
+
}
|
|
4049
|
+
const group = productGroups.find(
|
|
4050
|
+
(candidate) => candidate.product.uuid === productUuid
|
|
4051
|
+
);
|
|
4052
|
+
if (!group) {
|
|
4053
|
+
return;
|
|
4054
|
+
}
|
|
4055
|
+
const nextState = !group.purposes.every(
|
|
4056
|
+
(purpose) => selectedPurposes[productPurposeKey(productUuid, purpose.uuid)]
|
|
4057
|
+
);
|
|
4058
|
+
setSelectedPurposes((prev) => {
|
|
4059
|
+
const updated = { ...prev };
|
|
4060
|
+
group.purposes.forEach((purpose) => {
|
|
4061
|
+
updated[productPurposeKey(productUuid, purpose.uuid)] = nextState;
|
|
4062
|
+
});
|
|
4063
|
+
return updated;
|
|
4064
|
+
});
|
|
4065
|
+
setSelectedDataElements((prev) => {
|
|
4066
|
+
const updated = { ...prev };
|
|
4067
|
+
group.purposes.forEach((purpose) => {
|
|
4068
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
4069
|
+
purpose.data_elements.forEach((element) => {
|
|
4070
|
+
updated[`${key}-${element.uuid}`] = nextState;
|
|
4071
|
+
});
|
|
4072
|
+
});
|
|
4073
|
+
return updated;
|
|
4074
|
+
});
|
|
4075
|
+
if (!nextState) {
|
|
4076
|
+
setCollapsedProducts((prev) => ({ ...prev, [productUuid]: false }));
|
|
4077
|
+
}
|
|
4078
|
+
};
|
|
4079
|
+
const handleDataElementCheckboxChange = (elementUuid, purposeUuid, productUuid) => {
|
|
3685
4080
|
if (!content) return;
|
|
3686
|
-
const
|
|
4081
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
4082
|
+
const combinedId = `${key}-${elementUuid}`;
|
|
3687
4083
|
setSelectedDataElements((prev) => {
|
|
3688
4084
|
const newState = {
|
|
3689
4085
|
...prev,
|
|
@@ -3697,16 +4093,16 @@ var RedactoNoticeConsent = ({
|
|
|
3697
4093
|
let shouldCheckPurpose;
|
|
3698
4094
|
if (requiredElements.length > 0) {
|
|
3699
4095
|
shouldCheckPurpose = requiredElements.every(
|
|
3700
|
-
(el) => newState[`${
|
|
4096
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
3701
4097
|
);
|
|
3702
4098
|
} else {
|
|
3703
4099
|
shouldCheckPurpose = purpose.data_elements.some(
|
|
3704
|
-
(el) => newState[`${
|
|
4100
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
3705
4101
|
);
|
|
3706
4102
|
}
|
|
3707
4103
|
setSelectedPurposes((prevPurposes) => ({
|
|
3708
4104
|
...prevPurposes,
|
|
3709
|
-
[
|
|
4105
|
+
[key]: shouldCheckPurpose
|
|
3710
4106
|
}));
|
|
3711
4107
|
}
|
|
3712
4108
|
return newState;
|
|
@@ -3716,14 +4112,16 @@ var RedactoNoticeConsent = ({
|
|
|
3716
4112
|
const submitController = new AbortController();
|
|
3717
4113
|
try {
|
|
3718
4114
|
if (isMinorFlow && !verificationReference) {
|
|
3719
|
-
setErrorMessage(
|
|
4115
|
+
setErrorMessage(
|
|
4116
|
+
"Guardian verification is required before consent can be submitted."
|
|
4117
|
+
);
|
|
3720
4118
|
return;
|
|
3721
4119
|
}
|
|
3722
4120
|
setIsSubmittingAccept(true);
|
|
3723
4121
|
setIsSubmitting(true);
|
|
3724
4122
|
setErrorMessage(null);
|
|
3725
4123
|
if (content) {
|
|
3726
|
-
const selection = buildSelectionForMode(
|
|
4124
|
+
const selection = buildSelectionForMode(purposeRows, mode, {
|
|
3727
4125
|
selectedPurposes,
|
|
3728
4126
|
selectedDataElements
|
|
3729
4127
|
});
|
|
@@ -3736,14 +4134,20 @@ var RedactoNoticeConsent = ({
|
|
|
3736
4134
|
baseUrl,
|
|
3737
4135
|
ledgerBaseUrl,
|
|
3738
4136
|
noticeUuid: content.notice_uuid,
|
|
3739
|
-
|
|
4137
|
+
// One entry per (product, purpose) once a notice covers several. The
|
|
4138
|
+
// ledger keys consent on the pair, and repeating a purpose under two
|
|
4139
|
+
// products is how one submission accepts it for one and declines it
|
|
4140
|
+
// for the other. Collapses to content.purposes on a single-product
|
|
4141
|
+
// notice, so that payload is byte-identical to before.
|
|
4142
|
+
purposes: purposeRows.map(({ purpose, productUuid }) => {
|
|
4143
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
3740
4144
|
const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
|
|
3741
4145
|
(p) => p.uuid === purpose.uuid
|
|
3742
4146
|
)) || false;
|
|
3743
|
-
let purposeSelected = selection.selectedPurposes[
|
|
4147
|
+
let purposeSelected = selection.selectedPurposes[stateKey] || false;
|
|
3744
4148
|
if (mode === "selected" && isAlreadyConsented) {
|
|
3745
4149
|
const wasModified = purpose.data_elements.some((element) => {
|
|
3746
|
-
const combinedId = `${
|
|
4150
|
+
const combinedId = `${stateKey}-${element.uuid}`;
|
|
3747
4151
|
const currentSelection = selection.selectedDataElements[combinedId] || false;
|
|
3748
4152
|
const initialSelection = initialDataElementSelections[combinedId] || false;
|
|
3749
4153
|
return currentSelection !== initialSelection;
|
|
@@ -3754,10 +4158,11 @@ var RedactoNoticeConsent = ({
|
|
|
3754
4158
|
}
|
|
3755
4159
|
return {
|
|
3756
4160
|
...purpose,
|
|
4161
|
+
...productUuid ? { product_uuid: productUuid } : {},
|
|
3757
4162
|
selected: purposeSelected,
|
|
3758
4163
|
data_elements: purpose.data_elements.map((element) => ({
|
|
3759
4164
|
...element,
|
|
3760
|
-
selected: element.required ? true : selection.selectedDataElements[`${
|
|
4165
|
+
selected: element.required ? true : selection.selectedDataElements[`${stateKey}-${element.uuid}`] || false
|
|
3761
4166
|
}))
|
|
3762
4167
|
};
|
|
3763
4168
|
}),
|
|
@@ -3860,7 +4265,9 @@ var RedactoNoticeConsent = ({
|
|
|
3860
4265
|
return;
|
|
3861
4266
|
}
|
|
3862
4267
|
if (!response.session_token || !response.digilocker_redirect_url) {
|
|
3863
|
-
throw new Error(
|
|
4268
|
+
throw new Error(
|
|
4269
|
+
"Invalid response from server: missing required fields"
|
|
4270
|
+
);
|
|
3864
4271
|
}
|
|
3865
4272
|
setShowGuardianForm(false);
|
|
3866
4273
|
setShowVerificationScreen(true);
|
|
@@ -3950,7 +4357,18 @@ var RedactoNoticeConsent = ({
|
|
|
3950
4357
|
} finally {
|
|
3951
4358
|
setIsSubmittingGuardian(false);
|
|
3952
4359
|
}
|
|
3953
|
-
}, [
|
|
4360
|
+
}, [
|
|
4361
|
+
accessToken,
|
|
4362
|
+
sandboxParams,
|
|
4363
|
+
baseUrl,
|
|
4364
|
+
guardianFormData,
|
|
4365
|
+
digilockerMode,
|
|
4366
|
+
digilockerCallbackUrl,
|
|
4367
|
+
selectedPurposes,
|
|
4368
|
+
selectedDataElements,
|
|
4369
|
+
noticeId,
|
|
4370
|
+
onError
|
|
4371
|
+
]);
|
|
3954
4372
|
const handleAgeVerificationYes = (0, import_react3.useCallback)(() => {
|
|
3955
4373
|
setShowAgeVerification(false);
|
|
3956
4374
|
setIsMinorFlow(false);
|
|
@@ -4001,20 +4419,21 @@ var RedactoNoticeConsent = ({
|
|
|
4001
4419
|
} catch {
|
|
4002
4420
|
}
|
|
4003
4421
|
}
|
|
4004
|
-
setVerificationError(
|
|
4005
|
-
"Verification window was closed. Please try again."
|
|
4006
|
-
);
|
|
4422
|
+
setVerificationError("Verification window was closed. Please try again.");
|
|
4007
4423
|
setIsPollingStatus(false);
|
|
4008
4424
|
isPollingStatusRef.current = false;
|
|
4009
4425
|
setIsInitiatingVerification(false);
|
|
4010
4426
|
}, [accessToken, sandboxParams, baseUrl]);
|
|
4011
|
-
const startPopupMonitoring = (0, import_react3.useCallback)(
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4427
|
+
const startPopupMonitoring = (0, import_react3.useCallback)(
|
|
4428
|
+
(popup) => {
|
|
4429
|
+
popupCheckIntervalRef.current = window.setInterval(() => {
|
|
4430
|
+
if (popup.closed) {
|
|
4431
|
+
handlePopupClosed();
|
|
4432
|
+
}
|
|
4433
|
+
}, 500);
|
|
4434
|
+
},
|
|
4435
|
+
[handlePopupClosed]
|
|
4436
|
+
);
|
|
4018
4437
|
const getVerificationErrorMessage = (0, import_react3.useCallback)(
|
|
4019
4438
|
(errorCode, fallbackError) => {
|
|
4020
4439
|
switch (errorCode) {
|
|
@@ -4116,7 +4535,10 @@ var RedactoNoticeConsent = ({
|
|
|
4116
4535
|
return;
|
|
4117
4536
|
}
|
|
4118
4537
|
if (!paused) {
|
|
4119
|
-
statusPollIntervalRef.current = window.setTimeout(
|
|
4538
|
+
statusPollIntervalRef.current = window.setTimeout(
|
|
4539
|
+
poll,
|
|
4540
|
+
POLL_INTERVAL
|
|
4541
|
+
);
|
|
4120
4542
|
}
|
|
4121
4543
|
} catch (error) {
|
|
4122
4544
|
const err = error;
|
|
@@ -4137,7 +4559,10 @@ var RedactoNoticeConsent = ({
|
|
|
4137
4559
|
);
|
|
4138
4560
|
return;
|
|
4139
4561
|
}
|
|
4140
|
-
statusPollIntervalRef.current = window.setTimeout(
|
|
4562
|
+
statusPollIntervalRef.current = window.setTimeout(
|
|
4563
|
+
poll,
|
|
4564
|
+
POLL_INTERVAL
|
|
4565
|
+
);
|
|
4141
4566
|
}
|
|
4142
4567
|
};
|
|
4143
4568
|
const onVisibilityChange = () => {
|
|
@@ -4438,12 +4863,19 @@ var RedactoNoticeConsent = ({
|
|
|
4438
4863
|
const dataElementsAudioCount = ((_a2 = purpose.data_elements) == null ? void 0 : _a2.length) || 0;
|
|
4439
4864
|
const totalPurposeAudioCount = purposeAudioCount + dataElementsAudioCount;
|
|
4440
4865
|
if (currentIndex >= audioOffset && currentIndex < audioOffset + totalPurposeAudioCount) {
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4866
|
+
setCollapsedPurposes((prev) => {
|
|
4867
|
+
const next = { ...prev };
|
|
4868
|
+
let changed = false;
|
|
4869
|
+
for (const row of purposeRows) {
|
|
4870
|
+
if (row.purpose.uuid !== purpose.uuid) continue;
|
|
4871
|
+
const rowKey = productPurposeKey(row.productUuid, purpose.uuid);
|
|
4872
|
+
if (next[rowKey]) {
|
|
4873
|
+
next[rowKey] = false;
|
|
4874
|
+
changed = true;
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
return changed ? next : prev;
|
|
4878
|
+
});
|
|
4447
4879
|
break;
|
|
4448
4880
|
}
|
|
4449
4881
|
audioOffset += totalPurposeAudioCount;
|
|
@@ -4521,7 +4953,15 @@ var RedactoNoticeConsent = ({
|
|
|
4521
4953
|
return () => {
|
|
4522
4954
|
ttsAbortController.abort();
|
|
4523
4955
|
};
|
|
4524
|
-
}, [
|
|
4956
|
+
}, [
|
|
4957
|
+
content,
|
|
4958
|
+
selectedLanguage,
|
|
4959
|
+
accessToken,
|
|
4960
|
+
sandboxParams,
|
|
4961
|
+
baseUrl,
|
|
4962
|
+
ledgerBaseUrl,
|
|
4963
|
+
getLanguageCode
|
|
4964
|
+
]);
|
|
4525
4965
|
const modalStyle = {
|
|
4526
4966
|
borderRadius: (settings == null ? void 0 : settings.borderRadius) || "8px",
|
|
4527
4967
|
backgroundColor: (settings == null ? void 0 : settings.backgroundColor) || "#ffffff",
|
|
@@ -5220,7 +5660,7 @@ var RedactoNoticeConsent = ({
|
|
|
5220
5660
|
},
|
|
5221
5661
|
`purpose-section-heading-${selectedLanguage}`
|
|
5222
5662
|
),
|
|
5223
|
-
categorizedPurposes ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles.optionsContainer, children: [
|
|
5663
|
+
categorizedPurposes && !isMultiProduct(content == null ? void 0 : content.products) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles.optionsContainer, children: [
|
|
5224
5664
|
categorizedPurposes.alreadyConsented.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5225
5665
|
PurposeItem,
|
|
5226
5666
|
{
|
|
@@ -5262,7 +5702,62 @@ var RedactoNoticeConsent = ({
|
|
|
5262
5702
|
))
|
|
5263
5703
|
] }) : (
|
|
5264
5704
|
/* Regular consent UI */
|
|
5265
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles.optionsContainer, children: (
|
|
5705
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles.optionsContainer, children: isMultiProduct(content == null ? void 0 : content.products) ? productGroups.map((group) => {
|
|
5706
|
+
const selectedInGroup = group.purposes.filter(
|
|
5707
|
+
(purpose) => selectedPurposes[productPurposeKey(
|
|
5708
|
+
group.product.uuid,
|
|
5709
|
+
purpose.uuid
|
|
5710
|
+
)]
|
|
5711
|
+
).length;
|
|
5712
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
5713
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5714
|
+
ProductSectionHeader,
|
|
5715
|
+
{
|
|
5716
|
+
product: group.product,
|
|
5717
|
+
purposeCount: group.purposes.length,
|
|
5718
|
+
allSelected: selectedInGroup === group.purposes.length,
|
|
5719
|
+
someSelected: selectedInGroup > 0,
|
|
5720
|
+
collapsed: collapsedProducts[group.product.uuid] || false,
|
|
5721
|
+
locked: isFullyConsentedReviewMode,
|
|
5722
|
+
settings,
|
|
5723
|
+
styles,
|
|
5724
|
+
responsiveStyles,
|
|
5725
|
+
onToggleCollapse: toggleProductCollapse,
|
|
5726
|
+
onToggleSelect: handleProductCheckboxChange,
|
|
5727
|
+
getTranslatedText
|
|
5728
|
+
}
|
|
5729
|
+
),
|
|
5730
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5731
|
+
"div",
|
|
5732
|
+
{
|
|
5733
|
+
id: `product-${group.product.uuid}`,
|
|
5734
|
+
style: styles.sectionBody,
|
|
5735
|
+
hidden: collapsedProducts[group.product.uuid] || false,
|
|
5736
|
+
children: group.purposes.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5737
|
+
PurposeItem,
|
|
5738
|
+
{
|
|
5739
|
+
purpose,
|
|
5740
|
+
productUuid: group.product.uuid,
|
|
5741
|
+
selectedPurposes,
|
|
5742
|
+
collapsedPurposes,
|
|
5743
|
+
selectedDataElements,
|
|
5744
|
+
settings,
|
|
5745
|
+
styles,
|
|
5746
|
+
responsiveStyles,
|
|
5747
|
+
onPurposeToggle: handlePurposeCheckboxChange,
|
|
5748
|
+
onPurposeCollapse: togglePurposeCollapse,
|
|
5749
|
+
onDataElementToggle: handleDataElementCheckboxChange,
|
|
5750
|
+
getTranslatedText,
|
|
5751
|
+
isAlreadyConsented: isFullyConsentedReviewMode,
|
|
5752
|
+
selectedLanguage,
|
|
5753
|
+
initialDataElementSelections
|
|
5754
|
+
},
|
|
5755
|
+
`${group.product.uuid}-${purpose.uuid}-${selectedLanguage}`
|
|
5756
|
+
))
|
|
5757
|
+
}
|
|
5758
|
+
)
|
|
5759
|
+
] }, group.product.uuid);
|
|
5760
|
+
}) : (_y = content == null ? void 0 : content.purposes) == null ? void 0 : _y.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5266
5761
|
PurposeItem,
|
|
5267
5762
|
{
|
|
5268
5763
|
purpose,
|
|
@@ -5527,16 +6022,20 @@ var submitConsentEvent2 = async ({
|
|
|
5527
6022
|
declined,
|
|
5528
6023
|
meta_data
|
|
5529
6024
|
};
|
|
5530
|
-
const
|
|
5531
|
-
|
|
5532
|
-
|
|
6025
|
+
const url = `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/submit-consent`;
|
|
6026
|
+
const serialisedBody = JSON.stringify(payload);
|
|
6027
|
+
const response = await withIdempotencyKey(
|
|
6028
|
+
url,
|
|
6029
|
+
serialisedBody,
|
|
6030
|
+
(idempotencyHeaders) => fetch(url, {
|
|
5533
6031
|
method: "POST",
|
|
5534
6032
|
headers: {
|
|
5535
6033
|
Authorization: `Bearer ${accessToken}`,
|
|
5536
|
-
"Content-Type": "application/json"
|
|
6034
|
+
"Content-Type": "application/json",
|
|
6035
|
+
...idempotencyHeaders
|
|
5537
6036
|
},
|
|
5538
|
-
body:
|
|
5539
|
-
}
|
|
6037
|
+
body: serialisedBody
|
|
6038
|
+
})
|
|
5540
6039
|
);
|
|
5541
6040
|
if (!response.ok) {
|
|
5542
6041
|
throw await parseApiError(
|
|
@@ -5973,7 +6472,6 @@ var RedactoConsentInlineComponent = ({
|
|
|
5973
6472
|
settings,
|
|
5974
6473
|
applicationId
|
|
5975
6474
|
}) => {
|
|
5976
|
-
var _a;
|
|
5977
6475
|
const [content, setContent] = (0, import_react5.useState)(null);
|
|
5978
6476
|
const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
|
|
5979
6477
|
const [isSubmitting, setIsSubmitting] = (0, import_react5.useState)(false);
|
|
@@ -6030,7 +6528,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
6030
6528
|
}
|
|
6031
6529
|
}, [hasAlreadyConsented, onAccept]);
|
|
6032
6530
|
const getTranslatedText = (key, defaultText, itemId) => {
|
|
6033
|
-
var
|
|
6531
|
+
var _a, _b, _c;
|
|
6034
6532
|
if (!content) return defaultText;
|
|
6035
6533
|
if (selectedLanguage === "English" || selectedLanguage === "en" || selectedLanguage === "EN") {
|
|
6036
6534
|
if (key === "privacy_policy_anchor_text" && content.privacy_policy_anchor_text) {
|
|
@@ -6047,7 +6545,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
6047
6545
|
}
|
|
6048
6546
|
if (itemId) {
|
|
6049
6547
|
if (key === "purposes.name" || key === "purposes.description") {
|
|
6050
|
-
const purposeData = (
|
|
6548
|
+
const purposeData = (_a = translationMap.purposes) == null ? void 0 : _a[itemId];
|
|
6051
6549
|
if (purposeData) {
|
|
6052
6550
|
if (typeof purposeData === "string") {
|
|
6053
6551
|
return key === "purposes.name" ? purposeData : defaultText;
|
|
@@ -6056,8 +6554,18 @@ var RedactoConsentInlineComponent = ({
|
|
|
6056
6554
|
}
|
|
6057
6555
|
return defaultText;
|
|
6058
6556
|
}
|
|
6557
|
+
if (key === "products.name" || key === "products.description") {
|
|
6558
|
+
const productData = (_b = translationMap.products) == null ? void 0 : _b[itemId];
|
|
6559
|
+
if (productData) {
|
|
6560
|
+
if (typeof productData === "string") {
|
|
6561
|
+
return key === "products.name" ? productData : defaultText;
|
|
6562
|
+
}
|
|
6563
|
+
return key === "products.name" ? productData.name || defaultText : productData.description || defaultText;
|
|
6564
|
+
}
|
|
6565
|
+
return defaultText;
|
|
6566
|
+
}
|
|
6059
6567
|
if (key.startsWith("data_elements.")) {
|
|
6060
|
-
return ((
|
|
6568
|
+
return ((_c = translationMap.data_elements) == null ? void 0 : _c[itemId]) || defaultText;
|
|
6061
6569
|
}
|
|
6062
6570
|
}
|
|
6063
6571
|
const value = translationMap[key];
|
|
@@ -6166,25 +6674,27 @@ var RedactoConsentInlineComponent = ({
|
|
|
6166
6674
|
controller.abort();
|
|
6167
6675
|
};
|
|
6168
6676
|
}, [ledgerBaseUrl, applicationId, accessToken, content, notice_uuid]);
|
|
6169
|
-
const togglePurposeCollapse = (purposeUuid) => {
|
|
6677
|
+
const togglePurposeCollapse = (purposeUuid, productUuid) => {
|
|
6678
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
6170
6679
|
setCollapsedPurposes((prev) => ({
|
|
6171
6680
|
...prev,
|
|
6172
|
-
[
|
|
6681
|
+
[key]: !prev[key]
|
|
6173
6682
|
}));
|
|
6174
6683
|
};
|
|
6175
|
-
const handlePurposeCheckboxChange = (purposeUuid) => {
|
|
6684
|
+
const handlePurposeCheckboxChange = (purposeUuid, productUuid) => {
|
|
6176
6685
|
if (content) {
|
|
6177
6686
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
6178
6687
|
if (purpose) {
|
|
6179
|
-
const
|
|
6688
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
6689
|
+
const newPurposeState = !selectedPurposes[key];
|
|
6180
6690
|
setSelectedPurposes((prev) => ({
|
|
6181
6691
|
...prev,
|
|
6182
|
-
[
|
|
6692
|
+
[key]: newPurposeState
|
|
6183
6693
|
}));
|
|
6184
6694
|
setSelectedDataElements((prev) => {
|
|
6185
6695
|
const updated = { ...prev };
|
|
6186
6696
|
purpose.data_elements.forEach((el) => {
|
|
6187
|
-
const combinedId = `${
|
|
6697
|
+
const combinedId = `${key}-${el.uuid}`;
|
|
6188
6698
|
updated[combinedId] = newPurposeState;
|
|
6189
6699
|
});
|
|
6190
6700
|
return updated;
|
|
@@ -6192,7 +6702,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
6192
6702
|
}
|
|
6193
6703
|
}
|
|
6194
6704
|
};
|
|
6195
|
-
const handleDataElementCheckboxChange = (elementUuid, purposeUuid) => {
|
|
6705
|
+
const handleDataElementCheckboxChange = (elementUuid, purposeUuid, productUuid) => {
|
|
6196
6706
|
if (!content) return;
|
|
6197
6707
|
const purpose = content.purposes.find((p) => p.uuid === purposeUuid);
|
|
6198
6708
|
if (!purpose) return;
|
|
@@ -6200,7 +6710,8 @@ var RedactoConsentInlineComponent = ({
|
|
|
6200
6710
|
(el) => el.uuid === elementUuid
|
|
6201
6711
|
);
|
|
6202
6712
|
if (!dataElement) return;
|
|
6203
|
-
const
|
|
6713
|
+
const key = productPurposeKey(productUuid, purposeUuid);
|
|
6714
|
+
const combinedId = `${key}-${elementUuid}`;
|
|
6204
6715
|
const currentState = selectedDataElements[combinedId] || false;
|
|
6205
6716
|
const newElementState = !currentState;
|
|
6206
6717
|
setSelectedDataElements((prev) => {
|
|
@@ -6214,16 +6725,16 @@ var RedactoConsentInlineComponent = ({
|
|
|
6214
6725
|
let shouldCheckPurpose;
|
|
6215
6726
|
if (requiredElements.length > 0) {
|
|
6216
6727
|
shouldCheckPurpose = requiredElements.every(
|
|
6217
|
-
(el) => newState[`${
|
|
6728
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
6218
6729
|
);
|
|
6219
6730
|
} else {
|
|
6220
6731
|
shouldCheckPurpose = purpose.data_elements.some(
|
|
6221
|
-
(el) => newState[`${
|
|
6732
|
+
(el) => newState[`${key}-${el.uuid}`]
|
|
6222
6733
|
);
|
|
6223
6734
|
}
|
|
6224
6735
|
setSelectedPurposes((prevPurposes) => ({
|
|
6225
6736
|
...prevPurposes,
|
|
6226
|
-
[
|
|
6737
|
+
[key]: shouldCheckPurpose
|
|
6227
6738
|
}));
|
|
6228
6739
|
return newState;
|
|
6229
6740
|
});
|
|
@@ -6244,20 +6755,36 @@ var RedactoConsentInlineComponent = ({
|
|
|
6244
6755
|
baseUrl,
|
|
6245
6756
|
ledgerBaseUrl,
|
|
6246
6757
|
noticeUuid: content.notice_uuid,
|
|
6247
|
-
|
|
6758
|
+
// One entry per (product, purpose) once a notice covers several, so a
|
|
6759
|
+
// purpose can be accepted for one product and declined for another.
|
|
6760
|
+
// Collapses to content.purposes below two products, leaving that
|
|
6761
|
+
// payload byte-identical to before.
|
|
6762
|
+
purposes: (isMultiProduct(content.products) ? expandPurposesByProduct(
|
|
6763
|
+
content.products,
|
|
6764
|
+
content.purposes,
|
|
6765
|
+
content.product_purpose_order
|
|
6766
|
+
).map((row) => ({
|
|
6767
|
+
purpose: row.purpose,
|
|
6768
|
+
productUuid: row.product.uuid
|
|
6769
|
+
})) : content.purposes.map((purpose) => ({
|
|
6770
|
+
purpose,
|
|
6771
|
+
productUuid: void 0
|
|
6772
|
+
}))).map(({ purpose, productUuid }) => {
|
|
6773
|
+
const key = productPurposeKey(productUuid, purpose.uuid);
|
|
6248
6774
|
const hasSelectedRequiredElement = purpose.data_elements.some(
|
|
6249
|
-
(element) => element.required && (selectedDataElements[`${
|
|
6775
|
+
(element) => element.required && (selectedDataElements[`${key}-${element.uuid}`] || false)
|
|
6250
6776
|
);
|
|
6251
6777
|
const hasSelectedDataElement = purpose.data_elements.some(
|
|
6252
|
-
(element) => selectedDataElements[`${
|
|
6778
|
+
(element) => selectedDataElements[`${key}-${element.uuid}`] || false
|
|
6253
6779
|
);
|
|
6254
|
-
const purposeSelected = selectedPurposes[
|
|
6780
|
+
const purposeSelected = selectedPurposes[key] || hasSelectedRequiredElement || hasSelectedDataElement;
|
|
6255
6781
|
return {
|
|
6256
6782
|
...purpose,
|
|
6783
|
+
...productUuid ? { product_uuid: productUuid } : {},
|
|
6257
6784
|
selected: purposeSelected,
|
|
6258
6785
|
data_elements: purpose.data_elements.map((element) => ({
|
|
6259
6786
|
...element,
|
|
6260
|
-
selected: selectedDataElements[`${
|
|
6787
|
+
selected: selectedDataElements[`${key}-${element.uuid}`] || false
|
|
6261
6788
|
}))
|
|
6262
6789
|
};
|
|
6263
6790
|
}),
|
|
@@ -6358,133 +6885,99 @@ var RedactoConsentInlineComponent = ({
|
|
|
6358
6885
|
children: errorMessage
|
|
6359
6886
|
}
|
|
6360
6887
|
),
|
|
6361
|
-
(
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
onClick: () => togglePurposeCollapse(purpose.uuid),
|
|
6368
|
-
role: "button",
|
|
6369
|
-
tabIndex: 0,
|
|
6370
|
-
"aria-expanded": !collapsedPurposes[purpose.uuid],
|
|
6371
|
-
"aria-controls": `purpose-${purpose.uuid}`,
|
|
6372
|
-
"aria-label": `${collapsedPurposes[purpose.uuid] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
6373
|
-
`purposes.name`,
|
|
6374
|
-
purpose.name,
|
|
6375
|
-
purpose.uuid
|
|
6376
|
-
)} details`,
|
|
6377
|
-
onKeyDown: (e) => {
|
|
6378
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
6379
|
-
e.preventDefault();
|
|
6380
|
-
togglePurposeCollapse(purpose.uuid);
|
|
6381
|
-
}
|
|
6382
|
-
},
|
|
6383
|
-
children: [
|
|
6384
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6385
|
-
"div",
|
|
6386
|
-
{
|
|
6387
|
-
style: {
|
|
6388
|
-
display: "flex",
|
|
6389
|
-
alignItems: "center",
|
|
6390
|
-
justifyContent: "center",
|
|
6391
|
-
marginLeft: "5px"
|
|
6392
|
-
},
|
|
6393
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6394
|
-
"svg",
|
|
6395
|
-
{
|
|
6396
|
-
width: "7",
|
|
6397
|
-
height: "12",
|
|
6398
|
-
viewBox: "0 0 7 12",
|
|
6399
|
-
fill: "none",
|
|
6400
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
6401
|
-
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
6402
|
-
strokeWidth: "2",
|
|
6403
|
-
strokeLinecap: "round",
|
|
6404
|
-
strokeLinejoin: "round",
|
|
6405
|
-
style: {
|
|
6406
|
-
transform: !collapsedPurposes[purpose.uuid] ? "rotate(90deg)" : "rotate(0deg)",
|
|
6407
|
-
transition: "transform 0.3s ease"
|
|
6408
|
-
},
|
|
6409
|
-
"aria-hidden": "true",
|
|
6410
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M1 1L6 6L1 11" })
|
|
6411
|
-
}
|
|
6412
|
-
)
|
|
6413
|
-
}
|
|
6414
|
-
),
|
|
6415
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles2.optionTextContainer, children: [
|
|
6416
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
6417
|
-
"h2",
|
|
6418
|
-
{
|
|
6419
|
-
style: {
|
|
6420
|
-
...styles2.optionTitle,
|
|
6421
|
-
...responsiveStyles.optionTitle,
|
|
6422
|
-
...headingStyle
|
|
6423
|
-
},
|
|
6424
|
-
children: [
|
|
6425
|
-
getTranslatedText(
|
|
6426
|
-
`purposes.name`,
|
|
6427
|
-
purpose.name,
|
|
6428
|
-
purpose.uuid
|
|
6429
|
-
),
|
|
6430
|
-
hasRequiredDataElement(purpose) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RequiredMarker, {})
|
|
6431
|
-
]
|
|
6432
|
-
}
|
|
6433
|
-
),
|
|
6434
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6435
|
-
"h3",
|
|
6436
|
-
{
|
|
6437
|
-
style: {
|
|
6438
|
-
...styles2.optionDescription,
|
|
6439
|
-
...responsiveStyles.optionDescription,
|
|
6440
|
-
...textStyle
|
|
6441
|
-
},
|
|
6442
|
-
children: getTranslatedText(
|
|
6443
|
-
`purposes.description`,
|
|
6444
|
-
purpose.description,
|
|
6445
|
-
purpose.uuid
|
|
6446
|
-
)
|
|
6447
|
-
}
|
|
6448
|
-
)
|
|
6449
|
-
] })
|
|
6450
|
-
]
|
|
6451
|
-
}
|
|
6452
|
-
),
|
|
6453
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6454
|
-
"input",
|
|
6455
|
-
{
|
|
6456
|
-
type: "checkbox",
|
|
6457
|
-
checked: selectedPurposes[purpose.uuid] || false,
|
|
6458
|
-
onChange: () => handlePurposeCheckboxChange(purpose.uuid),
|
|
6459
|
-
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
6460
|
-
`purposes.name`,
|
|
6461
|
-
purpose.name,
|
|
6462
|
-
purpose.uuid
|
|
6463
|
-
)}`
|
|
6464
|
-
}
|
|
6465
|
-
)
|
|
6466
|
-
] }),
|
|
6467
|
-
!collapsedPurposes[purpose.uuid] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6468
|
-
"div",
|
|
6469
|
-
{
|
|
6470
|
-
id: `purpose-${purpose.uuid}`,
|
|
6471
|
-
style: styles2.dataElementsContainer,
|
|
6472
|
-
children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles2.dataElementItem, children: [
|
|
6888
|
+
(() => {
|
|
6889
|
+
var _a, _b;
|
|
6890
|
+
const renderPurpose = (purpose, productUuid) => {
|
|
6891
|
+
const stateKey = productPurposeKey(productUuid, purpose.uuid);
|
|
6892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
6893
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles2.optionItem, children: [
|
|
6473
6894
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
6474
|
-
"
|
|
6895
|
+
"div",
|
|
6475
6896
|
{
|
|
6476
|
-
style:
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6897
|
+
style: styles2.optionLeft,
|
|
6898
|
+
onClick: () => togglePurposeCollapse(purpose.uuid, productUuid),
|
|
6899
|
+
role: "button",
|
|
6900
|
+
tabIndex: 0,
|
|
6901
|
+
"aria-expanded": !collapsedPurposes[stateKey],
|
|
6902
|
+
"aria-controls": `purpose-${stateKey}`,
|
|
6903
|
+
"aria-label": `${collapsedPurposes[stateKey] ? "Expand" : "Collapse"} ${getTranslatedText(
|
|
6904
|
+
`purposes.name`,
|
|
6905
|
+
purpose.name,
|
|
6906
|
+
purpose.uuid
|
|
6907
|
+
)} details`,
|
|
6908
|
+
onKeyDown: (e) => {
|
|
6909
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6910
|
+
e.preventDefault();
|
|
6911
|
+
togglePurposeCollapse(purpose.uuid, productUuid);
|
|
6912
|
+
}
|
|
6480
6913
|
},
|
|
6481
6914
|
children: [
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6915
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6916
|
+
"div",
|
|
6917
|
+
{
|
|
6918
|
+
style: {
|
|
6919
|
+
display: "flex",
|
|
6920
|
+
alignItems: "center",
|
|
6921
|
+
justifyContent: "center",
|
|
6922
|
+
marginLeft: "5px"
|
|
6923
|
+
},
|
|
6924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6925
|
+
"svg",
|
|
6926
|
+
{
|
|
6927
|
+
width: "7",
|
|
6928
|
+
height: "12",
|
|
6929
|
+
viewBox: "0 0 7 12",
|
|
6930
|
+
fill: "none",
|
|
6931
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6932
|
+
stroke: (settings == null ? void 0 : settings.headingColor) || "#323B4B",
|
|
6933
|
+
strokeWidth: "2",
|
|
6934
|
+
strokeLinecap: "round",
|
|
6935
|
+
strokeLinejoin: "round",
|
|
6936
|
+
style: {
|
|
6937
|
+
transform: !collapsedPurposes[stateKey] ? "rotate(90deg)" : "rotate(0deg)",
|
|
6938
|
+
transition: "transform 0.3s ease"
|
|
6939
|
+
},
|
|
6940
|
+
"aria-hidden": "true",
|
|
6941
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M1 1L6 6L1 11" })
|
|
6942
|
+
}
|
|
6943
|
+
)
|
|
6944
|
+
}
|
|
6486
6945
|
),
|
|
6487
|
-
|
|
6946
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles2.optionTextContainer, children: [
|
|
6947
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
6948
|
+
"h2",
|
|
6949
|
+
{
|
|
6950
|
+
style: {
|
|
6951
|
+
...styles2.optionTitle,
|
|
6952
|
+
...responsiveStyles.optionTitle,
|
|
6953
|
+
...headingStyle
|
|
6954
|
+
},
|
|
6955
|
+
children: [
|
|
6956
|
+
getTranslatedText(
|
|
6957
|
+
`purposes.name`,
|
|
6958
|
+
purpose.name,
|
|
6959
|
+
purpose.uuid
|
|
6960
|
+
),
|
|
6961
|
+
hasRequiredDataElement(purpose) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RequiredMarker, {})
|
|
6962
|
+
]
|
|
6963
|
+
}
|
|
6964
|
+
),
|
|
6965
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6966
|
+
"h3",
|
|
6967
|
+
{
|
|
6968
|
+
style: {
|
|
6969
|
+
...styles2.optionDescription,
|
|
6970
|
+
...responsiveStyles.optionDescription,
|
|
6971
|
+
...textStyle
|
|
6972
|
+
},
|
|
6973
|
+
children: getTranslatedText(
|
|
6974
|
+
`purposes.description`,
|
|
6975
|
+
purpose.description,
|
|
6976
|
+
purpose.uuid
|
|
6977
|
+
)
|
|
6978
|
+
}
|
|
6979
|
+
)
|
|
6980
|
+
] })
|
|
6488
6981
|
]
|
|
6489
6982
|
}
|
|
6490
6983
|
),
|
|
@@ -6492,22 +6985,87 @@ var RedactoConsentInlineComponent = ({
|
|
|
6492
6985
|
"input",
|
|
6493
6986
|
{
|
|
6494
6987
|
type: "checkbox",
|
|
6495
|
-
checked:
|
|
6496
|
-
onChange: () =>
|
|
6497
|
-
|
|
6988
|
+
checked: selectedPurposes[stateKey] || false,
|
|
6989
|
+
onChange: () => handlePurposeCheckboxChange(purpose.uuid, productUuid),
|
|
6990
|
+
"aria-label": `Select all data elements for ${getTranslatedText(
|
|
6991
|
+
`purposes.name`,
|
|
6992
|
+
purpose.name,
|
|
6498
6993
|
purpose.uuid
|
|
6499
|
-
)
|
|
6500
|
-
"aria-label": `Select ${getTranslatedText(
|
|
6501
|
-
`data_elements.name`,
|
|
6502
|
-
dataElement.name,
|
|
6503
|
-
dataElement.uuid
|
|
6504
|
-
)}${dataElement.required ? " (required)" : ""}`
|
|
6994
|
+
)}`
|
|
6505
6995
|
}
|
|
6506
6996
|
)
|
|
6507
|
-
] },
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6997
|
+
] }),
|
|
6998
|
+
!collapsedPurposes[stateKey] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
6999
|
+
"div",
|
|
7000
|
+
{
|
|
7001
|
+
id: `purpose-${stateKey}`,
|
|
7002
|
+
style: styles2.dataElementsContainer,
|
|
7003
|
+
children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7004
|
+
"div",
|
|
7005
|
+
{
|
|
7006
|
+
style: styles2.dataElementItem,
|
|
7007
|
+
children: [
|
|
7008
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7009
|
+
"span",
|
|
7010
|
+
{
|
|
7011
|
+
style: {
|
|
7012
|
+
...styles2.dataElementText,
|
|
7013
|
+
...responsiveStyles.dataElementText,
|
|
7014
|
+
...textStyle
|
|
7015
|
+
},
|
|
7016
|
+
children: [
|
|
7017
|
+
getTranslatedText(
|
|
7018
|
+
`data_elements.name`,
|
|
7019
|
+
dataElement.name,
|
|
7020
|
+
dataElement.uuid
|
|
7021
|
+
),
|
|
7022
|
+
dataElement.required && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RequiredMarker, {})
|
|
7023
|
+
]
|
|
7024
|
+
}
|
|
7025
|
+
),
|
|
7026
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7027
|
+
"input",
|
|
7028
|
+
{
|
|
7029
|
+
type: "checkbox",
|
|
7030
|
+
checked: selectedDataElements[`${stateKey}-${dataElement.uuid}`] || false,
|
|
7031
|
+
onChange: () => handleDataElementCheckboxChange(
|
|
7032
|
+
dataElement.uuid,
|
|
7033
|
+
purpose.uuid,
|
|
7034
|
+
productUuid
|
|
7035
|
+
),
|
|
7036
|
+
"aria-label": `Select ${getTranslatedText(
|
|
7037
|
+
`data_elements.name`,
|
|
7038
|
+
dataElement.name,
|
|
7039
|
+
dataElement.uuid
|
|
7040
|
+
)}${dataElement.required ? " (required)" : ""}`
|
|
7041
|
+
}
|
|
7042
|
+
)
|
|
7043
|
+
]
|
|
7044
|
+
},
|
|
7045
|
+
dataElement.uuid
|
|
7046
|
+
))
|
|
7047
|
+
}
|
|
7048
|
+
)
|
|
7049
|
+
] }, stateKey);
|
|
7050
|
+
};
|
|
7051
|
+
if (!isMultiProduct(content == null ? void 0 : content.products)) {
|
|
7052
|
+
return (_a = content == null ? void 0 : content.purposes) == null ? void 0 : _a.map((purpose) => renderPurpose(purpose));
|
|
7053
|
+
}
|
|
7054
|
+
return groupPurposesByProduct(
|
|
7055
|
+
content == null ? void 0 : content.products,
|
|
7056
|
+
(_b = content == null ? void 0 : content.purposes) != null ? _b : [],
|
|
7057
|
+
content == null ? void 0 : content.product_purpose_order
|
|
7058
|
+
).map((group) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
7059
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...styles2.optionTitle, margin: "0 0 8px" }, children: getTranslatedText(
|
|
7060
|
+
"products.name",
|
|
7061
|
+
group.product.name,
|
|
7062
|
+
group.product.uuid
|
|
7063
|
+
) }),
|
|
7064
|
+
group.purposes.map(
|
|
7065
|
+
(purpose) => renderPurpose(purpose, group.product.uuid)
|
|
7066
|
+
)
|
|
7067
|
+
] }, group.product.uuid));
|
|
7068
|
+
})()
|
|
6511
7069
|
] });
|
|
6512
7070
|
};
|
|
6513
7071
|
RedactoConsentInlineComponent.displayName = "RedactoConsentInline";
|
|
@@ -7647,16 +8205,22 @@ var submitAssistedConsent = async ({
|
|
|
7647
8205
|
language: language || void 0
|
|
7648
8206
|
};
|
|
7649
8207
|
const url = `${publicScope(ledgerBaseUrl || baseUrl, organisationUuid, workspaceUuid)}/submit-consent`;
|
|
7650
|
-
const
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
8208
|
+
const serialisedBody = JSON.stringify(payload);
|
|
8209
|
+
const response = await withIdempotencyKey(
|
|
8210
|
+
url,
|
|
8211
|
+
serialisedBody,
|
|
8212
|
+
(idempotencyHeaders) => fetch(url, {
|
|
8213
|
+
method: "POST",
|
|
8214
|
+
headers: {
|
|
8215
|
+
accept: "application/json",
|
|
8216
|
+
Authorization: `Bearer ${accessToken}`,
|
|
8217
|
+
"Content-Type": "application/json",
|
|
8218
|
+
...idempotencyHeaders
|
|
8219
|
+
},
|
|
8220
|
+
body: serialisedBody,
|
|
8221
|
+
signal
|
|
8222
|
+
})
|
|
8223
|
+
);
|
|
7660
8224
|
if (!response.ok) {
|
|
7661
8225
|
throw await parseApiError(
|
|
7662
8226
|
response,
|
|
@@ -9649,10 +10213,14 @@ var RedactoNoticeAssisted = ({
|
|
|
9649
10213
|
const handleConfirmStep = (0, import_react7.useCallback)(
|
|
9650
10214
|
(mode = "selected") => {
|
|
9651
10215
|
if (mode !== "selected" && content) {
|
|
9652
|
-
const selection = buildSelectionForMode(
|
|
9653
|
-
|
|
9654
|
-
|
|
9655
|
-
|
|
10216
|
+
const selection = buildSelectionForMode(
|
|
10217
|
+
noticePurposeRows(void 0, content.purposes),
|
|
10218
|
+
mode,
|
|
10219
|
+
{
|
|
10220
|
+
selectedPurposes,
|
|
10221
|
+
selectedDataElements
|
|
10222
|
+
}
|
|
10223
|
+
);
|
|
9656
10224
|
setSelectedPurposes(selection.selectedPurposes);
|
|
9657
10225
|
setSelectedDataElements(selection.selectedDataElements);
|
|
9658
10226
|
}
|
|
@@ -9853,10 +10421,14 @@ var RedactoNoticeAssisted = ({
|
|
|
9853
10421
|
return;
|
|
9854
10422
|
}
|
|
9855
10423
|
}
|
|
9856
|
-
const selection = buildSelectionForMode(
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
10424
|
+
const selection = buildSelectionForMode(
|
|
10425
|
+
noticePurposeRows(void 0, content.purposes),
|
|
10426
|
+
acceptMode,
|
|
10427
|
+
{
|
|
10428
|
+
selectedPurposes,
|
|
10429
|
+
selectedDataElements
|
|
10430
|
+
}
|
|
10431
|
+
);
|
|
9860
10432
|
const submitPurposes = content.purposes.map((purpose) => ({
|
|
9861
10433
|
...purpose,
|
|
9862
10434
|
selected: selection.selectedPurposes[purpose.uuid] || false,
|