From bc76c4f767a75d23bd2b278f025c9f8164a36df5 Mon Sep 17 00:00:00 2001 From: stellarshenson Date: Tue, 6 Jan 2026 21:15:42 +0100 Subject: [PATCH] feat: add loading spinner during credentials fetch --- .claude/JOURNAL.md | 6 ++++ .../jupyterhub/templates_enhanced/admin.html | 35 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/.claude/JOURNAL.md b/.claude/JOURNAL.md index 6ea9414..a540792 100644 --- a/.claude/JOURNAL.md +++ b/.claude/JOURNAL.md @@ -87,3 +87,9 @@ This journal tracks substantive work on documents, diagrams, and documentation c 28. **Task - Fix admin template URL handling**: Fixed fetch interceptor and nav links in templates_enhanced
**Result**: Fixed `isUserCreation` check in admin.html to strip query params (`?_xsrf=...`) before checking if URL ends with `api/users` - React admin adds XSRF token as query param which broke the endpoint detection. Fixed double "hub" prefix in page.html nav links - changed `{{ base_url }}hub/authorize` to `{{ base_url }}authorize` and `{{ base_url }}hub/change-password` to `{{ base_url }}change-password` since base_url already includes `/hub/` + +29. **Task - Fix credentials API route conflict**: Changed credentials endpoint from `/api/users/credentials` to `/api/admin/credentials`
+ **Result**: JupyterHub's built-in `/api/users/*` handler was catching requests before custom handler, returning "Invalid JSON keys" error. Changed route in jupyterhub_config.py, admin.html, and custom_handlers.py docstring + +30. **Task - Credentials modal UX improvements**: Enhanced modal layout, scrolling, and loading feedback
+ **Result**: Moved Copy/Download buttons to top of modal body. Added scrollable container (max-height 300px) for long user lists. Removed `` styling for plain text display. Added loading spinner modal shown between user creation and credentials display. Improved Makefile version output format to show "Current version" and "New version" lines diff --git a/services/jupyterhub/templates_enhanced/admin.html b/services/jupyterhub/templates_enhanced/admin.html index da53b60..89a54b3 100644 --- a/services/jupyterhub/templates_enhanced/admin.html +++ b/services/jupyterhub/templates_enhanced/admin.html @@ -51,6 +51,20 @@ + + + {% endblock main %} {% block footer %} @@ -131,6 +145,9 @@ console.log('[Admin] Users created:', createdUsers); pendingUsernames.push(...createdUsers); + // Show loading spinner + showLoadingSpinner(); + // Debounce - wait for batch completion then fetch credentials clearTimeout(window._credentialsFetchTimeout); window._credentialsFetchTimeout = setTimeout(() => { @@ -172,14 +189,32 @@ } } else { console.error('[Admin] Failed to fetch credentials:', response.status); + hideLoadingSpinner(); } } catch (e) { console.error('[Admin] Error fetching credentials:', e); + hideLoadingSpinner(); + } + } + + // Loading spinner functions + let loadingModal = null; + function showLoadingSpinner() { + const modalEl = document.getElementById('loading-modal'); + if (!loadingModal) { + loadingModal = new bootstrap.Modal(modalEl); + } + loadingModal.show(); + } + function hideLoadingSpinner() { + if (loadingModal) { + loadingModal.hide(); } } // Show modal with credentials function showCredentialsModal(credentials) { + hideLoadingSpinner(); const tbody = document.getElementById('credentials-body'); tbody.innerHTML = '';