fix: wait for access before opening a draft-only item from the picker (#12064)

This commit is contained in:
AlexRV12
2026-10-28 18:49:04 +01:00
committed by GitHub
parent 09ddf1e0c7
commit bfd31df5d5
2 changed files with 33 additions and 9 deletions
@@ -168,21 +168,35 @@ section or the flat layout.
// saying "show me this", so it lands on the deployed page, and `navigate`
// would otherwise keep whichever side the re-pointed tab happened to be on.
// A draft-only item opens its editor, unless this user cannot save there.
function itemTarget(item: WorkspaceItem): PreviewTarget {
return { type: 'item', item, mode: canEdit(item) ? previewModeFor(item) : 'view' }
}
function tagItems(nodes: DrillNode<WorkspaceItem>[]): DrillNode<PreviewTarget>[] {
return nodes.map((n) =>
n.type === 'leaf'
? {
...n,
data: {
type: 'item',
item: n.data,
mode: canEdit(n.data) ? previewModeFor(n.data) : 'view'
}
}
? { ...n, data: itemTarget(n.data) }
: { ...n, children: tagItems(n.children) }
)
}
// The mode is saved with the tab and never re-checked, and `canEdit` refuses until the
// rights and protection rules arrive: a draft-only item picked before then would open in a
// viewer that has nothing to show. Hold the pick until both have answered.
let heldItem = $state<WorkspaceItem | undefined>(undefined)
$effect(() => {
if (!heldItem || !permissions.settled) return
const item = heldItem
heldItem = undefined
untrack(() => onPick(itemTarget(item)))
})
function pick(target: PreviewTarget) {
if (target.type === 'item' && target.item.draftOnly && !permissions.settled) {
heldItem = target.item
} else {
onPick(target)
}
}
// Open the item's editor. Offered on every item row this user can edit, including the
// draft-only ones a plain click already opens there: a row that drops the button to say
// "you were getting this anyway" reads as one that cannot be edited.
@@ -392,7 +406,7 @@ section or the flat layout.
<DrillPicker
bind:this={inner}
{tree}
onPick={(leaf) => onPick(leaf.data)}
onPick={(leaf) => pick(leaf.data)}
initialScope={computedInitialScope}
{initialHighlight}
{externalFilter}
@@ -37,6 +37,11 @@ export function useSessionReadOnly(workspace: () => string | undefined) {
get known() {
const ws = workspace()
return !!ws && (verdictFor(ws) ?? false)
},
/** Whether the rules were read, a failed read included, which settles as read-only. */
get settled() {
const ws = workspace()
return !!ws && verdictFor(ws) !== undefined
}
}
}
@@ -75,6 +80,11 @@ export function useSessionPermissions(
get readOnly() {
return readOnly
},
/** Whether `canEditItem` answers for real rather than refusing while it waits for this
* user's rights or the protection rules. */
get settled() {
return user.resolved(workspace()) && protectedWorkspace.settled
},
/** Whether this user can save the drafts the `kind` editor writes. */
canOpenEditor: (kind: string) => !readOnly && rights.roleCanDraft(kind),
/** The same, and this item's own permissions let them write it. */