126 lines
4.3 KiB
JavaScript
126 lines
4.3 KiB
JavaScript
|
|
import { api } from '../api.js';
|
||
|
|
|
||
|
|
export class FileUpload extends HTMLElement {
|
||
|
|
constructor() {
|
||
|
|
super();
|
||
|
|
this.folderId = null;
|
||
|
|
this.handleEscape = this.handleEscape.bind(this);
|
||
|
|
this.render();
|
||
|
|
this.attachListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
setFolder(folderId) {
|
||
|
|
this.folderId = folderId;
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
this.innerHTML = `
|
||
|
|
<div class="upload-modal" id="upload-modal" style="display: none;">
|
||
|
|
<div class="upload-modal-content">
|
||
|
|
<div class="upload-header">
|
||
|
|
<h3>Upload Files</h3>
|
||
|
|
<button class="close-btn" id="close-upload">×</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="drop-zone" id="drop-zone">
|
||
|
|
<div class="drop-zone-text">
|
||
|
|
<p>Drag and drop files here</p>
|
||
|
|
<p>or</p>
|
||
|
|
<button class="button button-primary" id="select-files-btn">Select Files</button>
|
||
|
|
<input type="file" id="file-input" multiple style="display: none;">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="upload-list" id="upload-list"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
|
||
|
|
attachListeners() {
|
||
|
|
const modal = this.querySelector('#upload-modal');
|
||
|
|
const dropZone = this.querySelector('#drop-zone');
|
||
|
|
const fileInput = this.querySelector('#file-input');
|
||
|
|
const selectBtn = this.querySelector('#select-files-btn');
|
||
|
|
const closeBtn = this.querySelector('#close-upload');
|
||
|
|
|
||
|
|
selectBtn.addEventListener('click', () => fileInput.click());
|
||
|
|
fileInput.addEventListener('change', (e) => this.handleFiles(e.target.files));
|
||
|
|
|
||
|
|
closeBtn.addEventListener('click', () => this.hide());
|
||
|
|
|
||
|
|
dropZone.addEventListener('dragover', (e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
dropZone.classList.add('drag-over');
|
||
|
|
});
|
||
|
|
|
||
|
|
dropZone.addEventListener('dragleave', () => {
|
||
|
|
dropZone.classList.remove('drag-over');
|
||
|
|
});
|
||
|
|
|
||
|
|
dropZone.addEventListener('drop', (e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
dropZone.classList.remove('drag-over');
|
||
|
|
this.handleFiles(e.dataTransfer.files);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
handleEscape(e) {
|
||
|
|
if (e.key === 'Escape') {
|
||
|
|
const modal = this.querySelector('#upload-modal');
|
||
|
|
if (modal.style.display === 'flex') {
|
||
|
|
this.hide();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
show() {
|
||
|
|
this.querySelector('#upload-modal').style.display = 'flex';
|
||
|
|
document.addEventListener('keydown', this.handleEscape);
|
||
|
|
}
|
||
|
|
|
||
|
|
hide() {
|
||
|
|
this.querySelector('#upload-modal').style.display = 'none';
|
||
|
|
this.querySelector('#upload-list').innerHTML = '';
|
||
|
|
document.removeEventListener('keydown', this.handleEscape);
|
||
|
|
}
|
||
|
|
|
||
|
|
async handleFiles(files) {
|
||
|
|
const uploadList = this.querySelector('#upload-list');
|
||
|
|
|
||
|
|
for (const file of files) {
|
||
|
|
const itemId = `upload-${Date.now()}-${Math.random()}`;
|
||
|
|
const item = document.createElement('div');
|
||
|
|
item.className = 'upload-item';
|
||
|
|
item.id = itemId;
|
||
|
|
item.innerHTML = `
|
||
|
|
<div class="upload-item-name">${file.name}</div>
|
||
|
|
<div class="upload-item-progress">
|
||
|
|
<div class="progress-bar">
|
||
|
|
<div class="progress-fill" style="width: 0%"></div>
|
||
|
|
</div>
|
||
|
|
<span class="upload-status">Uploading...</span>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
uploadList.appendChild(item);
|
||
|
|
|
||
|
|
try {
|
||
|
|
await api.uploadFile(file, this.folderId);
|
||
|
|
const status = item.querySelector('.upload-status');
|
||
|
|
const progressFill = item.querySelector('.progress-fill');
|
||
|
|
progressFill.style.width = '100%';
|
||
|
|
status.textContent = 'Complete';
|
||
|
|
status.classList.add('success');
|
||
|
|
} catch (error) {
|
||
|
|
const status = item.querySelector('.upload-status');
|
||
|
|
status.textContent = 'Failed: ' + error.message;
|
||
|
|
status.classList.add('error');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.dispatchEvent(new CustomEvent('upload-complete'));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
customElements.define('file-upload', FileUpload);
|