Skip to content

ENG-2920: Allow for showing multiple links in privacy center + show them below forms too#7612

Merged
nreyes-dev merged 13 commits intomainfrom
nreyes/eng-2920
Mar 13, 2026
Merged

ENG-2920: Allow for showing multiple links in privacy center + show them below forms too#7612
nreyes-dev merged 13 commits intomainfrom
nreyes/eng-2920

Conversation

@nreyes-dev
Copy link
Copy Markdown
Contributor

@nreyes-dev nreyes-dev commented Mar 10, 2026

Ticket ENG-2920

Description Of Changes

The Privacy Center previously supported only a single configurable link (Privacy Policy) rendered at the bottom of the home page. This adds a new links array field to the config schema, allowing any number of named links to be displayed. Links now also appear on privacy request form pages, where they were previously absent. The legacy privacy_policy_url / privacy_policy_url_text fields continue to work unchanged, but are marked as deprecated.

Code Changes

  • Added PrivacyCenterLink schema (Python + TypeScript) and links: List[PrivacyCenterLink] = [] field to PrivacyCenterConfig
  • Added URL scheme validation (http/https only) on PrivacyCenterLink.url
  • Deprecated privacy_policy_url / privacy_policy_url_text with backwards-compatible fallback via getEffectivePrivacyCenterLinks helper
  • Updated HomePage.tsx to render all links vertically
  • Updated AuthFormLayout.tsx to render links below the form card (new — previously no links appeared on form pages); links open in a new tab with rel="noopener noreferrer"
  • Added unit tests for getEffectivePrivacyCenterLinks

Steps to Confirm

  1. Add "links": [{"label": "Privacy Policy", "url": "https://example.com"}, {"label": "Terms of Service", "url": "https://example.com/tos"}] to config.json and verify both links render on the home page and on a privacy request form page
  2. Remove links and use the legacy privacy_policy_url / privacy_policy_url_text fields — verify the single link still renders on both pages

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

Summary by CodeRabbit

  • New Features

    • Privacy Center footer now supports multiple configurable links on both the home and form pages.
  • Deprecations

    • Legacy single privacy policy URL/text settings are deprecated; prefer the new multi-link configuration (legacy fields kept for compatibility).
  • Tests

    • Added unit tests covering multi-link precedence and fallback behavior.
  • Changelog

    • Added an entry documenting the multi-link feature.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Mar 13, 2026 1:11pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 13, 2026 1:11pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds typed multi-link support for the Privacy Center: new PrivacyCenterLink type, a links field on PrivacyCenterConfig (legacy privacy_policy_* fields deprecated), a getEffectivePrivacyCenterLinks utility, updated example config, and components updated to render multiple footer links.

Changes

