Merge pull request #606 from ZogStriP/better-client-side-upload

improved images upload on the client side
This commit is contained in:
Robin Ward 2013-04-01 07:11:26 -07:00
commit 75d5049c0a
6 changed files with 76 additions and 51 deletions

View File

@ -51,6 +51,11 @@
{{#if Discourse.currentUser}} {{#if Discourse.currentUser}}
<a href="#" {{action togglePreview target="controller"}} class='toggle-preview'>{{{content.toggleText}}}</a> <a href="#" {{action togglePreview target="controller"}} class='toggle-preview'>{{{content.toggleText}}}</a>
<div class='saving-draft'></div> <div class='saving-draft'></div>
{{#if view.loadingImage}}
<div id="image-uploading">
{{i18n image_selector.uploading_image}} {{view.uploadProgress}}% <a {{action cancelUpload target="view"}}>{{i18n cancel}}</a>
</div>
{{/if}}
{{/if}} {{/if}}
</div> </div>
@ -58,11 +63,6 @@
<div class='submit-panel'> <div class='submit-panel'>
<button {{action save target="controller"}} tabindex="4" {{bindAttr disabled="content.cantSubmitPost"}} class='btn btn-primary create'>{{view.content.saveText}}</button> <button {{action save target="controller"}} tabindex="4" {{bindAttr disabled="content.cantSubmitPost"}} class='btn btn-primary create'>{{view.content.saveText}}</button>
<a href='#' {{action cancel target="controller"}} class='cancel' tabindex="4">{{i18n cancel}}</a> <a href='#' {{action cancel target="controller"}} class='cancel' tabindex="4">{{i18n cancel}}</a>
{{#if view.loadingImage}}
<div id="image-uploading">
{{i18n image_selector.uploading_image}} {{view.uploadProgress}}% <a {{action cancelUpload target="view"}}>{{i18n cancel}}</a>
</div>
{{/if}}
</div> </div>
{{/if}} {{/if}}

View File

@ -271,47 +271,65 @@ Discourse.ComposerView = Discourse.View.extend({
// In case it's still bound somehow // In case it's still bound somehow
$uploadTarget.fileupload('destroy'); $uploadTarget.fileupload('destroy');
$uploadTarget.off();
$uploadTarget.fileupload({ $uploadTarget.fileupload({
url: '/uploads', url: '/uploads',
dataType: 'json', dataType: 'json',
timeout: 20000, timeout: 20000,
formData: { formData: { topic_id: 1234 }
topic_id: 1234 });
},
paste: function(e, data) { var addImages = function (e, data) {
if (data.files.length > 0) { console.log('addImages');
_this.set('loadingImage', true); // can only upload one image at a time
_this.set('uploadProgress', 0); if (data.files.length > 1) {
} bootbox.alert(Em.String.i18n('post.errors.upload_too_many_images'));
return true; } else if (data.files.length > 0) {
}, // check image size
drop: function(e, data) { var fileSizeInKB = data.files[0].size / 1024;
if (e.originalEvent.dataTransfer.files.length === 1) { if (fileSizeInKB > Discourse.SiteSettings.max_upload_size_kb) {
_this.set('loadingImage', true); bootbox.alert(Em.String.i18n('post.errors.upload_too_large', { max_size_kb: Discourse.SiteSettings.max_upload_size_kb }));
return _this.set('uploadProgress', 0);
}
},
progressall: function(e, data) {
var progress;
progress = parseInt(data.loaded / data.total * 100, 10);
return _this.set('uploadProgress', progress);
},
done: function(e, data) {
var html, upload;
_this.set('loadingImage', false);
upload = data.result;
html = "<img src=\"" + upload.url + "\" width=\"" + upload.width + "\" height=\"" + upload.height + "\">";
return _this.addMarkdown(html);
},
fail: function(e, data) {
// 413 == entity too large, returned usually from nginx
if(data.jqXHR && data.jqXHR.status === 413) {
bootbox.alert(Em.String.i18n('post.errors.upload_too_large', {max_size_kb: Discourse.SiteSettings.max_upload_size_kb}));
} else { } else {
bootbox.alert(Em.String.i18n('post.errors.upload')); // reset upload status
_this.setProperties({
uploadProgress: 0,
loadingImage: true
});
return true;
} }
return _this.set('loadingImage', false); }
return false;
};
// paste
$uploadTarget.on('fileuploadpaste', addImages);
// drop
$uploadTarget.on('fileuploaddrop', addImages);
// progress all
$uploadTarget.on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
_this.set('uploadProgress', progress);
});
// done
$uploadTarget.on('fileuploaddone', function (e, data) {
var upload = data.result;
var html = "<img src=\"" + upload.url + "\" width=\"" + upload.width + "\" height=\"" + upload.height + "\">";
_this.addMarkdown(html);
_this.set('loadingImage', false);
});
// fail
$uploadTarget.on('fileuploadfail', function (e, data) {
_this.set('loadingImage', false);
// 413 == entity too large, returned usually from nginx
if(data.jqXHR && data.jqXHR.status === 413) {
bootbox.alert(Em.String.i18n('post.errors.upload_too_large', {max_size_kb: Discourse.SiteSettings.max_upload_size_kb}));
} else {
bootbox.alert(Em.String.i18n('post.errors.upload'));
} }
}); });
@ -372,5 +390,3 @@ Discourse.NotifyingTextArea = Ember.TextArea.extend({
}); });
RSVP.EventTarget.mixin(Discourse.ComposerView); RSVP.EventTarget.mixin(Discourse.ComposerView);

View File

@ -55,7 +55,7 @@
} }
#reply-control { #reply-control {
.toggle-preview, .saving-draft { .toggle-preview, .saving-draft, #image-uploading {
position: absolute; position: absolute;
bottom: -31px; bottom: -31px;
margin-top: 0px; margin-top: 0px;
@ -64,6 +64,11 @@
right: 5px; right: 5px;
text-decoration: underline; text-decoration: underline;
} }
#image-uploading {
left: 51%;
font-size: 12px;
color: darken($gray, 40);
}
.saving-draft { .saving-draft {
right: 51%; right: 51%;
color: lighten($black, 60); color: lighten($black, 60);
@ -250,6 +255,10 @@
img { img {
// Otherwise we get the wrong size in JS // Otherwise we get the wrong size in JS
max-width: none; max-width: none;
border-radius: 4px;
moz-border-radius: 4px;
webkit-border-radius: 4px;
ms-border-radius: 4px;
} }
} }
#wmd-preview { #wmd-preview {
@ -271,12 +280,6 @@
position: absolute; position: absolute;
display: block; display: block;
bottom: 8px; bottom: 8px;
#image-uploading {
display: inline-block;
margin-left: 330px;
font-size: 12px;
color: darken($gray, 40);
}
} }
} }
} }

