732 lines
33 KiB
HTML
Executable File
732 lines
33 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="robots" content="noindex, nofollow, noarchive">
|
|
<title>Media Library - MSPE Admin</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha384-t1nt8BQoYMLFN5p42tRAtuAAFQaCQODekUVeKKZrEnEyp4H2R0RHFz0KWpmj7i8g" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="/admin/css/admin.css">
|
|
</head>
|
|
<body>
|
|
<div class="admin-wrapper">
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">
|
|
<a href="/admin/dashboard.html" class="sidebar-logo">
|
|
<i class="fas fa-cube"></i>
|
|
<span>MSPE</span>
|
|
</a>
|
|
<button class="sidebar-toggle" id="sidebar-toggle">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<nav class="sidebar-nav">
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Main</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/dashboard.html" class="nav-link">
|
|
<i class="fas fa-th-large"></i>
|
|
<span>Dashboard</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Content</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/pages.html" class="nav-link">
|
|
<i class="fas fa-file-alt"></i>
|
|
<span>Pages</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/services.html" class="nav-link">
|
|
<i class="fas fa-concierge-bell"></i>
|
|
<span>Services</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/portfolio.html" class="nav-link">
|
|
<i class="fas fa-briefcase"></i>
|
|
<span>Portfolio</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/news.html" class="nav-link">
|
|
<i class="fas fa-newspaper"></i>
|
|
<span>News & Events</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/testimonials.html" class="nav-link">
|
|
<i class="fas fa-quote-right"></i>
|
|
<span>Testimonials</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/team.html" class="nav-link">
|
|
<i class="fas fa-users"></i>
|
|
<span>Team</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Media</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item active">
|
|
<a href="/admin/media.html" class="nav-link">
|
|
<i class="fas fa-images"></i>
|
|
<span>Media Library</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Inquiries</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/messages.html" class="nav-link">
|
|
<i class="fas fa-envelope"></i>
|
|
<span>Messages</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/subscribers.html" class="nav-link">
|
|
<i class="fas fa-bell"></i>
|
|
<span>Subscribers</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/bookings.html" class="nav-link">
|
|
<i class="fas fa-calendar-check"></i>
|
|
<span>Bookings</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Settings</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/settings.html" class="nav-link">
|
|
<i class="fas fa-cog"></i>
|
|
<span>Site Settings</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/users.html" class="nav-link">
|
|
<i class="fas fa-user-shield"></i>
|
|
<span>Admin Users</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="sidebar-footer">
|
|
<a href="/index.html" class="view-site-btn" target="_blank">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
<span>View Website</span>
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main Content -->
|
|
<main class="main-content">
|
|
<!-- Header -->
|
|
<header class="admin-header">
|
|
<div class="header-left">
|
|
<button class="mobile-toggle" id="mobile-toggle">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
<h1 class="page-title">Media Library</h1>
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
<button class="btn btn-primary" onclick="openUploadModal()">
|
|
<i class="fas fa-upload"></i> Upload Files
|
|
</button>
|
|
|
|
<div class="header-user">
|
|
<div class="user-avatar">
|
|
<img src="https://ui-avatars.com/api/?name=Admin&background=0ea5e9&color=fff" alt="Admin">
|
|
</div>
|
|
<div class="user-info">
|
|
<span class="user-name">Admin</span>
|
|
<span class="user-role">Administrator</span>
|
|
</div>
|
|
<div class="user-dropdown">
|
|
<button class="dropdown-toggle">
|
|
<i class="fas fa-chevron-down"></i>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a href="/admin/settings.html"><i class="fas fa-cog"></i> Settings</a></li>
|
|
<li class="divider"></li>
|
|
<li><a href="#" id="logout-btn"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Content -->
|
|
<div class="content-wrapper">
|
|
<div class="media-stats">
|
|
<div class="storage-overview">
|
|
<div class="storage-used">
|
|
<i class="fas fa-database"></i>
|
|
<div>
|
|
<span class="storage-value">0 Bytes</span>
|
|
<span class="storage-label">Used of 5 GB</span>
|
|
</div>
|
|
</div>
|
|
<div class="storage-bar">
|
|
<div class="storage-progress" style="width: 0%;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="media-counts">
|
|
<div class="media-count-item">
|
|
<i class="fas fa-image"></i>
|
|
<span>0 Images</span>
|
|
</div>
|
|
<div class="media-count-item">
|
|
<i class="fas fa-file-pdf"></i>
|
|
<span>0 Documents</span>
|
|
</div>
|
|
<div class="media-count-item">
|
|
<i class="fas fa-video"></i>
|
|
<span>0 Videos</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters & Search -->
|
|
<div class="media-toolbar">
|
|
<div class="toolbar-left">
|
|
<div class="search-box">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" placeholder="Search files..." id="media-search">
|
|
</div>
|
|
<select class="form-select" id="type-filter">
|
|
<option value="">All Types</option>
|
|
<option value="image">Images</option>
|
|
<option value="document">Documents</option>
|
|
<option value="video">Videos</option>
|
|
</select>
|
|
<select class="form-select" id="folder-filter">
|
|
<option value="">All Folders</option>
|
|
<option value="news">News</option>
|
|
<option value="portfolio">Portfolio</option>
|
|
<option value="team">Team</option>
|
|
<option value="clients">Clients</option>
|
|
<option value="general">General</option>
|
|
</select>
|
|
</div>
|
|
<div class="toolbar-right">
|
|
<button class="btn btn-outline btn-sm" onclick="createFolder()">
|
|
<i class="fas fa-folder-plus"></i> New Folder
|
|
</button>
|
|
<div class="view-toggle">
|
|
<button class="view-btn active" data-view="grid"><i class="fas fa-th"></i></button>
|
|
<button class="view-btn" data-view="list"><i class="fas fa-list"></i></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Folders -->
|
|
<div class="media-folders" id="media-folders">
|
|
<div class="folder-item" data-folder="news">
|
|
<i class="fas fa-folder"></i>
|
|
<span>news</span>
|
|
<small>0 files</small>
|
|
</div>
|
|
<div class="folder-item" data-folder="portfolio">
|
|
<i class="fas fa-folder"></i>
|
|
<span>portfolio</span>
|
|
<small>0 files</small>
|
|
</div>
|
|
<div class="folder-item" data-folder="team">
|
|
<i class="fas fa-folder"></i>
|
|
<span>team</span>
|
|
<small>0 files</small>
|
|
</div>
|
|
<div class="folder-item" data-folder="clients">
|
|
<i class="fas fa-folder"></i>
|
|
<span>clients</span>
|
|
<small>0 files</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Media Grid -->
|
|
<div class="media-grid" id="media-grid">
|
|
<div style="grid-column:1/-1;text-align:center;padding:3rem;color:var(--gray-400);">
|
|
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
|
<p style="margin-top:1rem;">Loading media...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bulk Actions -->
|
|
<div class="bulk-actions" id="bulk-actions" style="display: none;">
|
|
<span class="selected-count">0 selected</span>
|
|
<button class="btn btn-outline btn-sm" onclick="moveSelected()">
|
|
<i class="fas fa-folder"></i> Move
|
|
</button>
|
|
<button class="btn btn-outline btn-sm" onclick="downloadSelected()">
|
|
<i class="fas fa-download"></i> Download
|
|
</button>
|
|
<button class="btn btn-danger btn-sm" onclick="deleteSelected()">
|
|
<i class="fas fa-trash"></i> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- Upload Modal -->
|
|
<div class="modal" id="upload-modal">
|
|
<div class="modal-backdrop"></div>
|
|
<div class="modal-container">
|
|
<div class="modal-header">
|
|
<h2>Upload Files</h2>
|
|
<button class="modal-close" onclick="closeUploadModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="upload-dropzone" id="dropzone">
|
|
<i class="fas fa-cloud-upload-alt"></i>
|
|
<h3>Drag & Drop Files Here</h3>
|
|
<p>or click to browse</p>
|
|
<span class="upload-hint">Supports: JPG, PNG, GIF, PDF, DOC, MP4 (Max 50MB each)</span>
|
|
<input type="file" id="file-input" multiple accept="image/*,.pdf,.doc,.docx,.mp4" style="display: none;">
|
|
</div>
|
|
|
|
<div class="form-group" style="margin-top: 1rem;">
|
|
<label>Upload to Folder</label>
|
|
<select class="form-select" id="upload-folder">
|
|
<option value="">Root (uploads/)</option>
|
|
<option value="news">news/</option>
|
|
<option value="portfolio">portfolio/</option>
|
|
<option value="team">team/</option>
|
|
<option value="clients">clients/</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="upload-queue" id="upload-queue" style="display: none;">
|
|
<h4>Upload Queue</h4>
|
|
<div class="queue-list" id="queue-list"></div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-outline" onclick="closeUploadModal()">Cancel</button>
|
|
<button class="btn btn-primary" id="start-upload" disabled>
|
|
<i class="fas fa-upload"></i> Start Upload
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Media View Modal -->
|
|
<div class="modal" id="view-modal">
|
|
<div class="modal-backdrop"></div>
|
|
<div class="modal-container modal-lg">
|
|
<div class="modal-header">
|
|
<h2 id="view-title">File Details</h2>
|
|
<button class="modal-close" onclick="closeViewModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="media-view-content">
|
|
<div class="media-view-preview">
|
|
<img src="" id="view-image" alt="">
|
|
</div>
|
|
<div class="media-view-details">
|
|
<div class="detail-row">
|
|
<label>File Name</label>
|
|
<span id="detail-name">-</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>Type</label>
|
|
<span id="detail-type">-</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>Size</label>
|
|
<span id="detail-size">-</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>Dimensions</label>
|
|
<span id="detail-dimensions">-</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>Uploaded</label>
|
|
<span id="detail-date">-</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>URL</label>
|
|
<div class="url-copy">
|
|
<input type="text" id="detail-url" readonly>
|
|
<button class="btn btn-sm btn-outline" onclick="copyDetailUrl()">
|
|
<i class="fas fa-copy"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="detail-row">
|
|
<label>Alt Text</label>
|
|
<input type="text" class="form-control" id="detail-alt" placeholder="Enter alt text...">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-danger" onclick="deleteFromView()">
|
|
<i class="fas fa-trash"></i> Delete
|
|
</button>
|
|
<button class="btn btn-outline" onclick="downloadFile()">
|
|
<i class="fas fa-download"></i> Download
|
|
</button>
|
|
<button class="btn btn-primary" onclick="saveDetails()">
|
|
<i class="fas fa-save"></i> Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/admin/js/admin.js"></script>
|
|
<script>
|
|
let allMedia = [];
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadMedia();
|
|
|
|
// Search & Filter
|
|
document.getElementById('media-search').addEventListener('input', MSPE.debounce(filterMedia, 300));
|
|
document.getElementById('type-filter').addEventListener('change', filterMedia);
|
|
document.getElementById('folder-filter').addEventListener('change', filterMedia);
|
|
|
|
// File Input for Upload
|
|
document.getElementById('file-input').addEventListener('change', handleFileSelect);
|
|
document.getElementById('start-upload').addEventListener('click', uploadFiles);
|
|
});
|
|
|
|
async function loadMedia() {
|
|
try {
|
|
const response = await MSPE.API.get('media.php');
|
|
if (response && response.success) {
|
|
allMedia = response.data;
|
|
renderMedia(allMedia);
|
|
updateStats(allMedia);
|
|
updateFolderCounts(allMedia);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading media:', error);
|
|
document.getElementById('media-grid').innerHTML = '<div class="empty-state">Failed to load media</div>';
|
|
}
|
|
}
|
|
|
|
function updateFolderCounts(media) {
|
|
document.querySelectorAll('#media-folders .folder-item').forEach(el => {
|
|
const folder = el.dataset.folder;
|
|
const count = media.filter(m => m.folder === folder).length;
|
|
el.querySelector('small').textContent = count + ' files';
|
|
});
|
|
}
|
|
|
|
function renderMedia(media) {
|
|
const container = document.getElementById('media-grid');
|
|
if (media.length === 0) {
|
|
container.innerHTML = '<div class="empty-state"><i class="fas fa-images"></i><p>No media files found</p></div>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = media.map(item => `
|
|
<div class="media-item" data-id="${item.id}" data-type="${item.type}">
|
|
<div class="media-preview ${item.type.includes('image') ? '' : 'document'}">
|
|
${item.type.includes('image')
|
|
? `<img src="/${item.path}" alt="${item.name}">`
|
|
: `<i class="fas fa-file-${getFileIcon(item.type)}"></i>`
|
|
}
|
|
<div class="media-overlay">
|
|
<button class="btn btn-sm" onclick="viewMedia('${item.id}')"><i class="fas fa-eye"></i></button>
|
|
<button class="btn btn-sm" onclick="copyUrl('/${item.path}')"><i class="fas fa-link"></i></button>
|
|
<button class="btn btn-sm" onclick="deleteMedia('${item.id}')"><i class="fas fa-trash"></i></button>
|
|
</div>
|
|
</div>
|
|
<div class="media-info">
|
|
<span class="media-name">${item.name}</span>
|
|
<span class="media-size">${formatBytes(item.size)}</span>
|
|
</div>
|
|
<label class="media-checkbox">
|
|
<input type="checkbox" name="selected[]" value="${item.id}" onchange="updateBulkActions()">
|
|
<span class="checkmark"></span>
|
|
</label>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
function getFileIcon(type) {
|
|
if (type.includes('pdf')) return 'pdf';
|
|
if (type.includes('video')) return 'video';
|
|
if (type.includes('word') || type.includes('document')) return 'word';
|
|
return 'alt';
|
|
}
|
|
|
|
function filterMedia() {
|
|
const search = document.getElementById('media-search').value.toLowerCase();
|
|
const type = document.getElementById('type-filter').value;
|
|
const folder = document.getElementById('folder-filter').value;
|
|
|
|
let filtered = allMedia;
|
|
|
|
if (search) filtered = filtered.filter(m => m.name.toLowerCase().includes(search));
|
|
if (type) filtered = filtered.filter(m => m.type.includes(type));
|
|
if (folder) filtered = filtered.filter(m => m.folder === folder);
|
|
|
|
renderMedia(filtered);
|
|
}
|
|
|
|
function updateStats(media) {
|
|
const totalSize = media.reduce((acc, item) => acc + parseInt(item.size), 0);
|
|
const images = media.filter(m => m.type.includes('image')).length;
|
|
const videos = media.filter(m => m.type.includes('video')).length;
|
|
const docs = media.length - images - videos;
|
|
|
|
document.querySelector('.storage-value').textContent = formatBytes(totalSize);
|
|
document.querySelectorAll('.media-count-item span')[0].textContent = images + ' Images';
|
|
document.querySelectorAll('.media-count-item span')[1].textContent = docs + ' Documents';
|
|
document.querySelectorAll('.media-count-item span')[2].textContent = videos + ' Videos';
|
|
|
|
// Simple progress bar logic (assuming 500MB limit for demo)
|
|
const pct = Math.min((totalSize / (500 * 1024 * 1024)) * 100, 100);
|
|
document.querySelector('.storage-progress').style.width = pct + '%';
|
|
}
|
|
|
|
function formatBytes(bytes, decimals = 2) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
const k = 1024;
|
|
const dm = decimals < 0 ? 0 : decimals;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// Upload Logic
|
|
let uploadFilesList = [];
|
|
|
|
function handleFileSelect(e) {
|
|
const files = Array.from(e.target.files);
|
|
uploadFilesList = files;
|
|
|
|
const queueList = document.getElementById('queue-list');
|
|
document.getElementById('upload-queue').style.display = 'block';
|
|
queueList.innerHTML = files.map(f => `
|
|
<div class="queue-item">
|
|
<span>${f.name}</span>
|
|
<small>${formatBytes(f.size)}</small>
|
|
</div>
|
|
`).join('');
|
|
|
|
document.getElementById('start-upload').disabled = false;
|
|
}
|
|
|
|
async function uploadFiles() {
|
|
const folder = document.getElementById('upload-folder').value;
|
|
const formData = new FormData();
|
|
|
|
formData.append('folder', folder);
|
|
uploadFilesList.forEach(file => {
|
|
formData.append('files[]', file); // Use array name for multiple
|
|
});
|
|
|
|
const btn = document.getElementById('start-upload');
|
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Uploading...';
|
|
btn.disabled = true;
|
|
|
|
try {
|
|
const result = await MSPE.API.upload('media.php', formData);
|
|
|
|
if (result && result.success) {
|
|
MSPE.showNotification('Upload successful', 'success');
|
|
closeUploadModal();
|
|
loadMedia();
|
|
} else {
|
|
MSPE.showNotification(result?.message || 'Upload failed', 'error');
|
|
}
|
|
} catch (error) {
|
|
MSPE.showNotification('Error uploading files', 'error');
|
|
} finally {
|
|
btn.innerHTML = '<i class="fas fa-upload"></i> Start Upload';
|
|
btn.disabled = false;
|
|
}
|
|
}
|
|
|
|
async function deleteMedia(id) {
|
|
if (!await MSPE.confirmDialog('Delete this file?')) return;
|
|
|
|
try {
|
|
const response = await MSPE.API.delete(`media.php?id=${id}`);
|
|
if (response.success) {
|
|
MSPE.showNotification('File deleted', 'success');
|
|
loadMedia();
|
|
}
|
|
} catch (error) {
|
|
MSPE.showNotification('Error deleting file', 'error');
|
|
}
|
|
}
|
|
|
|
function copyUrl(path) {
|
|
const url = window.location.origin + path;
|
|
navigator.clipboard.writeText(url).then(() => {
|
|
MSPE.showNotification('URL copied to clipboard', 'success');
|
|
});
|
|
}
|
|
|
|
// --- Modals ---
|
|
function openUploadModal() {
|
|
document.getElementById('upload-modal').classList.add('active');
|
|
uploadFilesList = [];
|
|
document.getElementById('queue-list').innerHTML = '';
|
|
document.getElementById('upload-queue').style.display = 'none';
|
|
document.getElementById('start-upload').disabled = true;
|
|
}
|
|
|
|
function closeUploadModal() {
|
|
document.getElementById('upload-modal').classList.remove('active');
|
|
}
|
|
|
|
function viewMedia(id) {
|
|
const item = allMedia.find(m => m.id === id);
|
|
if (!item) return;
|
|
|
|
document.getElementById('view-modal').classList.add('active');
|
|
document.getElementById('view-image').src = '/' + item.path;
|
|
document.getElementById('detail-name').textContent = item.name;
|
|
document.getElementById('detail-type').textContent = item.type;
|
|
document.getElementById('detail-size').textContent = formatBytes(item.size);
|
|
document.getElementById('detail-date').textContent = MSPE.formatDate(item.created_at);
|
|
document.getElementById('detail-url').value = window.location.origin + '/' + item.path;
|
|
}
|
|
|
|
function closeViewModal() {
|
|
document.getElementById('view-modal').classList.remove('active');
|
|
}
|
|
|
|
// Drag & Drop
|
|
const dropzone = document.getElementById('dropzone');
|
|
const fileInput = document.getElementById('file-input');
|
|
|
|
dropzone.addEventListener('click', () => fileInput.click());
|
|
dropzone.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
dropzone.classList.add('dragover');
|
|
});
|
|
dropzone.addEventListener('dragleave', () => {
|
|
dropzone.classList.remove('dragover');
|
|
});
|
|
dropzone.addEventListener('drop', (e) => {
|
|
e.preventDefault();
|
|
dropzone.classList.remove('dragover');
|
|
fileInput.files = e.dataTransfer.files;
|
|
handleFileSelect({ target: fileInput });
|
|
});
|
|
|
|
function updateBulkActions() {
|
|
const checked = document.querySelectorAll('.media-checkbox input:checked');
|
|
const bulkActions = document.getElementById('bulk-actions');
|
|
if (checked.length > 0) {
|
|
bulkActions.style.display = 'flex';
|
|
bulkActions.querySelector('.selected-count').textContent = checked.length + ' selected';
|
|
} else {
|
|
bulkActions.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function createFolder() {
|
|
const name = prompt('Enter folder name:');
|
|
if (name) {
|
|
MSPE.showNotification('Folder management is handled on the server file system', 'info');
|
|
}
|
|
}
|
|
|
|
function moveSelected() {
|
|
const checked = document.querySelectorAll('.media-checkbox input:checked');
|
|
if (checked.length === 0) return;
|
|
MSPE.showNotification('Move functionality coming soon', 'info');
|
|
}
|
|
|
|
async function downloadSelected() {
|
|
const checked = document.querySelectorAll('.media-checkbox input:checked');
|
|
if (checked.length === 0) return;
|
|
checked.forEach(cb => {
|
|
const item = allMedia.find(m => m.id === cb.value);
|
|
if (item) downloadFile('/' + item.path);
|
|
});
|
|
}
|
|
|
|
async function deleteSelected() {
|
|
const checked = document.querySelectorAll('.media-checkbox input:checked');
|
|
if (checked.length === 0) return;
|
|
if (!await MSPE.confirmDialog(`Delete ${checked.length} selected file(s)?`)) return;
|
|
|
|
let success = 0;
|
|
for (const cb of checked) {
|
|
try {
|
|
const response = await MSPE.API.delete(`media.php?id=${cb.value}`);
|
|
if (response && response.success) success++;
|
|
} catch (e) { /* continue */ }
|
|
}
|
|
MSPE.showNotification(`${success} file(s) deleted`, 'success');
|
|
loadMedia();
|
|
}
|
|
|
|
function downloadFile(path) {
|
|
const link = document.createElement('a');
|
|
link.href = path || '';
|
|
link.download = '';
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
}
|
|
|
|
function copyDetailUrl() {
|
|
const url = document.getElementById('detail-url').value;
|
|
navigator.clipboard.writeText(url).then(() => {
|
|
MSPE.showNotification('URL copied to clipboard', 'success');
|
|
});
|
|
}
|
|
|
|
async function deleteFromView() {
|
|
const img = document.getElementById('view-image');
|
|
const item = allMedia.find(m => img.src.includes(m.path));
|
|
if (!item) return;
|
|
|
|
if (!await MSPE.confirmDialog('Delete this file?')) return;
|
|
|
|
try {
|
|
const response = await MSPE.API.delete(`media.php?id=${item.id}`);
|
|
if (response && response.success) {
|
|
MSPE.showNotification('File deleted', 'success');
|
|
closeViewModal();
|
|
loadMedia();
|
|
}
|
|
} catch (error) {
|
|
MSPE.showNotification('Error deleting file', 'error');
|
|
}
|
|
}
|
|
|
|
function saveDetails() {
|
|
const alt = document.getElementById('detail-alt').value;
|
|
MSPE.showNotification('Details saved', 'success');
|
|
closeViewModal();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|