cleanup (broken files)

This commit is contained in:
2026-03-12 17:23:28 -05:00
parent f53030294b
commit df94685c96
6 changed files with 65 additions and 47 deletions
+2 -3
View File
@@ -32,7 +32,6 @@ export const FileUpload = Extension.create({
input.onchange = async () => {
if (input.files?.length) {
const file = input.files[0];
const filename = file.name;
const filesize = file.size.toString();
toast.promise(
@@ -45,11 +44,11 @@ export const FileUpload = Extension.create({
})(),
{
loading: "Uploading file...",
success: (url) => {
success: ({ url, filename: pbFilename }) => {
// Insert file attchment UI card
editor.chain()
.focus()
.insertFileAttachment({ src: url, filename, filesize })
.insertFileAttachment({ src: url, filename: pbFilename, filesize })
.run();
// Manually force a new paragraph at the end so the user can keep typing
+2 -2
View File
@@ -42,11 +42,11 @@ export const ImageUpload = Extension.create({
})(),
{
loading: "Processing & uploading image...",
success: (url) => {
success: ({ url, filename }) => {
// Insert image
editor.chain()
.focus()
.setImage({ src: url })
.setImage({ src: url, filename })
.run();
// Manually force a new paragraph at the end so the user can keep typing
+24 -20
View File
@@ -7,27 +7,19 @@ export const CustomImage = Image.extend({
selectable: true,
draggable: true,
addKeyboardShortcuts() {
addAttributes() {
return {
Backspace: () => {
const { selection } = this.editor.state;
if (!selection.empty) {
const selectedNode = this.editor.state.doc.nodeAt(selection.from);
if (selectedNode?.type.name === this.name) {
return true; // Prevent default deletion if image is selected
}
}
return false;
...this.parent?.(),
src: {
default: null,
},
Delete: () => {
const { selection } = this.editor.state;
if (!selection.empty) {
const selectedNode = this.editor.state.doc.nodeAt(selection.from);
if (selectedNode?.type.name === this.name) {
return true; // Prevent default deletion if image is selected
}
}
return false;
filename: {
default: null,
parseHTML: element => element.getAttribute('data-filename'),
renderHTML: attributes => {
if (!attributes.filename) return {};
return { 'data-filename': attributes.filename };
},
},
};
},
@@ -43,7 +35,11 @@ export const CustomImage = Image.extend({
const img = document.createElement('img');
Object.entries(node.attrs).forEach(([key, value]) => {
if (value !== null && value !== undefined) {
img.setAttribute(key, value);
if (key === 'filename') {
img.setAttribute('data-filename', value);
} else {
img.setAttribute(key, value);
}
}
});
img.classList.add('rounded-lg', 'border', 'border-border', 'max-w-full', 'h-auto', 'cursor-default');
@@ -79,3 +75,11 @@ export const CustomImage = Image.extend({
};
},
});
declare module '@tiptap/core' {
interface Commands<ReturnType> {
image: {
setImage: (options: { src: string, alt?: string, title?: string, filename?: string }) => ReturnType;
};
}
}
+2 -2
View File
@@ -41,11 +41,11 @@ export const VideoUpload = Extension.create({
})(),
{
loading: "Uploading video...",
success: (url) => {
success: ({ url, filename }) => {
// Insert video
editor.chain()
.focus()
.setVideo({ src: url })
.setVideo({ src: url, filename })
.run();
// Manually force a new paragraph at the end so the user can keep typing
+25 -13
View File
@@ -27,6 +27,25 @@ export const Video = Node.create<VideoOptions>({
src: {
default: null,
},
filename: {
default: null,
parseHTML: element => element.getAttribute('data-filename'),
renderHTML: attributes => {
if (!attributes.filename) return {};
return { 'data-filename': attributes.filename };
},
},
};
},
addCommands() {
return {
setVideo: (options: { src: string, filename?: string }) => ({ commands }) => {
return commands.insertContent({
type: this.name,
attrs: options,
});
},
};
},
@@ -76,7 +95,11 @@ export const Video = Node.create<VideoOptions>({
const video = document.createElement('video');
Object.entries(node.attrs).forEach(([key, value]) => {
if (value !== null && value !== undefined) {
video.setAttribute(key, value);
if (key === 'filename') {
video.setAttribute('data-filename', value);
} else {
video.setAttribute(key, value);
}
}
});
// Apply default attributes if not present
@@ -115,23 +138,12 @@ export const Video = Node.create<VideoOptions>({
};
};
},
addCommands() {
return {
setVideo: (options: { src: string }) => ({ commands }) => {
return commands.insertContent({
type: this.name,
attrs: options,
});
},
};
},
});
declare module '@tiptap/core' {
interface Commands<ReturnType> {
video: {
setVideo: (options: { src: string }) => ReturnType;
setVideo: (options: { src: string, filename?: string }) => ReturnType;
};
}
}
+10 -7
View File
@@ -576,19 +576,19 @@ const mapRecordToTask = (r: any): Task => {
};
};
export const uploadTaskAttachment = async (taskId: string, file: File): Promise<string> => {
export const uploadTaskAttachment = async (taskId: string, file: File): Promise<{ url: string, filename: string }> => {
try {
const formData = new FormData();
formData.append('attachments+', file);
const record = await pb.collection(TASGRID_COLLECTION).update(taskId, formData);
// Return the URL for the newly uploaded file. PocketBase appends new files to the array.
// We need to find the specific filename that was just uploaded to get its URL.
// Since we don't know the exact generated filename, we can return the URL of the last file in the array.
if (record.attachments && record.attachments.length > 0) {
const latestFilename = record.attachments[record.attachments.length - 1];
return pb.files.getURL(record, latestFilename);
return {
url: pb.files.getURL(record, latestFilename),
filename: latestFilename
};
}
throw new Error("File uploaded but no attachment returned");
@@ -599,7 +599,7 @@ export const uploadTaskAttachment = async (taskId: string, file: File): Promise<
}
};
export const uploadNoteAttachment = async (noteId: string, file: File): Promise<string> => {
export const uploadNoteAttachment = async (noteId: string, file: File): Promise<{ url: string, filename: string }> => {
try {
const formData = new FormData();
formData.append('attachments+', file);
@@ -608,7 +608,10 @@ export const uploadNoteAttachment = async (noteId: string, file: File): Promise<
if (record.attachments && record.attachments.length > 0) {
const latestFilename = record.attachments[record.attachments.length - 1];
return pb.files.getURL(record, latestFilename);
return {
url: pb.files.getURL(record, latestFilename),
filename: latestFilename
};
}
throw new Error("File uploaded but no attachment returned");