feat: integrate nightly survey system into app#8480
feat: integrate nightly survey system into app#8480christian-byrne wants to merge 2 commits intomainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a lazy-loaded NightlySurveyController rendered from the sidebar when nightly mode is active, a new NightlySurveyController component that renders popovers for enabled surveys, and a useSurveyFeatureTracking composable with unit tests for tracking survey feature usage. Changes
Sequence Diagram(s)sequenceDiagram
participant Sidebar as SideToolbar
participant Controller as NightlySurveyController
participant Registry as SurveyRegistry / getEnabledSurveys
participant Popover as NightlySurveyPopover
participant Tracker as useSurveyFeatureTracking
Sidebar->>Controller: lazy-load when isNightly && !isCloud && !isDesktop
Controller->>Registry: getEnabledSurveys()
Registry-->>Controller: list of enabled survey configs
Controller->>Popover: render popover for each config
Popover->>Tracker: call trackFeatureUsed(featureId) on interaction
Tracker->>Tracker: delegate to useFeatureUsageTracker or no-op
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🎭 Playwright: ✅ 555 passed, 0 failed · 2 flaky📊 Browser Reports
|
🎨 Storybook: ✅ Built — View Storybook |
19a90e5 to
1b8b0fa
Compare
1b8b0fa to
e25b7b8
Compare
## Summary Adds NightlySurveyPopover component that displays a Typeform survey to eligible nightly users after a configurable delay. ## Changes - **What**: Vue component that uses `useSurveyEligibility` to show/hide a survey popover with accept, dismiss, and opt-out actions. Loads Typeform embed script dynamically with HTTPS and deduplication. ## Review Focus - Typeform script injection security (HTTPS-only, load-once guard, typeformId alphanumeric validation) - Timeout lifecycle (clears pending timeout when eligibility changes) ## Part of Nightly Survey System This is part 4 of a stacked PR chain: 1. ✅ feat/feature-usage-tracker - useFeatureUsageTracker (merged in #8189) 2. ✅ feat/survey-eligibility - useSurveyEligibility (#8189, merged) 3. ✅ feat/survey-config - surveyRegistry.ts (#8355, merged) 4. **feat/survey-popover** - NightlySurveyPopover.vue (this PR) 5. feat/survey-integration - NightlySurveyController.vue (#8480) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9083-feat-add-NightlySurveyPopover-component-for-feature-surveys-30f6d73d365081d1beb2f92555a4b2f4) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com>
19e4751 to
7cfa2e3
Compare
📦 Bundle: 4.49 MB gzip 🔴 +2.86 kBDetailsSummary
Category Glance App Entry Points — 17.7 kB (baseline 17.7 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 913 kB (baseline 913 kB) • 🔴 +358 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 72.1 kB (baseline 72.1 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 10 added / 10 removed Panels & Settings — 436 kB (baseline 436 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 10 added / 10 removed User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 6 added / 6 removed Editors & Dialogs — 736 B (baseline 736 B) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 1 added / 1 removed UI Components — 47 kB (baseline 47 kB) • ⚪ 0 BReusable component library chunks
Status: 7 added / 7 removed Data & Services — 2.73 MB (baseline 2.73 MB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 13 added / 13 removed Utilities & Hooks — 55.5 kB (baseline 55.5 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 11 added / 11 removed Vendor & Third-Party — 8.86 MB (baseline 8.86 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 7.92 MB (baseline 7.91 MB) • 🔴 +8.92 kBBundles that do not match a named category
Status: 62 added / 61 removed |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/sidebar/SideToolbar.vue`:
- Line 54: The async component NightlySurveyController is being rendered
directly; wrap its usage in a Vue <Suspense> so the defineAsyncComponent
resolves correctly — replace the direct <component :is="NightlySurveyController"
v-if="NightlySurveyController" /> with a <Suspense> that conditionally renders
the async component in the default slot (and provide a simple fallback in the
fallback slot or via template `#fallback`) to satisfy async-component guidelines;
ensure you still check NightlySurveyController (or guard in setup) so the
Suspense only mounts when the async is available.
In `@src/platform/surveys/useSurveyFeatureTracking.test.ts`:
- Around line 3-15: The tests use a module-level mutable object
mockSurveyConfigs and a vi.mock that reads it; replace this pattern by hoisting
a mock function with vi.hoisted and using that in the mock implementation for
getSurveyConfig, then reset/configure that hoisted mock per test instead of
mutating mockSurveyConfigs. Concretely, create a hoisted const (e.g., const
hoistedGetSurveyConfig = vi.hoisted(() => vi.fn())) and have
vi.mock('./surveyRegistry', () => ({ getSurveyConfig: hoistedGetSurveyConfig }))
so the mock is created before module init; in beforeEach call
hoistedGetSurveyConfig.mockReset() and set
hoistedGetSurveyConfig.mockImplementationOnce(...) or mockReturnValue(...) for
each test to control returned { enabled } values rather than clearing a shared
object.
7cfa2e3 to
9719333
Compare
⚡ Performance Report
Raw data{
"timestamp": "2026-03-05T00:19:54.560Z",
"gitSha": "0f70f92d04143afb385f3c41ae67a2310687d4a3",
"branch": "feat/survey-integration",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2057.7799999999797,
"styleRecalcs": 125,
"styleRecalcDurationMs": 19.258999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 411.87300000000005,
"heapDeltaBytes": -1941600
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1795.548999999994,
"styleRecalcs": 163,
"styleRecalcDurationMs": 45.966,
"layouts": 12,
"layoutDurationMs": 3.133,
"taskDurationMs": 760.972,
"heapDeltaBytes": -2555492
},
{
"name": "dom-widget-clipping",
"durationMs": 548.2139999999731,
"styleRecalcs": 40,
"styleRecalcDurationMs": 12.551,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 349.22800000000007,
"heapDeltaBytes": 8144348
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 632.0900000000051,
"styleRecalcs": 75,
"styleRecalcDurationMs": 15.683999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 428.568,
"heapDeltaBytes": -9920704
},
{
"name": "subgraph-idle",
"durationMs": 2008.088999999984,
"styleRecalcs": 123,
"styleRecalcDurationMs": 23.416999999999998,
"layouts": 1,
"layoutDurationMs": 0.25599999999999995,
"taskDurationMs": 382.38300000000004,
"heapDeltaBytes": -2578340
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1738.833999999997,
"styleRecalcs": 157,
"styleRecalcDurationMs": 49.719,
"layouts": 16,
"layoutDurationMs": 4.034,
"taskDurationMs": 729.485,
"heapDeltaBytes": -3810900
}
]
} |
Myestery
left a comment
There was a problem hiding this comment.
Should we go with config.enabled!=false or !!config.enabled?
| export function useSurveyFeatureTracking(featureId: string) { | ||
| const config = getSurveyConfig(featureId) | ||
|
|
||
| if (!config?.enabled) { |
There was a problem hiding this comment.
useSurveyFeatureTracking treats enabled as required-true, while the rest of the survey system defaults missing enabled to true, so a survey without enabled set can render and pass eligibility but won’t record usage, potentially never reaching its threshold.
see
Summary
Wires the nightly survey system into the app by adding a controller component and a convenience composable for feature-site usage tracking.
Changes
Review Focus
Part of Nightly Survey System
This is part 5 of a stacked PR chain: