mirror of
https://github.com/flarum/framework.git
synced 2024-11-27 19:13:37 +08:00
Add drag and drop avatar uploading
This commit is contained in:
parent
f3b4d35587
commit
123c8bb73d
|
@ -23,6 +23,13 @@ export default class AvatarEditor extends Component {
|
|||
* @type {Boolean}
|
||||
*/
|
||||
this.loading = false;
|
||||
|
||||
/**
|
||||
* Whether or not an image has been dragged over the dropzone.
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isDraggedOver = false;
|
||||
}
|
||||
|
||||
static initProps(props) {
|
||||
|
@ -35,12 +42,17 @@ export default class AvatarEditor extends Component {
|
|||
const user = this.props.user;
|
||||
|
||||
return (
|
||||
<div className={'AvatarEditor Dropdown ' + this.props.className + (this.loading ? ' loading' : '')}>
|
||||
<div className={'AvatarEditor Dropdown ' + this.props.className + (this.loading ? ' loading' : '') + (this.isDraggedOver ? ' dragover' : '')}>
|
||||
{avatar(user)}
|
||||
<a className={ user.avatarUrl() ? "Dropdown-toggle" : "Dropdown-toggle AvatarEditor--noAvatar" }
|
||||
title={app.translator.trans('core.forum.user.avatar_upload_tooltip')}
|
||||
data-toggle="dropdown"
|
||||
onclick={this.quickUpload.bind(this)}>
|
||||
onclick={this.quickUpload.bind(this)}
|
||||
ondragover={this.enableDragover.bind(this)}
|
||||
ondragenter={this.enableDragover.bind(this)}
|
||||
ondragleave={this.disableDragover.bind(this)}
|
||||
ondragend={this.disableDragover.bind(this)}
|
||||
ondrop={this.dropUpload.bind(this)}>
|
||||
{this.loading ? LoadingIndicator.component() : (user.avatarUrl() ? icon('pencil') : icon('plus-circle'))}
|
||||
</a>
|
||||
<ul className="Dropdown-menu Menu">
|
||||
|
@ -62,7 +74,7 @@ export default class AvatarEditor extends Component {
|
|||
Button.component({
|
||||
icon: 'upload',
|
||||
children: app.translator.trans('core.forum.user.avatar_upload_button'),
|
||||
onclick: this.upload.bind(this)
|
||||
onclick: this.openPicker.bind(this)
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -77,6 +89,40 @@ export default class AvatarEditor extends Component {
|
|||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable dragover style
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
enableDragover(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.isDraggedOver = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable dragover style
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
disableDragover(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.isDraggedOver = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload avatar when file is dropped into dropzone.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
dropUpload(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.isDraggedOver = false;
|
||||
this.upload(e.dataTransfer.files[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user doesn't have an avatar, there's no point in showing the
|
||||
* controls dropdown, because only one option would be viable: uploading.
|
||||
|
@ -89,14 +135,14 @@ export default class AvatarEditor extends Component {
|
|||
if (!this.props.user.avatarUrl()) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.upload();
|
||||
this.openPicker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user to upload a new avatar.
|
||||
* Upload avatar using file picker
|
||||
*/
|
||||
upload() {
|
||||
openPicker() {
|
||||
if (this.loading) return;
|
||||
|
||||
// Create a hidden HTML input element and click on it so the user can select
|
||||
|
@ -105,24 +151,36 @@ export default class AvatarEditor extends Component {
|
|||
const $input = $('<input type="file">');
|
||||
|
||||
$input.appendTo('body').hide().click().on('change', e => {
|
||||
const data = new FormData();
|
||||
data.append('avatar', $(e.target)[0].files[0]);
|
||||
|
||||
this.loading = true;
|
||||
m.redraw();
|
||||
|
||||
app.request({
|
||||
method: 'POST',
|
||||
url: app.forum.attribute('apiUrl') + '/users/' + user.id() + '/avatar',
|
||||
serialize: raw => raw,
|
||||
data
|
||||
}).then(
|
||||
this.success.bind(this),
|
||||
this.failure.bind(this)
|
||||
);
|
||||
this.upload($(e.target)[0].files[0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload avatar
|
||||
*
|
||||
* @param {File} file
|
||||
*/
|
||||
upload(file) {
|
||||
if (this.loading) return;
|
||||
|
||||
const user = this.props.user;
|
||||
const data = new FormData();
|
||||
data.append('avatar', file);
|
||||
|
||||
this.loading = true;
|
||||
m.redraw();
|
||||
|
||||
app.request({
|
||||
method: 'POST',
|
||||
url: app.forum.attribute('apiUrl') + '/users/' + user.id() + '/avatar',
|
||||
serialize: raw => raw,
|
||||
data
|
||||
}).then(
|
||||
this.success.bind(this),
|
||||
this.failure.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user's avatar.
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
.AvatarEditor--noAvatar {
|
||||
opacity: 0.7;
|
||||
}
|
||||
&:hover .Dropdown-toggle, &.open .Dropdown-toggle, &.loading .Dropdown-toggle {
|
||||
&:hover .Dropdown-toggle,
|
||||
&.open .Dropdown-toggle,
|
||||
&.loading .Dropdown-toggle,
|
||||
&.dragover .Dropdown-toggle {
|
||||
opacity: 1;
|
||||
}
|
||||
.LoadingIndicator {
|
||||
|
|
Loading…
Reference in New Issue
Block a user