Spaces:
Sleeping
Sleeping
| <html> | |
| <head> | |
| <title>API Comparison Results</title> | |
| <link | |
| rel="stylesheet" | |
| href="{{url_for('static', path='css/styles.css') }}" | |
| /> | |
| <style> | |
| .diff-highlight-add { | |
| background-color: #e6ffe6; | |
| color: green; | |
| } | |
| .diff-highlight-remove { | |
| background-color: #ffe6e6; | |
| color: red; | |
| } | |
| .spinner { | |
| display: none; | |
| width: 50px; | |
| height: 50px; | |
| border: 5px solid #f3f3f3; | |
| border-top: 5px solid #4caf50; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin: 20px auto; | |
| } | |
| @keyframes spin { | |
| 0% { | |
| transform: rotate(0deg); | |
| } | |
| 100% { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| .api-info { | |
| background-color: #f8f9fa; | |
| padding: 10px; | |
| border-radius: 4px; | |
| margin-bottom: 10px; | |
| border-left: 4px solid #4caf50; | |
| } | |
| .api-endpoint { | |
| font-family: monospace; | |
| color: #0056b3; | |
| word-break: break-all; | |
| } | |
| .session-timeout-warning { | |
| display: none; | |
| background-color: #fff3cd; | |
| border: 1px solid #ffeeba; | |
| padding: 10px; | |
| border-radius: 4px; | |
| margin: 20px auto; | |
| text-align: center; | |
| } | |
| .session-timeout-warning h3 { | |
| margin: 0; | |
| font-size: 18px; | |
| color: #856404; | |
| } | |
| .session-timeout-warning p { | |
| margin: 10px 0; | |
| font-size: 14px; | |
| color: #856404; | |
| } | |
| .session-timeout-warning button { | |
| margin: 5px; | |
| padding: 5px 10px; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| } | |
| .session-timeout-warning .continue { | |
| background-color: #4caf50; | |
| color: white; | |
| } | |
| .session-timeout-warning .logout { | |
| background-color: #f44336; | |
| color: white; | |
| } | |
| .alert { | |
| padding: 15px; | |
| margin-bottom: 20px; | |
| border: 1px solid transparent; | |
| border-radius: 4px; | |
| } | |
| .alert-error { | |
| color: #721c24; | |
| background-color: #f8d7da; | |
| border-color: #f5c6cb; | |
| } | |
| .alert-error .close { | |
| float: right; | |
| font-size: 20px; | |
| font-weight: bold; | |
| line-height: 20px; | |
| cursor: pointer; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <a href="/compare"> | |
| <img | |
| src="{{ url_for('static', path='/images/TD-logo.jpeg') }}" | |
| alt="Logo" | |
| class="logo" | |
| /> | |
| </a> | |
| <div class="user-menu"> | |
| <div>Welcome, {{ username }}!</div> | |
| <div class="user-menu-content"> | |
| <a href="/logout">Logout</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="errorAlert" class="alert alert-error" style="display: none"> | |
| <span class="close" onclick="this.parentElement.style.display='none';" | |
| >×</span | |
| > | |
| <strong>Error!</strong> <span id="errorMessage"></span> | |
| </div> | |
| <div id="session-timeout" class="session-timeout-warning"> | |
| <h3>Session Timeout Warning</h3> | |
| <p> | |
| Your session will expire in | |
| <span id="timeout-countdown">60</span> seconds due to inactivity. | |
| </p> | |
| <button class="continue" onclick="extendSession()"> | |
| Continue Session | |
| </button> | |
| <button class="logout" onclick="window.location.href='/logout'"> | |
| Logout | |
| </button> | |
| </div> | |
| <div class="results"> | |
| <h2>API Comparison Results</h2> | |
| <div id="loading-spinner" class="spinner"></div> | |
| <div class="grid"> | |
| <div> | |
| <h3>First API</h3> | |
| <div class="api-info"> | |
| <p> | |
| <strong>Endpoint:</strong> | |
| <span class="api-endpoint" | |
| >{{ api1_url }} ({{ api1_method }})</span | |
| > | |
| </p> | |
| <p>Execution Time: {{ execution_time_api1 }}s</p> | |
| <p>Status Code: {{ status_code1 }}</p> | |
| </div> | |
| <form | |
| method="POST" | |
| action="/download/" | |
| style="display: inline" | |
| onsubmit="return handleDownload(event, this)" | |
| > | |
| <input type="hidden" name="content" value="{{ api1_result }}" /> | |
| <input type="hidden" name="filename" value="api1_result.json" /> | |
| <input type="hidden" name="username" value="{{ username }}" /> | |
| <button type="submit" class="download-button"> | |
| Download API 1 Result | |
| </button> | |
| </form> | |
| <div class="json-content"> | |
| <pre id="api1-content">{{ api1_result | safe }}</pre> | |
| </div> | |
| </div> | |
| <div> | |
| <h3>Second API</h3> | |
| <div class="api-info"> | |
| <p> | |
| <strong>Endpoint:</strong> | |
| <span class="api-endpoint" | |
| >{{ api2_url }} ({{ api2_method }})</span | |
| > | |
| </p> | |
| <p>Execution Time: {{ execution_time_api2 }}s</p> | |
| <p>Status Code: {{ status_code2 }}</p> | |
| </div> | |
| <form | |
| method="POST" | |
| action="/download/" | |
| style="display: inline" | |
| onsubmit="return handleDownload(event, this)" | |
| > | |
| <input type="hidden" name="content" value="{{ api2_result }}" /> | |
| <input type="hidden" name="filename" value="api2_result.json" /> | |
| <input type="hidden" name="username" value="{{ username }}" /> | |
| <button type="submit" class="download-button"> | |
| Download API 2 Result | |
| </button> | |
| </form> | |
| <div class="json-content"> | |
| <pre id="api2-content">{{ api2_result | safe }}</pre> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="comparison-results"> | |
| <h3>Differences</h3> | |
| <form | |
| method="POST" | |
| action="/download/" | |
| style="display: inline" | |
| onsubmit="return handleDownload(event, this)" | |
| > | |
| <input type="hidden" name="content" value="{{ diff_text }}" /> | |
| <input | |
| type="hidden" | |
| name="filename" | |
| value="comparison_result.txt" | |
| /> | |
| <input type="hidden" name="username" value="{{ username }}" /> | |
| <button type="submit" class="download-button"> | |
| Download Comparison Result | |
| </button> | |
| </form> | |
| <div class="results-view"> | |
| {% if view_mode == "line" %} {% if diff_result.strip() == '' %} | |
| <div class="success">Both responses are identical.</div> | |
| {% else %} | |
| <div class="diff-content">{{ diff_result | safe }}</div> | |
| {% endif %} {% else %} | |
| <pre>{{ diff_result | safe }}</pre> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <div style="margin-top: 20px"> | |
| <a href="/compare" class="button">Compare More APIs</a> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| function highlightDifferences() { | |
| const api1Content = document.getElementById("api1-content"); | |
| const api2Content = document.getElementById("api2-content"); | |
| if (!api1Content || !api2Content) return; | |
| const lines1 = api1Content.textContent.split("\n"); | |
| const lines2 = api2Content.textContent.split("\n"); | |
| let html1 = ""; | |
| let html2 = ""; | |
| const maxLines = Math.max(lines1.length, lines2.length); | |
| for (let i = 0; i < maxLines; i++) { | |
| const line1 = lines1[i] || ""; | |
| const line2 = lines2[i] || ""; | |
| if (line1 !== line2) { | |
| html1 += `<span class="diff-highlight-remove">${line1}</span>\n`; | |
| html2 += `<span class="diff-highlight-remove">${line2}</span>\n`; | |
| } else { | |
| html1 += line1 + "\n"; | |
| html2 += line2 + "\n"; | |
| } | |
| } | |
| api1Content.innerHTML = html1; | |
| api2Content.innerHTML = html2; | |
| } | |
| document.addEventListener("DOMContentLoaded", highlightDifferences); | |
| function extendSession() { | |
| document.getElementById("session-timeout").style.display = "none"; | |
| } | |
| setTimeout(() => { | |
| document.getElementById("session-timeout").style.display = "block"; | |
| }, 300000); | |
| async function handleDownload(event, form) { | |
| event.preventDefault(); | |
| try { | |
| const formData = new FormData(form); | |
| const response = await fetch(form.action, { | |
| method: "POST", | |
| body: formData, | |
| }); | |
| if (!response.ok) { | |
| const data = await response.json().catch(() => null); | |
| throw new Error( | |
| data?.detail || "Failed to download file. Please try again." | |
| ); | |
| } | |
| const blob = await response.blob(); | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement("a"); | |
| a.href = url; | |
| a.download = formData.get("filename"); | |
| document.body.appendChild(a); | |
| a.click(); | |
| window.URL.revokeObjectURL(url); | |
| document.body.removeChild(a); | |
| } catch (error) { | |
| showError(error.message || "Something went wrong. Please try again."); | |
| } | |
| return false; | |
| } | |
| function showError(message) { | |
| const errorAlert = document.getElementById("errorAlert"); | |
| const errorMessage = document.getElementById("errorMessage"); | |
| errorMessage.textContent = message; | |
| errorAlert.style.display = "block"; | |
| setTimeout(() => { | |
| errorAlert.style.display = "none"; | |
| }, 5000); | |
| } | |
| window.addEventListener("unhandledrejection", function (event) { | |
| showError( | |
| "Network error occurred. Please check your connection and try again." | |
| ); | |
| }); | |
| </script> | |
| <div | |
| style="text-align: center; margin-top: 20px; color: #666; font-size: 12px" | |
| > | |
| Copyright © 2025 TELUS Digital. All rights reserved.<br /> | |
| For internal use only. | |
| </div> | |
| </body> | |
| </html> | |