initial commit

This commit is contained in:
2025-02-14 22:37:52 -05:00
commit df1c16aa50
14 changed files with 1276 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Static Site Host - {% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" id="theme-style">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const themeToggle = document.querySelector('#theme-toggle');
const body = document.body;
// Get saved theme from localStorage
const savedTheme = localStorage.getItem('theme') || 'dark';
body.setAttribute('data-theme', savedTheme);
if (!savedTheme) localStorage.setItem('theme', savedTheme);
// Set initial button text
themeToggle.textContent = savedTheme === 'dark' ? 'Light Mode' : 'Dark Mode';
themeToggle.addEventListener('click', () => {
const isDark = body.getAttribute('data-theme') === 'dark';
body.setAttribute('data-theme', isDark ? 'light' : 'dark');
localStorage.setItem('theme', isDark ? 'light' : 'dark');
themeToggle.textContent = isDark ? 'Dark Mode' : 'Light Mode';
});
});
</script>
</head>
<body>
<nav class="navbar">
<div class="container">
<a href="{{ url_for('home') }}">Home</a>
{% if current_user.is_authenticated %}
<a href="{{ url_for('dashboard') }}">Dashboard</a>
<a href="{{ url_for('logout') }}">Logout</a>
{% else %}
<a href="{{ url_for('login') }}">Login</a>
<a href="{{ url_for('register') }}">Register</a>
{% endif %}
<button id="theme-toggle" class="btn">Toggle Dark Mode</button>
</div>
</nav>
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="flash-message flash-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h2>Your Sites</h2>
<h3>Create New Site</h3>
<form method="POST" action="{{ url_for('upload_site') }}" enctype="multipart/form-data">
<div class="form-group">
<label>Site Name:</label>
<input type="text" name="name" required>
</div>
<div class="form-group" onclick="document.querySelector('#file-input').click()">
<label class="upload-label">
Upload Files
<input type="file" name="files" style="display: none;" id="file-input" multiple accept=".html,.css,.js" required>
</label>
</div>
<!-- File Preview Section -->
<div id="file-preview" class="file-preview">
<h5>Selected Files:</h5>
<div id="file-grid" class="file-grid"></div>
</div>
<button type="submit" class="btn" style="margin-top: 20px;">Create Site</button>
</form>
<div style="margin-bottom: 30px;"></div>
<h1>My Sites</h1>
<div class="sites-list">
{% for site in sites %}
<div class="site-card">
<h4>{{ site.name }}</h4>
<p>Created: {{ site.created_at.strftime('%Y-%m-%d') }}</p>
<!-- Display uploaded files -->
<div class="uploaded-files">
<h5>Uploaded Files:</h5>
<div class="file-grid">
{% set site_dir = 'sites/' + current_user.id|string + '/' + site.id|string %}
{% for file in list_files(site_dir) %}
<div class="file-card">
<div
class="file-icon {{ 'html' if file.endswith('.html') else 'css' if file.endswith('.css') else 'js' }}">
</div>
<span class="file-name">{{ file }}</span>
<form method="POST" action="{{ url_for('delete_file', site_id=site.id, filename=file) }}"
style="display: inline;">
<button type="submit" class="file-close">&times;</button>
</form>
</div>
{% endfor %}
</div>
</div>
<!-- Site Actions -->
<div class="site-actions">
<a href="{{ url_for('edit_site', site_id=site.id) }}" class="btn">Edit</a>
<a href="{{ url_for('serve_site_content', user_id=current_user.id, site_id=site.id) }}" class="btn"
target="_blank">View Site</a>
<form method="POST" action="{{ url_for('delete_site', site_id=site.id) }}" style="display: inline;">
<button type="submit" class="btn btn-danger">Delete Site</button>
</form>
</div>
</div>
{% endfor %}
</div>
<!-- for File Management -->
<script>
const fileInput = document.querySelector('#file-input');
const fileGrid = document.querySelector('#file-grid');
function getFileIconClass(filename) {
if (filename.endsWith('.html')) return 'html';
if (filename.endsWith('.css')) return 'css';
if (filename.endsWith('.js')) return 'js';
return 'generic';
}
function updateFilePreview() {
fileGrid.innerHTML = '';
const files = Array.from(fileInput.files);
files.forEach((file, index) => {
const fileCard = document.createElement('div');
fileCard.className = 'file-card';
fileCard.innerHTML = `
<div class="file-icon ${getFileIconClass(file.name)}"></div>
<span class="file-name">${file.name}</span>
<button type="button" class="file-close" onclick="removeFile(${index})">&times;</button>
`;
fileGrid.appendChild(fileCard);
});
}
function removeFile(index) {
const files = Array.from(fileInput.files);
files.splice(index, 1);
const newFileList = new DataTransfer();
files.forEach(file => newFileList.items.add(file));
fileInput.files = newFileList.files;
updateFilePreview();
}
window.addEventListener('DOMContentLoaded', updateFilePreview);
fileInput.addEventListener('change', () => {
document.querySelector('#file-preview').style.display = fileInput.files.length ? 'block' : 'non'
updateFilePreview();
});
</script>
{% endblock %}
+59
View File
@@ -0,0 +1,59 @@
{% extends "base.html" %}
{% block title %}Edit Site{% endblock %}
{% block content %}
<h2>Edit {{ site.name }}</h2>
<a href="{{ url_for('serve_site_content', user_id=current_user.id, site_id=site.id) }}" class="btn" target="_blank">View
Site</a>
<div style="margin-bottom: 30px;"></div>
<label for="theme-selector">Select Theme:</label>
<select id="theme-selector" style="width: 200px;">
<!-- Theme options will be populated here -->
</select>
<form method="POST">
<div class="form-group">
<label>Site Name:</label>
<input type="text" name="name" value="{{ site.name }}">
</div>
{% for filename, content in files.items() %}
<div class="form-group">
<label>{{ filename }}:</label>
<textarea name="{{ filename }}" rows="20"
data-language="{% if filename.endswith('.css') %}css{% elif filename.endswith('.js') %}javascript{% else %}htmlmixed{% endif %}">{{ content|trim }}</textarea>
</div>
{% endfor %}
<button type="submit">Save Changes</button>
</form>
<!-- Ace Editor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/ext-themelist.js"></script>
<!-- Select2 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<script src="{{ url_for('static', filename='editor.js') }}"></script>
<style>
/* Style for the Select2 dropdown */
.select2-container {
margin-bottom: 10px;
}
/* Ensure the editor has a defined height */
#editor {
width: 100%;
max-height: 500px;
border: 1px solid #ddd;
}
</style>
{% endblock %}
+8
View File
@@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to Static Site Host</h1>
<p>Upload and manage your static websites easily!</p>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="POST" action="{{ url_for('login') }}">
<div class="form-group">
<label>Email:</label>
<input type="email" name="email" required>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}Register{% endblock %}
{% block content %}
<h2>Register</h2>
<form method="POST" action="{{ url_for('register') }}">
<div class="form-group">
<label>Email:</label>
<input type="email" name="email" required>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" name="password" required>
</div>
<button type="submit">Register</button>
</form>
{% endblock %}