diff --git a/mcpgateway/templates/admin.html b/mcpgateway/templates/admin.html index 0046a917f..e8c8ad992 100644 --- a/mcpgateway/templates/admin.html +++ b/mcpgateway/templates/admin.html @@ -2712,6 +2712,29 @@

+ + + @@ -3181,7 +3204,33 @@

-
+ +
+ +
+ + + @@ -10633,6 +10682,7 @@

Available Log Files

document.getElementById("import-preview").classList.add("hidden"); document.getElementById("import-status").classList.add("hidden"); document.getElementById("import-loading").classList.add("hidden"); + document.getElementById("import-statistics").classList.add("hidden"); // Reset validation status document.getElementById("json-validation-status").textContent = ""; @@ -11024,6 +11074,9 @@

Available Log Files

document.getElementById("import-loading").classList.add("hidden"); if (response.ok) { + // Update statistics display + updateImportStatistics(result); + if (result.success) { // Complete success showImportSuccess(result); @@ -11044,16 +11097,16 @@

Available Log Files

}, 5000); // Longer delay to see the message } else { // Complete failure - showImportError(result.message || "All tools failed to import"); + showImportError(result.message || "All tools failed to import", result); document.getElementById("import-submit-btn").disabled = false; } } else { - showImportError(result.message || "Import failed"); + showImportError(result.message || "Import failed", result); document.getElementById("import-submit-btn").disabled = false; } } catch (error) { document.getElementById("import-loading").classList.add("hidden"); - showImportError(`Network error: ${error.message}`); + showImportError(`Network error: ${error.message}`, null); document.getElementById("import-submit-btn").disabled = false; } }; @@ -11064,6 +11117,7 @@

Available Log Files

const isPartialSuccess = result.failed_count > 0; const bgColor = isPartialSuccess ? "yellow" : "green"; const textColor = isPartialSuccess ? "yellow" : "green"; + const totalTools = (result.created_count || 0) + (result.failed_count || 0); statusDiv.innerHTML = `
@@ -11073,33 +11127,64 @@

Available Log Files

-
+

${isPartialSuccess ? "Import Partially Completed" : "Import Completed Successfully"}

-
-

${result.created_count} tools imported successfully

- ${result.failed_count > 0 ? `

${result.failed_count} tools failed to import

` : ""} + + +
+
+
${totalTools}
+
Total Tools
+
+
+
${result.created_count || 0}
+
Successful
+
+
+
${result.failed_count || 0}
+
Failed
+
+
+ +
+

${result.created_count || 0} tools imported successfully out of ${totalTools} total tools

+ ${result.failed_count > 0 ? `

${result.failed_count} tools failed to import

` : ""} ${ result.errors && result.errors.length > 0 ? ` -
- View errors -
    - ${result.errors - .slice(0, 5) - .map( - (error) => - `
  • ${error.name || "Tool"}: ${error.error?.message || "Unknown error"}
  • `, - ) - .join("")} - ${result.errors.length > 5 ? `
  • ... and ${result.errors.length - 5} more errors
  • ` : ""} -
+
+ + 📋 View Failed Tools (${result.errors.length}) + +
+
+ ${result.errors + .map( + (error, index) => ` +
+
+
+ ${index + 1}. ${escapeHtml(error.name || error.tool_name || "Unnamed Tool")} +
+ +
+
+ Error: ${escapeHtml(error.error?.message || error.message || "Unknown error")} +
+ ${error.url ? `
URL: ${escapeHtml(error.url)}
` : ""} +
+ ` + ) + .join("")} +
+
` : "" } -

Page will refresh automatically...

+

Page will refresh automatically...

@@ -11109,8 +11194,36 @@

${escapeHtml(message)}

`; + + // If we have detailed error information, show statistics + if (result && (result.failed_count > 0 || result.errors)) { + const totalTools = (result.created_count || 0) + (result.failed_count || 0); + const successCount = result.created_count || 0; + const failedCount = result.failed_count || 0; + + errorContent = ` +
+
+
${totalTools}
+
Total Tools
+
+
+
${successCount}
+
Successful
+
+
+
${failedCount}
+
Failed
+
+
+

