123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import React from 'react';
- import ImmutablePropTypes from 'react-immutable-proptypes';
- import PropTypes from 'prop-types';
- import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
- import ImmutablePureComponent from 'react-immutable-pure-component';
- import Textarea from 'react-textarea-autosize';
- import { is } from 'immutable';
- const messages = defineMessages({
- placeholder: { id: 'account_note.placeholder', defaultMessage: 'Click to add a note' },
- });
- class InlineAlert extends React.PureComponent {
- static propTypes = {
- show: PropTypes.bool,
- };
- state = {
- mountMessage: false,
- };
- static TRANSITION_DELAY = 200;
- componentWillReceiveProps (nextProps) {
- if (!this.props.show && nextProps.show) {
- this.setState({ mountMessage: true });
- } else if (this.props.show && !nextProps.show) {
- setTimeout(() => this.setState({ mountMessage: false }), InlineAlert.TRANSITION_DELAY);
- }
- }
- render () {
- const { show } = this.props;
- const { mountMessage } = this.state;
- return (
- <span aria-live='polite' role='status' className='inline-alert' style={{ opacity: show ? 1 : 0 }}>
- {mountMessage && <FormattedMessage id='generic.saved' defaultMessage='Saved' />}
- </span>
- );
- }
- }
- export default @injectIntl
- class AccountNote extends ImmutablePureComponent {
- static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
- value: PropTypes.string,
- onSave: PropTypes.func.isRequired,
- intl: PropTypes.object.isRequired,
- };
- state = {
- value: null,
- saving: false,
- saved: false,
- };
- componentWillMount () {
- this._reset();
- }
- componentWillReceiveProps (nextProps) {
- const accountWillChange = !is(this.props.account, nextProps.account);
- const newState = {};
- if (accountWillChange && this._isDirty()) {
- this._save(false);
- }
- if (accountWillChange || nextProps.value === this.state.value) {
- newState.saving = false;
- }
- if (this.props.value !== nextProps.value) {
- newState.value = nextProps.value;
- }
- this.setState(newState);
- }
- componentWillUnmount () {
- if (this._isDirty()) {
- this._save(false);
- }
- }
- setTextareaRef = c => {
- this.textarea = c;
- }
- handleChange = e => {
- this.setState({ value: e.target.value, saving: false });
- };
- handleKeyDown = e => {
- if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
- e.preventDefault();
- this._save();
- if (this.textarea) {
- this.textarea.blur();
- }
- } else if (e.keyCode === 27) {
- e.preventDefault();
- this._reset(() => {
- if (this.textarea) {
- this.textarea.blur();
- }
- });
- }
- }
- handleBlur = () => {
- if (this._isDirty()) {
- this._save();
- }
- }
- _save (showMessage = true) {
- this.setState({ saving: true }, () => this.props.onSave(this.state.value));
- if (showMessage) {
- this.setState({ saved: true }, () => setTimeout(() => this.setState({ saved: false }), 2000));
- }
- }
- _reset (callback) {
- this.setState({ value: this.props.value }, callback);
- }
- _isDirty () {
- return !this.state.saving && this.props.value !== null && this.state.value !== null && this.state.value !== this.props.value;
- }
- render () {
- const { account, intl } = this.props;
- const { value, saved } = this.state;
- if (!account) {
- return null;
- }
- return (
- <div className='account__header__account-note'>
- <label htmlFor={`account-note-${account.get('id')}`}>
- <FormattedMessage id='account.account_note_header' defaultMessage='Note' /> <InlineAlert show={saved} />
- </label>
- <Textarea
- id={`account-note-${account.get('id')}`}
- className='account__header__account-note__content'
- disabled={this.props.value === null || value === null}
- placeholder={intl.formatMessage(messages.placeholder)}
- value={value || ''}
- onChange={this.handleChange}
- onKeyDown={this.handleKeyDown}
- onBlur={this.handleBlur}
- ref={this.setTextareaRef}
- />
- </div>
- );
- }
- }
|