From 741bbce42850483b23b102827ef8f47268ad93ca Mon Sep 17 00:00:00 2001 From: Sean Preston Date: Wed, 7 Jun 2023 11:32:49 -0400 Subject: [PATCH] Privacy center customisations (#3432) --- CHANGELOG.md | 3 ++ clients/privacy-center/components/Layout.tsx | 2 +- .../ConsentRequestForm.tsx | 24 ++++----- .../ConsentRequestModal.tsx | 1 + .../PrivacyRequestForm.tsx | 4 +- clients/privacy-center/config/config.json | 14 ++++-- .../privacy-center/cypress/e2e/consent.cy.ts | 49 +++++++++++++++++++ clients/privacy-center/pages/index.tsx | 11 ++++- clients/privacy-center/types/config.ts | 6 +++ .../privacy_center/config/config.json | 2 +- 10 files changed, 92 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4cea973ff7..cd6bc45b61f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ The types of changes are: - Added the ability to use custom CAs with Redis via TLS [#3451](https://github.com/ethyca/fides/pull/3451) - Add default experience configs on startup [#3449](https://github.com/ethyca/fides/pull/3449) - Load default privacy notices on startup [#3401](https://github.com/ethyca/fides/pull/3401/files) +- Add privacy centre button text customisations [#3432](https://github.com/ethyca/fides/pull/3432) +- Add privacy centre favicon customisation [#3432](https://github.com/ethyca/fides/pull/3432) ### Fixed @@ -42,6 +44,7 @@ The types of changes are: - Bump SlowAPI Version [#3456](https://github.com/ethyca/fides/pull/3456) - Bump Psycopg2-binary Version [#3473](https://github.com/ethyca/fides/pull/3473) - Reduced duplication between PrivacyExperience and PrivacyExperienceConfig [#3470](https://github.com/ethyca/fides/pull/3470) +- Update privacy centre email and phone validation to allow for both to be blank [#3432](https://github.com/ethyca/fides/pull/3432) ### Developer Experience diff --git a/clients/privacy-center/components/Layout.tsx b/clients/privacy-center/components/Layout.tsx index 65c6b8595b9..f80a6be9fca 100644 --- a/clients/privacy-center/components/Layout.tsx +++ b/clients/privacy-center/components/Layout.tsx @@ -15,7 +15,7 @@ const Layout: React.FC = ({ children }) => { Privacy Center - + {styles ? : null}
diff --git a/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestForm.tsx b/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestForm.tsx index 56f01851c28..b2684b02f0f 100644 --- a/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestForm.tsx +++ b/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestForm.tsx @@ -127,26 +127,20 @@ const useConsentRequestForm = ({ validationSchema: Yup.object().shape({ email: emailValidation(identityInputs?.email).test( "one of email or phone entered", - "You must enter either email or phone", + "You must enter an email", (value, context) => { - if ( - identityInputs?.email === "optional" && - identityInputs?.phone === "optional" - ) { - return Boolean(context.parent.phone || context.parent.email); + if (identityInputs?.email === "required") { + return Boolean(context.parent.email); } return true; } ), phone: phoneValidation(identityInputs?.phone).test( "one of email or phone entered", - "You must enter either email or phone", + "You must enter a phone number", (value, context) => { - if ( - identityInputs?.email === "optional" && - identityInputs?.phone === "optional" - ) { - return Boolean(context.parent.phone || context.parent.email); + if (identityInputs?.phone === "required") { + return Boolean(context.parent.phone); } return true; } @@ -208,7 +202,7 @@ const ConsentRequestForm: React.FC = ({ return ( <> - {config.consent?.button.title} + {config.consent?.button.modalTitle || config.consent?.button.title} @@ -280,7 +274,7 @@ const ConsentRequestForm: React.FC = ({ diff --git a/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestModal.tsx b/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestModal.tsx index 007b231d111..6b4a318217e 100644 --- a/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestModal.tsx +++ b/clients/privacy-center/components/modals/consent-request-modal/ConsentRequestModal.tsx @@ -31,6 +31,7 @@ export const useConsentRequestModal = () => { setIsOpen(false); setCurrentView(ModalViews.ConsentRequest); setConsentRequestId(""); + router.push("/", undefined, { shallow: true }); }; return { diff --git a/clients/privacy-center/components/modals/privacy-request-modal/PrivacyRequestForm.tsx b/clients/privacy-center/components/modals/privacy-request-modal/PrivacyRequestForm.tsx index f58dc19356e..c9755f7b178 100644 --- a/clients/privacy-center/components/modals/privacy-request-modal/PrivacyRequestForm.tsx +++ b/clients/privacy-center/components/modals/privacy-request-modal/PrivacyRequestForm.tsx @@ -308,7 +308,7 @@ const PrivacyRequestForm: React.FC = ({ diff --git a/clients/privacy-center/config/config.json b/clients/privacy-center/config/config.json index d171f8c84d7..c11e68f965f 100644 --- a/clients/privacy-center/config/config.json +++ b/clients/privacy-center/config/config.json @@ -4,6 +4,7 @@ "description_subtext": [], "addendum": [], "logo_path": "/logo.svg", + "favicon_path": "/favicon.ico", "actions": [ { "policy_key": "default_access_policy", @@ -13,7 +14,9 @@ "description_subtext": [], "identity_inputs": { "email": "required" - } + }, + "confirmButtonText": "Continue", + "cancelButtonText": "Cancel" }, { "policy_key": "default_erasure_policy", @@ -23,7 +26,9 @@ "description_subtext": [], "identity_inputs": { "email": "required" - } + }, + "confirmButtonText": "Continue", + "cancelButtonText": "Cancel" } ], "includeConsent": true, @@ -37,7 +42,10 @@ "identity_inputs": { "email": "optional" }, - "title": "Manage your consent" + "title": "Manage your consent", + "modalTitle": "Manage your consent", + "confirmButtonText": "Continue", + "cancelButtonText": "Cancel" }, "page": { "consentOptions": [ diff --git a/clients/privacy-center/cypress/e2e/consent.cy.ts b/clients/privacy-center/cypress/e2e/consent.cy.ts index 79e9136b74c..f4cf0f104dd 100644 --- a/clients/privacy-center/cypress/e2e/consent.cy.ts +++ b/clients/privacy-center/cypress/e2e/consent.cy.ts @@ -3,6 +3,55 @@ import { GpcStatus } from "~/features/consent/types"; import { ConsentPreferencesWithVerificationCode } from "~/types/api"; import { API_URL } from "../support/constants"; +describe("Consent modal deeplink", () => { + beforeEach(() => { + cy.visit("/?showConsentModal=true"); + cy.loadConfigFixture("config/config_consent.json").as("config"); + cy.intercept("POST", `${API_URL}/consent-request`, { + body: { + consent_request_id: "consent-request-id", + }, + }).as("postConsentRequest"); + cy.intercept( + "POST", + `${API_URL}/consent-request/consent-request-id/verify`, + { fixture: "consent/verify" } + ).as("postConsentRequestVerify"); + }); + + it("opens the consent modal", () => { + // This test does the same as below, without clicking the card + cy.getByTestId("consent-request-form").should("be.visible"); + cy.getByTestId("consent-request-form").within(() => { + cy.get("input#email").type("test@example.com"); + cy.get("button").contains("Continue").click(); + }); + cy.wait("@postConsentRequest"); + + cy.getByTestId("verification-form").within(() => { + cy.get("input").type("112358"); + cy.get("button").contains("Submit code").click(); + }); + cy.wait("@postConsentRequestVerify"); + + cy.location("pathname").should("eq", "/consent"); + cy.getByTestId("consent"); + }); + + it("closes the modal and purges the query param", () => { + cy.getByTestId("consent-request-form").should("be.visible"); + + cy.getByTestId("consent-request-form").within(() => { + cy.get("input#email").type("test@example.com"); + cy.get("button").contains("Cancel").click(); + }); + + // assert the modal is closed and query_param removed + cy.url().should("not.contain", "showConsentModal=true"); + cy.getByTestId("consent-request-form").should("not.exist"); + }); +}); + describe("Consent settings", () => { beforeEach(() => { cy.visit("/"); diff --git a/clients/privacy-center/pages/index.tsx b/clients/privacy-center/pages/index.tsx index 88160be9274..016be182b47 100644 --- a/clients/privacy-center/pages/index.tsx +++ b/clients/privacy-center/pages/index.tsx @@ -1,6 +1,7 @@ import { Flex, Heading, Text, Stack, useToast } from "@fidesui/react"; import React, { useEffect, useState } from "react"; import type { NextPage } from "next"; +import { useRouter } from "next/router"; import { ConfigErrorToastOptions } from "~/common/toast-options"; import { @@ -17,6 +18,7 @@ import ConsentCard from "~/components/ConsentCard"; import { useConfig } from "~/features/common/config.slice"; const Home: NextPage = () => { + const router = useRouter(); const config = useConfig(); const [isVerificationRequired, setIsVerificationRequired] = useState(false); @@ -34,7 +36,7 @@ const Home: NextPage = () => { } = usePrivacyRequestModal(); const { - isOpen: isConsentModalOpen, + isOpen: isConsentModalOpenConst, onOpen: onConsentModalOpen, onClose: onConsentModalClose, currentView: currentConsentModalView, @@ -43,7 +45,7 @@ const Home: NextPage = () => { setConsentRequestId, successHandler: consentModalSuccessHandler, } = useConsentRequestModal(); - + let isConsentModalOpen = isConsentModalOpenConst; const getIdVerificationConfigQuery = useGetIdVerificationConfigQuery(); useEffect(() => { @@ -89,6 +91,11 @@ const Home: NextPage = () => { onOpen={onConsentModalOpen} /> ); + if (router.query?.showConsentModal === "true") { + // manually override whether to show the consent modal given + // the query param `showConsentModal` + isConsentModalOpen = true; + } } return ( diff --git a/clients/privacy-center/types/config.ts b/clients/privacy-center/types/config.ts index c0443749e86..0f4810ef96c 100644 --- a/clients/privacy-center/types/config.ts +++ b/clients/privacy-center/types/config.ts @@ -27,6 +27,7 @@ export type Config = { server_url_development?: string; server_url_production?: string; logo_path: string; + favicon_path?: string; actions: PrivacyRequestOption[]; includeConsent?: boolean; consent?: ConsentConfig; @@ -45,9 +46,12 @@ export type ConsentConfig = { button: { description: string; description_subtext?: string[]; + confirmButtonText?: string; + cancelButtonText?: string; icon_path: string; identity_inputs?: IdentityInputs; title: string; + modalTitle?: string; }; page: { consentOptions: ConfigConsentOption[]; @@ -64,6 +68,8 @@ export type PrivacyRequestOption = { title: string; description: string; description_subtext?: string[]; + confirmButtonText?: string; + cancelButtonText?: string; identity_inputs?: IdentityInputs; }; diff --git a/src/fides/data/sample_project/privacy_center/config/config.json b/src/fides/data/sample_project/privacy_center/config/config.json index 16d449a0a1b..2e3e9e2b35c 100644 --- a/src/fides/data/sample_project/privacy_center/config/config.json +++ b/src/fides/data/sample_project/privacy_center/config/config.json @@ -86,4 +86,4 @@ "title": "Manage your consent" } } -} \ No newline at end of file +}