@redacto.io/consent-sdk-react 9.5.0-beta.0 → 10.0.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/dist/index.d.mts +4 -2
  3. package/dist/index.d.ts +4 -2
  4. package/dist/index.js +122 -15
  5. package/dist/index.mjs +122 -15
  6. package/dist/privacy-center.d.mts +31 -7
  7. package/dist/privacy-center.d.ts +31 -7
  8. package/dist/privacy-center.js +173 -38
  9. package/dist/privacy-center.mjs +173 -38
  10. package/package.json +1 -1
  11. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +5 -0
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +29 -4
  13. package/src/RedactoNoticeConsent/api/index.ts +131 -2
  14. package/src/RedactoNoticeConsent/api/types.ts +33 -1
  15. package/src/RedactoNoticeConsent/types.ts +1 -0
  16. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +3 -1
  17. package/src/RedactoNoticeConsentInline/api/index.ts +5 -2
  18. package/src/RedactoNoticeConsentInline/api/types.ts +1 -1
  19. package/src/RedactoNoticeConsentInline/types.ts +1 -0
  20. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +3 -1
  21. package/src/RedactoPrivacyCenter/api/actions.ts +10 -3
  22. package/src/RedactoPrivacyCenter/api/client.ts +67 -21
  23. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +12 -1
  24. package/src/RedactoPrivacyCenter/components/Form.tsx +58 -6
  25. package/src/RedactoPrivacyCenter/components/groupHelpers.ts +64 -1
  26. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +8 -2
  27. package/src/RedactoPrivacyCenter/context/types.ts +1 -0
  28. package/src/RedactoPrivacyCenter/lib/api.ts +8 -0
  29. package/src/RedactoPrivacyCenter/lib/constants.ts +9 -0
  30. package/src/RedactoPrivacyCenter/lib/types.ts +11 -1
  31. package/tests/Form.test.tsx +5 -0
  32. package/tests/mocks.ts +1 -0
@@ -31,9 +31,11 @@ type BaseRequest = {
31
31
  /**
32
32
  * Consent service client factory.
33
33
  * Creates a client instance with a specific base URL.
34
- * @param baseUrl - Consent server base URL
34
+ * @param baseUrl - Consent server base URL (Python service, e.g. http://host/consent)
35
+ * @param ledgerBaseUrl - Go ledger base URL (e.g. http://host:8090/consent-ledger).
36
+ * Used for user-consents reads which are served from the ledger's `/public/...` paths.
35
37
  */
36
- declare function createConsentClient(baseUrl: string): {
38
+ declare function createConsentClient(baseUrl: string, ledgerBaseUrl: string): {
37
39
  /**
38
40
  * Get form data (privacy center)
39
41
  */
@@ -92,9 +94,21 @@ declare function createConsentClient(baseUrl: string): {
92
94
  nominator_uuid?: string;
93
95
  }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
94
96
  /**
95
- * Manage consent (privacy center) - revoke, regrant, or renew
97
+ * Manage consent (privacy center) - revoke, regrant, or renew.
98
+ *
99
+ * The Go ledger has no manage-consent route, so this is expressed as a
100
+ * `partial` submit-consent on the ledger — mirroring the Python dual-write
101
+ * relay (`build_consent_management_payload`): the affected purpose is
102
+ * re-submitted with `selected: false` to revoke or `selected: true` to
103
+ * regrant/renew, and `partial: true` so the rest of the notice's purposes
104
+ * are left untouched. The principal is resolved from the JWT, so no
105
+ * `contact`/identifiers are sent in the body, and `consent_event_uuid` is
106
+ * omitted so the ledger mints a fresh event.
96
107
  */
97
- manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], productUuid?: string): Promise<unknown>;
108
+ manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], productUuid?: string, noticeUuid?: string, dataElements?: Array<{
109
+ uuid: string;
110
+ selected: boolean;
111
+ }>): Promise<unknown>;
98
112
  /**
99
113
  * Get activities (privacy center)
100
114
  */
@@ -358,6 +372,7 @@ type PurposeItem = {
358
372
  method: string;
359
373
  data_elements: ConsentDataElement[];
360
374
  link_reason: string | null;
375
+ notice_uuid: string | null;
361
376
  };