${escapeHtml(message)}

+ `; + } + statusDiv.innerHTML = `
@@ -11119,12 +11232,12 @@

-
+

- Import Error + Import ${result && result.created_count > 0 ? 'Partially Failed' : 'Failed'}

-

${escapeHtml(message)}

+ ${errorContent}
@@ -11133,6 +11246,20 @@

statusDiv.classList.remove("hidden"); } + // Update import statistics display + function updateImportStatistics(result) { + const totalTools = (result.created_count || 0) + (result.failed_count || 0); + const successCount = result.created_count || 0; + const failedCount = result.failed_count || 0; + + document.getElementById("stats-total").textContent = totalTools; + document.getElementById("stats-success").textContent = successCount; + document.getElementById("stats-failed").textContent = failedCount; + + // Show the statistics section + document.getElementById("import-statistics").classList.remove("hidden"); + } + // Format file size function formatFileSize(bytes) { if (bytes === 0) return "0 Bytes"; @@ -11265,10 +11392,44 @@

window.showDropdownStatus = function (type, message) { const status = document.getElementById("dropdown-status"); - status.innerHTML = `
${escapeHtml(message)}
`; + const colorClass = type === "error" ? "red" : type === "warning" ? "yellow" : "green"; + const content = message.includes('${content}

`; status.classList.remove("hidden"); }; + window.showDropdownResults = function (total, success, failed) { + document.getElementById("dropdown-stats-total").textContent = total; + document.getElementById("dropdown-stats-success").textContent = success; + document.getElementById("dropdown-stats-failed").textContent = failed; + document.getElementById("dropdown-results").classList.remove("hidden"); + }; + + window.showDropdownFailedTools = function (errors) { + const failedToolsHtml = errors.map((error, index) => + `
+
${index + 1}. ${escapeHtml(error.name || error.tool_name || "Unnamed Tool")}
+
${escapeHtml(error.error?.message || error.message || "Unknown error")}
+
` + ).join(''); + + showDropdownStatus("error", `
Failed Tools (${errors.length}):
${failedToolsHtml}
`); + }; + + window.showDropdownActionButtons = function() { + const actionButtonsHtml = `
+ + +
`; + + const statusDiv = document.getElementById("dropdown-status"); + statusDiv.innerHTML += actionButtonsHtml; + }; + window.resetDropdownImport = function () { document.getElementById("dropdown-file-input").value = ""; document.getElementById("dropdown-json-textarea").value = ""; @@ -11276,6 +11437,7 @@

document.getElementById("dropdown-json-status").textContent = ""; document.getElementById("dropdown-preview").classList.add("hidden"); document.getElementById("dropdown-status").classList.add("hidden"); + document.getElementById("dropdown-results").classList.add("hidden"); document.getElementById("dropdown-import-btn").disabled = true; }; @@ -11333,18 +11495,31 @@

const result = await response.json(); if (response.ok) { - showDropdownStatus( - "success", - `✅ Successfully imported ${result.imported} tools`, - ); - resetDropdownImport(); - setTimeout(() => { - window.location.reload(); - }, 2000); + const totalTools = (result.created_count || result.imported || 0) + (result.failed_count || 0); + const successCount = result.created_count || result.imported || 0; + const failedCount = result.failed_count || 0; + + // Show statistics + showDropdownResults(totalTools, successCount, failedCount); + + let statusMessage = `✅ Import completed: ${successCount}/${totalTools} tools imported successfully`; + if (failedCount > 0) { + statusMessage = `⚠️ Partial success: ${successCount}/${totalTools} tools imported, ${failedCount} failed`; + } + + showDropdownStatus("success", statusMessage); + + // Show failed tools if any + if (result.errors && result.errors.length > 0) { + showDropdownFailedTools(result.errors); + } + + // Show close/refresh buttons after import + showDropdownActionButtons(); } else { showDropdownStatus( "error", - `❌ Import failed: ${result.detail || "Unknown error"}`, + `❌ Import failed: ${result.detail || result.message || "Unknown error"}`, ); } } catch (error) {