From 67d23ff8ae691397ae9a5c12699397e01e34408e Mon Sep 17 00:00:00 2001 From: "Sam X. Chen" Date: Sat, 10 Aug 2019 21:21:42 -0400 Subject: Add Feature: Richer Editor insert picture as attachment instead of b64 string --- .meteor-1.6-snap/package.json | 13 ++++--- client/components/cards/attachments.js | 27 ++++---------- client/components/main/editor.js | 65 ++++++++++++++++++++++++++-------- client/lib/utils.js | 25 +++++++++++++ package.json | 1 + 5 files changed, 91 insertions(+), 40 deletions(-) diff --git a/.meteor-1.6-snap/package.json b/.meteor-1.6-snap/package.json index cff817b0..c8ddd53f 100644 --- a/.meteor-1.6-snap/package.json +++ b/.meteor-1.6-snap/package.json @@ -53,16 +53,21 @@ "prettier-eslint": "^8.8.2" }, "dependencies": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.5.4", + "ajv": "^5.0.0", "babel-runtime": "^6.26.0", - "bson-ext": "^2.0.0", + "bcrypt": "^3.0.2", + "bson": "^4.0.0", + "bunyan": "^1.8.12", "es6-promise": "^4.2.4", - "hoek": "^5.0.4", + "gridfs-stream": "^0.5.3", + "ldapjs": "^1.0.2", "meteor-node-stubs": "^0.4.1", + "mongodb": "^2.2.19", "os": "^0.1.1", "page": "^1.8.6", "qs": "^6.5.2", - "source-map-support": "^0.5.9", + "source-map-support": "^0.5.12", "xss": "^1.0.6" } } diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index d60169c3..843f1eb7 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -55,27 +55,12 @@ Template.cardAttachmentsPopup.events({ 'change .js-attach-file'(event) { const card = this; const processFile = f => { - const file = new FS.File(f); - if (card.isLinkedCard()) { - file.boardId = Cards.findOne(card.linkedId).boardId; - file.cardId = card.linkedId; - } else { - file.boardId = card.boardId; - file.swimlaneId = card.swimlaneId; - file.listId = card.listId; - file.cardId = card._id; - } - file.userId = Meteor.userId(); - if (file.original) { - file.original.name = f.name; - } - const attachment = Attachments.insert(file); - - if (attachment && attachment._id && attachment.isImage()) { - card.setCover(attachment._id); - } - - Popup.close(); + Utils.processUploadedAttachment(card, f, attachment => { + if (attachment && attachment._id && attachment.isImage()) { + card.setCover(attachment._id); + } + Popup.close(); + }); }; FS.Utility.eachFile(event, f => { diff --git a/client/components/main/editor.js b/client/components/main/editor.js index e217e113..248f4588 100755 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -176,36 +176,71 @@ Template.editor.onRendered(() => { const $summernote = getSummernote(this); if (files && files.length > 0) { const image = files[0]; - const reader = new FileReader(); + const currentCard = Cards.findOne(Session.get('currentCard')); const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL; const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO; - const processData = function(dataURL) { + const insertImage = src => { const img = document.createElement('img'); - img.src = dataURL; + img.src = src; img.setAttribute('width', '100%'); $summernote.summernote('insertNode', img); }; - reader.onload = function(e) { - const dataurl = e && e.target && e.target.result; - if (dataurl !== undefined) { - if (MAX_IMAGE_PIXEL) { + const processData = function(fileObj) { + Utils.processUploadedAttachment( + currentCard, + fileObj, + attachment => { + if ( + attachment && + attachment._id && + attachment.isImage() + ) { + attachment.one('uploaded', function() { + const maxTry = 3; + const checkItvl = 500; + let retry = 0; + const checkUrl = function() { + // even though uploaded event fired, attachment.url() is still null somehow //TODO + const url = attachment.url(); + if (url) { + insertImage(url); + } else { + retry++; + if (retry < maxTry) { + setTimeout(checkUrl, checkItvl); + } + } + }; + checkUrl(); + }); + } + }, + ); + }; + if (MAX_IMAGE_PIXEL) { + const reader = new FileReader(); + reader.onload = function(e) { + const dataurl = e && e.target && e.target.result; + if (dataurl !== undefined) { // need to shrink image Utils.shrinkImage({ dataurl, maxSize: MAX_IMAGE_PIXEL, ratio: COMPRESS_RATIO, - callback(changed) { - if (changed !== false && !!changed) { - processData(changed); + toBlob: true, + callback(blob) { + if (blob !== false) { + blob.name = image.name; + processData(blob); } }, }); - } else { - processData(dataurl); } - } - }; - reader.readAsDataURL(image); + }; + reader.readAsDataURL(image); + } else { + processData(image); + } } }, onPaste() { diff --git a/client/lib/utils.js b/client/lib/utils.js index f81e691c..81835929 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -26,6 +26,31 @@ Utils = { MAX_IMAGE_PIXEL: Meteor.settings.public.MAX_IMAGE_PIXEL, COMPRESS_RATIO: Meteor.settings.public.IMAGE_COMPRESS_RATIO, + processUploadedAttachment(card, fileObj, callback) { + const next = attachment => { + if (typeof callback === 'function') { + callback(attachment); + } + }; + if (!card) { + return next(); + } + const file = new FS.File(fileObj); + if (card.isLinkedCard()) { + file.boardId = Cards.findOne(card.linkedId).boardId; + file.cardId = card.linkedId; + } else { + file.boardId = card.boardId; + file.swimlaneId = card.swimlaneId; + file.listId = card.listId; + file.cardId = card._id; + } + file.userId = Meteor.userId(); + if (file.original) { + file.original.name = fileObj.name; + } + return next(Attachments.insert(file)); + }, shrinkImage(options) { // shrink image to certain size const dataurl = options.dataurl, diff --git a/package.json b/package.json index 670569fc..c8ddd53f 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "dependencies": { "@babel/runtime": "^7.5.4", "ajv": "^5.0.0", + "babel-runtime": "^6.26.0", "bcrypt": "^3.0.2", "bson": "^4.0.0", "bunyan": "^1.8.12", -- cgit v1.2.3-1-g7c22