A comprehensive gallery component with upload tracking functionality for Creaditor
npm install @creaditor/galleryThis gallery component now includes comprehensive upload tracking functionality that allows developers to monitor upload progress, completion, and errors in real-time.
- Real-time Upload Progress: Track upload progress with percentage completion
- Upload Status Tracking: Monitor upload status (uploading, completed, error)
- Event-driven Architecture: Listen to upload events for custom handling
- Visual Progress Indicators: Beautiful loading UI with progress bars
- Error Handling: Comprehensive error tracking and display
- Multiple Upload Support: Handle multiple simultaneous uploads
A visual component that displays upload progress in the top-right corner of the screen.
Features:
- Animated progress bars
- Status indicators (uploading, completed, error)
- Auto-dismissal after completion
- Manual close button
- Multiple upload support
The main gallery component with integrated upload tracking.
New Properties:
- uploadStatus: Object tracking upload status for each file
New Events:
- upload-start: Fired when upload begins
- upload-progress: Fired during upload progress
- upload-complete: Fired when upload completes
- upload-error: Fired when upload fails
``javascript
// Include the upload loading component in your HTML
// Listen for upload events
document.addEventListener('upload-start', (event) => {
const { uploadId, fileName, file } = event.detail;
console.log(Upload started: ${fileName});
});
document.addEventListener('upload-progress', (event) => {
const { uploadId, fileName, progress } = event.detail;
console.log(Progress: ${fileName} - ${progress}%);
});
document.addEventListener('upload-complete', (event) => {
const { uploadId, fileName, result } = event.detail;
console.log(Upload completed: ${fileName});
});
document.addEventListener('upload-error', (event) => {
const { uploadId, fileName, error } = event.detail;
console.error(Upload failed: ${fileName}, error);`
});
`javascript
class MyUploadHandler {
constructor() {
this.activeUploads = new Map();
this.setupEventListeners();
}
setupEventListeners() {
document.addEventListener('upload-start', this.handleUploadStart.bind(this));
document.addEventListener('upload-progress', this.handleUploadProgress.bind(this));
document.addEventListener('upload-complete', this.handleUploadComplete.bind(this));
document.addEventListener('upload-error', this.handleUploadError.bind(this));
}
handleUploadStart(event) {
const { uploadId, fileName, file } = event.detail;
// Track the upload
this.activeUploads.set(uploadId, {
fileName,
file,
startTime: Date.now(),
status: 'uploading'
});
// Update UI
this.updateUploadButton(true);
this.showNotification(Starting upload: ${fileName});
}
handleUploadProgress(event) {
const { uploadId, fileName, progress } = event.detail;
// Update progress
const upload = this.activeUploads.get(uploadId);
if (upload) {
upload.progress = progress;
}
// Update UI
this.updateProgressBar(uploadId, progress);
}
handleUploadComplete(event) {
const { uploadId, fileName, result } = event.detail;
// Mark as completed
const upload = this.activeUploads.get(uploadId);
if (upload) {
upload.status = 'completed';
upload.endTime = Date.now();
upload.duration = upload.endTime - upload.startTime;
}
// Update UI
this.updateUploadButton(false);
this.showNotification(Upload completed: ${fileName}, 'success');
// Clean up after delay
setTimeout(() => {
this.activeUploads.delete(uploadId);
}, 3000);
}
handleUploadError(event) {
const { uploadId, fileName, error } = event.detail;
// Mark as failed
const upload = this.activeUploads.get(uploadId);
if (upload) {
upload.status = 'error';
upload.error = error;
}
// Update UI
this.updateUploadButton(false);
this.showNotification(Upload failed: ${fileName}, 'error');
// Clean up after delay
setTimeout(() => {
this.activeUploads.delete(uploadId);
}, 5000);
}
updateUploadButton(isUploading) {
const button = document.querySelector('#uploadButton');
if (button) {
button.disabled = isUploading;
button.textContent = isUploading ? 'Uploading...' : 'Upload';
}
}
updateProgressBar(uploadId, progress) {
// Custom progress bar implementation
const progressBar = document.querySelector(#progress-${uploadId});${progress}%
if (progressBar) {
progressBar.style.width = ;
}
}
showNotification(message, type = 'info') {
// Custom notification implementation
console.log(${type.toUpperCase()}: ${message});
}
getActiveUploads() {
return Array.from(this.activeUploads.values());
}
getUploadStatus(uploadId) {
return this.activeUploads.get(uploadId);
}
}
// Initialize
const uploadHandler = new MyUploadHandler();
`
If you need to implement your own upload logic while still using the tracking system:
`javascript${file.name}-${Date.now()}
class CustomUploader {
async uploadFile(file) {
const uploadId = ;
// Dispatch start event
this.dispatchUploadEvent('upload-start', {
uploadId,
fileName: file.name,
file
});
try {
// Your custom upload logic here
const result = await this.performUpload(file, (progress) => {
// Dispatch progress event
this.dispatchUploadEvent('upload-progress', {
uploadId,
fileName: file.name,
progress
});
});
// Dispatch complete event
this.dispatchUploadEvent('upload-complete', {
uploadId,
fileName: file.name,
result
});
return result;
} catch (error) {
// Dispatch error event
this.dispatchUploadEvent('upload-error', {
uploadId,
fileName: file.name,
error
});
throw error;
}
}
async performUpload(file, onProgress) {
// Simulate upload with progress
return new Promise((resolve, reject) => {
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 20;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
onProgress(progress);
resolve({ success: true, url: 'https://example.com/uploaded-file.jpg' });
} else {
onProgress(Math.round(progress));
}
}, 200);
});
}
dispatchUploadEvent(type, detail) {
document.dispatchEvent(new CustomEvent(type, {
detail,
bubbles: true,
composed: true
}));
}
}
`
javascript
{
uploadId: string, // Unique identifier for the upload
fileName: string, // Name of the file being uploaded
file: File // The file object
}
`$3
`javascript
{
uploadId: string, // Unique identifier for the upload
fileName: string, // Name of the file being uploaded
progress: number // Progress percentage (0-100)
}
`$3
`javascript
{
uploadId: string, // Unique identifier for the upload
fileName: string, // Name of the file being uploaded
result: object // Result from the upload operation
}
`$3
`javascript
{
uploadId: string, // Unique identifier for the upload
fileName: string, // Name of the file being uploaded
error: Error // Error object or error message
}
`Styling
The upload loading component uses CSS custom properties for theming:
`css
cdtr-upload-loading {
--upload-bg-color: white;
--upload-border-color: #e0e0e0;
--upload-progress-color: #007bff;
--upload-success-color: #28a745;
--upload-error-color: #dc3545;
}
`Browser Support
- Modern browsers with ES6+ support
- Requires LitElement framework
- Event-driven architecture for maximum compatibility
Examples
See
upload-example.js` for a complete working example of how to implement upload tracking in your application.