- Added /admin redirect to login page in nginx config - Fixed backend server.js route ordering for proper admin handling - Updated authentication middleware and routes - Added user management routes - Configured PostgreSQL integration - Updated environment configuration
134 lines
4.6 KiB
Plaintext
134 lines
4.6 KiB
Plaintext
@model List<string>
|
|
@{
|
|
Layout = "~/Views/Shared/_AdminLayout.cshtml";
|
|
ViewData["Title"] = "Media Upload";
|
|
}
|
|
|
|
<div class="mb-4">
|
|
<h2>Media Upload</h2>
|
|
<p class="text-muted">Upload and manage your images</p>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Upload New Image</h5>
|
|
<form id="uploadForm" enctype="multipart/form-data">
|
|
<div class="mb-3">
|
|
<input type="file" class="form-control" id="imageFile" accept="image/*" multiple>
|
|
</div>
|
|
<button type="button" class="btn btn-primary" onclick="uploadImage()">
|
|
<i class="bi bi-cloud-upload"></i> Upload Image
|
|
</button>
|
|
</form>
|
|
<div id="uploadProgress" class="mt-3" style="display: none;">
|
|
<div class="progress">
|
|
<div class="progress-bar" role="progressbar" style="width: 0%"></div>
|
|
</div>
|
|
</div>
|
|
<div id="uploadResult" class="mt-3"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Uploaded Images (@Model.Count)</h5>
|
|
@if (Model.Any())
|
|
{
|
|
<div class="row g-3">
|
|
@foreach (var image in Model)
|
|
{
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<img src="@image" class="card-img-top" alt="Uploaded image" style="height: 200px; object-fit: cover;">
|
|
<div class="card-body p-2">
|
|
<div class="input-group input-group-sm">
|
|
<input type="text" class="form-control" value="@image" readonly onclick="this.select()">
|
|
<button class="btn btn-outline-secondary" type="button" onclick="copyToClipboard('@image')">
|
|
<i class="bi bi-clipboard"></i>
|
|
</button>
|
|
</div>
|
|
<button class="btn btn-sm btn-danger w-100 mt-2" onclick="deleteImage('@image', this)">
|
|
<i class="bi bi-trash"></i> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<p class="text-muted">No images uploaded yet.</p>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@section Scripts {
|
|
<script>
|
|
function uploadImage() {
|
|
const fileInput = document.getElementById('imageFile');
|
|
const files = fileInput.files;
|
|
|
|
if (files.length === 0) {
|
|
alert('Please select at least one file');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
Array.from(files).forEach(file => {
|
|
formData.append('files', file);
|
|
});
|
|
|
|
document.getElementById('uploadProgress').style.display = 'block';
|
|
|
|
fetch('/admin/upload/multiple', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
document.getElementById('uploadProgress').style.display = 'none';
|
|
if (result.success) {
|
|
document.getElementById('uploadResult').innerHTML =
|
|
'<div class="alert alert-success">Images uploaded successfully!</div>';
|
|
setTimeout(() => location.reload(), 1000);
|
|
} else {
|
|
document.getElementById('uploadResult').innerHTML =
|
|
'<div class="alert alert-danger">Upload failed: ' + result.message + '</div>';
|
|
}
|
|
})
|
|
.catch(error => {
|
|
document.getElementById('uploadProgress').style.display = 'none';
|
|
document.getElementById('uploadResult').innerHTML =
|
|
'<div class="alert alert-danger">Upload failed: ' + error + '</div>';
|
|
});
|
|
}
|
|
|
|
function copyToClipboard(text) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
alert('URL copied to clipboard!');
|
|
});
|
|
}
|
|
|
|
function deleteImage(imageUrl, button) {
|
|
if (!confirm('Are you sure you want to delete this image?')) return;
|
|
|
|
fetch('/admin/upload/delete', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(imageUrl)
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.success) {
|
|
button.closest('.col-md-3').remove();
|
|
} else {
|
|
alert('Delete failed: ' + result.message);
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
}
|