init
This commit is contained in:
157
calendar/EventFileList.js
Normal file
157
calendar/EventFileList.js
Normal file
@@ -0,0 +1,157 @@
|
||||
class EventFileList extends Shadow {
|
||||
constructor(existingAttachments, onDeleteExisting = null, onDeleteNew = null, onPreview = null) {
|
||||
super();
|
||||
this.existingAttachments = existingAttachments ?? [];
|
||||
this.newFiles = [];
|
||||
this.objectURLs = new Map();
|
||||
this.onDeleteExisting = onDeleteExisting;
|
||||
this.onDeleteNew = onDeleteNew;
|
||||
this.onPreview = onPreview;
|
||||
}
|
||||
|
||||
update(files) {
|
||||
this.newFiles.push(...Array.from(files));
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
removeExisting(fileId) {
|
||||
this.existingAttachments = this.existingAttachments.filter(f => f.id !== fileId);
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
removeNew(index) {
|
||||
const file = this.newFiles[index];
|
||||
if (this.objectURLs.has(file)) {
|
||||
URL.revokeObjectURL(this.objectURLs.get(file));
|
||||
this.objectURLs.delete(file);
|
||||
}
|
||||
this.newFiles.splice(index, 1);
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
commitNew(insertedFiles) {
|
||||
this.newFiles.forEach(file => {
|
||||
if (this.objectURLs.has(file)) {
|
||||
URL.revokeObjectURL(this.objectURLs.get(file));
|
||||
this.objectURLs.delete(file);
|
||||
}
|
||||
});
|
||||
this.newFiles = [];
|
||||
this.existingAttachments = [...this.existingAttachments, ...insertedFiles];
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
getObjectURL(file) {
|
||||
if (!this.objectURLs.has(file)) {
|
||||
this.objectURLs.set(file, URL.createObjectURL(file));
|
||||
}
|
||||
return this.objectURLs.get(file);
|
||||
}
|
||||
|
||||
render() {
|
||||
const hasFiles = this.existingAttachments.length > 0 || this.newFiles.length > 0;
|
||||
this.style.display = hasFiles ? "flex" : "none";
|
||||
this.style.padding = "1em";
|
||||
this.style.paddingTop = "0.5em";
|
||||
this.style.boxSizing = "border-box";
|
||||
|
||||
VStack(() => {
|
||||
this.existingAttachments.forEach(file => {
|
||||
const isImage = file.type?.startsWith("image/");
|
||||
const url = `${config.SERVER}/db/images/events/${file.name}`
|
||||
const row = HStack(() => {
|
||||
if (isImage) {
|
||||
img(`${config.UI}/db/images/events/${file.name}`, "1.5em", "1.5em")
|
||||
.objectFit("cover")
|
||||
.borderRadius(3, px)
|
||||
.flexShrink(0)
|
||||
} else {
|
||||
span("📎")
|
||||
}
|
||||
span(file.original_name ?? file.name)
|
||||
.overflow("hidden")
|
||||
.textOverflow("ellipsis")
|
||||
.whiteSpace("nowrap")
|
||||
.flex(1)
|
||||
|
||||
span(file.size_bytes != null ? `${(file.size_bytes / 1024).toFixed(1)} KB` : "")
|
||||
.opacity(0.5)
|
||||
.flexShrink(0)
|
||||
.fontSize(0.85, rem)
|
||||
.width("5em")
|
||||
|
||||
if (this.onDeleteExisting) {
|
||||
span("×")
|
||||
.color("var(--quillred)")
|
||||
.opacity(0.7)
|
||||
.fontSize(1.2, em)
|
||||
.fontWeight("600")
|
||||
.flexShrink(0)
|
||||
.cursor("pointer")
|
||||
.padding(0.5, em)
|
||||
.margin(-0.5, em)
|
||||
.onTap((e) => { e?.stopPropagation(); if (window.isMobile() === true) this.onDeleteExisting(file.id) })
|
||||
.onClick((done, e) => { e?.stopPropagation(); if (done && window.isMobile() === false) this.onDeleteExisting(file.id) })
|
||||
}
|
||||
})
|
||||
.alignItems("center")
|
||||
.gap(0.5, em)
|
||||
if (this.onPreview) {
|
||||
row.cursor("pointer")
|
||||
.onClick((done) => { if (done) this.onPreview(file, url) })
|
||||
}
|
||||
})
|
||||
|
||||
this.newFiles.forEach((file, index) => {
|
||||
const isImage = file.type.startsWith("image/");
|
||||
const url = this.getObjectURL(file)
|
||||
const row = HStack(() => {
|
||||
if (isImage) {
|
||||
img(url, "1.5em", "1.5em")
|
||||
.objectFit("cover")
|
||||
.borderRadius(3, px)
|
||||
.flexShrink(0)
|
||||
} else {
|
||||
span("📎")
|
||||
}
|
||||
span(file.name)
|
||||
.overflow("hidden")
|
||||
.textOverflow("ellipsis")
|
||||
.whiteSpace("nowrap")
|
||||
.flex(1)
|
||||
|
||||
span(`${(file.size / 1024).toFixed(1)} KB`)
|
||||
.opacity(0.5)
|
||||
.flexShrink(0)
|
||||
.fontSize(0.85, rem)
|
||||
.width("5em")
|
||||
|
||||
if (this.onDeleteNew) {
|
||||
span("×")
|
||||
.color("var(--quillred)")
|
||||
.opacity(0.7)
|
||||
.fontSize(1.2, em)
|
||||
.fontWeight("600")
|
||||
.flexShrink(0)
|
||||
.cursor("pointer")
|
||||
.padding(0.5, em)
|
||||
.margin(-0.5, em)
|
||||
.onTap((e) => { e?.stopPropagation(); if (window.isMobile() === true) this.onDeleteNew(index) })
|
||||
.onClick((done, e) => { e?.stopPropagation(); if (done && window.isMobile() === false) this.onDeleteNew(index) })
|
||||
}
|
||||
})
|
||||
.alignItems("center")
|
||||
.gap(0.5, em)
|
||||
if (this.onPreview) {
|
||||
row.cursor("pointer")
|
||||
.onClick((done) => { if (done) this.onPreview(file, url) })
|
||||
}
|
||||
})
|
||||
})
|
||||
.gap(1, em)
|
||||
.color("var(--text)")
|
||||
.fontSize(0.85, rem)
|
||||
.fontFamily("Arial")
|
||||
}
|
||||
}
|
||||
register(EventFileList)
|
||||
Reference in New Issue
Block a user