add loading state
This commit is contained in:
parent
22dcb0fe62
commit
06aac15f83
1 changed files with 136 additions and 18 deletions
|
@ -45,6 +45,17 @@ const {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-[calc(100%-4rem)] bg-base-200 rounded-lg">
|
<div class="h-[calc(100%-4rem)] bg-base-200 rounded-lg">
|
||||||
|
<!-- Loading Skeleton -->
|
||||||
|
<div id={`${id}-loading`} class="w-full h-full hidden">
|
||||||
|
<div class="flex flex-col items-center justify-center h-full">
|
||||||
|
<div
|
||||||
|
class="loading loading-spinner loading-lg text-primary"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-base-content/70">Loading preview...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Preview Container -->
|
<!-- Preview Container -->
|
||||||
<div id={`${id}-preview-container`} class="w-full h-full"></div>
|
<div id={`${id}-preview-container`} class="w-full h-full"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -58,6 +69,27 @@ const {
|
||||||
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
|
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Multiple Files Loading Skeleton -->
|
||||||
|
<div id={`${id}-multiple-loading`} class="hidden">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{
|
||||||
|
Array(6)
|
||||||
|
.fill(0)
|
||||||
|
.map(() => (
|
||||||
|
<div class="card bg-base-200 animate-pulse">
|
||||||
|
<div class="aspect-video bg-base-300 rounded-t-lg" />
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="h-4 bg-base-300 rounded w-3/4" />
|
||||||
|
<div class="h-3 bg-base-300 rounded w-1/2 mt-2 opacity-70" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Files Grid -->
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
|
||||||
id={`${id}-file-grid`}
|
id={`${id}-file-grid`}
|
||||||
|
@ -85,6 +117,10 @@ const {
|
||||||
this.externalLink = document.getElementById(
|
this.externalLink = document.getElementById(
|
||||||
`${modalId}-external-link`
|
`${modalId}-external-link`
|
||||||
);
|
);
|
||||||
|
this.loadingElement = document.getElementById(`${modalId}-loading`);
|
||||||
|
this.multipleLoadingElement = document.getElementById(
|
||||||
|
`${modalId}-multiple-loading`
|
||||||
|
);
|
||||||
|
|
||||||
// Close modal when clicking backdrop
|
// Close modal when clicking backdrop
|
||||||
this.modal.addEventListener("click", (e) => {
|
this.modal.addEventListener("click", (e) => {
|
||||||
|
@ -141,9 +177,10 @@ const {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "pdf":
|
case "pdf":
|
||||||
element = document.createElement("iframe");
|
element = document.createElement("embed");
|
||||||
element.className = "w-full h-full";
|
element.className = "w-full h-full";
|
||||||
element.src = file.url;
|
element.type = "application/pdf";
|
||||||
|
element.src = file.url + "#toolbar=0&navpanes=0";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -164,16 +201,89 @@ const {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
showFile(file) {
|
showLoading(isMultiple = false) {
|
||||||
|
if (isMultiple) {
|
||||||
|
if (this.multipleLoadingElement) {
|
||||||
|
this.multipleLoadingElement.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
if (this.fileGrid) {
|
||||||
|
this.fileGrid.classList.add("hidden");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.loadingElement) {
|
||||||
|
this.loadingElement.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
if (this.previewContainer) {
|
||||||
|
this.previewContainer.classList.add("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLoading(isMultiple = false) {
|
||||||
|
if (isMultiple) {
|
||||||
|
if (this.multipleLoadingElement) {
|
||||||
|
this.multipleLoadingElement.classList.add("hidden");
|
||||||
|
}
|
||||||
|
if (this.fileGrid) {
|
||||||
|
this.fileGrid.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.loadingElement) {
|
||||||
|
this.loadingElement.classList.add("hidden");
|
||||||
|
}
|
||||||
|
if (this.previewContainer) {
|
||||||
|
this.previewContainer.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async showFile(file) {
|
||||||
this.titleElement.textContent = file.name;
|
this.titleElement.textContent = file.name;
|
||||||
this.externalLink.href = file.url;
|
this.externalLink.href = file.url;
|
||||||
|
|
||||||
// Clear previous preview
|
// Show loading state
|
||||||
this.previewContainer.innerHTML = "";
|
this.showLoading(false);
|
||||||
|
|
||||||
// Create and append new preview
|
try {
|
||||||
const previewElement = this.createPreviewElement(file);
|
// Clear previous preview
|
||||||
this.previewContainer.appendChild(previewElement);
|
this.previewContainer.innerHTML = "";
|
||||||
|
|
||||||
|
// Create and append new preview
|
||||||
|
const previewElement = this.createPreviewElement(file);
|
||||||
|
|
||||||
|
// Only wait for images to load, PDFs and other files load in their own context
|
||||||
|
if (previewElement instanceof HTMLImageElement) {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
previewElement.onload = resolve;
|
||||||
|
previewElement.onerror = reject;
|
||||||
|
// Add a timeout to prevent infinite loading
|
||||||
|
setTimeout(reject, 10000); // 10 second timeout
|
||||||
|
}).catch((error) => {
|
||||||
|
console.warn("Image load timeout or error:", error);
|
||||||
|
// Continue anyway, the image might still load
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previewContainer.appendChild(previewElement);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading file:", error);
|
||||||
|
this.previewContainer.innerHTML = `
|
||||||
|
<div class="flex items-center justify-center h-full">
|
||||||
|
<div class="text-center text-error">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<p>Failed to load preview</p>
|
||||||
|
<a href="${file.url}" target="_blank" class="btn btn-primary btn-sm mt-4">Open in New Tab</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} finally {
|
||||||
|
// Hide loading state after a short delay to ensure UI elements are ready
|
||||||
|
setTimeout(() => {
|
||||||
|
this.hideLoading(false);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
// Show single view
|
// Show single view
|
||||||
this.singleView.classList.remove("hidden");
|
this.singleView.classList.remove("hidden");
|
||||||
|
@ -216,26 +326,34 @@ const {
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
show(files) {
|
async show(files) {
|
||||||
|
this.modal.showModal();
|
||||||
|
|
||||||
if (!Array.isArray(files)) {
|
if (!Array.isArray(files)) {
|
||||||
// Single file
|
// Single file
|
||||||
this.showFile(files);
|
await this.showFile(files);
|
||||||
} else if (files.length === 1) {
|
} else if (files.length === 1) {
|
||||||
// Single file in array
|
// Single file in array
|
||||||
this.showFile(files[0]);
|
await this.showFile(files[0]);
|
||||||
} else {
|
} else {
|
||||||
// Multiple files
|
// Multiple files
|
||||||
this.singleView.classList.add("hidden");
|
this.singleView.classList.add("hidden");
|
||||||
this.multipleView.classList.remove("hidden");
|
this.multipleView.classList.remove("hidden");
|
||||||
|
|
||||||
// Clear and populate file grid
|
// Show loading state
|
||||||
this.fileGrid.innerHTML = "";
|
this.showLoading(true);
|
||||||
files.forEach((file) => {
|
|
||||||
this.fileGrid.appendChild(this.createFileCard(file));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.modal.showModal();
|
try {
|
||||||
|
// Clear and populate file grid
|
||||||
|
this.fileGrid.innerHTML = "";
|
||||||
|
files.forEach((file) => {
|
||||||
|
this.fileGrid.appendChild(this.createFileCard(file));
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
// Hide loading state
|
||||||
|
this.hideLoading(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
|
Loading…
Reference in a new issue