avatar-upload-form.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import Ember from 'ember';
  2. import { fileSize } from 'misago/helpers/file-size';
  3. import { endsWith } from 'misago/utils/strings';
  4. export default Ember.Component.extend({
  5. classNames: 'avatar-upload',
  6. allowUpload: true,
  7. selectedImage: null,
  8. isUploading: false,
  9. progress: 0,
  10. uploadHash: null,
  11. apiUrl: function() {
  12. return 'users/' + this.auth.get('user.id') + '/avatar';
  13. }.property(),
  14. setupInput: function() {
  15. var self = this;
  16. this.$('input').change(function() {
  17. self.uploadImage(Ember.$(this)[0].files[0]);
  18. });
  19. }.on('didInsertElement'),
  20. destroyInput: function() {
  21. this.$('input').off();
  22. }.on('willDestroyElement'),
  23. uploadImage: function(image) {
  24. if (this.isDestroyed || this.get('isUploading')) { return; }
  25. this.set('allowUpload', false);
  26. // validate file
  27. if (image.size > this.get('options.upload.limit')) {
  28. var msg = gettext('Selected file is too big. (%(filesize)s)');
  29. this.toast.warning(msg.replace('%(filesize)s', fileSize(image.size)));
  30. this.set('allowUpload', true);
  31. return;
  32. }
  33. var invalidTypeMsg = gettext('Selected file type is not supported.');
  34. if (this.get('options.upload.allowed_mime_types').indexOf(image.type) === -1) {
  35. this.toast.warning(invalidTypeMsg);
  36. }
  37. var isExtensionFound = false;
  38. var loweredFilename = image.name.toLowerCase();
  39. var extensions = this.get('options.upload.allowed_extensions');
  40. Ember.EnumerableUtils.forEach(extensions, function(extension) {
  41. if (endsWith(loweredFilename, extension.toLowerCase())) {
  42. isExtensionFound = true;
  43. }
  44. });
  45. if (!isExtensionFound) {
  46. this.toast.warning(invalidTypeMsg);
  47. this.set('allowUpload', true);
  48. return;
  49. }
  50. // begin upload!
  51. this.setProperties({
  52. 'selectedImage': image,
  53. 'isUploading': true,
  54. 'progress': 0
  55. });
  56. var data = new FormData();
  57. data.append('avatar', 'upload');
  58. data.append('image', image);
  59. var self = this;
  60. Ember.run.scheduleOnce('afterRender', function() {
  61. if (self.isDestroyed) { return; }
  62. var reader = new FileReader();
  63. reader.onload = function(e) {
  64. self.$('img')[0].src = e.target.result;
  65. };
  66. reader.readAsDataURL(image);
  67. });
  68. self.ajax.post(self.get('apiUrl'), data, function(e) {
  69. if (self.isDestroyed) { return; }
  70. if (e.lengthComputable) {
  71. self.set('progress', Math.round((e.loaded * 100) / e.total));
  72. }
  73. }).then(function(data) {
  74. if (self.isDestroyed) { return; }
  75. self.toast.info(gettext("Your image was uploaded successfully."));
  76. self.set('uploadHash', data.detail);
  77. self.get('options').setProperties(data.options);
  78. }, function(jhXHR) {
  79. if (self.isDestroyed) { return; }
  80. self.setProperties({
  81. 'allowUpload': true,
  82. 'selectedImage': null,
  83. 'progress': 0
  84. });
  85. if (jhXHR.status === 400) {
  86. self.toast.error(jhXHR.responseJSON.detail);
  87. } else {
  88. self.toast.apiError(jhXHR);
  89. }
  90. }).finally(function() {
  91. if (self.isDestroyed) { return; }
  92. self.set('isUploading', false);
  93. });
  94. },
  95. extensions: function() {
  96. var finalList = [];
  97. var extensions = this.get('options.upload.allowed_extensions');
  98. Ember.EnumerableUtils.forEach(extensions, function(extension) {
  99. finalList.push(extension.substr(1));
  100. });
  101. return finalList.join(', ');
  102. }.property('options.upload.allowed_extensions'),
  103. progressBarWidth: function() {
  104. this.$('.progress-bar').css('width', this.get('progress') + '%');
  105. }.observes('progress'),
  106. actions: {
  107. selectFile: function() {
  108. // reset input
  109. this.$('input').wrap('<form>').closest('form').get(0).reset();
  110. this.$('input').unwrap();
  111. this.$('input').trigger('click');
  112. },
  113. cancel: function() {
  114. this.set('activeForm', 'select-avatar-type-form');
  115. }
  116. }
  117. });