From 6aaae9939c32199f7eecd7cf7d2e3e1a32f3a284 Mon Sep 17 00:00:00 2001 From: stellarshenson Date: Fri, 6 Feb 2026 15:37:04 +0100 Subject: [PATCH] feat: add immediate loading spinners for admin user operations - show spinner immediately on "Add Users" click before POST completes, then transition message to "Generating credentials..." after response - add spinner for user rename (PATCH) with "Renaming user..." message - add error path cleanup hiding spinner on failed creation, empty response, or parse errors --- .../html_templates_enhanced/admin.html | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/services/jupyterhub/html_templates_enhanced/admin.html b/services/jupyterhub/html_templates_enhanced/admin.html index fe8867f..296c28b 100644 --- a/services/jupyterhub/html_templates_enhanced/admin.html +++ b/services/jupyterhub/html_templates_enhanced/admin.html @@ -168,12 +168,22 @@ const userDeleteMatch = urlPath.match(/api\/users\/([^\/]+)$/); const isUserDeletion = method === 'DELETE' && userDeleteMatch; + // Check for user rename - PATCH to api/users/{username} + const userPatchMatch = urlPath.match(/api\/users\/([^\/]+)$/); + const isUserRename = method === 'PATCH' && userPatchMatch; + // Show spinner for deletion if (isUserDeletion) { const username = decodeURIComponent(userDeleteMatch[1]); showLoadingSpinner('Deleting user ' + username + '...'); } + // Show spinner for rename + if (isUserRename) { + const username = decodeURIComponent(userPatchMatch[1]); + showLoadingSpinner('Renaming user ' + username + '...'); + } + // Capture request body before fetch (for batch user creation) let requestUsernames = []; if (isUserCreation) { @@ -191,6 +201,11 @@ } } + // Show spinner immediately when user creation POST is detected + if (isUserCreation && requestUsernames.length > 0) { + showLoadingSpinner('Creating users...'); + } + const response = await originalFetch.apply(this, args); // console.log('[Admin Fetch] Response status:', response.status); @@ -217,8 +232,8 @@ // console.log('[Admin] Users created:', createdUsers); pendingUsernames.push(...createdUsers); - // Show loading spinner - showLoadingSpinner('Generating credentials...'); + // Update spinner message for credential generation phase + document.getElementById('loading-modal-text').textContent = 'Generating credentials...'; // Debounce - wait for batch completion then fetch credentials clearTimeout(window._credentialsFetchTimeout); @@ -228,10 +243,15 @@ pendingUsernames = []; } }, 1000); + } else { + hideLoadingSpinner(); } + } else { + hideLoadingSpinner(); } } catch (e) { // console.error('[Admin] Error processing user creation:', e); + hideLoadingSpinner(); } } @@ -240,6 +260,11 @@ hideLoadingSpinner(); } + // Hide spinner after user rename completes + if (isUserRename) { + hideLoadingSpinner(); + } + return response; };