gcp-hockey-results/motm_app/templates/edit_club.html

335 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Club - HKFC Men's C Team</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3>Edit Club #{{ club_id }}</h3>
</div>
<div class="card-body">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else 'success' }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.hockey_club.label(class="form-label") }}
{{ form.hockey_club(class="form-control") }}
{% if form.hockey_club.errors %}
<div class="text-danger">
{% for error in form.hockey_club.errors %}
<small>{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.logo_url.label(class="form-label") }}
<div class="input-group">
{{ form.logo_url(class="form-control", id="logoUrl", onchange="previewLogo()") }}
<button type="button" class="btn btn-outline-secondary" onclick="browseS3()" title="Browse S3 Storage">
<i class="fas fa-cloud"></i> Browse S3
</button>
</div>
{% if form.logo_url.errors %}
<div class="text-danger">
{% for error in form.logo_url.errors %}
<small>{{ error }}</small>
{% endfor %}
</div>
{% endif %}
<small class="form-text text-muted">Enter the full URL to the club's logo image or use the S3 browser to select from your configured storage.</small>
<!-- Logo Preview -->
<div id="logoPreview" class="mt-2" style="display: none;">
<label class="form-label small">Preview:</label>
<div class="border rounded p-2 bg-light">
<img id="previewImage" src="" alt="Logo preview" style="max-height: 80px; max-width: 120px;" onerror="this.style.display='none'; document.getElementById('previewError').style.display='block';" onload="document.getElementById('previewError').style.display='none';">
<div id="previewError" class="text-muted small" style="display: none;">Unable to load image</div>
</div>
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
{{ form.cancel(class="btn btn-secondary me-md-2") }}
{{ form.save_club(class="btn btn-primary") }}
</div>
</form>
</div>
</div>
<!-- S3 Browser Modal -->
<div class="modal fade" id="s3BrowserModal" tabindex="-1" aria-labelledby="s3BrowserModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="s3BrowserModalLabel">Browse S3 Storage</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="s3BrowserContent">
<div class="text-center">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p>Loading S3 contents...</p>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="selectS3FileBtn" onclick="selectS3File()" disabled>Select File</button>
</div>
</div>
</div>
</div>
<div class="mt-3">
<a href="/admin/clubs" class="btn btn-outline-secondary">Back to Club Management</a>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function previewLogo() {
const urlInput = document.getElementById('logoUrl');
const previewDiv = document.getElementById('logoPreview');
const previewImg = document.getElementById('previewImage');
if (urlInput.value.trim()) {
previewImg.src = urlInput.value;
previewDiv.style.display = 'block';
} else {
previewDiv.style.display = 'none';
}
}
// S3 Browser functionality
let selectedS3File = null;
let currentS3Path = '';
function browseS3() {
// Reset state
selectedS3File = null;
currentS3Path = '';
// Show loading state
document.getElementById('s3BrowserContent').innerHTML = `
<div class="text-center">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p>Loading S3 contents...</p>
</div>
`;
// Show modal
const s3BrowserModal = new bootstrap.Modal(document.getElementById('s3BrowserModal'));
s3BrowserModal.show();
// Load S3 contents from root of assets folder
loadS3Contents('');
}
function loadS3Contents(path) {
fetch(`/admin/api/s3-browser?path=${encodeURIComponent(path)}`)
.then(response => response.json())
.then(data => {
if (data.success) {
displayS3Contents(data);
} else {
document.getElementById('s3BrowserContent').innerHTML = `
<div class="alert alert-danger" role="alert">
<strong>Error:</strong> ${data.message}
</div>
`;
}
})
.catch(error => {
console.error('Error:', error);
document.getElementById('s3BrowserContent').innerHTML = `
<div class="alert alert-danger" role="alert">
<strong>Error:</strong> Failed to load S3 contents. Please try again.
</div>
`;
});
}
function displayS3Contents(data) {
currentS3Path = data.path;
let html = `
<div class="row mb-3">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="#" onclick="loadS3Contents('')">assets</a>
</li>
`;
// Build breadcrumb
if (data.path !== '') {
const pathParts = data.path.split('/').filter(p => p);
let currentPath = '';
pathParts.forEach((part, index) => {
currentPath += part + '/';
const isLast = index === pathParts.length - 1;
html += `<li class="breadcrumb-item ${isLast ? 'active' : ''}">`;
if (!isLast) {
html += `<a href="#" onclick="loadS3Contents('${currentPath}')">${part}</a>`;
} else {
html += part;
}
html += '</li>';
});
}
html += `
</ol>
</nav>
</div>
</div>
<div class="row">
`;
// Display folders
if (data.folders.length > 0) {
data.folders.forEach(folder => {
html += `
<div class="col-md-3 mb-3">
<div class="card h-100 folder-card" onclick="loadS3Contents('${folder.path}')" style="cursor: pointer;">
<div class="card-body text-center">
<i class="fas fa-folder fa-3x text-warning mb-2"></i>
<h6 class="card-title">${folder.name}</h6>
</div>
</div>
</div>
`;
});
}
// Display files
if (data.files.length > 0) {
data.files.forEach(file => {
const isImage = /\.(jpg|jpeg|png|gif|svg|webp)$/i.test(file.name);
const fileSize = formatFileSize(file.size);
html += `
<div class="col-md-3 mb-3">
<div class="card h-100 file-card" onclick="selectS3FileItem('${file.path}', '${file.url}')" style="cursor: pointer;">
<div class="card-body text-center">
`;
if (isImage) {
html += `
<img src="${file.url}" alt="${file.name}" class="img-fluid mb-2" style="max-height: 100px; max-width: 100%; object-fit: contain;">
`;
} else {
html += `
<i class="fas fa-file fa-3x text-primary mb-2"></i>
`;
}
html += `
<h6 class="card-title">${file.name}</h6>
<small class="text-muted">${fileSize}</small>
</div>
</div>
</div>
`;
});
}
if (data.folders.length === 0 && data.files.length === 0) {
html += `
<div class="col-12">
<div class="alert alert-info text-center">
<i class="fas fa-info-circle"></i> No files or folders found in this directory.
</div>
</div>
`;
}
html += `
</div>
`;
document.getElementById('s3BrowserContent').innerHTML = html;
}
function selectS3FileItem(filePath, fileUrl) {
// Remove previous selection
document.querySelectorAll('.file-card').forEach(card => {
card.classList.remove('border-primary');
});
// Add selection to clicked card
event.currentTarget.classList.add('border-primary');
// Store selected file
selectedS3File = {
path: filePath,
url: fileUrl
};
// Enable select button
document.getElementById('selectS3FileBtn').disabled = false;
}
function selectS3File() {
if (selectedS3File) {
// Update the logo URL field
const logoUrlField = document.getElementById('logoUrl');
if (logoUrlField) {
logoUrlField.value = selectedS3File.path;
// Trigger preview update
previewLogo();
}
// Close modal
const s3BrowserModal = bootstrap.Modal.getInstance(document.getElementById('s3BrowserModal'));
s3BrowserModal.hide();
}
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// Preview logo on page load if URL is already filled
document.addEventListener('DOMContentLoaded', function() {
previewLogo();
});
</script>
</body>
</html>