feat(ui-rewrite): delete a prompt from the details panel#5670
Conversation
|
@marekdano , PR opened to merge into your branch for the dialog height issue introduced in a recent commit: #5695 The delete functionality works as expected; the bug was introduced prior to this work. |
vishu-bh
left a comment
There was a problem hiding this comment.
approach is clean, left some inline comments.
Worth checking if all ui components are used instead of adding html one by default
| ref={ref} | ||
| className={cn( | ||
| "fixed inset-0 z-50 m-auto grid h-fit w-full max-w-lg gap-4 border bg-popover p-6 shadow-lg duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 sm:rounded-lg", | ||
| "fixed inset-x-0 top-1/2 z-50 mx-auto grid w-full max-w-lg -translate-y-1/2 gap-5 border bg-popover p-7 shadow-lg duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 sm:rounded-lg", |
There was a problem hiding this comment.
Using top-1/2 -translate-y-1/2, without default max-height or scrolling.
Dialogs taller than viewport extend above screen; top content and close button become unreachable. This affects every shared DialogContent, not only prompt deletion. ManageTeamMembersDialog is one likely dynamic-height consumer.
adding viewport bound and scrolling, such as max-h-[calc(100vh-2rem)] overflow-y-auto, or keep oversized dialogs top-aligned. Add small-viewport/large-content test.
There was a problem hiding this comment.
Good catch! This affected every DialogContent, not just the delete flow. Added max-h-[calc(100vh-2rem)] overflow-y-auto so tall dialogs stay within the viewport and scroll internally, keeping the header and close button reachable. Added a large-content test asserting the bounding classes.
| } | ||
| } catch (err) { | ||
| // Restore the pre-delete list and reopen the group on failure. | ||
| setPromptsData(() => previousData); |
There was a problem hiding this comment.
Could we reconcile with the server after a failed DELETE instead of unconditionally restoring this snapshot? PromptService.delete_prompt() commits before running notification and cache invalidation. If one of those post-commit operations fails, the endpoint returns an error even though the prompt is already deleted. Restoring previousData here would therefore show a prompt that no longer exists. Refetching after failure would handle both pre-commit and post-commit failures correctly.
There was a problem hiding this comment.
Also, restoring the entire snapshot can overwrite newer state when two deletions overlap. For example, one deletion may succeed while an earlier request fails later and restores both prompts. Could we either prevent another deletion while one is pending, or roll back only the failed prompt using a functional state update? An out-of-order request test would help protect this case.
There was a problem hiding this comment.
You're right on both counts. Since PromptService.delete_prompt() commits before notification/cache invalidation, a post-commit failure would return an error even though the row is already gone — and restoring the snapshot would resurrect it (and could clobber a concurrent delete's state). I dropped the snapshot rollback and now refetch() to reconcile with server truth on failure, then re-resolve the open drawer's group from that fresh data. This handles both pre- and post-commit failures, and reconciling against the server sidesteps the overlapping-delete clobbering rather than restoring stale client state.
Note the optimistic removal itself is unchanged — only the rollback strategy changed. Trade-off is the row now reappears after a network round-trip on a genuine failure rather than instantly.
On tests: reframed the existing failure test as the pre-commit case (prompt survives → row reappears) and added a post-commit case (DELETE errors but the server row is gone → prompt is not resurrected).
I held off on a full out-of-order/overlap test since it needs deferred request timing to be deterministic — happy to add it if you think it's worth the harness; the refetch reconciliation is what makes that case safe regardless.
Signed-off-by: Marek Dano <Marek.Dano@ibm.com>
Signed-off-by: a-effort <anna.effort@ibm.com>
Signed-off-by: Marek Dano <Marek.Dano@ibm.com>
Signed-off-by: Marek Dano <Marek.Dano@ibm.com>
d1c6031 to
8b33cf8
Compare
Summary
Wires up the previously-stubbed Delete action in the prompt details panel. Selecting Delete on a prompt row now opens a confirmation dialog and, on confirm, calls
DELETE /prompts/{id}and removes the prompt from the UI. Mirrors the existing Tools page delete flow.Closes #5103
delete_prompt.mov
What changed
client/src/api/prompts.ts): addedpromptsApi.delete(id)→DELETE /prompts/{id}. Validates the prompt ID (^[a-zA-Z0-9_-]+$) andencodeURIComponent-wraps it, matchingupdateTags; the backend enforces theprompts.deletepermission.client/src/pages/Prompts.tsx): replaced the no-ophandleDeletePromptplaceholder with the real flow — destructiveConfirmDialognaming the prompt, optimistic removal from the list (handles both array and cursor-paginated shapes), success/error toasts, and arefetch(). On failure it rolls back both the list and the open drawer group.parseApiErrorhelper (@/lib/errorUtils) to surface the backend failure reason, falling back to a localized message.prompts.delete.confirm.*,prompts.delete.success, andprompts.delete.errorto en-US / es-ES / pt-BR.Notes / behavior
PromptDetailsPanelderivesselectedasfind(...) ?? prompts[0]), so no stale view.handleEditPromptremains an intentional no-op stub — edit mode needs aPromptFormedit capability that doesn't exist yet (tracked for a follow-up).Tests