Skip to content

Commit

Permalink
Merge branch 'main' into PROD-2130-BE-add-query-param-key-to-privacy-…
Browse files Browse the repository at this point in the history
…center-config
  • Loading branch information
galvana authored May 31, 2024
2 parents ad9a975 + 0ef9822 commit 9e9eaa8
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 102 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The types of changes are:
### Changed
- Set default ports for local development of client projects (:3001 for privacy center and :3000 for admin-ui) [#4912](https://github.com/ethyca/fides/pull/4912)
- Update privacy center port to :3001 for nox [#4918](https://github.com/ethyca/fides/pull/4918)
- Optimize speed by generating the uuids in the client side for consent requests [#4933](https://github.com/ethyca/fides/pull/4933)
- Update Privacy Center toast text for consistent capitalization [#4936](https://github.com/ethyca/fides/pull/4936)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion clients/fides-js/src/components/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import {
shouldResurfaceConsent,
} from "../lib/consent-utils";
import { dispatchFidesEvent } from "../lib/events";
import { useHasMounted } from "../lib/hooks";
import type { I18n } from "../lib/i18n";

import ConsentModal from "./ConsentModal";
import ConsentContent from "./ConsentContent";
import "./fides.css";
import { blockPageScrolling, unblockPageScrolling } from "../lib/ui-utils";
import { FIDES_OVERLAY_WRAPPER } from "../lib/consent-constants";
import { useHasMounted } from "../lib/hooks";

interface RenderBannerProps {
isOpen: boolean;
Expand Down
9 changes: 5 additions & 4 deletions clients/fides-js/src/components/notices/NoticeOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "../fides.css";

import { FunctionComponent, h } from "preact";

import { useCallback, useEffect, useMemo, useState } from "preact/hooks";

import { getConsentContext } from "../../lib/consent-context";
Expand All @@ -21,7 +22,6 @@ import {
updateCookieFromNoticePreferences,
} from "../../lib/cookie";
import { dispatchFidesEvent } from "../../lib/events";
import { useConsentServed } from "../../lib/hooks";
import {
selectBestExperienceConfigTranslation,
selectBestNoticeTranslation,
Expand All @@ -34,6 +34,7 @@ import Overlay from "../Overlay";
import { OverlayProps } from "../types";
import { NoticeToggleProps, NoticeToggles } from "./NoticeToggles";
import { useI18n } from "../../lib/i18n/i18n-context";
import { useConsentServed } from "../../lib/hooks";

/**
* Define a special PrivacyNoticeItem, where we've narrowed the list of
Expand Down Expand Up @@ -148,7 +149,7 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
};
});

const { servedNotice } = useConsentServed({
const { servedNoticeHistoryId } = useConsentServed({
privacyExperienceConfigHistoryId,
privacyNoticeHistoryIds: privacyNoticeItems.reduce((ids, e) => {
const id = e.bestTranslation?.privacy_notice_history_id;
Expand Down Expand Up @@ -197,7 +198,7 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
options,
userLocationString: fidesRegionString,
cookie,
servedNoticeHistoryId: servedNotice?.served_notice_history_id,
servedNoticeHistoryId,
updateCookie: (oldCookie) =>
updateCookieFromNoticePreferences(
oldCookie,
Expand All @@ -214,7 +215,7 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
options,
privacyExperienceConfigHistoryId,
privacyNoticeItems,
servedNotice,
servedNoticeHistoryId,
]
);

Expand Down
8 changes: 4 additions & 4 deletions clients/fides-js/src/components/tcf/TcfOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import { transformTcfPreferencesToCookieKeys } from "../../lib/cookie";
import InitialLayer from "./InitialLayer";
import TcfTabs from "./TcfTabs";
import Button from "../Button";
import { useConsentServed } from "../../lib/hooks";
import VendorInfoBanner from "./VendorInfoBanner";
import { dispatchFidesEvent } from "../../lib/events";
import { selectBestExperienceConfigTranslation } from "../../lib/i18n";
Expand All @@ -47,6 +46,7 @@ import {
transformUserPreferenceToBoolean,
} from "../../lib/shared-consent-utils";
import { useI18n } from "../../lib/i18n/i18n-context";
import { useConsentServed } from "../../lib/hooks";

const resolveConsentValueFromTcfModel = (
model:
Expand Down Expand Up @@ -255,7 +255,7 @@ const TcfOverlay: FunctionComponent<OverlayProps> = ({
return undefined;
}, [experience, i18n]);

const { servedNotice } = useConsentServed({
const { servedNoticeHistoryId } = useConsentServed({
privacyExperienceConfigHistoryId,
privacyNoticeHistoryIds: [],
options,
Expand All @@ -280,7 +280,7 @@ const TcfOverlay: FunctionComponent<OverlayProps> = ({
cookie,
debug: options.debug,
tcf,
servedNoticeHistoryId: servedNotice?.served_notice_history_id,
servedNoticeHistoryId,
updateCookie: (oldCookie) =>
updateCookie(oldCookie, tcf, enabledIds, experience),
});
Expand All @@ -292,7 +292,7 @@ const TcfOverlay: FunctionComponent<OverlayProps> = ({
fidesRegionString,
options,
privacyExperienceConfigHistoryId,
servedNotice,
servedNoticeHistoryId,
]
);

Expand Down
13 changes: 13 additions & 0 deletions clients/fides-js/src/lib/common-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
export const raise = (message: string) => {
throw new Error(message);
};

/**
* Extracts the id value of each object in the list and returns a list
* of IDs, either strings or numbers based on the IDs' type.
*/
export const extractIds = <T extends { id: string | number }[]>(
modelList?: T
): any[] => {
if (!modelList) {
return [];
}
return modelList.map((model) => model.id);
};
2 changes: 2 additions & 0 deletions clients/fides-js/src/lib/consent-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ export enum ServingComponent {
* Request body when indicating that notices were served in the UI
*/
export type RecordConsentServedRequest = {
served_notice_history_id: string; // a generated uuidv4 string

browser_identity: Identity;
code?: string;
privacy_notice_history_ids?: Array<string>;
Expand Down
4 changes: 4 additions & 0 deletions clients/fides-js/src/lib/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as useConsentServed } from "./useConsentServed";
export { default as useHasMounted } from "./useHasMounted";
export { default as useUUID4 } from "./useUUID4";
export { default as useDisclosure } from "./useDisclosure";
Original file line number Diff line number Diff line change
@@ -1,81 +1,14 @@
import { useEffect, useState, useCallback } from "preact/hooks";
import { FidesEvent } from "./events";
import { useEffect, useCallback, useState } from "preact/hooks";
import { v4 as uuidv4 } from "uuid";
import { FidesEvent } from "../events";
import {
FidesInitOptions,
PrivacyExperience,
RecordConsentServedRequest,
ServingComponent,
RecordsServedResponse,
} from "./consent-types";
import { patchNoticesServed } from "../services/api";

/**
* Hook which tracks if the app has mounted yet.
*
* Used to make sure the server and client UIs match for hydration
* Adapted from https://www.joshwcomeau.com/react/the-perils-of-rehydration/
*/
export const useHasMounted = () => {
const [hasMounted, setHasMounted] = useState(false);

useEffect(() => {
setHasMounted(true);
}, []);

return hasMounted;
};

/**
* Hook to facilitate showing/hiding while adhering to WAI
* based on chakra-ui's `useDisclosure`
*/
export const useDisclosure = ({ id }: { id: string }) => {
const [isOpen, setIsOpen] = useState(false);

const onClose = useCallback(() => setIsOpen(false), []);
const onOpen = useCallback(() => setIsOpen(true), []);

const onToggle = useCallback(() => {
if (isOpen) {
onClose();
} else {
onOpen();
}
}, [isOpen, onOpen, onClose]);

const getButtonProps = () => ({
"aria-expanded": isOpen,
"aria-controls": id,
onClick: onToggle,
});

const getDisclosureProps = () => ({
id,
className: isOpen ? "fides-disclosure-visible" : "fides-disclosure-hidden",
});

return {
isOpen,
onOpen,
onClose,
onToggle,
getButtonProps,
getDisclosureProps,
};
};

/**
* Extracts the id value of each object in the list and returns a list
* of IDs, either strings or numbers based on the IDs' type.
*/
const extractIds = <T extends { id: string | number }[]>(
modelList?: T
): any[] => {
if (!modelList) {
return [];
}
return modelList.map((model) => model.id);
};
} from "../consent-types";
import { patchNoticesServed } from "../../services/api";
import { extractIds } from "../common-utils";

export const useConsentServed = ({
options,
Expand All @@ -92,8 +25,9 @@ export const useConsentServed = ({
userGeography?: string;
acknowledgeMode?: boolean;
}) => {
const [servedNotice, setServedNotice] =
useState<RecordsServedResponse | null>(null);
const [servedNoticeHistoryId, setServedNoticeHistoryId] = useState<string>(
uuidv4()
);

const handleUIEvent = useCallback(
async (event: FidesEvent) => {
Expand All @@ -114,8 +48,13 @@ export const useConsentServed = ({
return;
}

// Create new uuid for each served notice
const newUUID = uuidv4();
setServedNoticeHistoryId(newUUID);

// Construct the notices-served API request and send!
const request: RecordConsentServedRequest = {
served_notice_history_id: newUUID,
browser_identity: event.detail.identity,
privacy_experience_config_history_id:
privacyExperienceConfigHistoryId || "",
Expand Down Expand Up @@ -145,13 +84,12 @@ export const useConsentServed = ({
),
serving_component: String(event.detail.extraDetails.servingComponent),
};
const result = await patchNoticesServed({

// Send the request to the notices-served API
patchNoticesServed({
request,
options,
});
if (result) {
setServedNotice(result);
}
},
[
privacyExperienceConfigHistoryId,
Expand All @@ -170,5 +108,6 @@ export const useConsentServed = ({
};
}, [handleUIEvent]);

return { servedNotice };
return { servedNoticeHistoryId };
};
export default useConsentServed;
41 changes: 41 additions & 0 deletions clients/fides-js/src/lib/hooks/useDisclosure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useCallback, useState } from "preact/hooks";

/**
* Hook to facilitate showing/hiding while adhering to WAI
* based on chakra-ui's `useDisclosure`
*/
const useDisclosure = ({ id }: { id: string }) => {
const [isOpen, setIsOpen] = useState(false);

const onClose = useCallback(() => setIsOpen(false), []);
const onOpen = useCallback(() => setIsOpen(true), []);

const onToggle = useCallback(() => {
if (isOpen) {
onClose();
} else {
onOpen();
}
}, [isOpen, onOpen, onClose]);

const getButtonProps = () => ({
"aria-expanded": isOpen,
"aria-controls": id,
onClick: onToggle,
});

const getDisclosureProps = () => ({
id,
className: isOpen ? "fides-disclosure-visible" : "fides-disclosure-hidden",
});

return {
isOpen,
onOpen,
onClose,
onToggle,
getButtonProps,
getDisclosureProps,
};
};
export default useDisclosure;
18 changes: 18 additions & 0 deletions clients/fides-js/src/lib/hooks/useHasMounted.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect, useState } from "preact/hooks";

/**
* Hook which tracks if the app has mounted yet.
*
* Used to make sure the server and client UIs match for hydration
* Adapted from https://www.joshwcomeau.com/react/the-perils-of-rehydration/
*/
const useHasMounted = () => {
const [hasMounted, setHasMounted] = useState(false);

useEffect(() => {
setHasMounted(true);
}, []);

return hasMounted;
};
export default useHasMounted;
14 changes: 14 additions & 0 deletions clients/fides-js/src/lib/hooks/useUUID4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useState } from "preact/hooks";
import { v4 as uuidv4 } from "uuid";

/**
* Custom hook that generates a UUIDv4.
* The returned value stays the same for the lifetime of the component.
* @returns The generated UUIDv4.
*/
const useUUID4 = () => {
const [uuid] = useState<string>(uuidv4());

return uuid;
};
export default useUUID4;
2 changes: 2 additions & 0 deletions clients/fides-js/src/lib/initialize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ContainerNode } from "preact";
import { v4 as uuidv4 } from "uuid";

import {
DEFAULT_MODAL_LINK_LABEL,
Expand Down Expand Up @@ -168,6 +169,7 @@ const automaticallyApplyGPCPreferences = async ({

if (gpcApplied) {
await updateConsentPreferences({
servedNoticeHistoryId: uuidv4(),
consentPreferencesToSave,
privacyExperienceConfigHistoryId,
experience: effectiveExperience,
Expand Down
Loading

0 comments on commit 9e9eaa8

Please sign in to comment.