362
377
  type ConsentGroup = {
363
378
  product_uuid: string;
@@ -609,6 +624,7 @@ declare const useInternalNavigation: () => NavigationContextType;
609
624
 
610
625
  interface RedactoPrivacyCenterProps {
611
626
  baseUrl: string;
627
+ ledgerBaseUrl: string;
612
628
  slug: string;
613
629
  accessToken: string;
614
630
  refreshToken: string;
@@ -616,7 +632,7 @@ interface RedactoPrivacyCenterProps {
616
632
  initialPage?: InternalPage;
617
633
  onBack?: 'back' | 'signout';
618
634
  }
619
- declare function RedactoPrivacyCenter({ baseUrl, slug, accessToken, refreshToken, onError, initialPage, onBack, }: RedactoPrivacyCenterProps): react_jsx_runtime.JSX.Element;
635
+ declare function RedactoPrivacyCenter({ baseUrl, ledgerBaseUrl, slug, accessToken, refreshToken, onError, initialPage, onBack, }: RedactoPrivacyCenterProps): react_jsx_runtime.JSX.Element;
620
636
 
621
637
  interface PrivacyCenterLayoutProps {
622
638
  children: ReactNode;
@@ -646,15 +662,18 @@ type AuthContextValue = Readonly<{
646
662
  }>;
647
663
  type BaseUrlContextValue = Readonly<{
648
664
  baseUrl: string;
665
+ ledgerBaseUrl: string;
649
666
  consentClient: ReturnType<typeof createConsentClient>;
650
667
  }>;
651
668
 
652
- declare const BaseUrlProvider: ({ children, baseUrl, }: {
669
+ declare const BaseUrlProvider: ({ children, baseUrl, ledgerBaseUrl, }: {
653
670
  children: ReactNode;
654
671
  baseUrl: string;
672
+ ledgerBaseUrl: string;
655
673
  }) => react_jsx_runtime.JSX.Element;
656
674
  declare const useBaseUrl: () => Readonly<{
657
675
  baseUrl: string;
676
+ ledgerBaseUrl: string;
658
677
  consentClient: ReturnType<typeof createConsentClient>;
659
678
  }>;
660
679
 
@@ -801,7 +820,7 @@ type FetchGroupPurposesParams = {
801
820
  consentClient?: BaseUrlContextValue['consentClient'];
802
821
  };
803
822
  declare const fetchGroupPurposes: (params: FetchGroupPurposesParams) => Promise<GroupPurposesOut | null>;
804
- declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, productUuid, }: {
823
+ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, productUuid, noticeUuid, dataElements, }: {
805
824
  organizationId: string;
806
825
  workspaceId: string;
807
826
  purposeId: string;
@@ -812,6 +831,11 @@ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact,
812
831
  nominatorContact?: string;
813
832
  dataElementUuids?: string[];
814
833
  productUuid?: string;
834
+ noticeUuid?: string;
835
+ dataElements?: Array<{
836
+ uuid: string;
837
+ selected: boolean;
838
+ }>;
815
839
  }) => Promise<boolean | null>;
816
840
  declare const fetchActivities: (organizationId: string, workspaceId: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<ActivityDetail | null>;
817
841
  declare const fetchCaseHistory: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<CaseHistoryDetail | null>;
@@ -8642,13 +8642,12 @@ async function fetchGroupPurposesServer(params) {
8642
8642
  }
8643
8643
  }
8644
8644
  async function manageConsentServer(params) {
8645
- var _a;
8646
8645
  try {
8647
8646
  if (!params.consentClient) {
8648
8647
  throw new Error("Consent client is required");
8649
8648
  }
8650
8649
  const baseRequest = buildBaseRequest(params.organizationId, params.workspaceId, params.authToken);
8651
- const result = await params.consentClient.manageConsent(
8650
+ await params.consentClient.manageConsent(
8652
8651
  baseRequest,
8653
8652
  params.purposeId,
8654
8653
  params.contact,
@@ -8657,9 +8656,11 @@ async function manageConsentServer(params) {
8657
8656
  void 0,
8658
8657
  params.nominatorContact,
8659
8658
  params.dataElementUuids,
8660
- params.productUuid
8659
+ params.productUuid,
8660
+ params.noticeUuid,
8661
+ params.dataElements
8661
8662
  );
8662
- return (_a = result == null ? void 0 : result.success) != null ? _a : null;
8663
+ return true;
8663
8664
  } catch (error) {
8664
8665
  const errorMsg = (error == null ? void 0 : error.message) || "";
8665
8666
  if (errorMsg.includes("nominator_not_found")) {
@@ -9096,6 +9097,7 @@ var MIN_REFRESH_BACKOFF_MS = 3e4;
9096
9097
  var MAX_REFRESH_BACKOFF_MS = 3e5;
9097
9098
  var REFRESH_TOKEN_STORAGE_KEY = "redacto_pc_refresh_token";
9098
9099
  var LEGACY_REFRESH_TOKEN_COOKIE = "refresh_token";
9100
+ var FORM_PICKER_GROUP_LIMIT = 100;
9099
9101
  var POLL_INTERVAL = 3e4;
9100
9102
  var NOTIFICATION_PAGE_SIZE = 10;
9101
9103
  var NOTIFICATION_DROPDOWN_LIMIT = 5;
@@ -9759,7 +9761,9 @@ var manageConsent = async ({
9759
9761
  consentClient,
9760
9762
  nominatorContact,
9761
9763
  dataElementUuids,
9762
- productUuid
9764
+ productUuid,
9765
+ noticeUuid,
9766
+ dataElements
9763
9767
  }) => {
9764
9768
  try {
9765
9769
  const accessToken = await ensureValidToken(organizationId, workspaceId, void 0, authContext, consentClient);
@@ -9776,7 +9780,9 @@ var manageConsent = async ({
9776
9780
  consentClient,
9777
9781
  nominatorContact,
9778
9782
  dataElementUuids,
9779
- productUuid
9783
+ productUuid,
9784
+ noticeUuid,
9785
+ dataElements
9780
9786
  });
9781
9787
  return result;
9782
9788
  } catch (error) {
@@ -9796,7 +9802,9 @@ var manageConsent = async ({
9796
9802
  consentClient,
9797
9803
  nominatorContact,
9798
9804
  dataElementUuids,
9799
- productUuid
9805
+ productUuid,
9806
+ noticeUuid,
9807
+ dataElements
9800
9808
  });
9801
9809
  }
9802
9810
  console.error(`Error ${action} consent:`, error);
@@ -10105,7 +10113,11 @@ var useAuth = () => {
10105
10113
  var import_react4 = require("react");
10106
10114
 
10107
10115
  // src/RedactoPrivacyCenter/api/client.ts
10108
- function createConsentClient(baseUrl) {
10116
+ function createConsentClient(baseUrl, ledgerBaseUrl) {
10117
+ if (!ledgerBaseUrl) {
10118
+ throw new Error("ledgerBaseUrl is required to create the consent client");
10119
+ }
10120
+ const ledgerBase = ledgerBaseUrl.replace(/\/$/, "");
10109
10121
  async function privacyCenterApiFetch(url, options) {
10110
10122
  const { authToken, getAuthToken, headers = {}, ...fetchOptions } = options;
10111
10123
  const requestHeaders = new Headers();
@@ -10198,6 +10210,9 @@ function createConsentClient(baseUrl) {
10198
10210
  function privacyCenterUrl(baseRequest, path) {
10199
10211
  return `${baseUrl}/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}/dsar/privacy-center${path}`;
10200
10212
  }
10213
+ function ledgerUrl(baseRequest, path) {
10214
+ return `${ledgerBase}/public/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}${path}`;
10215
+ }
10201
10216
  function caseUrl(baseRequest, caseUuid, path = "") {
10202
10217
  return privacyCenterUrl(baseRequest, `/cases/${caseUuid}${path}`);
10203
10218
  }
@@ -10331,7 +10346,8 @@ function createConsentClient(baseUrl) {
10331
10346
  if (params.product_uuid) queryParams.append("product_uuid", params.product_uuid);
10332
10347
  if (params.language) queryParams.append("language", params.language);
10333
10348
  const queryString = queryParams.toString();
10334
- const url = privacyCenterUrl(baseRequest, `/user-consents${queryString ? `?${queryString}` : ""}`);
10349
+ const suffix = `/user-consents${queryString ? `?${queryString}` : ""}`;
10350
+ const url = ledgerUrl(baseRequest, suffix);
10335
10351
  return privacyCenterApiFetch(url, {
10336
10352
  ...options,
10337
10353
  method: "GET",
@@ -10352,10 +10368,8 @@ function createConsentClient(baseUrl) {
10352
10368
  if (params.language) queryParams.append("language", params.language);
10353
10369
  if (params.nominator_uuid) queryParams.append("nominator_uuid", params.nominator_uuid);
10354
10370
  const queryString = queryParams.toString();
10355
- const url = privacyCenterUrl(
10356
- baseRequest,
10357
- `/user-consents/${productUuid}/purposes${queryString ? `?${queryString}` : ""}`
10358
- );
10371
+ const suffix = `/user-consents/${productUuid}/purposes${queryString ? `?${queryString}` : ""}`;
10372
+ const url = ledgerUrl(baseRequest, suffix);
10359
10373
  return privacyCenterApiFetch(url, {
10360
10374
  ...options,
10361
10375
  method: "GET",
@@ -10364,20 +10378,48 @@ function createConsentClient(baseUrl) {
10364
10378
  });
10365
10379
  },
10366
10380
  /**
10367
- * Manage consent (privacy center) - revoke, regrant, or renew
10381
+ * Manage consent (privacy center) - revoke, regrant, or renew.
10382
+ *
10383
+ * The Go ledger has no manage-consent route, so this is expressed as a
10384
+ * `partial` submit-consent on the ledger — mirroring the Python dual-write
10385
+ * relay (`build_consent_management_payload`): the affected purpose is
10386
+ * re-submitted with `selected: false` to revoke or `selected: true` to
10387
+ * regrant/renew, and `partial: true` so the rest of the notice's purposes
10388
+ * are left untouched. The principal is resolved from the JWT, so no
10389
+ * `contact`/identifiers are sent in the body, and `consent_event_uuid` is
10390
+ * omitted so the ledger mints a fresh event.
10368
10391
  */
10369
- async manageConsent(baseRequest, purposeId, contact, status, authToken, options, nominatorContact, dataElementUuids, productUuid) {
10370
- const url = privacyCenterUrl(baseRequest, `/manage-consent?status=${status}`);
10371
- const body = { purpose_uuid: purposeId, contact };
10372
- if (nominatorContact) {
10373
- body.nominator_contact = nominatorContact;
10374
- }
10375
- if (Array.isArray(dataElementUuids) && dataElementUuids.length > 0) {
10376
- body.data_element_uuids = dataElementUuids;
10377
- }
10378
- if (productUuid) {
10379
- body.product_uuid = productUuid;
10380
- }
10392
+ async manageConsent(baseRequest, purposeId, contact, status, authToken, options, nominatorContact, dataElementUuids, productUuid, noticeUuid, dataElements) {
10393
+ if (!noticeUuid) {
10394
+ throw new Error("notice_uuid is required to manage consent via the ledger");
10395
+ }
10396
+ const purposeSelected = status !== "revoke";
10397
+ const elements = (dataElements != null ? dataElements : []).map((de) => {
10398
+ let selected;
10399
+ if (status === "revoke") {
10400
+ selected = false;
10401
+ } else if (status === "regrant") {
10402
+ selected = Array.isArray(dataElementUuids) ? dataElementUuids.includes(de.uuid) : de.selected;
10403
+ } else {
10404
+ selected = de.selected;
10405
+ }
10406
+ return { uuid: de.uuid, selected };
10407
+ });
10408
+ const body = {
10409
+ notice_uuid: noticeUuid,
10410
+ partial: true,
10411
+ declined: false,
10412
+ select_all_mandatory: false,
10413
+ self_declared_adult: false,
10414
+ purposes: [
10415
+ {
10416
+ purpose_uuid: purposeId,
10417
+ selected: purposeSelected,
10418
+ data_elements: elements
10419
+ }
10420
+ ]
10421
+ };
10422
+ const url = ledgerUrl(baseRequest, "/submit-consent");
10381
10423
  return privacyCenterApiFetch(url, {
10382
10424
  ...options,
10383
10425
  method: "POST",
@@ -10414,7 +10456,7 @@ function createConsentClient(baseUrl) {
10414
10456
  if (params.created_before) queryParams.append("created_before", params.created_before);
10415
10457
  if (params.language) queryParams.append("language", params.language);
10416
10458
  const queryString = queryParams.toString();
10417
- const url = privacyCenterUrl(baseRequest, `/receipts${queryString ? `?${queryString}` : ""}`);
10459
+ const url = ledgerUrl(baseRequest, `/receipts${queryString ? `?${queryString}` : ""}`);
10418
10460
  return privacyCenterApiFetch(url, {
10419
10461
  ...options,
10420
10462
  method: "GET",
@@ -10429,7 +10471,7 @@ function createConsentClient(baseUrl) {
10429
10471
  * and the Authorization header must be sent (anchor navigation wouldn't carry it).
10430
10472
  */
10431
10473
  async getReceiptPdf(baseRequest, receiptUuid, authToken) {
10432
- const url = privacyCenterUrl(baseRequest, `/receipts/${receiptUuid}/pdf`);
10474
+ const url = ledgerUrl(baseRequest, `/receipts/${receiptUuid}/download`);
10433
10475
  const token = resolveAuthToken(authToken, baseRequest);
10434
10476
  const requestHeaders = new Headers();
10435
10477
  requestHeaders.set("Accept", "application/pdf");
@@ -10615,15 +10657,20 @@ var import_jsx_runtime4 = require("react/jsx-runtime");
10615
10657
  var BaseUrlContext = (0, import_react4.createContext)(null);
10616
10658
  var BaseUrlProvider = ({
10617
10659
  children,
10618
- baseUrl
10660
+ baseUrl,
10661
+ ledgerBaseUrl
10619
10662
  }) => {
10620
- const consentClient = (0, import_react4.useMemo)(() => createConsentClient(baseUrl), [baseUrl]);
10663
+ const consentClient = (0, import_react4.useMemo)(
10664
+ () => createConsentClient(baseUrl, ledgerBaseUrl),
10665
+ [baseUrl, ledgerBaseUrl]
10666
+ );
10621
10667
  const value = (0, import_react4.useMemo)(
10622
10668
  () => ({
10623
10669
  baseUrl,
10670
+ ledgerBaseUrl,
10624
10671
  consentClient
10625
10672
  }),
10626
- [baseUrl, consentClient]
10673
+ [baseUrl, ledgerBaseUrl, consentClient]
10627
10674
  );
10628
10675
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BaseUrlContext.Provider, { value, children });
10629
10676
  };
@@ -18163,6 +18210,7 @@ function ConsentManager({ variant }) {
18163
18210
  );
18164
18211
  const handleManageConsent = (0, import_react37.useCallback)(
18165
18212
  async (purposeId, action, nominatorContact, dataElementUuids, productUuid) => {
18213
+ var _a2, _b2;
18166
18214
  if (!organizationId || !workspaceId || !contact) {
18167
18215
  toast.error(t("missingInfoToManage"));
18168
18216
  return;
@@ -18179,6 +18227,11 @@ function ConsentManager({ variant }) {
18179
18227
  renew: t("unableToRenewConsent")
18180
18228
  };
18181
18229
  try {
18230
+ const noticeUuid = (_a2 = selectedRecord == null ? void 0 : selectedRecord.notice_uuid) != null ? _a2 : void 0;
18231
+ const dataElements = ((_b2 = selectedRecord == null ? void 0 : selectedRecord.data_elements) != null ? _b2 : []).map((el) => ({
18232
+ uuid: el.uuid,
18233
+ selected: el.selected
18234
+ }));
18182
18235
  const response = await manageConsent({
18183
18236
  organizationId,
18184
18237
  workspaceId,
@@ -18189,7 +18242,9 @@ function ConsentManager({ variant }) {
18189
18242
  consentClient,
18190
18243
  nominatorContact,
18191
18244
  dataElementUuids,
18192
- productUuid
18245
+ productUuid,
18246
+ noticeUuid,
18247
+ dataElements
18193
18248
  });
18194
18249
  if (response) {
18195
18250
  toast.success(successMessages[action]);
@@ -18211,7 +18266,7 @@ function ConsentManager({ variant }) {
18211
18266
  handleCloseModal();
18212
18267
  }
18213
18268
  },
18214
- [organizationId, workspaceId, contact, fetchData, handleCloseModal, t, authContext, consentClient]
18269
+ [organizationId, workspaceId, contact, fetchData, handleCloseModal, t, authContext, consentClient, selectedRecord]
18215
18270
  );
18216
18271
  const getVar26 = (varName) => `var(${varName})`;
18217
18272
  const directBadge = (_c = (_b = consentDetail == null ? void 0 : consentDetail.status_summary) == null ? void 0 : _b.direct_purposes) != null ? _c : "";
@@ -18736,6 +18791,43 @@ var import_ai = require("react-icons/ai");
18736
18791
  var import_pi4 = require("react-icons/pi");
18737
18792
 
18738
18793
  // src/RedactoPrivacyCenter/components/groupHelpers.ts
18794
+ var consentGroupToFormProductGroup = (group) => {
18795
+ var _a;
18796
+ return {
18797
+ product_uuid: group.product_uuid,
18798
+ product_name: group.product_name,
18799
+ product_description: group.product_description,
18800
+ nominator: group.nominator,
18801
+ purposes: ((_a = group.purposes) != null ? _a : []).map(purposeItemToFormPurpose)
18802
+ };
18803
+ };
18804
+ var purposeItemToFormPurpose = (purpose) => {
18805
+ var _a, _b;
18806
+ return {
18807
+ uuid: purpose.purpose_uuid,
18808
+ purpose_uuid: purpose.purpose_uuid,
18809
+ name: purpose.name,
18810
+ description: (_a = purpose.description) != null ? _a : "",
18811
+ industries: "",
18812
+ selected: false,
18813
+ given_consent: false,
18814
+ status: purpose.status,
18815
+ validity: null,
18816
+ enabled: true,
18817
+ data_elements: ((_b = purpose.data_elements) != null ? _b : []).map(
18818
+ consentDataElementToFormDataElement
18819
+ )
18820
+ };
18821
+ };
18822
+ var consentDataElementToFormDataElement = (element) => ({
18823
+ uuid: element.uuid,
18824
+ name: element.name,
18825
+ description: "",
18826
+ enabled: element.enabled,
18827
+ required: element.required,
18828
+ given_consent: element.selected,
18829
+ selected: element.selected
18830
+ });
18739
18831
  var buildGroupPurposes = (group) => group.purposes.filter((p) => p !== null && p !== void 0).map((p) => {
18740
18832
  const validDataElements = Array.isArray(p.data_elements) ? p.data_elements.filter((de) => de !== null && de !== void 0 && Boolean(de.uuid)).map((de) => ({ ...de, selected: false })) : [];
18741
18833
  return {
@@ -19964,6 +20056,44 @@ function Form({
19964
20056
  },
19965
20057
  []
19966
20058
  );
20059
+ const withLedgerPickerGroups = (0, import_react41.useCallback)(
20060
+ async (form, language) => {
20061
+ var _a2, _b2;
20062
+ if (isPopup || isCaseManagementContext || !organizationId || !workspaceId) {
20063
+ return form;
20064
+ }
20065
+ const consents = await fetchUserConsents({
20066
+ organizationId,
20067
+ workspaceId,
20068
+ authContext,
20069
+ consentClient,
20070
+ // No status filter: include every status (active / expired / withdrawn
20071
+ // / declined), matching Python form/data, so a DSAR can target products
20072
+ // the user no longer actively consents to.
20073
+ limit: FORM_PICKER_GROUP_LIMIT,
20074
+ nominatedLimit: FORM_PICKER_GROUP_LIMIT,
20075
+ language
20076
+ });
20077
+ if (!consents) {
20078
+ return form;
20079
+ }
20080
+ return {
20081
+ ...form,
20082
+ direct_groups: ((_a2 = consents.direct) != null ? _a2 : []).map(consentGroupToFormProductGroup),
20083
+ nominated_groups: ((_b2 = consents.nominated) != null ? _b2 : []).map(
20084
+ consentGroupToFormProductGroup
20085
+ )
20086
+ };
20087
+ },
20088
+ [
20089
+ isPopup,
20090
+ isCaseManagementContext,
20091
+ organizationId,
20092
+ workspaceId,
20093
+ authContext,
20094
+ consentClient
20095
+ ]
20096
+ );
19967
20097
  const fetchAndApplyTranslations = (0, import_react41.useCallback)(async (langValue) => {
19968
20098
  if (!organizationId || !workspaceId || !data) {
19969
20099
  return;
@@ -19992,7 +20122,7 @@ function Form({
19992
20122
  toast.info(t("translationNotAvailable"));
19993
20123
  return;
19994
20124
  }
19995
- setData(translatedFormData);
20125
+ setData(await withLedgerPickerGroups(translatedFormData, langValue));
19996
20126
  if (translatedFormData.grievance_options) {
19997
20127
  const currentGrievanceSelections = { ...selectedGrievances };
19998
20128
  setGrievanceOptions(translatedFormData.grievance_options);
@@ -20008,7 +20138,7 @@ function Form({
20008
20138
  } finally {
20009
20139
  setIsTranslating(false);
20010
20140
  }
20011
- }, [organizationId, workspaceId, data, formData.contact, isPopup, isCaseManagementContext, authContext, consentClient, selectedGrievances, t]);
20141
+ }, [organizationId, workspaceId, data, formData.contact, isPopup, isCaseManagementContext, authContext, consentClient, selectedGrievances, t, withLedgerPickerGroups]);
20012
20142
  (0, import_react41.useEffect)(() => {
20013
20143
  if (!skipProductStep) {
20014
20144
  setSelectedProductKey(null);
@@ -20114,7 +20244,11 @@ function Form({
20114
20244
  console.warn("No purposes with data elements found in API response");
20115
20245
  }
20116
20246
  }
20117
- setData(displayData);
20247
+ const pickerData = await withLedgerPickerGroups(
20248
+ displayData,
20249
+ langParam || void 0
20250
+ );
20251
+ setData(pickerData);
20118
20252
  setGrievanceOptions(displayData.grievance_options || []);
20119
20253
  const initialGrievances = (displayData.grievance_options || []).reduce(
20120
20254
  (acc, option) => {
@@ -20134,7 +20268,7 @@ function Form({
20134
20268
  }
20135
20269
  };
20136
20270
  void initializePrivacyCenterForm();
20137
- }, [organizationId, workspaceId, isPopup, authContext, consentClient]);
20271
+ }, [organizationId, workspaceId, isPopup, authContext, consentClient, withLedgerPickerGroups]);
20138
20272
  const getEnglishDataElementName = (0, import_react41.useCallback)((translatedName) => {
20139
20273
  var _a2, _b2, _c2;
20140
20274
  if (!((_a2 = englishDataRef.current) == null ? void 0 : _a2.purposes)) {
@@ -27538,6 +27672,7 @@ var import_jsx_runtime90 = require("react/jsx-runtime");
27538
27672
  injectPCStyles();
27539
27673
  function RedactoPrivacyCenter({
27540
27674
  baseUrl,
27675
+ ledgerBaseUrl,
27541
27676
  slug,
27542
27677
  accessToken,
27543
27678
  refreshToken,
@@ -27545,7 +27680,7 @@ function RedactoPrivacyCenter({
27545
27680
  initialPage = "consent-manager",
27546
27681
  onBack
27547
27682
  }) {
27548
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_react_i18next52.I18nextProvider, { i18n: i18n_default, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(BrandingProvider, { slug, baseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(BaseUrlProvider, { baseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
27683
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_react_i18next52.I18nextProvider, { i18n: i18n_default, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(BrandingProvider, { slug, baseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(BaseUrlProvider, { baseUrl, ledgerBaseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
27549
27684
  AuthProvider,
27550
27685
  {
27551
27686
  accessToken,