Fix admin route access and backend configuration
- 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
This commit is contained in:
133
Sky_Art_shop/Views/AdminUpload/Index.cshtml
Normal file
133
Sky_Art_shop/Views/AdminUpload/Index.cshtml
Normal file
@@ -0,0 +1,133 @@
|
||||
@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>
|
||||
}
|
||||
Reference in New Issue
Block a user