feat(dashboards): add WidgetCard shell and dashboard widget UI glue (7/11)#60523
Merged
Conversation
This was referenced May 28, 2026
Closed
Member
Author
This was referenced May 28, 2026
Closed
Closed
07b7d6a to
fa6e73b
Compare
2049950 to
7b6c3c5
Compare
58653c9 to
400ebc6
Compare
400ebc6 to
067652e
Compare
Contributor
Prompt To Fix All With AIFix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
frontend/src/scenes/dashboard/dashboardLogic.tsx:1833-1837
**Public dashboard insights stop refreshing after this change**
Adding `DashboardPlacement.Public` to the exclusion in `handleDashboardLoadComplete` prevents `refreshDashboardItems` from ever being called on shared/public dashboards. `refreshDashboardItems` is the mechanism that fetches fresh data for stale insight tiles (it filters using `cache_target_age`). Skipping it entirely means insights on public dashboards will silently stall at whatever cached state they were in when the dashboard was loaded, even when their cache has expired.
The underlying motivation — avoiding `refreshDashboardWidgets` on public views — is already enforced: `refreshDashboardWidgets` returns early when `placement === DashboardPlacement.Public`. The `Public` guard here is redundant for widgets but harmful for insight tiles. Moving the `Public` exclusion to the widget-specific code block inside `refreshDashboardItems` (or simply removing it from `handleDashboardLoadComplete`) would preserve the original insight-refresh behaviour for public dashboards.
### Issue 2 of 3
products/dashboards/frontend/components/DashboardWidgetItem/DashboardWidgetItem.tsx:302-309
`userHasWidgetProductAccess` is missing an exhaustive `never` guard at the end of its switch, unlike the equivalent pattern used in `widgetAvailability.ts`. When `DashboardWidgetProductAccess` gains a new member (e.g. `'surveys'`), TypeScript will silently compile the function with an implicit `undefined` return instead of failing at compile time. Adding the guard aligns it with the existing safety pattern and catches omissions automatically.
```suggestion
switch (productAccess) {
// New gated widget types: add a case here — CONTRIBUTING.md
case 'error_tracking':
return userHasAccess(AccessControlResourceType.ErrorTracking, AccessControlLevel.Viewer)
case 'session_recording':
return userHasAccess(AccessControlResourceType.SessionRecording, AccessControlLevel.Viewer)
default: {
const _exhaustive: never = productAccess
return _exhaustive
}
}
}
```
### Issue 3 of 3
products/dashboards/frontend/widget_types/widgetAvailability.test.ts:14-42
The `session_replay_enabled` requirement is declared alongside `exception_autocapture` but has no test coverage. A parameterised table would cover both requirements without repeating the setup, and would automatically catch any future addition to `WidgetAvailabilityRequirementId`.
```suggestion
it.each([
{
requirement: 'exception_autocapture' as const,
teamPropKey: 'autocapture_exceptions_opt_in' as const,
},
{
requirement: 'session_replay_enabled' as const,
teamPropKey: 'session_recording_opt_in' as const,
},
])('evaluates $requirement requirement', ({ requirement, teamPropKey }) => {
expect(
isWidgetAvailabilityRequirementMet(requirement, {
...MOCK_DEFAULT_TEAM,
[teamPropKey]: false,
})
).toBe(false)
expect(
isWidgetAvailabilityRequirementMet(requirement, {
...MOCK_DEFAULT_TEAM,
[teamPropKey]: true,
})
).toBe(true)
})
```
Reviews (1): Last reviewed commit: "feat(dashboards): add WidgetCard shell a..." | Re-trigger Greptile |
Use satisfies Record for widget product access compile-time checks, replace ProductIntroduction tailwind overrides with SCSS, simplify utils, tighten date range schema validation, and remove unused modal sections file. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
bef55af to
73190dc
Compare
Use generated dashboardsPartialUpdate, fix project-scoped View href expectation, and scope dashboardLogic test mocks with spies. Co-authored-by: Cursor <cursoragent@cursor.com>
…ds_add_widgetcard_shell
Bump products/dashboards posthog-js to catalog 1.378.0 and dedupe jest snapshot entries so frozen install and build:products pass CI. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
3fa4158 to
69db79a
Compare
16 updated Run: 9cedf542-a10f-427d-9b3e-4c6b1f6fdae4 Co-authored-by: MattPua <3376526+MattPua@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Member
Author
This was referenced Jun 3, 2026
MattPua
added a commit
that referenced
this pull request
Jun 3, 2026
## Problem Dashboards need embeddable product widgets beyond insights. Error tracking issues are the first list-style widget: a ranked table of top issues that fits the WidgetCard shell and establishes patterns later widgets (session replay, etc.) reuse. This PR is **8/11** in the dashboard widgets Graphite stack (WidgetCard shell #60523 is merged). ## Changes - **`error_tracking_list`** **widget** — catalog/registry entry, backend runner, config schema, preview, and full frontend tile (component, edit modal, stories, tests) - **`ErrorTrackingIssueList`** **extraction** — shared list component + skeleton for dashboard embedding without pulling in the full error tracking scene - **Shared edit-modal infrastructure** — `editWidgetModalBuilders`, tile/filter section components, `buildWidgetTileMetadataPatch`, and kea patterns both widget types inherit - **Shared dashboard tile orchestration** (used by all widget types on this branch): - Single PATCH save via `updateWidgetTile` / `updateDashboardWidgetTile` (config + name + description) - `useAsyncActions` so edit modals await save before closing - Refresh widget data after duplicate - Unknown widget types: header + ⋯ menu stay usable; body-only `ErrorBoundary` (no fetch-error refresh UI) - Catalog setup prompts use stacked vertical `WidgetCardProductIntroduction` - New widgets append to the bottom row of the layout (not lowest-segment gap fill) - Server analytics: `dashboard widget added` alongside existing `dashboard tile added` - **Catalog header defaults** — `getDashboardWidgetCatalogEntry` / `tryGetDashboardWidgetCatalogEntry` resolve layout and header metadata - **Review follow-ups** — validation wiring, table layout/sparkline fixes, kea typegen-safe modal logic, Storybook/VR baseline updates ## How did you test this code? - Agent: Jest for error tracking widget, edit modal, registry, add-widget modal, config validation, `DashboardWidgetItem`, and `dashboardLogic` widget tile updates - Agent: backend `test_dashboard_widgets`, `test_run_widgets`, and `test_widget_layouts` - Feature remains behind the dashboard widgets feature flag 👉 _Stay up-to-date with_ [_PostHog coding conventions_](https://posthog.com/docs/contribute/coding-conventions) _for a smoother review._ ## Automatic notifications - [ ] Publish to changelog? - [x] Alert Sales and Marketing teams? ## Docs update Add the `skip-inkeep-docs` label — no user-facing docs yet (feature flagged). Agent skill/docs land in #60516. ## 🤖 Agent context - Split from former monolithic PR #60495; WidgetCard glue merged in #60523; session replay lands in #60496 - Several shared dashboard fixes landed here because they touch `dashboardLogic`, `DashboardWidgetItem`, and backend tile create paths used by every widget type - Cursor agent assisted on review fixes, CI resolution, and post-ship UX polish (save flow, error boundaries, layout placement)
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
Dashboard widgets need shared frontend shell components before any concrete widget type lands. This PR adds the WidgetCard compound component, add-widget modal, catalog/registry scaffolding, and dashboard scene glue with an empty widget catalog.
This PR is 7/11 in the dashboard widgets Graphite stack.
Depends on: PR 6 (#60494 — widget registry and run_widgets API)
Changes
WidgetCardcompound components,DashboardWidgetItem, add-widget modal, widget type pickerDASHBOARD_WIDGET_CATALOGandDASHBOARD_WIDGET_REGISTRY(concrete types in follow-up PRs)dashboardLogic,DashboardItems,widgetFetchUtils, empty-dashboard UXCardTopHeadingRow,DashboardTileRefreshDataButtonHow did you test this code?
👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Publish to changelog?
no — still feature flagged
Docs update
skip-inkeep-docs
🤖 Agent context