ENG-3100: Seed Data developer UI, DashboardSnapshot model, and dashboard polish#7737
ENG-3100: Seed Data developer UI, DashboardSnapshot model, and dashboard polish#7737galvana wants to merge 12 commits intofeat/pbac-ui-managementfrom
Conversation
Add a Seed Data page under the Developer nav (dev-only) that lets users select and trigger seed scenarios via the seed API. Includes RTK Query slice with status polling and cache tag invalidation mapped per seed task. Currently supports the PBAC scenario. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
Greptile SummaryThis PR adds a developer-only "Seed Data" page under the The one concrete bug to fix before merging is in Additional minor items:
Confidence Score: 4/5
Important Files Changed
Reviews (1): Last reviewed commit: "feat: add Seed Data developer page (ENG-..." | Re-trigger Greptile |
| try { | ||
| const result = await triggerSeed({ tasks }).unwrap(); | ||
| setExecutionId(result.execution_id); | ||
| } catch { | ||
| // Error is shown via the status polling | ||
| } |
There was a problem hiding this comment.
Silent error swallowing leaves no user feedback on trigger failure
When triggerSeed(...).unwrap() throws (e.g. 500, network error, 401), setExecutionId is never called, so polling never starts and statusData remains undefined. The comment "Error is shown via the status polling" only holds once an executionId has been set — it does not apply to this failure path. The user will see the button return to idle with no indication that anything went wrong.
Consider showing an error toast or inline Alert in the catch block:
| try { | |
| const result = await triggerSeed({ tasks }).unwrap(); | |
| setExecutionId(result.execution_id); | |
| } catch { | |
| // Error is shown via the status polling | |
| } | |
| try { | |
| const result = await triggerSeed({ tasks }).unwrap(); | |
| setExecutionId(result.execution_id); | |
| } catch (error) { | |
| // triggerSeed failed before an execution was created; surface the error directly | |
| const errorMessage = | |
| (error as { data?: { detail?: string } })?.data?.detail ?? | |
| "Failed to start seed. Please try again."; | |
| // Replace with your preferred error notification mechanism | |
| console.error("Seed trigger failed:", errorMessage); | |
| } |
There was a problem hiding this comment.
Addressed in b471019. Used RTK Query's isError state from the mutation hook to show an inline Alert when the trigger fails, rather than adding manual error state. This surfaces the failure to the user without needing an execution ID.
| const { data: statusData } = useGetSeedStatusQuery(executionId!, { | ||
| skip: !executionId, | ||
| pollingInterval: 2000, | ||
| }); |
There was a problem hiding this comment.
Development polling interval should be updated before merging
pollingInterval: 2000 (2 s) is a development-only value. Per the project's polling interval guidance, development values should be reviewed and updated before merging — even for dev-mode-only pages — to ensure intentional configuration. If a 2-second interval is the deliberate choice for this lightweight tool, add an explanatory comment so reviewers know it was considered.
| const { data: statusData } = useGetSeedStatusQuery(executionId!, { | |
| skip: !executionId, | |
| pollingInterval: 2000, | |
| }); | |
| const { data: statusData } = useGetSeedStatusQuery(executionId!, { | |
| skip: !executionId, | |
| // Seed tasks complete within seconds; 2 s polling is intentional for this dev-only tool. | |
| pollingInterval: 2000, | |
| }); |
Rule Used: Polling intervals for async operations should be s... (source)
Learnt From
ethyca/fides#6566
There was a problem hiding this comment.
Addressed in b471019. Added a clarifying comment that the 2s interval is intentional for this dev-only tool.
| const done = entries.filter( | ||
| (s) => | ||
| s.status === "complete" || s.status === "skipped" || s.status === "error", | ||
| ).length; |
There was a problem hiding this comment.
Single-character variable name
The parameter s should use a full descriptive name per the project's variable naming convention.
| const done = entries.filter( | |
| (s) => | |
| s.status === "complete" || s.status === "skipped" || s.status === "error", | |
| ).length; | |
| const done = entries.filter( | |
| (step) => | |
| step.status === "complete" || step.status === "skipped" || step.status === "error", | |
| ).length; |
Rule Used: Use full names for variables, not 1 to 2 character... (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Addressed in b471019. Renamed s to step.
| {showStatus ? ( | ||
| <div className="mt-4"> |
There was a problem hiding this comment.
Prefer component-library alternatives over bare
div
The <div className="mt-4"> wrapper is not purely a padding container — it groups the Progress bar, step list, and Alerts. Consider replacing it with a <Flex vertical gap="small"> or a <Space> component with a top margin, consistent with how the rest of the component uses Space and Flex for layout.
Rule Used: Avoid using div elements when possible. Use sema... (source)
Learnt From
ethyca/fides#6763
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Addressed in b471019. Replaced the bare div with <Flex vertical gap="small"> to stay consistent with the rest of the component.
4e0fe69 to
8b03868
Compare
- New DashboardSnapshot model with snapshot_date, metric_key, value columns - Unique constraint on (snapshot_date, metric_key) for daily snapshots - Alembic migration to create dashboardsnapshot table - Rename PostureCard title to "Governance posture" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add dashboard task to SeedTasksConfig interface - Add cache invalidation tags for dashboard seed task - Add "Dashboard (Landing Page)" scenario to seed data UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set explicit __tablename__ = "dashboard_snapshot" on model - Update migration table/index names to use dashboard_snapshot - Fix down_revision to chain after 190e4603ad38 (resolves multiple heads) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: - Add ACTIVE_REQUEST_STATUSES central definition to privacy_request schemas - Add is_overdue filter to PrivacyRequestFilter and query utils (filters to active statuses with due_date in the past) Frontend: - DSR status and briefing links filter by action_type and is_overdue via URL params (nuqs) instead of Redux dispatch - Sentence case card titles (DSR status, System coverage, SLA health) - Dynamic YAxis width in StackedBarChart based on longest label - Sort SLA bars alphabetically (Access before Erasure) - "X days overdue" badge for negative days instead of "-X days left" - Equal height System coverage and DSR status cards - ACTION_CTA supports is_overdue routing for DSR actions Tests: - ACTIVE_REQUEST_STATUSES membership and exclusion tests - PrivacyRequestFilter is_overdue field acceptance tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Surface trigger errors via RTK Query isError state and inline Alert - Add clarifying comment for 2s polling interval (dev-only tool) - Rename single-char variable `s` to `step` in computeProgress - Replace bare div with Flex component for semantic layout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add type: ignore for __tablename__ override in DashboardSnapshot - Use `as const` for STATUS_COLORS to satisfy Tag color prop types - Cast invalidatesTags return to satisfy RTK Query TagDescription type - Add is_overdue to PrivacyRequestParams interface - Add typeof guard before `in` operator for action_data.status Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add tests/unit/ to TEST_DIRECTORY_COVERAGE and pytest_misc_unit so the collect_tests check recognizes the new directory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ticket ENG-3100
Description Of Changes
Add the Seed Data developer page, DashboardSnapshot model for trend sparklines,
is_overdueprivacy request filter, and dashboard UI polish.Seed Data page:
/poc/seed-datawith scenario-based seeding UIDashboardSnapshot model:
dashboard_snapshottable with date+metric unique constraintPrivacy request
is_overduefilter:is_overdueboolean field onPrivacyRequestFilterschemadue_date < now() AND status IN active_statusesACTIVE_REQUEST_STATUSESfrozenset defined centrally in privacy request schemasnuqsURL param support in privacy request filter hookDashboard UI polish:
action_typeandis_overduevia URL paramsCode Changes
Backend:
src/fides/api/models/dashboard_snapshot.py— New DashboardSnapshot model withsnapshot_date,metric_key,valuecolumnssrc/fides/api/alembic/migrations/versions/xx_2026_03_24_*_add_dashboard_snapshot.py— Migration creatingdashboard_snapshottablesrc/fides/api/schemas/privacy_request.py— AddACTIVE_REQUEST_STATUSESfrozenset, addis_overduetoPrivacyRequestFiltersrc/fides/service/privacy_request/privacy_request_query_utils.py— Addis_overduefilter logicsrc/fides/api/db/base.py— Import DashboardSnapshot for Alembic discoveryFrontend:
clients/admin-ui/src/features/seed-data/seed-data.slice.ts— RTK Query slice with trigger/status endpoints and cache invalidation tagsclients/admin-ui/src/features/seed-data/SeedDataPanel.tsx— Seed scenario UI with Dashboard scenarioclients/admin-ui/src/features/privacy-requests/dashboard/hooks/usePrivacyRequestsFilters.ts— Addis_overdueURL param via nuqsclients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts— Addis_overdueto state andsetRequestOverdueactionclients/admin-ui/src/features/privacy-requests/dashboard/list-item/components/DaysLeft.tsx— Show "X days overdue" for negative valuesclients/admin-ui/src/features/dashboard/constants.ts— ACTION_CTA supportsis_overdueroutingclients/admin-ui/src/home/DSRStatusCard.tsx— Links filter by action_type and is_overdue via URL paramsclients/admin-ui/src/home/HomeDashboard.tsx— Equal height cards via flex containerclients/admin-ui/src/home/SystemCoverageCard.tsx— Sentence case titleclients/admin-ui/src/home/PostureCard.tsx— Rename to "Governance posture"clients/admin-ui/src/home/TrendCard.tsx— Rename to "Governance Posture"clients/fidesui/src/components/charts/StackedBarChart.tsx— Dynamic YAxis width, alphabetical sortTests:
tests/unit/test_active_request_statuses.py— Tests for ACTIVE_REQUEST_STATUSES membership and PrivacyRequestFilter is_overdue fieldSteps to Confirm
/poc/seed-dataPre-Merge Checklist
CHANGELOG.md🤖 Generated with Claude Code