feat: update top-up verification flow - #14605
Conversation
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1781 passed, 0 failed · 1 flaky📊 Browser Reports
📦 Bundle: 8.21 MB gzip 🔴 +1.15 kBDetailsSummary
Category Glance App Entry Points — 3.64 kB (baseline 3.64 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.29 MB (baseline 1.29 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 1 unchanged Views & Navigation — 111 kB (baseline 111 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 12 added / 12 removed / 4 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 15 unchanged User & Accounts — 28.7 kB (baseline 28.7 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 6 added / 6 removed / 1 unchanged UI Components — 70 kB (baseline 70 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 removed / 9 unchanged Data & Services — 3.45 MB (baseline 3.45 MB) • 🔴 +5.49 kBStores, services, APIs, and repositories
Status: 14 added / 14 removed / 3 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 19 added / 19 removed / 17 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.8 MB (baseline 12.8 MB) • 🔴 +349 BBundles that do not match a named category
Status: 78 added / 78 removed / 203 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-08-03T20:06:02.488Z",
"gitSha": "bdfcb60d920f2000f292da466c428e7866ad87ba",
"branch": "jaewon/fe-1494-new-ux-for-topup",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2116.5709999999935,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.926000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 583.5300000000001,
"heapDeltaBytes": 5251808,
"heapUsedBytes": 73225640,
"domNodes": 16,
"jsHeapTotalBytes": 19783680,
"scriptDurationMs": 19.579000000000004,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-idle",
"durationMs": 2017.7750000000287,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.496000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 455.9650000000001,
"heapDeltaBytes": 5219304,
"heapUsedBytes": 73161308,
"domNodes": 18,
"jsHeapTotalBytes": 19783680,
"scriptDurationMs": 14.325999999999999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1874.9969999999507,
"styleRecalcs": 75,
"styleRecalcDurationMs": 38.582,
"layouts": 12,
"layoutDurationMs": 3.2680000000000002,
"taskDurationMs": 870.2579999999999,
"heapDeltaBytes": -16919108,
"heapUsedBytes": 50908456,
"domNodes": -278,
"jsHeapTotalBytes": 22007808,
"scriptDurationMs": 126.227,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1786.011999999971,
"styleRecalcs": 74,
"styleRecalcDurationMs": 35.76500000000001,
"layouts": 12,
"layoutDurationMs": 3.498,
"taskDurationMs": 771.904,
"heapDeltaBytes": -16904196,
"heapUsedBytes": 50925024,
"domNodes": -281,
"jsHeapTotalBytes": 21483520,
"scriptDurationMs": 123.072,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1725.0420000000304,
"styleRecalcs": 30,
"styleRecalcDurationMs": 17.083000000000002,
"layouts": 6,
"layoutDurationMs": 0.6169999999999999,
"taskDurationMs": 371.73400000000004,
"heapDeltaBytes": 7939260,
"heapUsedBytes": 75876012,
"domNodes": 77,
"jsHeapTotalBytes": 20307968,
"scriptDurationMs": 18.143000000000004,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1753.6209999999528,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.307000000000002,
"layouts": 6,
"layoutDurationMs": 0.6099999999999999,
"taskDurationMs": 366.653,
"heapDeltaBytes": 7843236,
"heapUsedBytes": 75877128,
"domNodes": 78,
"jsHeapTotalBytes": 20307968,
"scriptDurationMs": 18.115,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 581.4389999999889,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.498999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 361.61299999999994,
"heapDeltaBytes": -12283412,
"heapUsedBytes": 55592264,
"domNodes": 18,
"jsHeapTotalBytes": 22405120,
"scriptDurationMs": 58.228,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 574.1620000000012,
"styleRecalcs": 10,
"styleRecalcDurationMs": 6.483999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 361.527,
"heapDeltaBytes": -12643040,
"heapUsedBytes": 55442252,
"domNodes": 16,
"jsHeapTotalBytes": 22667264,
"scriptDurationMs": 58.587,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2029.7580000000153,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.366000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 651.154,
"heapDeltaBytes": 8528320,
"heapUsedBytes": 67480256,
"domNodes": -283,
"jsHeapTotalBytes": 5038080,
"scriptDurationMs": 100.598,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-idle",
"durationMs": 2070.2529999999797,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.080999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 666.283,
"heapDeltaBytes": 8278684,
"heapUsedBytes": 67664560,
"domNodes": -283,
"jsHeapTotalBytes": 4775936,
"scriptDurationMs": 107.559,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2157.6349999999707,
"styleRecalcs": 70,
"styleRecalcDurationMs": 14.892000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1284.3149999999998,
"heapDeltaBytes": -4585112,
"heapUsedBytes": 55617520,
"domNodes": -281,
"jsHeapTotalBytes": 5038080,
"scriptDurationMs": 430.96799999999996,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-pan",
"durationMs": 2188.521000000037,
"styleRecalcs": 67,
"styleRecalcDurationMs": 12.014000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1266.0240000000001,
"heapDeltaBytes": 5955572,
"heapUsedBytes": 65669824,
"domNodes": -284,
"jsHeapTotalBytes": 5263360,
"scriptDurationMs": 429.878,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3147.0529999999712,
"styleRecalcs": 65,
"styleRecalcDurationMs": 14.969000000000003,
"layouts": 60,
"layoutDurationMs": 7.2170000000000005,
"taskDurationMs": 1454.6879999999999,
"heapDeltaBytes": 23499940,
"heapUsedBytes": 84591168,
"domNodes": 12,
"jsHeapTotalBytes": 7602176,
"scriptDurationMs": 517.0010000000001,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-zoom",
"durationMs": 3182.7110000000403,
"styleRecalcs": 65,
"styleRecalcDurationMs": 14.460000000000004,
"layouts": 60,
"layoutDurationMs": 6.969999999999999,
"taskDurationMs": 1480.713,
"heapDeltaBytes": -2240732,
"heapUsedBytes": 59100708,
"domNodes": -286,
"jsHeapTotalBytes": 6873088,
"scriptDurationMs": 514.761,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2056.714999999997,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.071000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 667.0589999999999,
"heapDeltaBytes": 8760232,
"heapUsedBytes": 69231624,
"domNodes": -283,
"jsHeapTotalBytes": 3989504,
"scriptDurationMs": 103.93299999999999,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2025.2519999999095,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.9959999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 653.8900000000001,
"heapDeltaBytes": 7996868,
"heapUsedBytes": 68349384,
"domNodes": -283,
"jsHeapTotalBytes": 4251648,
"scriptDurationMs": 99.446,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 610.9840000000304,
"styleRecalcs": 47,
"styleRecalcDurationMs": 9.873999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 400.41200000000003,
"heapDeltaBytes": -11575460,
"heapUsedBytes": 56569288,
"domNodes": 20,
"jsHeapTotalBytes": 21880832,
"scriptDurationMs": 116.514,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 592.1849999999722,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.458999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 391.92699999999996,
"heapDeltaBytes": -12285660,
"heapUsedBytes": 55827632,
"domNodes": 22,
"jsHeapTotalBytes": 22667264,
"scriptDurationMs": 116.12400000000001,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2029.6769999999924,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.061,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 451.395,
"heapDeltaBytes": 4387528,
"heapUsedBytes": 72392456,
"domNodes": 20,
"jsHeapTotalBytes": 20570112,
"scriptDurationMs": 12.429,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2007.1919999999182,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.531999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 444.85600000000005,
"heapDeltaBytes": 4409444,
"heapUsedBytes": 72339568,
"domNodes": 20,
"jsHeapTotalBytes": 20307968,
"scriptDurationMs": 12.715,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1699.7840000000224,
"styleRecalcs": 77,
"styleRecalcDurationMs": 34.178,
"layouts": 16,
"layoutDurationMs": 3.883,
"taskDurationMs": 775.691,
"heapDeltaBytes": -20768296,
"heapUsedBytes": 47215172,
"domNodes": -279,
"jsHeapTotalBytes": 20697088,
"scriptDurationMs": 88.362,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1684.0029999999615,
"styleRecalcs": 77,
"styleRecalcDurationMs": 34.566,
"layouts": 16,
"layoutDurationMs": 4.286,
"taskDurationMs": 752.8929999999999,
"heapDeltaBytes": -4490092,
"heapUsedBytes": 63502140,
"domNodes": 63,
"jsHeapTotalBytes": 21094400,
"scriptDurationMs": 91.481,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-transition-enter",
"durationMs": 1384.303999999986,
"styleRecalcs": 19,
"styleRecalcDurationMs": 29.675,
"layouts": 15,
"layoutDurationMs": 12.911000000000003,
"taskDurationMs": 900.2570000000001,
"heapDeltaBytes": 1352884,
"heapUsedBytes": 73167888,
"domNodes": 13673,
"jsHeapTotalBytes": 16777216,
"scriptDurationMs": 32.3,
"eventListeners": 2371,
"totalBlockingTimeMs": 136,
"frameDurationMs": 16.666666666666696,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8276.390999999989,
"styleRecalcs": 249,
"styleRecalcDurationMs": 34.689,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4396.383,
"heapDeltaBytes": 12949652,
"heapUsedBytes": 72333716,
"domNodes": -285,
"jsHeapTotalBytes": 6803456,
"scriptDurationMs": 1365.24,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "viewport-pan-sweep",
"durationMs": 8214.492999999948,
"styleRecalcs": 249,
"styleRecalcDurationMs": 36.223,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4425.5830000000005,
"heapDeltaBytes": 8983824,
"heapUsedBytes": 68241492,
"domNodes": -283,
"jsHeapTotalBytes": 6574080,
"scriptDurationMs": 1374.417,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 16907.519999999975,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16889.329,
"heapDeltaBytes": -45547316,
"heapUsedBytes": 166072872,
"domNodes": -8312,
"jsHeapTotalBytes": -11739136,
"scriptDurationMs": 530.486,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666763,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 16989.431999999964,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16952.344,
"heapDeltaBytes": -45818328,
"heapUsedBytes": 167243764,
"domNodes": -8312,
"jsHeapTotalBytes": -13049856,
"scriptDurationMs": 588.56,
"eventListeners": -16387,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.779999999999927,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 20118.885999999977,
"styleRecalcs": 136,
"styleRecalcDurationMs": 15.361000000000013,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 20089.365,
"heapDeltaBytes": -32745124,
"heapUsedBytes": 167004344,
"domNodes": -8312,
"jsHeapTotalBytes": -13312000,
"scriptDurationMs": 883.8350000000002,
"eventListeners": -16383,
"totalBlockingTimeMs": 126,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 20702.329000000078,
"styleRecalcs": 141,
"styleRecalcDurationMs": 16.69200000000004,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 20649.01,
"heapDeltaBytes": -44870112,
"heapUsedBytes": 177363048,
"domNodes": -8312,
"jsHeapTotalBytes": -10760192,
"scriptDurationMs": 895.469,
"eventListeners": -16385,
"totalBlockingTimeMs": 159,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 461.97999999998274,
"styleRecalcs": 12,
"styleRecalcDurationMs": 19.185,
"layouts": 3,
"layoutDurationMs": 0.624,
"taskDurationMs": 117.95800000000001,
"heapDeltaBytes": -15661736,
"heapUsedBytes": 51372900,
"domNodes": 128,
"jsHeapTotalBytes": 7200768,
"scriptDurationMs": 11.493,
"eventListeners": 67,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "workflow-execution",
"durationMs": 107.03399999999874,
"styleRecalcs": 9,
"styleRecalcDurationMs": 14.020000000000001,
"layouts": 2,
"layoutDurationMs": 0.846,
"taskDurationMs": 72.255,
"heapDeltaBytes": 2800372,
"heapUsedBytes": 69802972,
"domNodes": 126,
"jsHeapTotalBytes": 2883584,
"scriptDurationMs": 4.134,
"eventListeners": 17,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe credit top-up dialog now has amount, confirmation, and payment verification steps. Payment actions lock during pending operations. Workspace and browser tests cover navigation, verification loading, payment outcomes, permissions, and cloud billing setup. ChangesCredit top-up flow
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant TopUpCreditsDialogContentWorkspace
participant TopUpAPI
participant BillingOperation
User->>TopUpCreditsDialogContentWorkspace: select amount
TopUpCreditsDialogContentWorkspace-->>User: show confirmation
User->>TopUpCreditsDialogContentWorkspace: submit payment
TopUpCreditsDialogContentWorkspace->>TopUpAPI: request top-up
TopUpAPI-->>TopUpCreditsDialogContentWorkspace: return payment response
TopUpCreditsDialogContentWorkspace->>BillingOperation: start pending operation
BillingOperation-->>TopUpCreditsDialogContentWorkspace: update operation state
BillingOperation-->>User: show verification or payment result
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue`:
- Around line 426-430: Update the startOperation chain in
TopUpCreditsDialogContentWorkspace so rejections are handled explicitly: clear
paymentSubmitted and report the operation-start error in a rejection handler,
while preserving the existing success behavior and ensuring the promise is not
unhandled.
- Around line 213-220: Update the Pay button’s disabled condition near
handlePrimaryAction to also disable it when permissions.canTopUp is false, while
preserving the existing isValidAmount and paymentLocked checks.
- Around line 322-329: Update the displayTotal computed value to use the active
vue-i18n number formatter via n(), preserving USD currency formatting if
required by the payment flow, instead of hard-coding the en-US locale and dollar
prefix. Reuse the component’s existing i18n setup or repository currency helper.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6fbec13a-8a28-4629-b66f-11aabbb0561b
📒 Files selected for processing (5)
browser_tests/fixtures/components/TopUpCreditsDialog.tsbrowser_tests/tests/dialogs/creditsTile.spec.tssrc/locales/en/main.jsonsrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.tssrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## main #14605 +/- ##
==========================================
- Coverage 79.10% 79.09% -0.01%
==========================================
Files 1769 1769
Lines 118915 119236 +321
Branches 38244 38408 +164
==========================================
+ Hits 94062 94310 +248
- Misses 24223 24295 +72
- Partials 630 631 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 6 files with indirect coverage changes 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue`:
- Around line 460-476: Update reportPurchaseError to sanitize failures before
console.error and toast.add: map only accepted error classes or allowlisted
codes to localized summaries, and use credits.topUp.unknownError for all other
errors instead of exposing raw error.message. Update the regression test to
expect credits.topUp.unknownError rather than “Operation unavailable”.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9b358362-7d10-45ba-baa2-2581af5463a2
📒 Files selected for processing (2)
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.tssrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue (1)
373-379: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winEnforce
paymentLockedinhandleBuy.
paymentLockedremains true whilepaymentSubmitted, polling, or an action URL is active. ThehandleBuy()guard checksloadingonly. After a pending response,loadingresets while the operation is still locked. If a stale action reaches the handler, it can submit a second top-up request.Use
paymentLocked.valuein the handler guard.Proposed fix
async function handleBuy() { if ( - loading.value || + paymentLocked.value || !isValidAmount.value || (shouldUseWorkspaceBilling.value && !permissions.value.canTopUp) ) {Also applies to: 403-412
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue` around lines 373 - 379, Update the handleBuy guard to check paymentLocked.value in addition to loading, preventing submission while paymentSubmitted, polling, or an action URL keeps the payment operation locked. Ensure stale actions return without issuing a second top-up request.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue`:
- Around line 373-379: Update the handleBuy guard to check paymentLocked.value
in addition to loading, preventing submission while paymentSubmitted, polling,
or an action URL keeps the payment operation locked. Ensure stale actions return
without issuing a second top-up request.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0c8fa45b-0ef0-4873-9564-0c983d224b72
📒 Files selected for processing (2)
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.tssrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
|
Addressed the outside-diff |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts`:
- Around line 272-285: Update the “locks pending payment actions and prevents
duplicate top-ups” test to assert that the payButton is disabled after payment
enters the pending state and before dispatching the stale click event. Keep the
existing Back-button and single mockTopup assertions unchanged, using a
behavioral disabled-state assertion rather than relying only on the imperative
guard.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: cebbebbd-8b50-468b-a147-54f3c8ffd2c7
📒 Files selected for processing (2)
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.tssrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
|
Visual proof for 9087705 (route-mocked current-head cloud build). The screencast covers amount selection → confirmation → locked 3DS → closing and reopening into verification. Billing responses are mocked; the UI and build are pinned to this PR head. e90f6642ab30-pr-14605-top-up-verification.mp4 |
huang47
left a comment
There was a problem hiding this comment.
LGTM. Current-head screencast: #14605 (comment)
4a751f9
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc82c-9ff0-72bd-8994-3d39dd29a9ad Co-authored-by: Amp <amp@ampcode.com>
4a751f9 to
d48a5ad
Compare
huang47
left a comment
There was a problem hiding this comment.
Thanks for working on this, we really need to refactor the store otherwise the logic is becoming fragile and challenging to maintain 😬
Summary
Updates the workspace credit top-up dialog for FE-1494 so payment confirmation happens before the charge request, navigation locks once payment starts, and interrupted 3DS flows reopen directly in verification.
Root cause
The workspace top-up dialog submitted the charge from the amount-selection screen. Because it had no explicit confirmation or verification state, users could navigate or reopen the dialog without clear feedback while a billing operation was pending, and the verification action appeared alongside the original purchase controls.
Changes
Pay {amount}confirmation action, disable back navigation after submission, and derive the reopened verification state from the pending billing operation.Review Focus
Screenshots
AS IS
TO BE
3DS REQUIRED — CONFIRMATION
3DS REQUIRED — REOPENED PENDING PAYMENT