|
@@ -296,44 +296,13 @@ Template.cardAttachmentsPopup.events({
|
|
|
const files = event.currentTarget.files;
|
|
|
if (files) {
|
|
|
let uploads = [];
|
|
|
- for (const file of files) {
|
|
|
- const fileId = new ObjectID().toString();
|
|
|
- let fileName = DOMPurify.sanitize(file.name);
|
|
|
-
|
|
|
- // If sanitized filename is not same as original filename,
|
|
|
- // it could be XSS that is already fixed with sanitize,
|
|
|
- // or just normal mistake, so it is not a problem.
|
|
|
- // That is why here is no warning.
|
|
|
- if (fileName !== file.name) {
|
|
|
- // If filename is empty, only in that case add some filename
|
|
|
- if (fileName.length === 0) {
|
|
|
- fileName = 'Empty-filename-after-sanitize.txt';
|
|
|
- }
|
|
|
- }
|
|
|
+ const uploaders = handleFileUpload(card, files);
|
|
|
|
|
|
- const config = {
|
|
|
- file: file,
|
|
|
- fileId: fileId,
|
|
|
- fileName: fileName,
|
|
|
- meta: Utils.getCommonAttachmentMetaFrom(card),
|
|
|
- chunkSize: 'dynamic',
|
|
|
- };
|
|
|
- config.meta.fileId = fileId;
|
|
|
- const uploader = Attachments.insert(
|
|
|
- config,
|
|
|
- false,
|
|
|
- );
|
|
|
+ uploaders.forEach(uploader => {
|
|
|
uploader.on('start', function() {
|
|
|
uploads.push(this);
|
|
|
templateInstance.uploads.set(uploads);
|
|
|
});
|
|
|
- uploader.on('uploaded', (error, fileRef) => {
|
|
|
- if (!error) {
|
|
|
- if (fileRef.isImage) {
|
|
|
- card.setCover(fileRef._id);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
uploader.on('end', (error, fileRef) => {
|
|
|
uploads = uploads.filter(_upload => _upload.config.fileId != fileRef._id);
|
|
|
templateInstance.uploads.set(uploads);
|
|
@@ -341,8 +310,7 @@ Template.cardAttachmentsPopup.events({
|
|
|
Popup.back();
|
|
|
}
|
|
|
});
|
|
|
- uploader.start();
|
|
|
- }
|
|
|
+ });
|
|
|
}
|
|
|
},
|
|
|
'click .js-computer-upload'(event, templateInstance) {
|
|
@@ -356,6 +324,87 @@ const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
|
|
|
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
|
|
|
let pastedResults = null;
|
|
|
|
|
|
+// Shared upload logic for drag-and-drop functionality
|
|
|
+export function handleFileUpload(card, files) {
|
|
|
+ if (!files || files.length === 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if board allows attachments
|
|
|
+ const board = card.board();
|
|
|
+ if (!board || !board.allowsAttachments) {
|
|
|
+ console.warn('Attachments not allowed on this board');
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if user can modify the card
|
|
|
+ if (!card.canModifyCard()) {
|
|
|
+ console.warn('User does not have permission to modify this card');
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ const uploads = [];
|
|
|
+
|
|
|
+ for (const file of files) {
|
|
|
+ // Basic file validation
|
|
|
+ if (!file || !file.name) {
|
|
|
+ console.warn('Invalid file object');
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const fileId = new ObjectID().toString();
|
|
|
+ let fileName = DOMPurify.sanitize(file.name);
|
|
|
+
|
|
|
+ // If sanitized filename is not same as original filename,
|
|
|
+ // it could be XSS that is already fixed with sanitize,
|
|
|
+ // or just normal mistake, so it is not a problem.
|
|
|
+ // That is why here is no warning.
|
|
|
+ if (fileName !== file.name) {
|
|
|
+ // If filename is empty, only in that case add some filename
|
|
|
+ if (fileName.length === 0) {
|
|
|
+ fileName = 'Empty-filename-after-sanitize.txt';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const config = {
|
|
|
+ file: file,
|
|
|
+ fileId: fileId,
|
|
|
+ fileName: fileName,
|
|
|
+ meta: Utils.getCommonAttachmentMetaFrom(card),
|
|
|
+ chunkSize: 'dynamic',
|
|
|
+ };
|
|
|
+ config.meta.fileId = fileId;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const uploader = Attachments.insert(
|
|
|
+ config,
|
|
|
+ false,
|
|
|
+ );
|
|
|
+
|
|
|
+ uploader.on('uploaded', (error, fileRef) => {
|
|
|
+ if (!error) {
|
|
|
+ if (fileRef.isImage) {
|
|
|
+ card.setCover(fileRef._id);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.error('Upload error:', error);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ uploader.on('error', (error) => {
|
|
|
+ console.error('Upload error:', error);
|
|
|
+ });
|
|
|
+
|
|
|
+ uploads.push(uploader);
|
|
|
+ uploader.start();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to create uploader:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return uploads;
|
|
|
+}
|
|
|
+
|
|
|
Template.previewClipboardImagePopup.onRendered(() => {
|
|
|
// we can paste image from clipboard
|
|
|
const handle = results => {
|