Skip to content

Commit a2a6bf3

Browse files
committed
adding loading animation
1 parent f1a298e commit a2a6bf3

File tree

3 files changed

+129
-58
lines changed

3 files changed

+129
-58
lines changed

mcpgateway/static/admin.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,24 @@
77
color: #a94442;
88
border: 1px solid #ebccd1;
99
}
10+
11+
12+
/* Add this CSS for the spinner */
13+
.spinner {
14+
border: 4px solid #f3f3f3;
15+
border-top: 4px solid #3498db;
16+
border-radius: 50%;
17+
width: 24px;
18+
height: 24px;
19+
animation: spin 1s linear infinite;
20+
/* margin: 10px auto; */
21+
22+
/* Positioning to the left */
23+
margin: 10px 0 10px 10px; /* top, right, bottom, left */
24+
display: block; /* Ensures it behaves like a block-level element */
25+
}
26+
27+
@keyframes spin {
28+
0% { transform: rotate(0deg); }
29+
100% { transform: rotate(360deg); }
30+
}

mcpgateway/static/admin.js

Lines changed: 98 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -147,31 +147,70 @@ document.addEventListener("DOMContentLoaded", function () {
147147
}
148148
});
149149

150+
// document
151+
// .getElementById("add-gateway-form")
152+
// .addEventListener("submit", (e) => {
153+
// e.preventDefault();
154+
// const form = e.target;
155+
// const formData = new FormData(form);
156+
// fetch(`${window.ROOT_PATH}/admin/gateways`, {
157+
// method: "POST",
158+
// body: formData,
159+
// })
160+
// .then((response) => {
161+
// console.log(response);
162+
// if (!response.ok) {
163+
// const status = document.getElementById("status-gateways");
164+
// status.textContent = "Connection failed!";
165+
// status.classList.add("error-status");
166+
// } else {
167+
// location.reload();
168+
// console.log(response);
169+
// }
170+
// })
171+
// .catch((error) => {
172+
// console.error("Error:", error);
173+
// });
174+
// });
175+
150176
document
151-
.getElementById("add-gateway-form")
152-
.addEventListener("submit", (e) => {
153-
e.preventDefault();
154-
const form = e.target;
155-
const formData = new FormData(form);
156-
fetch(`${window.ROOT_PATH}/admin/gateways`, {
157-
method: "POST",
158-
body: formData,
177+
.getElementById("add-gateway-form")
178+
.addEventListener("submit", (e) => {
179+
e.preventDefault();
180+
181+
const form = e.target;
182+
const formData = new FormData(form);
183+
184+
const status = document.getElementById("status-gateways");
185+
const loading = document.getElementById("add-gateway-loading");
186+
187+
// Show loading and clear previous status
188+
loading.style.display = "block";
189+
status.textContent = "";
190+
status.classList.remove("error-status");
191+
192+
fetch(`${window.ROOT_PATH}/admin/gateways`, {
193+
method: "POST",
194+
body: formData,
195+
})
196+
.then((response) => {
197+
if (!response.ok) {
198+
status.textContent = "Connection failed!";
199+
status.classList.add("error-status");
200+
} else {
201+
location.reload(); // Will exit before hiding spinner
202+
}
159203
})
160-
.then((response) => {
161-
console.log(response);
162-
if (!response.ok) {
163-
const status = document.getElementById("status-gateways");
164-
status.textContent = "Connection failed!";
165-
status.classList.add("error-status");
166-
} else {
167-
location.reload();
168-
console.log(response);
169-
}
170-
})
171-
.catch((error) => {
172-
console.error("Error:", error);
173-
});
174-
});
204+
.catch((error) => {
205+
console.error("Error:", error);
206+
status.textContent = "An error occurred!";
207+
status.classList.add("error-status");
208+
})
209+
.finally(() => {
210+
loading.style.display = "none"; // Hide loading
211+
});
212+
});
213+
175214

176215
document
177216
.getElementById("add-resource-form")
@@ -319,7 +358,7 @@ document.addEventListener("DOMContentLoaded", function () {
319358

320359
const requestTypeMap = {
321360
MCP: ["SSE", "STREAMABLE", "STDIO"],
322-
REST: ["GET", "POST", "PUT", "PATCH", "DELETE"],
361+
REST: ["GET", "POST", "PUT", "DELETE"],
323362
};
324363

325364

@@ -1650,9 +1689,9 @@ async function runToolTest() {
16501689
const formData = new FormData(form);
16511690
const params = {};
16521691
for (const [key, value] of formData.entries()) {
1653-
if(isNaN(value)) {
1654-
if(value.toLowerCase() === "true" || value.toLowerCase() === "false") {
1655-
params[key] = Boolean(value.toLowerCase() === "true");
1692+
if (isNaN(value)) {
1693+
if (value.toLowerCase() === "true" || value.toLowerCase() === "false") {
1694+
params[key] = value.toLowerCase() === "true";
16561695
} else {
16571696
params[key] = value;
16581697
}
@@ -1661,46 +1700,47 @@ async function runToolTest() {
16611700
}
16621701
}
16631702

1664-
// Build the JSON-RPC payload using the tool's name as the method
16651703
const payload = {
16661704
jsonrpc: "2.0",
16671705
id: Date.now(),
16681706
method: currentTestTool.name,
16691707
params: params,
16701708
};
16711709

1672-
// Send the request to your /rpc endpoint
1673-
fetch(`${window.ROOT_PATH}/rpc`, {
1674-
method: "POST",
1675-
headers: {
1676-
"Content-Type": "application/json", // ← make sure we include this
1677-
},
1678-
body: JSON.stringify(payload),
1679-
credentials: "include",
1680-
})
1681-
.then((response) => response.json())
1682-
.then((result) => {
1683-
const resultStr = JSON.stringify(result, null, 2);
1684-
1685-
const container = document.getElementById("tool-test-result");
1686-
container.innerHTML = ''; // clear any old editor
1687-
1688-
toolTestResultEditor = window.CodeMirror(
1689-
document.getElementById("tool-test-result"),
1690-
{
1691-
value: resultStr,
1692-
mode: "application/json",
1693-
theme: "monokai",
1694-
readOnly: true,
1695-
lineNumbers: true,
1696-
},
1697-
);
1698-
})
1699-
.catch((error) => {
1700-
document.getElementById("tool-test-result").innerText = "Error: " + error;
1710+
// Show loading
1711+
const loadingElement = document.getElementById("tool-test-loading");
1712+
loadingElement.style.display = "block";
1713+
const resultContainer = document.getElementById("tool-test-result");
1714+
resultContainer.innerHTML = "";
1715+
1716+
try {
1717+
const response = await fetch(`${window.ROOT_PATH}/rpc`, {
1718+
method: "POST",
1719+
headers: {
1720+
"Content-Type": "application/json",
1721+
},
1722+
body: JSON.stringify(payload),
1723+
credentials: "include",
17011724
});
1725+
1726+
const result = await response.json();
1727+
const resultStr = JSON.stringify(result, null, 2);
1728+
1729+
toolTestResultEditor = window.CodeMirror(resultContainer, {
1730+
value: resultStr,
1731+
mode: "application/json",
1732+
theme: "monokai",
1733+
readOnly: true,
1734+
lineNumbers: true,
1735+
});
1736+
} catch (error) {
1737+
resultContainer.innerText = "Error: " + error;
1738+
} finally {
1739+
loadingElement.style.display = "none"; // Hide loading after fetch or error
1740+
}
17021741
}
17031742

1743+
17041744
/* ---------------------------------------------------------------
17051745
* Utility: copy a JSON string (or any text) to the system clipboard
17061746
* ------------------------------------------------------------- */
@@ -1759,7 +1799,7 @@ function closeModal(modalId, clearId=null) {
17591799

17601800
const integrationRequestMap = {
17611801
MCP: ["SSE", "STREAMABLE", "STDIO"],
1762-
REST: ["GET", "POST", "PUT", "PATCH", "DELETE"],
1802+
REST: ["GET", "POST", "PUT", "DELETE"],
17631803
};
17641804

17651805
function updateRequestTypeOptions(preselectedValue = null) {

mcpgateway/templates/admin.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,9 @@ <h3 class="text-lg font-bold mb-4">Add New Gateway</h3>
14781478
/>
14791479
</div>
14801480
</div>
1481+
<div id="add-gateway-loading" style="display: none;">
1482+
<div class="spinner"></div>
1483+
</div>
14811484
<div id="status-gateways"></div>
14821485
</div>
14831486
<div class="mt-6">
@@ -1730,6 +1733,10 @@ <h3 class="text-lg font-medium text-gray-900">Tool Details</h3>
17301733
Run Tool
17311734
</button>
17321735
</div>
1736+
<div id="tool-test-loading" style="display: none;">
1737+
<div class="spinner"></div>
1738+
</div>
1739+
17331740
</form>
17341741
<!-- The result area now uses a fixed height for a larger view -->
17351742
<div
@@ -1751,6 +1758,9 @@ <h3 class="text-lg font-medium text-gray-900">Tool Details</h3>
17511758
</div>
17521759
</div>
17531760

1761+
1762+
1763+
17541764
<!-- Tool Edit Modal -->
17551765
<div id="tool-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
17561766
<div

0 commit comments

Comments
 (0)