Files
frontend-app-profile/src/components/ProfilePage/ProfileAvatar.jsx
Adam Butterworth 599cbfc649 refactor: use raw html form elements (#123)
* refactor: use raw html for form elements

* test: update snapshot to reflect minor changes in html output

* refactor: replace all reactstrap with paragon or html

* test: update snapshot

* fix: add a noop to the button in async button if needed

This is a flaw in the Button component in Paragon. It calls props.onClick even if it doesn't exist.

* refactor: use classnames for toggling class names

* fix: remove unneeded ids. fix some form markup

* fix: update snapshot to reflect removed labels
2019-04-05 13:07:44 -04:00

175 lines
4.5 KiB
JavaScript

import React from 'react';
import PropTypes from 'prop-types';
import { Button, Dropdown } from '@edx/paragon';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { ReactComponent as DefaultAvatar } from '../../assets/avatar.svg';
import messages from './ProfileAvatar.messages';
class ProfileAvatar extends React.Component {
constructor(props) {
super(props);
this.fileInput = React.createRef();
this.form = React.createRef();
this.onClickUpload = this.onClickUpload.bind(this);
this.onClickDelete = this.onClickDelete.bind(this);
this.onChangeInput = this.onChangeInput.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onClickUpload() {
this.fileInput.current.click();
}
onClickDelete() {
this.props.onDelete();
}
onChangeInput() {
this.onSubmit();
}
onSubmit(e) {
if (e) e.preventDefault();
this.props.onSave(new FormData(this.form.current));
this.form.current.reset();
}
renderPending() {
return (
<div
className="position-absolute w-100 h-100 d-flex justify-content-center align-items-center rounded-circle"
style={{ backgroundColor: 'rgba(0,0,0,.65)' }}
>
<div className="spinner-border text-primary" role="status" />
</div>
);
}
renderMenuContent() {
if (this.props.isDefault) {
return (
<Button
className={'text-white btn-block btn-sm'.split(' ')}
buttonType="link"
onClick={this.onClickUpload}
label={
<FormattedMessage
id="profile.profileavatar.upload-button"
defaultMessage="Upload Photo"
description="Upload photo button"
/>
}
/>
);
}
return (
<Dropdown
buttonType="primary"
title={(
<FormattedMessage
id="profile.profileavatar.change-button"
defaultMessage="Change"
description="Change photo button"
/>
)}
menuItems={[
(
<button className="dropdown-item" onClick={this.onClickUpload}>
<FormattedMessage
id="profile.profileavatar.upload-button"
defaultMessage="Upload Photo"
description="Upload photo button"
/>
</button>
),
(
<button className="dropdown-item" onClick={this.onClickDelete}>
<FormattedMessage
id="profile.profileavatar.remove.button"
defaultMessage="Remove"
description="Remove photo button"
/>
</button>
),
]}
/>
);
}
renderMenu() {
if (!this.props.isEditable) return null;
return (
<div className="profile-avatar-menu-container">
{this.renderMenuContent()}
</div>
);
}
renderAvatar() {
const { intl } = this.props;
return this.props.isDefault ? (
<DefaultAvatar className="text-muted" role="img" aria-hidden focusable="false" viewBox="0 0 24 24" />
) : (
<img
className="w-100 h-100 d-block rounded-circle overflow-hidden"
style={{ objectFit: 'cover' }}
alt={intl.formatMessage(messages['profile.image.alt.attribute'])}
src={this.props.src}
/>
);
}
render() {
return (
<div className="profile-avatar-wrap position-relative">
<div className="profile-avatar rounded-circle bg-light">
{this.props.savePhotoState === 'pending' ? this.renderPending() : this.renderMenu() }
{this.renderAvatar()}
</div>
<form
ref={this.form}
onSubmit={this.onSubmit}
encType="multipart/form-data"
>
{/* The name of this input must be 'file' */}
<input
className="d-none form-control-file"
ref={this.fileInput}
type="file"
name="file"
id="photo-file"
onChange={this.onChangeInput}
accept=".jpg, .jpeg, .png"
/>
</form>
</div>
);
}
}
export default injectIntl(ProfileAvatar);
ProfileAvatar.propTypes = {
src: PropTypes.string,
isDefault: PropTypes.bool,
onSave: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
savePhotoState: PropTypes.oneOf([null, 'pending', 'complete', 'error']),
isEditable: PropTypes.bool,
intl: intlShape.isRequired,
};
ProfileAvatar.defaultProps = {
src: null,
isDefault: true,
savePhotoState: null,
isEditable: false,
};