155 lines
6.7 KiB
JavaScript
155 lines
6.7 KiB
JavaScript
export class FilePreview {
|
|
constructor(options = {}) {
|
|
this.options = {
|
|
containerId: options.containerId || 'filePreviewModal',
|
|
onClose: options.onClose || (() => {}),
|
|
...options
|
|
};
|
|
this.modal = null;
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Create modal if it doesn't exist
|
|
if (!document.getElementById(this.options.containerId)) {
|
|
const modalHtml = `
|
|
<div class="modal fade" id="${this.options.containerId}" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">File Preview</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="${this.options.containerId}Content" class="text-center">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
|
}
|
|
|
|
this.modal = new bootstrap.Modal(document.getElementById(this.options.containerId));
|
|
|
|
// Add event listener for modal close
|
|
document.getElementById(this.options.containerId).addEventListener('hidden.bs.modal', () => {
|
|
this.options.onClose();
|
|
});
|
|
}
|
|
|
|
getFileIcon(filename) {
|
|
const extension = filename.split('.').pop().toLowerCase();
|
|
const iconMap = {
|
|
pdf: 'fa-file-pdf',
|
|
doc: 'fa-file-word',
|
|
docx: 'fa-file-word',
|
|
xls: 'fa-file-excel',
|
|
xlsx: 'fa-file-excel',
|
|
ppt: 'fa-file-powerpoint',
|
|
pptx: 'fa-file-powerpoint',
|
|
txt: 'fa-file-alt',
|
|
jpg: 'fa-file-image',
|
|
jpeg: 'fa-file-image',
|
|
png: 'fa-file-image',
|
|
gif: 'fa-file-image',
|
|
zip: 'fa-file-archive',
|
|
rar: 'fa-file-archive',
|
|
mp3: 'fa-file-audio',
|
|
mp4: 'fa-file-video'
|
|
};
|
|
return iconMap[extension] || 'fa-file';
|
|
}
|
|
|
|
async previewFile(file) {
|
|
const contentDiv = document.getElementById('filePreviewContent');
|
|
const extension = file.name.split('.').pop().toLowerCase();
|
|
|
|
// Show loading spinner
|
|
contentDiv.innerHTML = `
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
`;
|
|
|
|
try {
|
|
// Handle different file types
|
|
if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'tiff'].includes(extension)) {
|
|
// Image preview
|
|
contentDiv.innerHTML = `
|
|
<img src="${file.url}" class="img-fluid" alt="${file.name}" style="max-height: 70vh;">
|
|
`;
|
|
} else if (['pdf'].includes(extension)) {
|
|
// PDF preview
|
|
contentDiv.innerHTML = `
|
|
<iframe src="${file.url}" width="100%" style="min-height: 600px;" frameborder="0"></iframe>
|
|
`;
|
|
} else if (['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv'].includes(extension)) {
|
|
// Video preview
|
|
contentDiv.innerHTML = `
|
|
<video controls class="w-100" style="max-height: 70vh;">
|
|
<source src="${file.url}" type="video/${extension}">
|
|
Your browser does not support the video tag.
|
|
</video>
|
|
`;
|
|
} else if (['mp3', 'wav', 'ogg', 'm4a', 'flac'].includes(extension)) {
|
|
// Audio preview
|
|
contentDiv.innerHTML = `
|
|
<audio controls class="w-100">
|
|
<source src="${file.url}" type="audio/${extension}">
|
|
Your browser does not support the audio tag.
|
|
</audio>
|
|
`;
|
|
} else if (['txt', 'md', 'csv', 'py', 'js', 'html', 'css', 'json', 'xml', 'sql', 'sh', 'bat'].includes(extension)) {
|
|
// Text/Code preview
|
|
const response = await fetch(file.url);
|
|
const text = await response.text();
|
|
contentDiv.innerHTML = `
|
|
<pre class="bg-light p-3 rounded" style="max-height: 70vh; overflow-y: auto;">${text}</pre>
|
|
`;
|
|
} else if (['docx', 'doc', 'xlsx', 'xls', 'pptx', 'ppt', 'odt', 'odp', 'ods'].includes(extension)) {
|
|
// Office document preview using Office Web Viewer
|
|
const encodedUrl = encodeURIComponent(file.url);
|
|
contentDiv.innerHTML = `
|
|
<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=${encodedUrl}"
|
|
width="100%" height="70vh" frameborder="0"></iframe>
|
|
`;
|
|
} else {
|
|
// Default preview for other file types
|
|
contentDiv.innerHTML = `
|
|
<div class="text-center py-5">
|
|
<i class="fas ${this.getFileIcon(file.name)} fa-4x mb-3" style="color: var(--secondary-color);"></i>
|
|
<h5 class="mb-3">${file.name}</h5>
|
|
<p class="text-muted">Preview not available for this file type.</p>
|
|
<a href="${file.url}" class="btn btn-primary" download>
|
|
<i class="fas fa-download me-2"></i>Download
|
|
</a>
|
|
</div>
|
|
`;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error previewing file:', error);
|
|
contentDiv.innerHTML = `
|
|
<div class="text-center py-5">
|
|
<i class="fas fa-exclamation-circle fa-4x mb-3 text-danger"></i>
|
|
<h5 class="mb-3">Error Loading Preview</h5>
|
|
<p class="text-muted">File could not be viewed. Please try downloading the file instead.</p>
|
|
<a href="${file.url}" class="btn btn-primary" download>
|
|
<i class="fas fa-download me-2"></i>Download
|
|
</a>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Show the modal
|
|
this.modal.show();
|
|
}
|
|
|
|
close() {
|
|
this.modal.hide();
|
|
}
|
|
}
|