Skip to content

fix(releases): show toast when bulk unpublish has no permitted targets - #13785

Open
tpc-faheem wants to merge 7 commits into
pr/detail-foundation-releasesfrom
cursor/fix-bulk-unpublish-no-targets-41d2
Open

fix(releases): show toast when bulk unpublish has no permitted targets#13785
tpc-faheem wants to merge 7 commits into
pr/detail-foundation-releasesfrom
cursor/fix-bulk-unpublish-no-targets-41d2

Conversation

@tpc-faheem

Copy link
Copy Markdown
Contributor

Description

Bulk unpublish runs permission checks before calling unpublishVersion. When every selected document is denied, the early return closed the dialog without feedback, so the selection stayed (correct) but users had no idea why nothing happened.

We show an error toast using a new releases i18n string and still skip onSuccess so the selection is preserved.

What to review

  • ReleaseBulkActionDialog.tsx — empty targets branch after permission filtering
  • resources.tsdashboard.details.bulk.unpublish-toast.no-permission
  • Test expectations for toast + no onSuccess

Testing

  • pnpm vitest run --project=sanity packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseBulkActionDialog.test.tsx

Notes for release

Fixes silent failure when confirming bulk unpublish without permission on any selected documents.

Open in Web Open in Cursor 

Faheem Hasan and others added 7 commits July 28, 2026 20:58
…es detail

Introduce shared detail-layout components and a shared document table, and adopt
them on the Releases detail page as the first consumer. Establishes the pattern
the variant definition surfaces follow. All behind beta.variants; production
unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YC1NYrgo5GE7yMePn9mCTb
DetailPropertyRow was re-exported but never imported; make it local. Keep
DetailPropertiesSection exported and use it in ReleaseDashboardDetails so it
isn't an unused export. Fixes the knip CI check.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YC1NYrgo5GE7yMePn9mCTb
When beta.variants enables DocumentTable on Release Summary, pass
alwaysShowCommandLane so Add document, Activity, Copy, search, and
filter tabs stay mounted when rows are empty or search filters to zero.

Co-authored-by: Faheem Hasan <[email protected]>
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
auth-test-studio Ready Ready Preview, Comment Jul 29, 2026 11:45am
page-building-studio Ready Ready Preview, Comment Jul 29, 2026 11:45am
studio-metrics Ready Ready Preview, Comment Jul 29, 2026 11:45am
test-studio Ready Ready Preview, Comment Jul 29, 2026 11:45am
test-studio-preview-iframe Ready Ready Preview, Comment Jul 29, 2026 11:45am

Request Review

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Stats — sanity

Compared against pr/detail-foundation-releases (7fdb9d77) · v6.7.0 (npm)

sanity

Metric Value vs pr/detail-foundation-releases (7fdb9d7) vs v6.7.0
Internal (raw) 4.10 MB - +2.2 KB, +0.1%
Internal (gzip) 1.01 MB +13 B, +0.0% +606 B, +0.1%
Bundled (raw) 12.38 MB +366 B, +0.0% +61.6 KB, +0.5%
Bundled (gzip) 2.90 MB +46 B, +0.0% +16.2 KB, +0.5%
Import time 1.68s -2ms, -0.1% +67ms, +4.2%

bin:sanity

Metric Value vs pr/detail-foundation-releases (7fdb9d7) vs v6.7.0
Internal (raw) 7.1 KB - -
Internal (gzip) 2.9 KB - -
Bundled (raw) 7.1 KB - -
Bundled (gzip) 2.8 KB - -
Import time 4ms +0ms, +0.7% +0ms, +4.0%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

📚 TypeDoc Generation Result

TypeDoc generated successfully!

  • File size: 8.3M
  • Total exports: 1085
  • Artifact: sanity-typedoc-bee1b65546c20fb3d36770e9e01e5352fa0896e8

The TypeDoc JSON file has been generated and validated. All documentation scripts completed successfully.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

⚡️ Editor Performance Report

Updated Wed, 29 Jul 2026 11:51:07 GMT

Benchmark reference
latency of sanity@latest
experiment
latency of this branch
Δ (%)
latency difference
arrayI18n (simple-en) 99.9+ efps (9ms) 99.9+ efps (10ms) +1ms (-/-%)
article (title) 90.9 efps (11ms) 74.1 efps (14ms) +3ms (-/-%)
article (body) 63.3 efps (16ms) 57.8 efps (17ms) +2ms (+9.5%)
article (string inside object) 99.9+ efps (10ms) 90.9 efps (11ms) +1ms (-/-%)
article (string inside array) 90.9 efps (11ms) 99.9+ efps (10ms) -1ms (-/-%)
recipe (name) 99.9+ efps (6ms) 99.9+ efps (5ms) -1ms (-/-%)
recipe (description) 55.6 efps (18ms) 58.8 efps (17ms) -1ms (-5.6%)
recipe (instructions) 99.9+ efps (5ms) 99.9+ efps (5ms) +0ms (-/-%)
singleString (stringField) 99.9+ efps (5ms) 99.9+ efps (5ms) +0ms (-/-%)
synthetic (title) 99.9+ efps (5ms) 99.9+ efps (5ms) +0ms (-/-%)
synthetic (string inside object) 99.9+ efps (4ms) 99.9+ efps (4ms) +0ms (-/-%)

