Skip to content

Commit

Permalink
Adding Fides.showModal (#4617)
Browse files Browse the repository at this point in the history
  • Loading branch information
galvana authored Feb 16, 2024
1 parent 57011ac commit 68c204a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The types of changes are:
- Support temporary credentials in AWS generate + scan features [#4607](https://github.com/ethyca/fides/pull/4603), [#4608](https://github.com/ethyca/fides/pull/4608)
- Add ability to store and read Fides cookie in Base64 format [#4556](https://github.com/ethyca/fides/pull/4556)
- Structured logging for SaaS connector requests [#4594](https://github.com/ethyca/fides/pull/4594)
- Added Fides.showModal() to fides.js to allow programmatic opening of consent modals [#4617](https://github.com/ethyca/fides/pull/4617)

### Fixed

Expand Down
35 changes: 25 additions & 10 deletions clients/fides-js/src/components/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { h, FunctionComponent, VNode } from "preact";
import { useEffect, useState, useCallback, useMemo } from "preact/hooks";
import {
useEffect,
useState,
useCallback,
useMemo,
useRef,
} from "preact/hooks";
import {
FidesCookie,
FidesOptions,
Expand All @@ -14,6 +20,7 @@ import ConsentModal from "./ConsentModal";
import { useHasMounted } from "../lib/hooks";
import { dispatchFidesEvent } from "../lib/events";
import ConsentContent from "./ConsentContent";
import { defaultShowModal } from "../fides";

interface RenderBannerProps {
isOpen: boolean;
Expand Down Expand Up @@ -53,6 +60,7 @@ const Overlay: FunctionComponent<Props> = ({
const delayModalLinkMilliseconds = 200;
const hasMounted = useHasMounted();
const [bannerIsOpen, setBannerIsOpen] = useState(false);
const modalLinkRef = useRef<HTMLElement | null>(null);

const dispatchCloseEvent = useCallback(
({ saved = false }: { saved?: boolean }) => {
Expand All @@ -75,6 +83,7 @@ const Overlay: FunctionComponent<Props> = ({

const handleOpenModal = useCallback(() => {
if (instance) {
setBannerIsOpen(false);
instance.show();
onOpen();
}
Expand All @@ -101,6 +110,8 @@ const Overlay: FunctionComponent<Props> = ({
}, [setBannerIsOpen]);

useEffect(() => {
window.Fides.showModal = handleOpenModal;
document.body.classList.add("fides-overlay-modal-link-shown");
// use a delay to ensure that link exists in the DOM
const delayModalLinkBinding = setTimeout(() => {
const modalLinkId = options.modalLinkId || "fides-modal-link";
Expand All @@ -110,19 +121,24 @@ const Overlay: FunctionComponent<Props> = ({
options.debug,
"Modal link element found, updating it to show and trigger modal on click."
);
// Update modal link to trigger modal on click
const modalLink = modalLinkEl;
modalLink.onclick = () => {
setBannerIsOpen(false);
handleOpenModal();
};
modalLinkRef.current = modalLinkEl;
modalLinkRef.current.addEventListener("click", window.Fides.showModal);
// Update to show the pre-existing modal link in the DOM
modalLink.classList.add("fides-modal-link-shown");
modalLinkRef.current.classList.add("fides-modal-link-shown");
} else {
debugLog(options.debug, "Modal link element not found.");
}
}, delayModalLinkMilliseconds);
return () => clearTimeout(delayModalLinkBinding);
return () => {
clearTimeout(delayModalLinkBinding);
if (modalLinkRef.current) {
modalLinkRef.current.removeEventListener(
"click",
window.Fides.showModal
);
}
window.Fides.showModal = defaultShowModal;
};
}, [options.modalLinkId, options.debug, handleOpenModal]);

const showBanner = useMemo(
Expand All @@ -136,7 +152,6 @@ const Overlay: FunctionComponent<Props> = ({

const handleManagePreferencesClick = (): void => {
handleOpenModal();
setBannerIsOpen(false);
};

if (!hasMounted) {
Expand Down
3 changes: 2 additions & 1 deletion clients/fides-js/src/fides-tcf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import {
} from "./lib/initialize";
import type { Fides } from "./lib/initialize";
import { dispatchFidesEvent } from "./lib/events";
import { debugLog, FidesCookie } from "./fides";
import { debugLog, FidesCookie, defaultShowModal } from "./fides";
import { renderOverlay } from "./lib/tcf/renderOverlay";
import type { GppFunction } from "./lib/gpp/types";
import { makeStub } from "./lib/tcf/stub";
Expand Down Expand Up @@ -243,6 +243,7 @@ _Fides = {
initialized: false,
meta,
shopify,
showModal: defaultShowModal,
};

if (typeof window !== "undefined") {
Expand Down
9 changes: 9 additions & 0 deletions clients/fides-js/src/fides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import type { Fides } from "./lib/initialize";

import { renderOverlay } from "./lib/renderOverlay";
import { customGetConsentPreferences } from "./services/external/preferences";
import { debugLog } from "./lib/consent-utils";

declare global {
interface Window {
Expand Down Expand Up @@ -161,6 +162,13 @@ const init = async (config: FidesConfig) => {
dispatchFidesEvent("FidesInitialized", cookie, config.options.debug);
};

export const defaultShowModal = () => {
debugLog(
window.Fides.options.debug,
"The current experience does not support displaying a modal."
);
};

// The global Fides object; this is bound to window.Fides if available
_Fides = {
consent: {},
Expand Down Expand Up @@ -198,6 +206,7 @@ _Fides = {
initialized: false,
meta,
shopify,
showModal: defaultShowModal,
};

if (typeof window !== "undefined") {
Expand Down
1 change: 1 addition & 0 deletions clients/fides-js/src/lib/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export type Fides = {
initialized: boolean;
meta: typeof meta;
shopify: typeof shopify;
showModal: () => void;
};

const retrieveEffectiveRegionString = async (
Expand Down
53 changes: 53 additions & 0 deletions clients/privacy-center/cypress/e2e/show-modal.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { stubConfig } from "../support/stubs";

describe("Fides.showModal", () => {
describe("Overlay enabled", () => {
beforeEach(() => {
stubConfig({
options: {
isOverlayEnabled: true,
},
experience: {
show_banner: false,
},
});
});

it("Should add 'fides-overlay-modal-link-shown' class to body", () => {
cy.get("body").should("have.class", "fides-overlay-modal-link-shown");
});

it("Should allow showModal", () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(100);
cy.window().its("Fides").invoke("showModal");
cy.get("@FidesUIShown").should("have.been.calledOnce");
cy.get(".fides-modal-content").should("be.visible");
});
});

describe("Overlay disabled", () => {
beforeEach(() => {
stubConfig({
options: {
isOverlayEnabled: false,
},
experience: {
show_banner: false,
},
});
});

it("Should not add 'fides-overlay-modal-link-shown' class to body", () => {
cy.get("body").should("not.have.class", "fides-overlay-modal-link-shown");
});

it("Should not allow showModal", () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(100);
cy.window().its("Fides").invoke("showModal");
cy.get("@FidesUIShown").should("not.have.been.called");
cy.get(".fides-modal-content").should("not.exist");
});
});
});

0 comments on commit 68c204a

Please sign in to comment.