| | <!DOCTYPE html>
|
| | <html lang="en" data-theme="light">
|
| | <head>
|
| | <meta charset="UTF-8">
|
| | <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| | <title data-i18n="nav.title">HF Space Deployer</title>
|
| |
|
| |
|
| | <link href="https://cdn.jsdelivr.net/npm/daisyui@4.6.0/dist/full.min.css" rel="stylesheet" type="text/css" />
|
| | <script src="https://cdn.tailwindcss.com"></script>
|
| |
|
| |
|
| | <link href="/static/style.css" rel="stylesheet" type="text/css" />
|
| |
|
| |
|
| | <script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
| |
|
| |
|
| | <script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
| |
|
| |
|
| | <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
| |
|
| |
|
| | <script src="/static/i18n.js"></script>
|
| |
|
| | <style>
|
| | .loading-spinner {
|
| | animation: spin 2s linear infinite;
|
| | }
|
| | @keyframes spin {
|
| | from { transform: rotate(0deg); }
|
| | to { transform: rotate(360deg); }
|
| | }
|
| | .fade-in {
|
| | animation: fadeIn 0.5s ease-in-out;
|
| | }
|
| | @keyframes fadeIn {
|
| | from { opacity: 0; transform: translateY(10px); }
|
| | to { opacity: 1; transform: translateY(0); }
|
| | }
|
| | </style>
|
| | </head>
|
| | <body class="min-h-screen bg-base-100">
|
| |
|
| | <div class="navbar bg-primary text-primary-content shadow-lg sticky top-0 z-50">
|
| | <div class="container mx-auto">
|
| | <div class="flex-1">
|
| | <a href="/" class="btn btn-ghost text-xl font-bold">
|
| | <i data-lucide="rocket" class="w-6 h-6 mr-2"></i>
|
| | <span data-i18n="nav.title">HF Space Deployer</span>
|
| | </a>
|
| | </div>
|
| | <div class="flex-none space-x-2">
|
| | <button
|
| | class="btn btn-ghost btn-circle"
|
| | onclick="toggleLanguage()"
|
| | data-i18n-title="nav.language"
|
| | title="Language"
|
| | >
|
| | <span class="text-lg font-bold lang-icon">EN</span>
|
| | </button>
|
| | <button
|
| | class="btn btn-ghost btn-circle"
|
| | onclick="toggleTheme()"
|
| | data-i18n-title="nav.theme"
|
| | title="Toggle Theme"
|
| | >
|
| | <i data-lucide="sun" class="w-5 h-5 theme-icon"></i>
|
| | </button>
|
| | </div>
|
| | </div>
|
| | </div>
|
| |
|
| |
|
| | <div id="toast-container" class="fixed top-20 right-4 z-50 space-y-2"></div>
|
| |
|
| |
|
| | <main class="container mx-auto px-4 py-8 max-w-6xl">
|
| | {% block content %}{% endblock %}
|
| | </main>
|
| |
|
| |
|
| | <footer class="footer footer-center p-8 bg-base-200 text-base-content mt-16">
|
| | <div>
|
| | <p class="font-bold text-lg" data-i18n="footer.title">HF Space Deployer</p>
|
| | <p class="text-sm opacity-70" data-i18n="footer.desc">Quick deployment tool</p>
|
| | </div>
|
| | <div class="flex items-center space-x-4 text-sm">
|
| | <a href="https://github.com/kfcx/HFSpaceDeploy.git" target="_blank" class="link link-hover">GitHub</a>
|
| | <span>•</span>
|
| | <a href="https://huggingface.co" target="_blank" class="link link-hover">HuggingFace</a>
|
| | </div>
|
| | </footer>
|
| |
|
| | <script>
|
| |
|
| | function updateLanguageIcon() {
|
| | const langIcon = document.querySelector('.lang-icon');
|
| | langIcon.textContent = currentLang === 'en' ? 'EN' : '中';
|
| | }
|
| |
|
| |
|
| | if (typeof window.originalToggleLanguage === 'undefined') {
|
| | window.originalToggleLanguage = toggleLanguage;
|
| | window.toggleLanguage = function() {
|
| | window.originalToggleLanguage();
|
| | updateLanguageIcon();
|
| | };
|
| | }
|
| |
|
| |
|
| | function toggleTheme() {
|
| | const currentTheme = document.documentElement.getAttribute('data-theme');
|
| | const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
| | setTheme(newTheme);
|
| | }
|
| |
|
| | function setTheme(theme) {
|
| | document.documentElement.setAttribute('data-theme', theme);
|
| | localStorage.setItem('theme', theme);
|
| |
|
| |
|
| | const themeIcon = document.querySelector('.theme-icon');
|
| | if (theme === 'dark') {
|
| | themeIcon.setAttribute('data-lucide', 'moon');
|
| | } else {
|
| | themeIcon.setAttribute('data-lucide', 'sun');
|
| | }
|
| | lucide.createIcons();
|
| | }
|
| |
|
| |
|
| | const savedTheme = localStorage.getItem('theme') || 'light';
|
| | setTheme(savedTheme);
|
| |
|
| |
|
| | lucide.createIcons();
|
| |
|
| |
|
| | document.body.addEventListener('htmx:afterRequest', function(evt) {
|
| |
|
| | lucide.createIcons();
|
| |
|
| | updatePageTranslations();
|
| | });
|
| |
|
| |
|
| | function copyToClipboard(text) {
|
| | navigator.clipboard.writeText(text).then(function() {
|
| | showToast(t('toast.copied'), 'success');
|
| | }).catch(function(err) {
|
| | showToast(t('toast.copyFailed'), 'error');
|
| | });
|
| | }
|
| |
|
| |
|
| | function showToast(message, type = 'info') {
|
| | const toastContainer = document.getElementById('toast-container');
|
| | const toast = document.createElement('div');
|
| | toast.className = `alert alert-${type} shadow-lg fade-in min-w-[300px]`;
|
| |
|
| | const icons = {
|
| | 'success': 'check-circle',
|
| | 'error': 'x-circle',
|
| | 'warning': 'alert-triangle',
|
| | 'info': 'info'
|
| | };
|
| |
|
| | toast.innerHTML = `
|
| | <i data-lucide="${icons[type]}" class="w-5 h-5"></i>
|
| | <span>${message}</span>
|
| | `;
|
| |
|
| | toastContainer.appendChild(toast);
|
| | lucide.createIcons();
|
| |
|
| |
|
| | setTimeout(() => {
|
| | toast.style.opacity = '0';
|
| | toast.style.transform = 'translateY(-10px)';
|
| | setTimeout(() => toast.remove(), 300);
|
| | }, 3000);
|
| | }
|
| |
|
| |
|
| | document.body.addEventListener('htmx:responseError', function(evt) {
|
| | showToast(t('toast.requestFailed'), 'error');
|
| | });
|
| |
|
| |
|
| | document.addEventListener('show-toast', function(event) {
|
| | const { message, type } = event.detail;
|
| | showToast(message, type);
|
| | });
|
| |
|
| |
|
| | document.addEventListener('DOMContentLoaded', function() {
|
| |
|
| | if (typeof lucide !== 'undefined') {
|
| | lucide.createIcons();
|
| | }
|
| |
|
| |
|
| | updateLanguageIcon();
|
| | });
|
| |
|
| |
|
| | if (typeof Alpine !== 'undefined') {
|
| | document.addEventListener('alpine:init', () => {
|
| | console.log('Alpine.js initialized');
|
| | });
|
| | }
|
| | </script>
|
| | </body>
|
| | </html> |