efps — editor "frames per second". The number of updates assumed to be possible within a second.

Derived from input latency. efps = 1000 / input_latency

Detailed information

🏠 Reference result

The performance result of sanity@latest

Benchmark latency p75 p90 p99 blocking time test duration
arrayI18n (simple-en) 9ms 12ms 17ms 52ms 10ms 6.7s
article (title) 11ms 16ms 32ms 88ms 84ms 8.3s
article (body) 16ms 18ms 50ms 114ms 314ms 6.1s
article (string inside object) 10ms 13ms 20ms 53ms 3ms 7.0s
article (string inside array) 11ms 16ms 18ms 46ms 16ms 7.5s
recipe (name) 6ms 9ms 13ms 32ms 0ms 4.9s
recipe (description) 18ms 21ms 24ms 39ms 0ms 4.4s
recipe (instructions) 5ms 6ms 6ms 13ms 0ms 2.9s
singleString (stringField) 5ms 7ms 10ms 13ms 0ms 4.2s
synthetic (title) 5ms 6ms 8ms 67ms 210ms 6.7s
synthetic (string inside object) 4ms 6ms 8ms 61ms 201ms 6.4s

🧪 Experiment result

The performance result of this branch

Benchmark latency p75 p90 p99 blocking time test duration
arrayI18n (simple-en) 10ms 16ms 28ms 36ms 32ms 7.2s
article (title) 14ms 20ms 25ms 78ms 91ms 8.8s
article (body) 17ms 25ms 54ms 93ms 222ms 6.6s
article (string inside object) 11ms 16ms 25ms 70ms 57ms 7.7s
article (string inside array) 10ms 12ms 24ms 42ms 23ms 7.6s
recipe (name) 5ms 8ms 11ms 14ms 0ms 4.8s
recipe (description) 17ms 19ms 21ms 24ms 0ms 4.3s
recipe (instructions) 5ms 6ms 9ms 12ms 0ms 2.9s
singleString (stringField) 5ms 7ms 8ms 15ms 0ms 4.2s
synthetic (title) 5ms 6ms 7ms 10ms 122ms 6.8s
synthetic (string inside object) 4ms 6ms 7ms 33ms 45ms 6.4s

📚 Glossary

column definitions

  • benchmark — the name of the test, e.g. "article", followed by the label of the field being measured, e.g. "(title)".
  • latency — the time between when a key was pressed and when it was rendered. derived from a set of samples. the median (p50) is shown to show the most common latency.
  • p75 — the 75th percentile of the input latency in the test run. 75% of the sampled inputs in this benchmark were processed faster than this value. this provides insight into the upper range of typical performance.
  • p90 — the 90th percentile of the input latency in the test run. 90% of the sampled inputs were faster than this. this metric helps identify slower interactions that occurred less frequently during the benchmark.
  • p99 — the 99th percentile of the input latency in the test run. only 1% of sampled inputs were slower than this. this represents the worst-case scenarios encountered during the benchmark, useful for identifying potential performance outliers.
  • blocking time — the total time during which the main thread was blocked, preventing user input and UI updates. this metric helps identify performance bottlenecks that may cause the interface to feel unresponsive.
  • test duration — how long the test run took to complete.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 43.68% 31452 / 71995
🔵 Statements 36.75% 41042 / 111667
🔵 Functions 35.32% 6736 / 19067
🔵 Branches 28.61% 26632 / 93073
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/sanity/src/core/releases/i18n/resources.ts 100% 100% 100% 100%
packages/sanity/src/core/releases/tool/detail/ReleaseBulkActionDialog.tsx 87.5% 48.52% 85.71% 94.44% 103, 154-161, 167, 187, 194, 195, 198, 206
Generated in workflow #63048 for commit 3a4ea4b by the Vitest Coverage Report Action

@tpc-faheem
tpc-faheem force-pushed the pr/detail-foundation-releases branch from 126b276 to 5bf9eb3 Compare July 29, 2026 11:54
@tpc-faheem
tpc-faheem marked this pull request as ready for review July 29, 2026 14:08
@tpc-faheem
tpc-faheem requested a review from a team as a code owner July 29, 2026 14:08
@tpc-faheem
tpc-faheem requested review from stipsan and removed request for a team and stipsan July 29, 2026 14:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3a4ea4b. Configure here.


setIsProcessing(false)
onSuccess()
onClose()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dialog sticks on permission errors

High Severity

handleConfirm sets isProcessing to true, then awaits permission filtering with no try/finally. If filterDocumentsWithUnpublishPermission rejects, isProcessing never resets. The dialog’s close and cancel handlers are gated on !isProcessing, so the dialog can become permanently stuck with no way to dismiss it.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3a4ea4b. Configure here.


setIsProcessing(false)
onSuccess()
onClose()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Failed bulk action clears selection

Medium Severity

After Promise.allSettled, onSuccess always runs—even when every operation was rejected. That clears the table selection via bulkAction.clear. The empty-targets path correctly skips onSuccess to keep the selection; total failure does not, so users lose their selection and must reselect to retry.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3a4ea4b. Configure here.

@tpc-faheem
tpc-faheem force-pushed the pr/detail-foundation-releases branch 3 times, most recently from b29c640 to 6cb1537 Compare July 29, 2026 16:14
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.

2 participants