<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>🔬 Aropha AI Biodegradation Prediction Platform</title> <style> /* General Styles */ body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0; padding: 0; background-color: #2C4555; color: #ffffff; display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; } .container { background: #1E2A34; padding: 30px; border-radius: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); width: 90%; max-width: 500px; text-align: center; } /* Logo */ .logo { width: 200px; margin-bottom: 20px; margin-top: 20px; } /* Headings */ h1 { margin-bottom: 20px; font-size: 24px; color: #ffffff; } /* Form Groups */ .form-group { margin-bottom: 15px; text-align: left; } label { display: block; margin: 10px 0 5px; font-weight: bold; color: #ffffff; } /* Input Fields */ input[type="email"], input[type="password"], input[type="file"] { width: 100%; padding: 10px; margin-bottom: 10px; border-radius: 5px; background: #24343D; color: #ffffff; border: none; outline: none; } input::placeholder { color: #b0b8bf; } /* Buttons */ button, input[type="submit"] { width: 100%; background-color: #007BFF; color: #ffffff; border: none; padding: 12px; border-radius: 5px; cursor: pointer; font-size: 16px; } button:hover, input[type="submit"]:hover { background-color: #0056b3; } /* Row with label + file input side by side */ .row-flex { display: flex; align-items: center; gap: 0.8em; flex-wrap: wrap; } /* Message Boxes */ #creditsBox, #messages { background: #24343D; padding: 15px; min-height: 50px; border: 1px solid #007BFF; margin-top: 15px; white-space: pre-wrap; border-radius: 5px; color: #ffffff; text-align: left; /* Align text to left */ } /* Footer Styles */ footer { text-align: center; padding: 10px; color: #b0b8bf; font-size: 14px; } footer a { color: #ffffff; text-decoration: underline; } </style> </head> <body> <div class="container"> <img src="https://www.users.aropha.com/static/assets/img/logo-rectangular.png" alt="Aropha Logo" class="logo"> <h1>Aropha's Biodegradation Prediction Platform</h1> <form id="arophaForm"> <!-- Email --> <div class="form-group"> <label for="email">Email:</label> <input type="email" id="email" name="email" placeholder="Enter your email" required /> </div> <!-- Password --> <div class="form-group"> <label for="password">Password:</label> <input type="password" id="password" name="password" placeholder="Enter your password" required /> </div> <!-- Check Credits button --> <div class="form-group"> <button id="checkCreditsBtn" type="button"> Check Your Credits </button> </div> <!-- Spreadsheet (.xlsx) label next to file chooser --> <div class="form-group row-flex"> <label for="spreadsheet" style="margin-bottom: 0;"> Spreadsheet (.xlsx): </label> <input type="file" id="spreadsheet" name="spreadsheet" accept=".xlsx" required /> </div> <!-- Submit Template Spreadsheet button --> <div class="form-group"> <button id="submitBtn" type="submit"> Submit Template Spreadsheet </button> </div> </form> <!-- Displays credit info from the server --> <div id="creditsBox"></div> <!-- Displays messages for final spreadsheet submission --> <div id="messages"></div> </div> <footer> <p> Follow us on <a href="https://www.linkedin.com/company/aropha/">LinkedIn</a> | © 2025 Aropha Inc. All Rights Reserved. </p> </footer> <script> // Utility: convert ArrayBuffer to Base64 function arrayBufferToBase64(buffer) { let binary = ''; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } // 1) Check Your Credits document.getElementById('checkCreditsBtn').addEventListener('click', async () => { const creditsBox = document.getElementById('creditsBox'); creditsBox.textContent = 'Checking credits...'; const email = document.getElementById('email').value.trim(); const password = document.getElementById('password').value; if (!email || !password) { creditsBox.textContent = 'Please enter Email and Password first.'; return; } // Construct JSON payload const json_data = { email, password, filename: 'filename_blank', raw_data: 'blank' }; try { const response = await fetch('https://modelserver.aropha.com/run_twin_engines', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(json_data) }); if (!response.ok) { try { const errorData = await response.json(); console.log('Full error response:', errorData); if (errorData.detail) { creditsBox.textContent = errorData.detail; } else { creditsBox.textContent = `Error: ${JSON.stringify(errorData, null, 2)}`; } } catch (jsonError) { const rawError = await response.text(); console.error('Raw error response:', rawError); creditsBox.textContent = `Error: Could not parse JSON. Raw response: ${rawError}`; } return; } const responseData = await response.json(); if (typeof responseData.credits !== 'undefined') { creditsBox.textContent = `You have ${responseData.credits} credits remaining.`; } else { creditsBox.textContent = 'Credits info not found in server response.'; } } catch (err) { creditsBox.textContent = 'Error: ' + err; } }); // 2) Submit the form (spreadsheet upload) document.getElementById('arophaForm').addEventListener('submit', async function (event) { event.preventDefault(); // Prevent normal form POST const messagesDiv = document.getElementById('messages'); messagesDiv.textContent = 'Preparing and uploading...'; const email = document.getElementById('email').value.trim(); const password = document.getElementById('password').value; const fileInput = document.getElementById('spreadsheet'); if (!fileInput.files || fileInput.files.length === 0) { messagesDiv.textContent = 'Please select a spreadsheet file.'; return; } const file = fileInput.files[0]; const filename = file.name; // Read the file as an ArrayBuffer let fileBuffer; try { fileBuffer = await file.arrayBuffer(); } catch (err) { messagesDiv.textContent = 'Error reading file: ' + err; return; } // Convert the ArrayBuffer to Base64 const raw_data_b64 = arrayBufferToBase64(fileBuffer); // Construct JSON payload const json_data = { email, password, filename, raw_data: raw_data_b64 }; // POST to Aropha modelserver try { const response = await fetch('https://modelserver.aropha.com/run_twin_engines', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(json_data) }); if (response.status === 422) { const responseData = await response.json(); if (responseData.detail) { messagesDiv.textContent = responseData.detail; } else { messagesDiv.textContent = JSON.stringify(responseData, null, 2); } if (responseData['flag data']) { const flagBase64 = responseData['flag data']; const byteChars = atob(flagBase64); const byteNumbers = new Array(byteChars.length); for (let i = 0; i < byteChars.length; i++) { byteNumbers[i] = byteChars.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const blob = new Blob([byteArray], { type: 'application/gzip' }); const now = new Date(); const currentDate = now.toISOString().split('T')[0]; const currentTime = now.toTimeString().split(' ')[0].replace(/:/g, '-'); const templateFileName = filename.replace(/\.[^/.]+$/, ''); const dynamicFileName = `flag_notes_${templateFileName}_${currentDate}_${currentTime}.gz`; const downloadUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = dynamicFileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(downloadUrl); } return; } else if (!response.ok) { try { const errorData = await response.json(); console.log('Full error response:', errorData); if (errorData.detail) { messagesDiv.textContent = errorData.detail; } else { messagesDiv.textContent = `Error: ${JSON.stringify(errorData, null, 2)}`; } } catch (jsonError) { const rawError = await response.text(); console.error('Raw error response:', rawError); messagesDiv.textContent = `Error: Could not parse JSON. Raw response: ${rawError}`; } return; } if (response.status === 200) { const message = await response.json(); messagesDiv.textContent = message.detail; } } catch (err) { messagesDiv.textContent = 'Error submitting data: ' + err; } }); </script> </body> </html>
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter