diff --git a/static/ui.js b/static/ui.js index c4a64f9ed..a16c4529b 100644 --- a/static/ui.js +++ b/static/ui.js @@ -5918,7 +5918,13 @@ function showPromptDialog(opts={}){ input.value=prefill;input.placeholder=opts.placeholder||''; input.autocomplete='off';input.spellcheck=false; } - if(cancelBtn) cancelBtn.textContent=opts.cancelLabel||t('cancel'); + if(cancelBtn){ + // A prior showConfirmDialog({hideCancel:true}) (e.g. the outside-symlink info + // dialog, #4581) may have hidden the shared Cancel button; always restore it + // so a subsequent prompt keeps its Cancel affordance. + cancelBtn.style.display=''; + cancelBtn.textContent=opts.cancelLabel||t('cancel'); + } if(confirmBtn){ confirmBtn.textContent=opts.confirmLabel||t('create'); confirmBtn.classList.toggle('danger',!!opts.danger); diff --git a/tests/test_workspace_context_menu_and_rename.py b/tests/test_workspace_context_menu_and_rename.py index 2a8958efe..672b026cc 100644 --- a/tests/test_workspace_context_menu_and_rename.py +++ b/tests/test_workspace_context_menu_and_rename.py @@ -184,6 +184,20 @@ class ShowPromptDialogPrefillTests(unittest.TestCase): break return self.src[start:end] + def test_show_prompt_dialog_restores_hidden_cancel_button(self): + """#4581: the outside-symlink info dialog calls showConfirmDialog with + hideCancel:true, which sets the shared #appDialogCancel button to + display:none. showPromptDialog reuses the same button, so it must restore + the display before showing — otherwise the next rename/new-file prompt + opens with no Cancel button after a user clicks an external symlink.""" + body = self._slice_show_prompt_dialog() + self.assertIn( + "cancelBtn.style.display=''", body.replace(" ", ""), + "showPromptDialog must reset cancelBtn.style.display so a prior " + "showConfirmDialog({hideCancel:true}) can't leave the Cancel button " + "hidden on a subsequent prompt (#4581 regression).", + ) + def test_show_prompt_dialog_accepts_default_value_alias(self): body = self._slice_show_prompt_dialog() # Must reference `opts.defaultValue` somewhere — the alias was the