tspace-nfs
Version:
tspace-nfs is a Network File System (NFS) and provides both server and client capabilities for accessing files over a network.
101 lines (88 loc) • 4.08 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NFS-Studio</title>
<style>
#loading {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
opacity: 0.75;
justify-content: center;
align-items: center;
z-index: 9999;
}
</style>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 dark:bg-gray-900">
<div id="loading" class="flex">
<div class="flex flex-col items-center">
<div class="animate-spin rounded-full h-20 w-20 border-t-4 border-b-4 border-blue-600"></div>
<p class="text-gray-800 dark:text-gray-200 text-xl font-semibold mt-4">Loading...</p>
</div>
</div>
<div class="flex items-center justify-center min-h-screen">
<div class="w-full max-w-md p-8 space-y-6 bg-white rounded-lg shadow-md dark:bg-gray-800">
<h2 class="text-3xl font-bold text-center text-gray-900 dark:text-gray-100">Login to Studio</h2>
<form id="loginForm" class="space-y-6" novalidate>
<div>
<label for="username" class="block text-sm font-medium text-gray-700 dark:text-gray-300">username</label>
<input type="username" id="username" name="username" required class="w-full p-2 mt-1 text-gray-900 border border-gray-300 rounded-md shadow-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Password</label>
<input type="password" id="password" name="password" required class="w-full p-2 mt-1 text-gray-900 border border-gray-300 rounded-md shadow-sm dark:bg-gray-700 dark:border-gray-600 dark:text-white focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div>
<button type="submit" class="w-full py-2 text-white bg-indigo-600 rounded-md hover:bg-indigo-700 focus:ring-2 focus:ring-indigo-500">Login</button>
</div>
<div id="errorMessage" class="text-red-500 text-sm hidden">Invalid username or password. Please try again.</div>
</form>
</div>
</div>
</body>
<script>
const $ = (element) => document.querySelector(element)
const loading = $('#loading')
const loginForm = $('#loginForm');
const errorMessage = $('#errorMessage');
const url = `${window.location.protocol}//${window.location.host}`
loginForm.addEventListener('submit', async (event) => {
event.preventDefault();
const username = $('#username').value;
const password = $('#password').value;
try {
loading.style.display = 'flex';
const response = await fetch(`${url}/studio/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
if (response.ok) {
const data = await response.json();
errorMessage.classList.add('hidden');
await new Promise(r => setTimeout(r, 1000));
loading.style.display = 'none'
window.location.reload()
return
}
await new Promise(r => setTimeout(r, 500));
loading.style.display = 'none';
errorMessage.classList.remove('hidden');
} catch (error) {
errorMessage.textContent = 'An error occurred. Please try again later.';
errorMessage.classList.remove('hidden');
loading.style.display = 'flex';
}
})
</script>
</html>