View File

@ -526,6 +526,10 @@
} }
img { img {
max-width: 100%; max-width: 100%;
border-radius: 4px;
webkit-border-radius: 4px;
ms-border-radius: 4px;
moz-border-radius: 4px;
} }
.topic-body { .topic-body {
position: relative; position: relative;

View File

@ -550,6 +550,7 @@ en:
edit: "Sorry, there was an error editing your post. Please try again." edit: "Sorry, there was an error editing your post. Please try again."
upload: "Sorry, there was an error uploading that file. Please try again." upload: "Sorry, there was an error uploading that file. Please try again."
upload_too_large: "Sorry, the file you are trying to upload is too big (maximum size is {{max_size_kb}}kb), please resize it and try again." upload_too_large: "Sorry, the file you are trying to upload is too big (maximum size is {{max_size_kb}}kb), please resize it and try again."
upload_too_many_images: "Sorry, but you can only upload one image at a time."
abandon: "Are you sure you want to abandon your post?" abandon: "Are you sure you want to abandon your post?"

View File

@ -554,6 +554,7 @@ fr:
edit: "Désolé, il y a eu une erreur lors de l'édition de votre message. Merci de réessayer." edit: "Désolé, il y a eu une erreur lors de l'édition de votre message. Merci de réessayer."
upload: "Désolé, il y a eu une erreur lors de l'envoi du fichier. Merci de réessayer." upload: "Désolé, il y a eu une erreur lors de l'envoi du fichier. Merci de réessayer."
upload_too_large: "Désolé, le fichier que vous êtes en train d'envoyer est trop grand (maximum {{max_size_kb}}Kb). Merci de le redimensionner et de réessayer." upload_too_large: "Désolé, le fichier que vous êtes en train d'envoyer est trop grand (maximum {{max_size_kb}}Kb). Merci de le redimensionner et de réessayer."
upload_too_many_images: "Désolé, mais vous ne pouvez envoyer qu'une seule image à la fois."
abandon: "Voulez-vous vraiment abandonner ce message ?" abandon: "Voulez-vous vraiment abandonner ce message ?"