Skip to content

ENG-3386: system-template badge + sectioned popover (demo/april)#7917

Merged
adamsachs merged 1 commit intodemo/aprilfrom
ENG-3386-fe-system-template-demo
Apr 14, 2026
Merged

ENG-3386: system-template badge + sectioned popover (demo/april)#7917
adamsachs merged 1 commit intodemo/aprilfrom
ENG-3386-fe-system-template-demo

Conversation

@adamsachs
Copy link
Copy Markdown
Contributor

@adamsachs adamsachs commented Apr 14, 2026

Ticket ENG-3386

Dependency: Requires the companion fidesplus PR to be merged first (provides system_template_key on CustomReportResponseMinimal).

Summary

Squashed backport of #7910 onto demo/april for early demo/testing.

  • Splits custom-reports popover into "Standard templates" and "Your reports" sections
  • System-owned templates display an info-coloured "Standard" tag with tooltip
  • Delete button hidden for system-template rows
  • Cypress tests for sectioning and delete suppression

Pre-Merge Checklist

  • All CI Pipelines Succeeded
  • Targeting demo/april

🤖 Generated with Claude Code

Companion frontend for OOTB regulatory reporting templates. Splits the
custom-reports popover into "Standard templates" and "Your reports"
sections. System-owned templates display a "Standard" tag with tooltip
and hide the delete button. Adds Cypress tests for both behaviours.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 14, 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 Apr 14, 2026 7:33pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Apr 14, 2026 7:33pm

Request Review

@adamsachs adamsachs marked this pull request as ready for review April 14, 2026 19:34
@adamsachs adamsachs requested a review from a team as a code owner April 14, 2026 19:34
@adamsachs adamsachs requested review from kruulik and removed request for a team April 14, 2026 19:34
@github-actions
Copy link
Copy Markdown

Title Lines Statements Branches Functions
admin-ui Coverage: 8%
6.08% (2660/43687) 5.2% (1288/24757) 4.19% (542/12932)
fides-js Coverage: 78%
78.98% (1962/2484) 65.55% (1214/1852) 72.57% (336/463)
privacy-center Coverage: 88%
85.93% (330/384) 81.1% (176/217) 78.87% (56/71)

@adamsachs adamsachs removed the request for review from kruulik April 14, 2026 19:38
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Code Review

Clean, well-scoped implementation. The sectioned popover approach is easy to follow, the useMemo split is correctly keyed on searchResults, and the delete-suppression logic (simply omitting the button for system rows) is minimal and correct.

Findings

One actionable issue (worth fixing before merge):

Search interaction with section headers (CustomReportTemplates.tsx:329) — The "Your reports" label is gated on systemReports.length > 0, but both systemReports and userReports come from the filtered searchResults. If a user types a query that hides all system templates but returns user reports, both the "Standard templates" section and the "Your reports" label vanish, leaving an unlabelled list. The fix is straightforward: derive hasSystemReports from the unfiltered customReportsList?.items and use that for header visibility while keeping the filtered arrays for row rendering.

Two observations (no action required, pre-existing or minor):

  • Empty search state (CustomReportTemplates.tsx:90) — When search matches nothing, isEmpty stays false and the Radio.Group renders empty with no feedback. Pre-existing behaviour; a follow-up "No results" state could address it.
  • JSDoc examples in generated types (CustomReportResponse.ts:26, CustomReportResponseMinimal.ts) — The inline 'ico', 'dpc', 'cnil' key examples will go stale as new templates are added. Low-friction fix: drop the examples or point to the backend source of truth.

What's well done

  • !!report.system_template_key correctly handles null, undefined, and empty string in one expression.
  • System template rows correctly omit the delete button without any extra permission check — they simply never enter the userReports array.
  • Cypress tests cover the two critical behaviours (sectioning and delete suppression) with a realistic fixture.
  • Type additions are additive (system_template_key?: string | null) and don't break existing consumers.

🔬 Codegraph: unavailable


💡 Write /code-review in a comment to re-run this review.

)}
{userReports.length > 0 && (
<>
{systemReports.length > 0 && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clients/admin-ui/src/features/common/custom-reports/CustomReportTemplates.tsx:329

The "Your reports" section header is conditionally rendered only when systemReports.length > 0. This works correctly today, but it creates a subtle interaction with search: if a user searches and their query happens to filter out all system templates (but returns user reports), the "Your reports" label will silently disappear because systemReports.length becomes 0 for the filtered set.

Since systemReports/userReports are derived from searchResults rather than the raw customReportsList?.items, this could produce a jarring UX: a user who starts typing sees the "Standard templates" section vanish and the "Your reports" label also vanish, leaving an unlabelled list. Consider basing the section-header visibility on whether system templates exist in the unfiltered list instead:

const hasSystemReports = (customReportsList?.items ?? []).some(
  (r) => !!r.system_template_key,
);

Then use hasSystemReports to decide whether to show section headers, while still using the filtered systemReports/userReports arrays for the rows themselves.

@@ -87,6 +89,14 @@ export const CustomReportTemplates = ({

const isEmpty = !isCustomReportsLoading && !customReportsList?.items?.length;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clients/admin-ui/src/features/common/custom-reports/CustomReportTemplates.tsx:90

isEmpty is derived from customReportsList?.items?.length (the unfiltered API response), but the rendered rows come from searchResultssystemReports/userReports. When a search term produces zero matches, isEmpty will remain false (because the raw list has items), so the Radio.Group renders but both systemReports and userReports are empty — resulting in blank space inside the popover with no "no results" feedback.

This is pre-existing behaviour (not introduced by this PR), but it's worth noting if you're already touching this area. A follow-up could add a "No results" empty state keyed off systemReports.length === 0 && userReports.length === 0 && !isEmpty.

*/
system_template_key?: string | null;
config: CustomReportConfig;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clients/admin-ui/src/types/api/models/CustomReportResponse.ts:26

The JSDoc comment here (system_template_key on CustomReportResponse) and the identical one on CustomReportResponseMinimal include inline examples of known key values ('ico', 'dpc', 'cnil'). If the backend adds new keys in future, these comments will silently go stale. Consider omitting the examples or referencing the backend enum by name instead, so the types file doesn't become a maintenance liability.

@adamsachs adamsachs merged commit 7581f24 into demo/april Apr 14, 2026
47 of 49 checks passed
@adamsachs adamsachs deleted the ENG-3386-fe-system-template-demo branch April 14, 2026 19:43
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.

1 participant