Cohort / File(s) Summary
Changelog
changelog/7612-privacy-center-multi-link.yaml
New changelog entry documenting multi-link Privacy Center support (PR #7612).
New Link Type & Config fields
clients/privacy-center/types/api/models/PrivacyCenterLink.ts, clients/admin-ui/src/types/api/models/PrivacyCenterLink.ts, clients/privacy-center/types/config.ts
Add PrivacyCenterLink type ({ label: string; url: string }) and links?: PrivacyCenterLink[]; add deprecation notes for legacy privacy_policy_* fields.
API Index Exports
clients/admin-ui/src/types/api/index.ts, clients/privacy-center/types/api/index.ts
Export the new PrivacyCenterLink type from API index files.
PrivacyCenterConfig schema
clients/admin-ui/src/types/api/models/PrivacyCenterConfig.ts, clients/privacy-center/types/api/models/PrivacyCenterConfig.ts, src/fides/api/schemas/privacy_center_config.py
Add links field to PrivacyCenterConfig schema/types; retain and document deprecation of privacy_policy_url and privacy_policy_url_text.
Config example & util
clients/privacy-center/config/config.json, clients/privacy-center/common/config-links.ts
Replace legacy fields in example with a links array; add getEffectivePrivacyCenterLinks to prefer links and synthesize a single fallback from deprecated fields.
UI components & tests
clients/privacy-center/components/HomePage.tsx, clients/privacy-center/components/common/AuthFormLayout.tsx, clients/privacy-center/__tests__/common/config-links.test.ts
Components use getEffectivePrivacyCenterLinks(config) and render multiple footer links; add unit tests covering precedence and fallback logic.

Sequence Diagram(s)

sequenceDiagram
  participant Config as Config (runtime / config.json)
  participant Util as getEffectivePrivacyCenterLinks
  participant Component as HomePage / AuthFormLayout
  participant Browser as Rendered UI

  Config->>Component: provide config
  Component->>Util: getEffectivePrivacyCenterLinks(config)
  Util-->>Component: PrivacyCenterLink[] (links or synthesized fallback)
  Component->>Browser: render each link (label → url)
  Browser-->>Component: user clicks link (external navigation)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through configs, old crumbs and new,

I paired each label with a URL true.
Footer links lined up, tidy and bright,
Fallbacks snugged in, tucked out of sight.
I twitched my whiskers — the links hop right!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for multiple configurable links in the Privacy Center and displaying them on form pages.
Description check ✅ Passed The pull request description is comprehensive and follows the repository template with all major sections completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nreyes/eng-2920

Comment @coderabbitai help to get the list of available commands and usage tips.

@nreyes-dev nreyes-dev marked this pull request as ready for review March 10, 2026 17:58
@nreyes-dev nreyes-dev requested review from a team as code owners March 10, 2026 17:58
@nreyes-dev nreyes-dev requested review from jpople and vcruces and removed request for a team March 10, 2026 17:58
@greptile-apps

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
clients/privacy-center/common/config-links.ts (1)

3-7: Consider using PrivacyCenterLink directly in the type definition.

The links field uses an inline type Array<{ label: string; url: string }> that duplicates the shape of PrivacyCenterLink. Using the imported type directly would improve consistency and reduce maintenance burden if PrivacyCenterLink evolves.

♻️ Suggested refactor
 import { PrivacyCenterLink } from "~/types/config";
 
 type ConfigWithLinks = {
-  links?: Array<{ label: string; url: string }>;
+  links?: PrivacyCenterLink[];
   privacy_policy_url?: string | null;
   privacy_policy_url_text?: string | null;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/privacy-center/common/config-links.ts` around lines 3 - 7, Replace
the inline link shape in the ConfigWithLinks type with the existing
PrivacyCenterLink type to avoid duplication: change links?: Array<{ label:
string; url: string }>; to use PrivacyCenterLink (e.g., links?:
PrivacyCenterLink[] or Array<PrivacyCenterLink>), ensuring you import or
reference the existing PrivacyCenterLink type and update any related usage to
match the new type name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@clients/privacy-center/common/config-links.ts`:
- Around line 3-7: Replace the inline link shape in the ConfigWithLinks type
with the existing PrivacyCenterLink type to avoid duplication: change links?:
Array<{ label: string; url: string }>; to use PrivacyCenterLink (e.g., links?:
PrivacyCenterLink[] or Array<PrivacyCenterLink>), ensuring you import or
reference the existing PrivacyCenterLink type and update any related usage to
match the new type name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c915a08-b200-4c72-9b60-2029b673e0a1

📥 Commits

Reviewing files that changed from the base of the PR and between d561b39 and 7da1fcd.

📒 Files selected for processing (2)
  • clients/privacy-center/common/config-links.ts
  • clients/privacy-center/config/config.json

@nreyes-dev
Copy link
Copy Markdown
Contributor Author

@greptileai review

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
clients/privacy-center/__tests__/common/config-links.test.ts (1)

3-52: Well-structured test suite with good coverage of the main logic paths.

The tests comprehensively cover:

  • Non-empty links array returns as-is
  • Fallback to deprecated fields when links is absent
  • Precedence of links over deprecated fields
  • Empty array handling with fallback behavior

Test data appropriately uses RFC 2606 reserved domain (example.com) and generic labels.

Consider adding tests for partial deprecated fields (only privacy_policy_url or only privacy_policy_url_text present) to explicitly document that incomplete deprecated config returns an empty array:

💡 Optional: Add edge case tests for partial deprecated fields
+  it("returns empty array when only privacy_policy_url is present", () => {
+    const result = getEffectivePrivacyCenterLinks({
+      privacy_policy_url: "https://example.com/privacy",
+    });
+    expect(result).toEqual([]);
+  });
+
+  it("returns empty array when only privacy_policy_url_text is present", () => {
+    const result = getEffectivePrivacyCenterLinks({
+      privacy_policy_url_text: "Privacy Policy",
+    });
+    expect(result).toEqual([]);
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/privacy-center/__tests__/common/config-links.test.ts` around lines 3
- 52, Add explicit tests to cover partial deprecated-field cases for
getEffectivePrivacyCenterLinks: add one test where only privacy_policy_url is
provided and assert it returns [], and another where only
privacy_policy_url_text is provided and assert it returns []; place them
alongside the existing cases in the describe("getEffectivePrivacyCenterLinks")
suite and give clear it(...) names like "returns empty array when only
privacy_policy_url is present" and "returns empty array when only
privacy_policy_url_text is present" so the behavior for incomplete deprecated
config is documented.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@clients/privacy-center/__tests__/common/config-links.test.ts`:
- Around line 3-52: Add explicit tests to cover partial deprecated-field cases
for getEffectivePrivacyCenterLinks: add one test where only privacy_policy_url
is provided and assert it returns [], and another where only
privacy_policy_url_text is provided and assert it returns []; place them
alongside the existing cases in the describe("getEffectivePrivacyCenterLinks")
suite and give clear it(...) names like "returns empty array when only
privacy_policy_url is present" and "returns empty array when only
privacy_policy_url_text is present" so the behavior for incomplete deprecated
config is documented.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5142cad7-91ea-4768-8fc6-48db36d3e499

📥 Commits

Reviewing files that changed from the base of the PR and between 81a2e4f and ec8840f.

📒 Files selected for processing (3)
  • clients/privacy-center/__tests__/common/config-links.test.ts
  • clients/privacy-center/common/config-links.ts
  • src/fides/api/schemas/privacy_center_config.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • clients/privacy-center/common/config-links.ts
  • src/fides/api/schemas/privacy_center_config.py

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/privacy-center/components/common/AuthFormLayout.tsx`:
- Around line 33-34: AuthFormLayout currently calls
getEffectivePrivacyCenterLinks(config) without ensuring config is non-null,
which can throw during initial renders; modify AuthFormLayout so you only
compute policyLinks when config exists (e.g., guard useConfig() result before
calling getEffectivePrivacyCenterLinks or default policyLinks to an empty
array). Locate the useConfig() call and the policyLinks variable in
AuthFormLayout and change the logic to: const config = useConfig(); const
policyLinks = config ? getEffectivePrivacyCenterLinks(config) : []; (or
equivalent optional chaining/guard) so the footer rendering safely omits links
when config is not yet available.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be468602-2718-41ef-8ffa-eefd93ed65ba

📥 Commits

Reviewing files that changed from the base of the PR and between ec8840f and 85a12b4.

📒 Files selected for processing (2)
  • clients/privacy-center/components/HomePage.tsx
  • clients/privacy-center/components/common/AuthFormLayout.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • clients/privacy-center/components/HomePage.tsx

@vcruces vcruces removed their request for review March 11, 2026 15:32
Copy link
Copy Markdown
Contributor

@jpople jpople left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, looking good to me!

@nreyes-dev nreyes-dev enabled auto-merge March 11, 2026 18:37
@nreyes-dev nreyes-dev disabled auto-merge March 11, 2026 18:37
@nreyes-dev nreyes-dev added this pull request to the merge queue Mar 13, 2026
Merged via the queue into main with commit 9de3a2d Mar 13, 2026
61 checks passed
@nreyes-dev nreyes-dev deleted the nreyes/eng-2920 branch March 13, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants