2017-08-18 06:27:42 +03:00
|
|
|
import $ from 'jquery';
|
2017-08-22 10:53:26 +03:00
|
|
|
import Component from '@ember/component';
|
2019-01-22 16:09:38 +03:00
|
|
|
import md5 from 'blueimp-md5';
|
2017-07-06 12:33:15 +03:00
|
|
|
import request from 'ember-ajax/request';
|
2019-01-22 16:09:38 +03:00
|
|
|
import validator from 'validator';
|
2017-08-22 10:53:26 +03:00
|
|
|
import {htmlSafe} from '@ember/string';
|
2017-10-30 12:38:01 +03:00
|
|
|
import {inject as service} from '@ember/service';
|
2017-07-06 12:33:15 +03:00
|
|
|
import {task, timeout} from 'ember-concurrency';
|
|
|
|
|
|
|
|
const ANIMATION_TIMEOUT = 1000;
|
2015-05-28 08:52:41 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A component to manage a user profile image. By default it just handles picture uploads,
|
|
|
|
* but if passed a bound 'email' property it will render the user's gravatar image
|
|
|
|
*
|
2015-10-26 14:48:38 +03:00
|
|
|
* Example: {{gh-profile-image email=controllerEmailProperty setImage="controllerActionName" debounce=500}}
|
2015-05-28 08:52:41 +03:00
|
|
|
*
|
2015-10-26 14:48:38 +03:00
|
|
|
* @param {int} size The size of the image to render
|
|
|
|
* @param {String} email Reference to a bound email object if gravatar image behavior is desired.
|
|
|
|
* @param {String|action} setImage The string name of the action on the controller to be called when an image is added.
|
|
|
|
* @param {int} debounce Period to wait after changes to email before attempting to load gravatar
|
|
|
|
* @property {Boolean} hasUploadedImage Whether or not the user has uploaded an image (whether or not to show the default image/gravatar image)
|
|
|
|
* @property {String} defaultImage String containing the background-image css property of the default user profile image
|
|
|
|
* @property {String} imageBackground String containing the background-image css property with the gravatar url
|
2015-05-28 08:52:41 +03:00
|
|
|
*/
|
2015-10-28 14:36:45 +03:00
|
|
|
export default Component.extend({
|
2018-01-11 20:43:23 +03:00
|
|
|
config: service(),
|
|
|
|
ghostPaths: service(),
|
|
|
|
|
2015-05-28 08:52:41 +03:00
|
|
|
email: '',
|
2016-09-19 16:38:42 +03:00
|
|
|
size: 180,
|
2015-10-26 14:48:38 +03:00
|
|
|
debounce: 300,
|
|
|
|
|
2017-08-18 06:27:42 +03:00
|
|
|
imageFile: null,
|
2015-05-28 08:52:41 +03:00
|
|
|
hasUploadedImage: false,
|
|
|
|
|
2018-01-11 20:43:23 +03:00
|
|
|
_defaultImageUrl: '',
|
|
|
|
|
2017-08-18 06:27:42 +03:00
|
|
|
// closure actions
|
|
|
|
setImage() {},
|
|
|
|
|
2017-07-06 12:33:15 +03:00
|
|
|
placeholderStyle: htmlSafe('background-image: url()'),
|
|
|
|
avatarStyle: htmlSafe('display: none'),
|
|
|
|
|
2015-10-28 14:36:45 +03:00
|
|
|
init() {
|
2015-11-20 19:40:41 +03:00
|
|
|
this._super(...arguments);
|
|
|
|
|
2018-04-03 13:59:33 +03:00
|
|
|
let defaultImage = '/img/user-image.png';
|
2018-08-16 01:58:37 +03:00
|
|
|
this._defaultImageUrl = this.get('ghostPaths.assetRoot').replace(/\/$/, '') + defaultImage;
|
2017-07-06 12:33:15 +03:00
|
|
|
this._setPlaceholderImage(this._defaultImageUrl);
|
2015-09-06 18:03:49 +03:00
|
|
|
},
|
|
|
|
|
2017-07-06 12:33:15 +03:00
|
|
|
didReceiveAttrs() {
|
|
|
|
this._super(...arguments);
|
|
|
|
|
|
|
|
if (this.get('config.useGravatar')) {
|
2019-03-06 16:53:54 +03:00
|
|
|
this.setGravatar.perform();
|
2017-07-06 12:33:15 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-01-11 20:43:23 +03:00
|
|
|
actions: {
|
|
|
|
imageSelected(fileList, resetInput) {
|
|
|
|
// eslint-disable-next-line
|
|
|
|
let imageFile = fileList[0];
|
|
|
|
|
|
|
|
if (imageFile) {
|
|
|
|
let reader = new FileReader();
|
|
|
|
|
|
|
|
this.set('imageFile', imageFile);
|
|
|
|
this.setImage(imageFile);
|
|
|
|
|
|
|
|
reader.addEventListener('load', () => {
|
|
|
|
let dataURL = reader.result;
|
|
|
|
this.set('previewDataURL', dataURL);
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
reader.readAsDataURL(imageFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
resetInput();
|
|
|
|
},
|
|
|
|
|
|
|
|
openFileDialog(event) {
|
|
|
|
// simulate click to open file dialog
|
|
|
|
// using jQuery because IE11 doesn't support MouseEvent
|
|
|
|
$(event.target)
|
|
|
|
.closest('figure')
|
|
|
|
.find('input[type="file"]')
|
|
|
|
.click();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-08-18 06:27:42 +03:00
|
|
|
dragOver(event) {
|
|
|
|
if (!event.dataTransfer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this is needed to work around inconsistencies with dropping files
|
|
|
|
// from Chrome's downloads bar
|
2017-12-12 14:53:35 +03:00
|
|
|
if (navigator.userAgent.indexOf('Chrome') > -1) {
|
|
|
|
let eA = event.dataTransfer.effectAllowed;
|
|
|
|
event.dataTransfer.dropEffect = (eA === 'move' || eA === 'linkMove') ? 'move' : 'copy';
|
|
|
|
}
|
2017-08-18 06:27:42 +03:00
|
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
event.preventDefault();
|
|
|
|
},
|
|
|
|
|
|
|
|
dragLeave(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
},
|
|
|
|
|
|
|
|
drop(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
if (event.dataTransfer.files) {
|
|
|
|
this.send('imageSelected', event.dataTransfer.files);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-07-06 12:33:15 +03:00
|
|
|
setGravatar: task(function* () {
|
2019-03-06 16:53:54 +03:00
|
|
|
yield timeout(this.debounce);
|
2017-07-06 12:33:15 +03:00
|
|
|
|
2019-03-06 16:53:54 +03:00
|
|
|
let email = this.email;
|
2017-07-06 12:33:15 +03:00
|
|
|
|
2018-03-19 20:56:09 +03:00
|
|
|
if (validator.isEmail(email || '')) {
|
2019-03-06 16:53:54 +03:00
|
|
|
let size = this.size;
|
2018-03-19 20:56:09 +03:00
|
|
|
let gravatarUrl = `//www.gravatar.com/avatar/${md5(email)}?s=${size}&d=404`;
|
2017-07-06 12:33:15 +03:00
|
|
|
|
|
|
|
try {
|
|
|
|
// HEAD request is needed otherwise jquery attempts to process
|
|
|
|
// binary data as JSON and throws an error
|
|
|
|
yield request(gravatarUrl, {type: 'HEAD'});
|
|
|
|
// gravatar exists so switch style and let browser load it
|
|
|
|
this._setAvatarImage(gravatarUrl);
|
|
|
|
// wait for fade-in animation to finish before removing placeholder
|
|
|
|
yield timeout(ANIMATION_TIMEOUT);
|
|
|
|
this._setPlaceholderImage('');
|
|
|
|
} catch (e) {
|
|
|
|
// gravatar doesn't exist so make sure we're still showing the placeholder
|
|
|
|
this._setPlaceholderImage(this._defaultImageUrl);
|
|
|
|
// then make sure the avatar isn't visible
|
|
|
|
this._setAvatarImage('');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).restartable(),
|
|
|
|
|
|
|
|
_setPlaceholderImage(url) {
|
|
|
|
this.set('placeholderStyle', htmlSafe(`background-image: url(${url});`));
|
|
|
|
},
|
|
|
|
|
|
|
|
_setAvatarImage(url) {
|
|
|
|
let display = url ? 'block' : 'none';
|
|
|
|
this.set('avatarStyle', htmlSafe(`background-image: url(${url}); display: ${display}`));
|
|
|
|
},
|
|
|
|
|
2015-10-28 14:36:45 +03:00
|
|
|
queueFile(e, data) {
|
|
|
|
let fileName = data.files[0].name;
|
2015-07-07 20:34:23 +03:00
|
|
|
|
|
|
|
if ((/\.(gif|jpe?g|png|svg?z)$/i).test(fileName)) {
|
2019-03-06 16:53:54 +03:00
|
|
|
let action = this.setImage;
|
2017-11-25 02:18:35 +03:00
|
|
|
if (action) {
|
|
|
|
action(data);
|
|
|
|
}
|
2015-07-07 20:34:23 +03:00
|
|
|
}
|
2015-05-28 08:52:41 +03:00
|
|
|
}
|
|
|
|
});
|